Back to home page

LXR

 
 

    


0001 /*
0002  *  linux/fs/filesystems.c
0003  *
0004  *  Copyright (C) 1991, 1992  Linus Torvalds
0005  *
0006  *  table of configured filesystems
0007  */
0008 
0009 #include <linux/syscalls.h>
0010 #include <linux/fs.h>
0011 #include <linux/proc_fs.h>
0012 #include <linux/seq_file.h>
0013 #include <linux/kmod.h>
0014 #include <linux/init.h>
0015 #include <linux/module.h>
0016 #include <linux/slab.h>
0017 #include <linux/uaccess.h>
0018 
0019 /*
0020  * Handling of filesystem drivers list.
0021  * Rules:
0022  *  Inclusion to/removals from/scanning of list are protected by spinlock.
0023  *  During the unload module must call unregister_filesystem().
0024  *  We can access the fields of list element if:
0025  *      1) spinlock is held or
0026  *      2) we hold the reference to the module.
0027  *  The latter can be guaranteed by call of try_module_get(); if it
0028  *  returned 0 we must skip the element, otherwise we got the reference.
0029  *  Once the reference is obtained we can drop the spinlock.
0030  */
0031 
0032 static struct file_system_type *file_systems;
0033 static DEFINE_RWLOCK(file_systems_lock);
0034 
0035 /* WARNING: This can be used only if we _already_ own a reference */
0036 void get_filesystem(struct file_system_type *fs)
0037 {
0038     __module_get(fs->owner);
0039 }
0040 
0041 void put_filesystem(struct file_system_type *fs)
0042 {
0043     module_put(fs->owner);
0044 }
0045 
0046 static struct file_system_type **find_filesystem(const char *name, unsigned len)
0047 {
0048     struct file_system_type **p;
0049     for (p = &file_systems; *p; p = &(*p)->next)
0050         if (strncmp((*p)->name, name, len) == 0 &&
0051             !(*p)->name[len])
0052             break;
0053     return p;
0054 }
0055 
0056 /**
0057  *  register_filesystem - register a new filesystem
0058  *  @fs: the file system structure
0059  *
0060  *  Adds the file system passed to the list of file systems the kernel
0061  *  is aware of for mount and other syscalls. Returns 0 on success,
0062  *  or a negative errno code on an error.
0063  *
0064  *  The &struct file_system_type that is passed is linked into the kernel 
0065  *  structures and must not be freed until the file system has been
0066  *  unregistered.
0067  */
0068  
0069 int register_filesystem(struct file_system_type * fs)
0070 {
0071     int res = 0;
0072     struct file_system_type ** p;
0073 
0074     BUG_ON(strchr(fs->name, '.'));
0075     if (fs->next)
0076         return -EBUSY;
0077     write_lock(&file_systems_lock);
0078     p = find_filesystem(fs->name, strlen(fs->name));
0079     if (*p)
0080         res = -EBUSY;
0081     else
0082         *p = fs;
0083     write_unlock(&file_systems_lock);
0084     return res;
0085 }
0086 
0087 EXPORT_SYMBOL(register_filesystem);
0088 
0089 /**
0090  *  unregister_filesystem - unregister a file system
0091  *  @fs: filesystem to unregister
0092  *
0093  *  Remove a file system that was previously successfully registered
0094  *  with the kernel. An error is returned if the file system is not found.
0095  *  Zero is returned on a success.
0096  *  
0097  *  Once this function has returned the &struct file_system_type structure
0098  *  may be freed or reused.
0099  */
0100  
0101 int unregister_filesystem(struct file_system_type * fs)
0102 {
0103     struct file_system_type ** tmp;
0104 
0105     write_lock(&file_systems_lock);
0106     tmp = &file_systems;
0107     while (*tmp) {
0108         if (fs == *tmp) {
0109             *tmp = fs->next;
0110             fs->next = NULL;
0111             write_unlock(&file_systems_lock);
0112             synchronize_rcu();
0113             return 0;
0114         }
0115         tmp = &(*tmp)->next;
0116     }
0117     write_unlock(&file_systems_lock);
0118 
0119     return -EINVAL;
0120 }
0121 
0122 EXPORT_SYMBOL(unregister_filesystem);
0123 
0124 #ifdef CONFIG_SYSFS_SYSCALL
0125 static int fs_index(const char __user * __name)
0126 {
0127     struct file_system_type * tmp;
0128     struct filename *name;
0129     int err, index;
0130 
0131     name = getname(__name);
0132     err = PTR_ERR(name);
0133     if (IS_ERR(name))
0134         return err;
0135 
0136     err = -EINVAL;
0137     read_lock(&file_systems_lock);
0138     for (tmp=file_systems, index=0 ; tmp ; tmp=tmp->next, index++) {
0139         if (strcmp(tmp->name, name->name) == 0) {
0140             err = index;
0141             break;
0142         }
0143     }
0144     read_unlock(&file_systems_lock);
0145     putname(name);
0146     return err;
0147 }
0148 
0149 static int fs_name(unsigned int index, char __user * buf)
0150 {
0151     struct file_system_type * tmp;
0152     int len, res;
0153 
0154     read_lock(&file_systems_lock);
0155     for (tmp = file_systems; tmp; tmp = tmp->next, index--)
0156         if (index <= 0 && try_module_get(tmp->owner))
0157             break;
0158     read_unlock(&file_systems_lock);
0159     if (!tmp)
0160         return -EINVAL;
0161 
0162     /* OK, we got the reference, so we can safely block */
0163     len = strlen(tmp->name) + 1;
0164     res = copy_to_user(buf, tmp->name, len) ? -EFAULT : 0;
0165     put_filesystem(tmp);
0166     return res;
0167 }
0168 
0169 static int fs_maxindex(void)
0170 {
0171     struct file_system_type * tmp;
0172     int index;
0173 
0174     read_lock(&file_systems_lock);
0175     for (tmp = file_systems, index = 0 ; tmp ; tmp = tmp->next, index++)
0176         ;
0177     read_unlock(&file_systems_lock);
0178     return index;
0179 }
0180 
0181 /*
0182  * Whee.. Weird sysv syscall. 
0183  */
0184 SYSCALL_DEFINE3(sysfs, int, option, unsigned long, arg1, unsigned long, arg2)
0185 {
0186     int retval = -EINVAL;
0187 
0188     switch (option) {
0189         case 1:
0190             retval = fs_index((const char __user *) arg1);
0191             break;
0192 
0193         case 2:
0194             retval = fs_name(arg1, (char __user *) arg2);
0195             break;
0196 
0197         case 3:
0198             retval = fs_maxindex();
0199             break;
0200     }
0201     return retval;
0202 }
0203 #endif
0204 
0205 int __init get_filesystem_list(char *buf)
0206 {
0207     int len = 0;
0208     struct file_system_type * tmp;
0209 
0210     read_lock(&file_systems_lock);
0211     tmp = file_systems;
0212     while (tmp && len < PAGE_SIZE - 80) {
0213         len += sprintf(buf+len, "%s\t%s\n",
0214             (tmp->fs_flags & FS_REQUIRES_DEV) ? "" : "nodev",
0215             tmp->name);
0216         tmp = tmp->next;
0217     }
0218     read_unlock(&file_systems_lock);
0219     return len;
0220 }
0221 
0222 #ifdef CONFIG_PROC_FS
0223 static int filesystems_proc_show(struct seq_file *m, void *v)
0224 {
0225     struct file_system_type * tmp;
0226 
0227     read_lock(&file_systems_lock);
0228     tmp = file_systems;
0229     while (tmp) {
0230         seq_printf(m, "%s\t%s\n",
0231             (tmp->fs_flags & FS_REQUIRES_DEV) ? "" : "nodev",
0232             tmp->name);
0233         tmp = tmp->next;
0234     }
0235     read_unlock(&file_systems_lock);
0236     return 0;
0237 }
0238 
0239 static int filesystems_proc_open(struct inode *inode, struct file *file)
0240 {
0241     return single_open(file, filesystems_proc_show, NULL);
0242 }
0243 
0244 static const struct file_operations filesystems_proc_fops = {
0245     .open       = filesystems_proc_open,
0246     .read       = seq_read,
0247     .llseek     = seq_lseek,
0248     .release    = single_release,
0249 };
0250 
0251 static int __init proc_filesystems_init(void)
0252 {
0253     proc_create("filesystems", 0, NULL, &filesystems_proc_fops);
0254     return 0;
0255 }
0256 module_init(proc_filesystems_init);
0257 #endif
0258 
0259 static struct file_system_type *__get_fs_type(const char *name, int len)
0260 {
0261     struct file_system_type *fs;
0262 
0263     read_lock(&file_systems_lock);
0264     fs = *(find_filesystem(name, len));
0265     if (fs && !try_module_get(fs->owner))
0266         fs = NULL;
0267     read_unlock(&file_systems_lock);
0268     return fs;
0269 }
0270 
0271 struct file_system_type *get_fs_type(const char *name)
0272 {
0273     struct file_system_type *fs;
0274     const char *dot = strchr(name, '.');
0275     int len = dot ? dot - name : strlen(name);
0276 
0277     fs = __get_fs_type(name, len);
0278     if (!fs && (request_module("fs-%.*s", len, name) == 0))
0279         fs = __get_fs_type(name, len);
0280 
0281     if (dot && fs && !(fs->fs_flags & FS_HAS_SUBTYPE)) {
0282         put_filesystem(fs);
0283         fs = NULL;
0284     }
0285     return fs;
0286 }
0287 
0288 EXPORT_SYMBOL(get_fs_type);