The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/fs/filesystems.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  *  linux/fs/filesystems.c
    3  *
    4  *  Copyright (C) 1991, 1992  Linus Torvalds
    5  *
    6  *  table of configured filesystems
    7  */
    8 
    9 #include <linux/syscalls.h>
   10 #include <linux/fs.h>
   11 #include <linux/proc_fs.h>
   12 #include <linux/seq_file.h>
   13 #include <linux/kmod.h>
   14 #include <linux/init.h>
   15 #include <linux/module.h>
   16 #include <linux/slab.h>
   17 #include <asm/uaccess.h>
   18 
   19 /*
   20  * Handling of filesystem drivers list.
   21  * Rules:
   22  *      Inclusion to/removals from/scanning of list are protected by spinlock.
   23  *      During the unload module must call unregister_filesystem().
   24  *      We can access the fields of list element if:
   25  *              1) spinlock is held or
   26  *              2) we hold the reference to the module.
   27  *      The latter can be guaranteed by call of try_module_get(); if it
   28  *      returned 0 we must skip the element, otherwise we got the reference.
   29  *      Once the reference is obtained we can drop the spinlock.
   30  */
   31 
   32 static struct file_system_type *file_systems;
   33 static DEFINE_RWLOCK(file_systems_lock);
   34 
   35 /* WARNING: This can be used only if we _already_ own a reference */
   36 void get_filesystem(struct file_system_type *fs)
   37 {
   38         __module_get(fs->owner);
   39 }
   40 
   41 void put_filesystem(struct file_system_type *fs)
   42 {
   43         module_put(fs->owner);
   44 }
   45 
   46 static struct file_system_type **find_filesystem(const char *name, unsigned len)
   47 {
   48         struct file_system_type **p;
   49         for (p=&file_systems; *p; p=&(*p)->next)
   50                 if (strlen((*p)->name) == len &&
   51                     strncmp((*p)->name, name, len) == 0)
   52                         break;
   53         return p;
   54 }
   55 
   56 /**
   57  *      register_filesystem - register a new filesystem
   58  *      @fs: the file system structure
   59  *
   60  *      Adds the file system passed to the list of file systems the kernel
   61  *      is aware of for mount and other syscalls. Returns 0 on success,
   62  *      or a negative errno code on an error.
   63  *
   64  *      The &struct file_system_type that is passed is linked into the kernel 
   65  *      structures and must not be freed until the file system has been
   66  *      unregistered.
   67  */
   68  
   69 int register_filesystem(struct file_system_type * fs)
   70 {
   71         int res = 0;
   72         struct file_system_type ** p;
   73 
   74         BUG_ON(strchr(fs->name, '.'));
   75         if (fs->next)
   76                 return -EBUSY;
   77         write_lock(&file_systems_lock);
   78         p = find_filesystem(fs->name, strlen(fs->name));
   79         if (*p)
   80                 res = -EBUSY;
   81         else
   82                 *p = fs;
   83         write_unlock(&file_systems_lock);
   84         return res;
   85 }
   86 
   87 EXPORT_SYMBOL(register_filesystem);
   88 
   89 /**
   90  *      unregister_filesystem - unregister a file system
   91  *      @fs: filesystem to unregister
   92  *
   93  *      Remove a file system that was previously successfully registered
   94  *      with the kernel. An error is returned if the file system is not found.
   95  *      Zero is returned on a success.
   96  *      
   97  *      Once this function has returned the &struct file_system_type structure
   98  *      may be freed or reused.
   99  */
  100  
  101 int unregister_filesystem(struct file_system_type * fs)
  102 {
  103         struct file_system_type ** tmp;
  104 
  105         write_lock(&file_systems_lock);
  106         tmp = &file_systems;
  107         while (*tmp) {
  108                 if (fs == *tmp) {
  109                         *tmp = fs->next;
  110                         fs->next = NULL;
  111                         write_unlock(&file_systems_lock);
  112                         synchronize_rcu();
  113                         return 0;
  114                 }
  115                 tmp = &(*tmp)->next;
  116         }
  117         write_unlock(&file_systems_lock);
  118 
  119         return -EINVAL;
  120 }
  121 
  122 EXPORT_SYMBOL(unregister_filesystem);
  123 
  124 static int fs_index(const char __user * __name)
  125 {
  126         struct file_system_type * tmp;
  127         struct filename *name;
  128         int err, index;
  129 
  130         name = getname(__name);
  131         err = PTR_ERR(name);
  132         if (IS_ERR(name))
  133                 return err;
  134 
  135         err = -EINVAL;
  136         read_lock(&file_systems_lock);
  137         for (tmp=file_systems, index=0 ; tmp ; tmp=tmp->next, index++) {
  138                 if (strcmp(tmp->name, name->name) == 0) {
  139                         err = index;
  140                         break;
  141                 }
  142         }
  143         read_unlock(&file_systems_lock);
  144         putname(name);
  145         return err;
  146 }
  147 
  148 static int fs_name(unsigned int index, char __user * buf)
  149 {
  150         struct file_system_type * tmp;
  151         int len, res;
  152 
  153         read_lock(&file_systems_lock);
  154         for (tmp = file_systems; tmp; tmp = tmp->next, index--)
  155                 if (index <= 0 && try_module_get(tmp->owner))
  156                         break;
  157         read_unlock(&file_systems_lock);
  158         if (!tmp)
  159                 return -EINVAL;
  160 
  161         /* OK, we got the reference, so we can safely block */
  162         len = strlen(tmp->name) + 1;
  163         res = copy_to_user(buf, tmp->name, len) ? -EFAULT : 0;
  164         put_filesystem(tmp);
  165         return res;
  166 }
  167 
  168 static int fs_maxindex(void)
  169 {
  170         struct file_system_type * tmp;
  171         int index;
  172 
  173         read_lock(&file_systems_lock);
  174         for (tmp = file_systems, index = 0 ; tmp ; tmp = tmp->next, index++)
  175                 ;
  176         read_unlock(&file_systems_lock);
  177         return index;
  178 }
  179 
  180 /*
  181  * Whee.. Weird sysv syscall. 
  182  */
  183 SYSCALL_DEFINE3(sysfs, int, option, unsigned long, arg1, unsigned long, arg2)
  184 {
  185         int retval = -EINVAL;
  186 
  187         switch (option) {
  188                 case 1:
  189                         retval = fs_index((const char __user *) arg1);
  190                         break;
  191 
  192                 case 2:
  193                         retval = fs_name(arg1, (char __user *) arg2);
  194                         break;
  195 
  196                 case 3:
  197                         retval = fs_maxindex();
  198                         break;
  199         }
  200         return retval;
  201 }
  202 
  203 int __init get_filesystem_list(char *buf)
  204 {
  205         int len = 0;
  206         struct file_system_type * tmp;
  207 
  208         read_lock(&file_systems_lock);
  209         tmp = file_systems;
  210         while (tmp && len < PAGE_SIZE - 80) {
  211                 len += sprintf(buf+len, "%s\t%s\n",
  212                         (tmp->fs_flags & FS_REQUIRES_DEV) ? "" : "nodev",
  213                         tmp->name);
  214                 tmp = tmp->next;
  215         }
  216         read_unlock(&file_systems_lock);
  217         return len;
  218 }
  219 
  220 #ifdef CONFIG_PROC_FS
  221 static int filesystems_proc_show(struct seq_file *m, void *v)
  222 {
  223         struct file_system_type * tmp;
  224 
  225         read_lock(&file_systems_lock);
  226         tmp = file_systems;
  227         while (tmp) {
  228                 seq_printf(m, "%s\t%s\n",
  229                         (tmp->fs_flags & FS_REQUIRES_DEV) ? "" : "nodev",
  230                         tmp->name);
  231                 tmp = tmp->next;
  232         }
  233         read_unlock(&file_systems_lock);
  234         return 0;
  235 }
  236 
  237 static int filesystems_proc_open(struct inode *inode, struct file *file)
  238 {
  239         return single_open(file, filesystems_proc_show, NULL);
  240 }
  241 
  242 static const struct file_operations filesystems_proc_fops = {
  243         .open           = filesystems_proc_open,
  244         .read           = seq_read,
  245         .llseek         = seq_lseek,
  246         .release        = single_release,
  247 };
  248 
  249 static int __init proc_filesystems_init(void)
  250 {
  251         proc_create("filesystems", 0, NULL, &filesystems_proc_fops);
  252         return 0;
  253 }
  254 module_init(proc_filesystems_init);
  255 #endif
  256 
  257 static struct file_system_type *__get_fs_type(const char *name, int len)
  258 {
  259         struct file_system_type *fs;
  260 
  261         read_lock(&file_systems_lock);
  262         fs = *(find_filesystem(name, len));
  263         if (fs && !try_module_get(fs->owner))
  264                 fs = NULL;
  265         read_unlock(&file_systems_lock);
  266         return fs;
  267 }
  268 
  269 struct file_system_type *get_fs_type(const char *name)
  270 {
  271         struct file_system_type *fs;
  272         const char *dot = strchr(name, '.');
  273         int len = dot ? dot - name : strlen(name);
  274 
  275         fs = __get_fs_type(name, len);
  276         if (!fs && (request_module("%.*s", len, name) == 0))
  277                 fs = __get_fs_type(name, len);
  278 
  279         if (dot && fs && !(fs->fs_flags & FS_HAS_SUBTYPE)) {
  280                 put_filesystem(fs);
  281                 fs = NULL;
  282         }
  283         return fs;
  284 }
  285 
  286 EXPORT_SYMBOL(get_fs_type);

Cache object: a2539cd49eae4fa6c226336df0faa333


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.