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/super.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/super.c
    3  *
    4  *  Copyright (C) 1991, 1992  Linus Torvalds
    5  *
    6  *  super.c contains code to handle: - mount structures
    7  *                                   - super-block tables
    8  *                                   - filesystem drivers list
    9  *                                   - mount system call
   10  *                                   - umount system call
   11  *                                   - ustat system call
   12  *
   13  * GK 2/5/95  -  Changed to support mounting the root fs via NFS
   14  *
   15  *  Added kerneld support: Jacques Gelinas and Bjorn Ekwall
   16  *  Added change_root: Werner Almesberger & Hans Lermen, Feb '96
   17  *  Added options to /proc/mounts:
   18  *    Torbjörn Lindh (torbjorn.lindh@gopta.se), April 14, 1996.
   19  *  Added devfs support: Richard Gooch <rgooch@atnf.csiro.au>, 13-JAN-1998
   20  *  Heavily rewritten for 'one fs - one tree' dcache architecture. AV, Mar 2000
   21  */
   22 
   23 #include <linux/config.h>
   24 #include <linux/slab.h>
   25 #include <linux/locks.h>
   26 #include <linux/smp_lock.h>
   27 #include <linux/devfs_fs_kernel.h>
   28 #include <linux/major.h>
   29 #include <linux/acct.h>
   30 #include <linux/quotaops.h>
   31 
   32 #include <asm/uaccess.h>
   33 
   34 #include <linux/kmod.h>
   35 #define __NO_VERSION__
   36 #include <linux/module.h>
   37 
   38 LIST_HEAD(super_blocks);
   39 spinlock_t sb_lock = SPIN_LOCK_UNLOCKED;
   40 
   41 /*
   42  * Handling of filesystem drivers list.
   43  * Rules:
   44  *      Inclusion to/removals from/scanning of list are protected by spinlock.
   45  *      During the unload module must call unregister_filesystem().
   46  *      We can access the fields of list element if:
   47  *              1) spinlock is held or
   48  *              2) we hold the reference to the module.
   49  *      The latter can be guaranteed by call of try_inc_mod_count(); if it
   50  *      returned 0 we must skip the element, otherwise we got the reference.
   51  *      Once the reference is obtained we can drop the spinlock.
   52  */
   53 
   54 static struct file_system_type *file_systems;
   55 static rwlock_t file_systems_lock = RW_LOCK_UNLOCKED;
   56 
   57 /* WARNING: This can be used only if we _already_ own a reference */
   58 static void get_filesystem(struct file_system_type *fs)
   59 {
   60         if (fs->owner)
   61                 __MOD_INC_USE_COUNT(fs->owner);
   62 }
   63 
   64 static void put_filesystem(struct file_system_type *fs)
   65 {
   66         if (fs->owner)
   67                 __MOD_DEC_USE_COUNT(fs->owner);
   68 }
   69 
   70 static struct file_system_type **find_filesystem(const char *name)
   71 {
   72         struct file_system_type **p;
   73         for (p=&file_systems; *p; p=&(*p)->next)
   74                 if (strcmp((*p)->name,name) == 0)
   75                         break;
   76         return p;
   77 }
   78 
   79 /**
   80  *      register_filesystem - register a new filesystem
   81  *      @fs: the file system structure
   82  *
   83  *      Adds the file system passed to the list of file systems the kernel
   84  *      is aware of for mount and other syscalls. Returns 0 on success,
   85  *      or a negative errno code on an error.
   86  *
   87  *      The &struct file_system_type that is passed is linked into the kernel 
   88  *      structures and must not be freed until the file system has been
   89  *      unregistered.
   90  */
   91  
   92 int register_filesystem(struct file_system_type * fs)
   93 {
   94         int res = 0;
   95         struct file_system_type ** p;
   96 
   97         if (!fs)
   98                 return -EINVAL;
   99         if (fs->next)
  100                 return -EBUSY;
  101         INIT_LIST_HEAD(&fs->fs_supers);
  102         write_lock(&file_systems_lock);
  103         p = find_filesystem(fs->name);
  104         if (*p)
  105                 res = -EBUSY;
  106         else
  107                 *p = fs;
  108         write_unlock(&file_systems_lock);
  109         return res;
  110 }
  111 
  112 /**
  113  *      unregister_filesystem - unregister a file system
  114  *      @fs: filesystem to unregister
  115  *
  116  *      Remove a file system that was previously successfully registered
  117  *      with the kernel. An error is returned if the file system is not found.
  118  *      Zero is returned on a success.
  119  *      
  120  *      Once this function has returned the &struct file_system_type structure
  121  *      may be freed or reused.
  122  */
  123  
  124 int unregister_filesystem(struct file_system_type * fs)
  125 {
  126         struct file_system_type ** tmp;
  127 
  128         write_lock(&file_systems_lock);
  129         tmp = &file_systems;
  130         while (*tmp) {
  131                 if (fs == *tmp) {
  132                         *tmp = fs->next;
  133                         fs->next = NULL;
  134                         write_unlock(&file_systems_lock);
  135                         return 0;
  136                 }
  137                 tmp = &(*tmp)->next;
  138         }
  139         write_unlock(&file_systems_lock);
  140         return -EINVAL;
  141 }
  142 
  143 static int fs_index(const char * __name)
  144 {
  145         struct file_system_type * tmp;
  146         char * name;
  147         int err, index;
  148 
  149         name = getname(__name);
  150         err = PTR_ERR(name);
  151         if (IS_ERR(name))
  152                 return err;
  153 
  154         err = -EINVAL;
  155         read_lock(&file_systems_lock);
  156         for (tmp=file_systems, index=0 ; tmp ; tmp=tmp->next, index++) {
  157                 if (strcmp(tmp->name,name) == 0) {
  158                         err = index;
  159                         break;
  160                 }
  161         }
  162         read_unlock(&file_systems_lock);
  163         putname(name);
  164         return err;
  165 }
  166 
  167 static int fs_name(unsigned int index, char * buf)
  168 {
  169         struct file_system_type * tmp;
  170         int len, res;
  171 
  172         read_lock(&file_systems_lock);
  173         for (tmp = file_systems; tmp; tmp = tmp->next, index--)
  174                 if (index <= 0 && try_inc_mod_count(tmp->owner))
  175                                 break;
  176         read_unlock(&file_systems_lock);
  177         if (!tmp)
  178                 return -EINVAL;
  179 
  180         /* OK, we got the reference, so we can safely block */
  181         len = strlen(tmp->name) + 1;
  182         res = copy_to_user(buf, tmp->name, len) ? -EFAULT : 0;
  183         put_filesystem(tmp);
  184         return res;
  185 }
  186 
  187 static int fs_maxindex(void)
  188 {
  189         struct file_system_type * tmp;
  190         int index;
  191 
  192         read_lock(&file_systems_lock);
  193         for (tmp = file_systems, index = 0 ; tmp ; tmp = tmp->next, index++)
  194                 ;
  195         read_unlock(&file_systems_lock);
  196         return index;
  197 }
  198 
  199 /*
  200  * Whee.. Weird sysv syscall. 
  201  */
  202 asmlinkage long sys_sysfs(int option, unsigned long arg1, unsigned long arg2)
  203 {
  204         int retval = -EINVAL;
  205 
  206         switch (option) {
  207                 case 1:
  208                         retval = fs_index((const char *) arg1);
  209                         break;
  210 
  211                 case 2:
  212                         retval = fs_name(arg1, (char *) arg2);
  213                         break;
  214 
  215                 case 3:
  216                         retval = fs_maxindex();
  217                         break;
  218         }
  219         return retval;
  220 }
  221 
  222 int get_filesystem_list(char * buf)
  223 {
  224         int len = 0;
  225         struct file_system_type * tmp;
  226 
  227         read_lock(&file_systems_lock);
  228         tmp = file_systems;
  229         while (tmp && len < PAGE_SIZE - 80) {
  230                 len += sprintf(buf+len, "%s\t%s\n",
  231                         (tmp->fs_flags & FS_REQUIRES_DEV) ? "" : "nodev",
  232                         tmp->name);
  233                 tmp = tmp->next;
  234         }
  235         read_unlock(&file_systems_lock);
  236         return len;
  237 }
  238 
  239 struct file_system_type *get_fs_type(const char *name)
  240 {
  241         struct file_system_type *fs;
  242         
  243         read_lock(&file_systems_lock);
  244         fs = *(find_filesystem(name));
  245         if (fs && !try_inc_mod_count(fs->owner))
  246                 fs = NULL;
  247         read_unlock(&file_systems_lock);
  248         if (!fs && (request_module(name) == 0)) {
  249                 read_lock(&file_systems_lock);
  250                 fs = *(find_filesystem(name));
  251                 if (fs && !try_inc_mod_count(fs->owner))
  252                         fs = NULL;
  253                 read_unlock(&file_systems_lock);
  254         }
  255         return fs;
  256 }
  257 
  258 /**
  259  *      alloc_super     -       create new superblock
  260  *
  261  *      Allocates and initializes a new &struct super_block.  alloc_super()
  262  *      returns a pointer new superblock or %NULL if allocation had failed.
  263  */
  264 static struct super_block *alloc_super(void)
  265 {
  266         static struct super_operations empty_sops = {};
  267         struct super_block *s = kmalloc(sizeof(struct super_block),  GFP_USER);
  268         if (s) {
  269                 memset(s, 0, sizeof(struct super_block));
  270                 INIT_LIST_HEAD(&s->s_dirty);
  271                 INIT_LIST_HEAD(&s->s_locked_inodes);
  272                 INIT_LIST_HEAD(&s->s_files);
  273                 INIT_LIST_HEAD(&s->s_instances);
  274                 init_rwsem(&s->s_umount);
  275                 sema_init(&s->s_lock, 1);
  276                 down_write(&s->s_umount);
  277                 s->s_count = S_BIAS;
  278                 atomic_set(&s->s_active, 1);
  279                 sema_init(&s->s_vfs_rename_sem,1);
  280                 sema_init(&s->s_nfsd_free_path_sem,1);
  281                 sema_init(&s->s_dquot.dqio_sem, 1);
  282                 sema_init(&s->s_dquot.dqoff_sem, 1);
  283                 s->s_maxbytes = MAX_NON_LFS;
  284                 s->s_op = &empty_sops;
  285                 s->dq_op = sb_dquot_ops;
  286                 s->s_qcop = sb_quotactl_ops;
  287         }
  288         return s;
  289 }
  290 
  291 /**
  292  *      destroy_super   -       frees a superblock
  293  *      @s: superblock to free
  294  *
  295  *      Frees a superblock.
  296  */
  297 static inline void destroy_super(struct super_block *s)
  298 {
  299         kfree(s);
  300 }
  301 
  302 /* Superblock refcounting  */
  303 
  304 /**
  305  *      deactivate_super        -       turn an active reference into temporary
  306  *      @s: superblock to deactivate
  307  *
  308  *      Turns an active reference into temporary one.  Returns 0 if there are
  309  *      other active references, 1 if we had deactivated the last one.
  310  */
  311 static inline int deactivate_super(struct super_block *s)
  312 {
  313         if (!atomic_dec_and_lock(&s->s_active, &sb_lock))
  314                 return 0;
  315         s->s_count -= S_BIAS-1;
  316         spin_unlock(&sb_lock);
  317         return 1;
  318 }
  319 
  320 /**
  321  *      put_super       -       drop a temporary reference to superblock
  322  *      @s: superblock in question
  323  *
  324  *      Drops a temporary reference, frees superblock if there's no
  325  *      references left.
  326  */
  327 static inline void put_super(struct super_block *s)
  328 {
  329         spin_lock(&sb_lock);
  330         if (!--s->s_count)
  331                 destroy_super(s);
  332         spin_unlock(&sb_lock);
  333 }
  334 
  335 /**
  336  *      grab_super      - acquire an active reference
  337  *      @s      - reference we are trying to make active
  338  *
  339  *      Tries to acquire an active reference.  grab_super() is used when we
  340  *      had just found a superblock in super_blocks or fs_type->fs_supers
  341  *      and want to turn it into a full-blown active reference.  grab_super()
  342  *      is called with sb_lock held and drops it.  Returns 1 in case of
  343  *      success, 0 if we had failed (superblock contents was already dead or
  344  *      dying when grab_super() had been called).
  345  */
  346 static int grab_super(struct super_block *s)
  347 {
  348         s->s_count++;
  349         spin_unlock(&sb_lock);
  350         down_write(&s->s_umount);
  351         if (s->s_root) {
  352                 spin_lock(&sb_lock);
  353                 if (s->s_count > S_BIAS) {
  354                         atomic_inc(&s->s_active);
  355                         s->s_count--;
  356                         spin_unlock(&sb_lock);
  357                         return 1;
  358                 }
  359                 spin_unlock(&sb_lock);
  360         }
  361         up_write(&s->s_umount);
  362         put_super(s);
  363         return 0;
  364 }
  365  
  366 /**
  367  *      insert_super    -       put superblock on the lists
  368  *      @s:     superblock in question
  369  *      @type:  filesystem type it will belong to
  370  *
  371  *      Associates superblock with fs type and puts it on per-type and global
  372  *      superblocks' lists.  Should be called with sb_lock held; drops it.
  373  */
  374 static void insert_super(struct super_block *s, struct file_system_type *type)
  375 {
  376         s->s_type = type;
  377         list_add(&s->s_list, super_blocks.prev);
  378         list_add(&s->s_instances, &type->fs_supers);
  379         spin_unlock(&sb_lock);
  380         get_filesystem(type);
  381 }
  382 
  383 static void put_anon_dev(kdev_t dev);
  384 
  385 /**
  386  *      remove_super    -       makes superblock unreachable
  387  *      @s:     superblock in question
  388  *
  389  *      Removes superblock from the lists, unlocks it, drop the reference
  390  *      and releases the hosting device.  @s should have no active
  391  *      references by that time and after remove_super() it's essentially
  392  *      in rundown mode - all remaining references are temporary, no new
  393  *      reference of any sort are going to appear and all holders of
  394  *      temporary ones will eventually drop them.  At that point superblock
  395  *      itself will be destroyed; all its contents is already gone.
  396  */
  397 static void remove_super(struct super_block *s)
  398 {
  399         kdev_t dev = s->s_dev;
  400         struct block_device *bdev = s->s_bdev;
  401         struct file_system_type *fs = s->s_type;
  402 
  403         spin_lock(&sb_lock);
  404         list_del(&s->s_list);
  405         list_del(&s->s_instances);
  406         spin_unlock(&sb_lock);
  407         up_write(&s->s_umount);
  408         put_super(s);
  409         put_filesystem(fs);
  410         if (bdev)
  411                 blkdev_put(bdev, BDEV_FS);
  412         else
  413                 put_anon_dev(dev);
  414 }
  415 
  416 struct vfsmount *alloc_vfsmnt(char *name);
  417 void free_vfsmnt(struct vfsmount *mnt);
  418 
  419 static inline struct super_block * find_super(kdev_t dev)
  420 {
  421         struct list_head *p;
  422 
  423         list_for_each(p, &super_blocks) {
  424                 struct super_block * s = sb_entry(p);
  425                 if (s->s_dev == dev) {
  426                         s->s_count++;
  427                         return s;
  428                 }
  429         }
  430         return NULL;
  431 }
  432 
  433 void drop_super(struct super_block *sb)
  434 {
  435         up_read(&sb->s_umount);
  436         put_super(sb);
  437 }
  438 
  439 static inline void write_super(struct super_block *sb)
  440 {
  441         lock_super(sb);
  442         if (sb->s_root && sb->s_dirt)
  443                 if (sb->s_op && sb->s_op->write_super)
  444                         sb->s_op->write_super(sb);
  445         unlock_super(sb);
  446 }
  447 
  448 /*
  449  * Note: check the dirty flag before waiting, so we don't
  450  * hold up the sync while mounting a device. (The newly
  451  * mounted device won't need syncing.)
  452  */
  453 void sync_supers(kdev_t dev, int wait)
  454 {
  455         struct super_block * sb;
  456 
  457         if (dev) {
  458                 sb = get_super(dev);
  459                 if (sb) {
  460                         if (sb->s_dirt)
  461                                 write_super(sb);
  462                         if (wait && sb->s_op && sb->s_op->sync_fs)
  463                                 sb->s_op->sync_fs(sb);
  464                         drop_super(sb);
  465                 }
  466                 return;
  467         }
  468 restart:
  469         spin_lock(&sb_lock);
  470         sb = sb_entry(super_blocks.next);
  471         while (sb != sb_entry(&super_blocks))
  472                 if (sb->s_dirt) {
  473                         sb->s_count++;
  474                         spin_unlock(&sb_lock);
  475                         down_read(&sb->s_umount);
  476                         write_super(sb);
  477                         if (wait && sb->s_root && sb->s_op && sb->s_op->sync_fs)
  478                                 sb->s_op->sync_fs(sb);
  479                         drop_super(sb);
  480                         goto restart;
  481                 } else
  482                         sb = sb_entry(sb->s_list.next);
  483         spin_unlock(&sb_lock);
  484 }
  485 
  486 /**
  487  *      get_super       -       get the superblock of a device
  488  *      @dev: device to get the superblock for
  489  *      
  490  *      Scans the superblock list and finds the superblock of the file system
  491  *      mounted on the device given. %NULL is returned if no match is found.
  492  */
  493  
  494 struct super_block * get_super(kdev_t dev)
  495 {
  496         struct super_block * s;
  497 
  498         if (!dev)
  499                 return NULL;
  500 restart:
  501         spin_lock(&sb_lock);
  502         s = find_super(dev);
  503         if (s) {
  504                 spin_unlock(&sb_lock);
  505                 down_read(&s->s_umount);
  506                 if (s->s_root)
  507                         return s;
  508                 drop_super(s);
  509                 goto restart;
  510         }
  511         spin_unlock(&sb_lock);
  512         return NULL;
  513 }
  514 
  515 asmlinkage long sys_ustat(dev_t dev, struct ustat * ubuf)
  516 {
  517         struct super_block *s;
  518         struct ustat tmp;
  519         struct statfs sbuf;
  520         int err = -EINVAL;
  521 
  522         s = get_super(to_kdev_t(dev));
  523         if (s == NULL)
  524                 goto out;
  525         err = vfs_statfs(s, &sbuf);
  526         drop_super(s);
  527         if (err)
  528                 goto out;
  529 
  530         memset(&tmp,0,sizeof(struct ustat));
  531         tmp.f_tfree = sbuf.f_bfree;
  532         tmp.f_tinode = sbuf.f_ffree;
  533 
  534         err = copy_to_user(ubuf,&tmp,sizeof(struct ustat)) ? -EFAULT : 0;
  535 out:
  536         return err;
  537 }
  538 
  539 /**
  540  *      do_remount_sb   -       asks filesystem to change mount options.
  541  *      @sb:    superblock in question
  542  *      @flags: numeric part of options
  543  *      @data:  the rest of options
  544  *
  545  *      Alters the mount options of a mounted file system.
  546  */
  547 int do_remount_sb(struct super_block *sb, int flags, void *data)
  548 {
  549         int retval;
  550         
  551         if (!(flags & MS_RDONLY) && sb->s_dev && is_read_only(sb->s_dev))
  552                 return -EACCES;
  553                 /*flags |= MS_RDONLY;*/
  554         if (flags & MS_RDONLY)
  555                 acct_auto_close(sb->s_dev);
  556         shrink_dcache_sb(sb);
  557         fsync_super(sb);
  558         /* If we are remounting RDONLY, make sure there are no rw files open */
  559         if ((flags & MS_RDONLY) && !(sb->s_flags & MS_RDONLY))
  560                 if (!fs_may_remount_ro(sb))
  561                         return -EBUSY;
  562         if (sb->s_op && sb->s_op->remount_fs) {
  563                 lock_super(sb);
  564                 retval = sb->s_op->remount_fs(sb, &flags, data);
  565                 unlock_super(sb);
  566                 if (retval)
  567                         return retval;
  568         }
  569         sb->s_flags = (sb->s_flags & ~MS_RMT_MASK) | (flags & MS_RMT_MASK);
  570         return 0;
  571 }
  572 
  573 /*
  574  * Unnamed block devices are dummy devices used by virtual
  575  * filesystems which don't use real block-devices.  -- jrs
  576  */
  577 
  578 enum {Max_anon = 256};
  579 static unsigned long unnamed_dev_in_use[Max_anon/(8*sizeof(unsigned long))];
  580 static spinlock_t unnamed_dev_lock = SPIN_LOCK_UNLOCKED;/* protects the above */
  581 
  582 /**
  583  *      put_anon_dev    -       release anonymous device number.
  584  *      @dev:   device in question
  585  */
  586 static void put_anon_dev(kdev_t dev)
  587 {
  588         spin_lock(&unnamed_dev_lock);
  589         clear_bit(MINOR(dev), unnamed_dev_in_use);
  590         spin_unlock(&unnamed_dev_lock);
  591 }
  592 
  593 /**
  594  *      get_anon_super  -       allocate a superblock for non-device fs
  595  *      @type:          filesystem type
  596  *      @compare:       check if existing superblock is what we want
  597  *      @data:          argument for @compare.
  598  *
  599  *      get_anon_super is a helper for non-blockdevice filesystems.
  600  *      It either finds and returns one of the superblocks of given type
  601  *      (if it can find one that would satisfy caller) or creates a new
  602  *      one.  In the either case we return an active reference to superblock
  603  *      with ->s_umount locked.  If superblock is new it gets a new
  604  *      anonymous device allocated for it and is inserted into lists -
  605  *      other initialization is left to caller.
  606  *
  607  *      Rather than duplicating all that logics every time when
  608  *      we want something that doesn't fit "nodev" and "single" we pull
  609  *      the relevant code into common helper and let get_sb_...() call
  610  *      it.
  611  *
  612  *      NB: get_sb_...() is going to become an fs type method, with
  613  *      current ->read_super() becoming a callback used by common instances.
  614  */
  615 struct super_block *get_anon_super(struct file_system_type *type,
  616         int (*compare)(struct super_block *,void *), void *data)
  617 {
  618         struct super_block *s = alloc_super();
  619         kdev_t dev;
  620         struct list_head *p;
  621 
  622         if (!s)
  623                 return ERR_PTR(-ENOMEM);
  624 
  625 retry:
  626         spin_lock(&sb_lock);
  627         if (compare) list_for_each(p, &type->fs_supers) {
  628                 struct super_block *old;
  629                 old = list_entry(p, struct super_block, s_instances);
  630                 if (!compare(old, data))
  631                         continue;
  632                 if (!grab_super(old))
  633                         goto retry;
  634                 destroy_super(s);
  635                 return old;
  636         }
  637 
  638         spin_lock(&unnamed_dev_lock);
  639         dev = find_first_zero_bit(unnamed_dev_in_use, Max_anon);
  640         if (dev == Max_anon) {
  641                 spin_unlock(&unnamed_dev_lock);
  642                 spin_unlock(&sb_lock);
  643                 destroy_super(s);
  644                 return ERR_PTR(-EMFILE);
  645         }
  646         set_bit(dev, unnamed_dev_in_use);
  647         spin_unlock(&unnamed_dev_lock);
  648 
  649         s->s_dev = dev;
  650         insert_super(s, type);
  651         return s;
  652 }
  653 
  654 static struct super_block *get_sb_bdev(struct file_system_type *fs_type,
  655         int flags, char *dev_name, void * data)
  656 {
  657         struct inode *inode;
  658         struct block_device *bdev;
  659         struct block_device_operations *bdops;
  660         devfs_handle_t de;
  661         struct super_block * s;
  662         struct nameidata nd;
  663         struct list_head *p;
  664         kdev_t dev;
  665         int error = 0;
  666         mode_t mode = FMODE_READ; /* we always need it ;-) */
  667 
  668         /* What device it is? */
  669         if (!dev_name || !*dev_name)
  670                 return ERR_PTR(-EINVAL);
  671         error = path_lookup(dev_name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, &nd);
  672         if (error)
  673                 return ERR_PTR(error);
  674         inode = nd.dentry->d_inode;
  675         error = -ENOTBLK;
  676         if (!S_ISBLK(inode->i_mode))
  677                 goto out;
  678         error = -EACCES;
  679         if (nd.mnt->mnt_flags & MNT_NODEV)
  680                 goto out;
  681         bd_acquire(inode);
  682         bdev = inode->i_bdev;
  683         de = devfs_get_handle_from_inode (inode);
  684         bdops = devfs_get_ops (de);         /*  Increments module use count  */
  685         if (bdops) bdev->bd_op = bdops;
  686         /* Done with lookups, semaphore down */
  687         dev = to_kdev_t(bdev->bd_dev);
  688         if (!(flags & MS_RDONLY))
  689                 mode |= FMODE_WRITE;
  690         error = blkdev_get(bdev, mode, 0, BDEV_FS);
  691         devfs_put_ops (de);   /*  Decrement module use count now we're safe  */
  692         if (error)
  693                 goto out;
  694         check_disk_change(dev);
  695         error = -EACCES;
  696         if (!(flags & MS_RDONLY) && is_read_only(dev))
  697                 goto out1;
  698 
  699         error = -ENOMEM;
  700         s = alloc_super();
  701         if (!s)
  702                 goto out1;
  703 
  704         error = -EBUSY;
  705 restart:
  706         spin_lock(&sb_lock);
  707 
  708         list_for_each(p, &super_blocks) {
  709                 struct super_block *old = sb_entry(p);
  710                 if (old->s_dev != dev)
  711                         continue;
  712                 if (old->s_type != fs_type ||
  713                     ((flags ^ old->s_flags) & MS_RDONLY)) {
  714                         spin_unlock(&sb_lock);
  715                         destroy_super(s);
  716                         goto out1;
  717                 }
  718                 if (!grab_super(old))
  719                         goto restart;
  720                 destroy_super(s);
  721                 blkdev_put(bdev, BDEV_FS);
  722                 path_release(&nd);
  723                 return old;
  724         }
  725         s->s_dev = dev;
  726         s->s_bdev = bdev;
  727         s->s_flags = flags;
  728         insert_super(s, fs_type);
  729         if (!fs_type->read_super(s, data, flags & MS_VERBOSE ? 1 : 0))
  730                 goto Einval;
  731         s->s_flags |= MS_ACTIVE;
  732         path_release(&nd);
  733         return s;
  734 
  735 Einval:
  736         deactivate_super(s);
  737         remove_super(s);
  738         error = -EINVAL;
  739         goto out;
  740 out1:
  741         blkdev_put(bdev, BDEV_FS);
  742 out:
  743         path_release(&nd);
  744         return ERR_PTR(error);
  745 }
  746 
  747 static struct super_block *get_sb_nodev(struct file_system_type *fs_type,
  748         int flags, char *dev_name, void *data)
  749 {
  750         struct super_block *s = get_anon_super(fs_type, NULL, NULL);
  751 
  752         if (IS_ERR(s))
  753                 return s;
  754 
  755         s->s_flags = flags;
  756         if (!fs_type->read_super(s, data, flags & MS_VERBOSE ? 1 : 0)) {
  757                 deactivate_super(s);
  758                 remove_super(s);
  759                 return ERR_PTR(-EINVAL);
  760         }
  761         s->s_flags |= MS_ACTIVE;
  762         return s;
  763 }
  764 
  765 static int compare_single(struct super_block *s, void *p)
  766 {
  767         return 1;
  768 }
  769 
  770 static struct super_block *get_sb_single(struct file_system_type *fs_type,
  771         int flags, char *dev_name, void *data)
  772 {
  773         struct super_block *s = get_anon_super(fs_type, compare_single, NULL);
  774 
  775         if (IS_ERR(s))
  776                 return s;
  777         if (!s->s_root) {
  778                 s->s_flags = flags;
  779                 if (!fs_type->read_super(s, data, flags & MS_VERBOSE ? 1 : 0)) {
  780                         deactivate_super(s);
  781                         remove_super(s);
  782                         return ERR_PTR(-EINVAL);
  783                 }
  784                 s->s_flags |= MS_ACTIVE;
  785         }
  786         do_remount_sb(s, flags, data);
  787         return s;
  788 }
  789 
  790 struct vfsmount *
  791 do_kern_mount(const char *fstype, int flags, char *name, void *data)
  792 {
  793         struct file_system_type *type = get_fs_type(fstype);
  794         struct super_block *sb = ERR_PTR(-ENOMEM);
  795         struct vfsmount *mnt;
  796 
  797         if (!type)
  798                 return ERR_PTR(-ENODEV);
  799 
  800         mnt = alloc_vfsmnt(name);
  801         if (!mnt)
  802                 goto out;
  803         if (type->fs_flags & FS_REQUIRES_DEV)
  804                 sb = get_sb_bdev(type, flags, name, data);
  805         else if (type->fs_flags & FS_SINGLE)
  806                 sb = get_sb_single(type, flags, name, data);
  807         else
  808                 sb = get_sb_nodev(type, flags, name, data);
  809         if (IS_ERR(sb))
  810                 goto out_mnt;
  811         if (type->fs_flags & FS_NOMOUNT)
  812                 sb->s_flags |= MS_NOUSER;
  813         mnt->mnt_sb = sb;
  814         mnt->mnt_root = dget(sb->s_root);
  815         mnt->mnt_mountpoint = sb->s_root;
  816         mnt->mnt_parent = mnt;
  817         up_write(&sb->s_umount);
  818         put_filesystem(type);
  819         return mnt;
  820 out_mnt:
  821         free_vfsmnt(mnt);
  822 out:
  823         put_filesystem(type);
  824         return (struct vfsmount *)sb;
  825 }
  826 
  827 void kill_super(struct super_block *sb)
  828 {
  829         struct dentry *root = sb->s_root;
  830         struct file_system_type *fs = sb->s_type;
  831         struct super_operations *sop = sb->s_op;
  832 
  833         if (!deactivate_super(sb))
  834                 return;
  835 
  836         down_write(&sb->s_umount);
  837         sb->s_root = NULL;
  838         /* Need to clean after the sucker */
  839         if (fs->fs_flags & FS_LITTER)
  840                 d_genocide(root);
  841         shrink_dcache_parent(root);
  842         dput(root);
  843         fsync_super(sb);
  844         lock_super(sb);
  845         lock_kernel();
  846         sb->s_flags &= ~MS_ACTIVE;
  847         invalidate_inodes(sb);  /* bad name - it should be evict_inodes() */
  848         if (sop) {
  849                 if (sop->write_super && sb->s_dirt)
  850                         sop->write_super(sb);
  851                 if (sop->put_super)
  852                         sop->put_super(sb);
  853         }
  854 
  855         /* Forget any remaining inodes */
  856         if (invalidate_inodes(sb)) {
  857                 printk(KERN_ERR "VFS: Busy inodes after unmount. "
  858                         "Self-destruct in 5 seconds.  Have a nice day...\n");
  859         }
  860 
  861         unlock_kernel();
  862         unlock_super(sb);
  863         remove_super(sb);
  864 }
  865 
  866 struct vfsmount *kern_mount(struct file_system_type *type)
  867 {
  868         return do_kern_mount(type->name, 0, (char *)type->name, NULL);
  869 }

Cache object: 2b35ab7e978dbf1b26b20c3bf6b48889


[ 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.