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/servers/fs/mount.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 /* This file performs the MOUNT and UMOUNT system calls.
    2  *
    3  * The entry points into this file are
    4  *   do_mount:  perform the MOUNT system call
    5  *   do_umount: perform the UMOUNT system call
    6  */
    7 
    8 #include "fs.h"
    9 #include <fcntl.h>
   10 #include <minix/com.h>
   11 #include <sys/stat.h>
   12 #include "buf.h"
   13 #include "file.h"
   14 #include "fproc.h"
   15 #include "inode.h"
   16 #include "param.h"
   17 #include "super.h"
   18 
   19 FORWARD _PROTOTYPE( dev_t name_to_dev, (char *path)                     );
   20 
   21 /*===========================================================================*
   22  *                              do_mount                                     *
   23  *===========================================================================*/
   24 PUBLIC int do_mount()
   25 {
   26 /* Perform the mount(name, mfile, rd_only) system call. */
   27 
   28   register struct inode *rip, *root_ip;
   29   struct super_block *xp, *sp;
   30   dev_t dev;
   31   mode_t bits;
   32   int rdir, mdir;               /* TRUE iff {root|mount} file is dir */
   33   int r, found;
   34 
   35   /* Only the super-user may do MOUNT. */
   36   if (!super_user) return(EPERM);
   37 
   38   /* If 'name' is not for a block special file, return error. */
   39   if (fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code);
   40   if ( (dev = name_to_dev(user_path)) == NO_DEV) return(err_code);
   41 
   42   /* Scan super block table to see if dev already mounted & find a free slot.*/
   43   sp = NIL_SUPER;
   44   found = FALSE;
   45   for (xp = &super_block[0]; xp < &super_block[NR_SUPERS]; xp++) {
   46         if (xp->s_dev == dev) found = TRUE;     /* is it mounted already? */
   47         if (xp->s_dev == NO_DEV) sp = xp;       /* record free slot */
   48   }
   49   if (found) return(EBUSY);     /* already mounted */
   50   if (sp == NIL_SUPER) return(ENFILE);  /* no super block available */
   51 
   52   /* Open the device the file system lives on. */
   53   if (dev_open(dev, who, m_in.rd_only ? R_BIT : (R_BIT|W_BIT)) != OK) 
   54         return(EINVAL);
   55 
   56   /* Make the cache forget about blocks it has open on the filesystem */
   57   (void) do_sync();
   58   invalidate(dev);
   59 
   60   /* Fill in the super block. */
   61   sp->s_dev = dev;              /* read_super() needs to know which dev */
   62   r = read_super(sp);
   63 
   64   /* Is it recognized as a Minix filesystem? */
   65   if (r != OK) {
   66         dev_close(dev);
   67         sp->s_dev = NO_DEV;
   68         return(r);
   69   }
   70 
   71   /* Now get the inode of the file to be mounted on. */
   72   if (fetch_name(m_in.name2, m_in.name2_length, M1) != OK) {
   73         dev_close(dev);
   74         sp->s_dev = NO_DEV;
   75         return(err_code);
   76   }
   77   if ( (rip = eat_path(user_path)) == NIL_INODE) {
   78         dev_close(dev);
   79         sp->s_dev = NO_DEV;
   80         return(err_code);
   81   }
   82 
   83   /* It may not be busy. */
   84   r = OK;
   85   if (rip->i_count > 1) r = EBUSY;
   86 
   87   /* It may not be special. */
   88   bits = rip->i_mode & I_TYPE;
   89   if (bits == I_BLOCK_SPECIAL || bits == I_CHAR_SPECIAL) r = ENOTDIR;
   90 
   91   /* Get the root inode of the mounted file system. */
   92   root_ip = NIL_INODE;          /* if 'r' not OK, make sure this is defined */
   93   if (r == OK) {
   94         if ( (root_ip = get_inode(dev, ROOT_INODE)) == NIL_INODE) r = err_code;
   95   }
   96   if (root_ip != NIL_INODE && root_ip->i_mode == 0) {
   97         r = EINVAL;
   98   }
   99 
  100   /* File types of 'rip' and 'root_ip' may not conflict. */
  101   if (r == OK) {
  102         mdir = ((rip->i_mode & I_TYPE) == I_DIRECTORY);  /* TRUE iff dir */
  103         rdir = ((root_ip->i_mode & I_TYPE) == I_DIRECTORY);
  104         if (!mdir && rdir) r = EISDIR;
  105   }
  106 
  107   /* If error, return the super block and both inodes; release the maps. */
  108   if (r != OK) {
  109         put_inode(rip);
  110         put_inode(root_ip);
  111         (void) do_sync();
  112         invalidate(dev);
  113         dev_close(dev);
  114         sp->s_dev = NO_DEV;
  115         return(r);
  116   }
  117 
  118   /* Nothing else can go wrong.  Perform the mount. */
  119   rip->i_mount = I_MOUNT;       /* this bit says the inode is mounted on */
  120   sp->s_imount = rip;
  121   sp->s_isup = root_ip;
  122   sp->s_rd_only = m_in.rd_only;
  123   return(OK);
  124 }
  125 
  126 /*===========================================================================*
  127  *                              do_umount                                    *
  128  *===========================================================================*/
  129 PUBLIC int do_umount()
  130 {
  131 /* Perform the umount(name) system call. */
  132   dev_t dev;
  133 
  134   /* Only the super-user may do UMOUNT. */
  135   if (!super_user) return(EPERM);
  136 
  137   /* If 'name' is not for a block special file, return error. */
  138   if (fetch_name(m_in.name, m_in.name_length, M3) != OK) return(err_code);
  139   if ( (dev = name_to_dev(user_path)) == NO_DEV) return(err_code);
  140 
  141   return(unmount(dev));
  142 }
  143 
  144 /*===========================================================================*
  145  *                              unmount                                      *
  146  *===========================================================================*/
  147 PUBLIC int unmount(dev)
  148 Dev_t dev;
  149 {
  150 /* Unmount a file system by device number. */
  151   register struct inode *rip;
  152   struct super_block *sp, *sp1;
  153   int count;
  154 
  155   /* See if the mounted device is busy.  Only 1 inode using it should be
  156    * open -- the root inode -- and that inode only 1 time.
  157    */
  158   count = 0;
  159   for (rip = &inode[0]; rip< &inode[NR_INODES]; rip++)
  160         if (rip->i_count > 0 && rip->i_dev == dev) count += rip->i_count;
  161   if (count > 1) return(EBUSY); /* can't umount a busy file system */
  162 
  163   /* Find the super block. */
  164   sp = NIL_SUPER;
  165   for (sp1 = &super_block[0]; sp1 < &super_block[NR_SUPERS]; sp1++) {
  166         if (sp1->s_dev == dev) {
  167                 sp = sp1;
  168                 break;
  169         }
  170   }
  171 
  172   /* Sync the disk, and invalidate cache. */
  173   (void) do_sync();             /* force any cached blocks out of memory */
  174   invalidate(dev);              /* invalidate cache entries for this dev */
  175   if (sp == NIL_SUPER) {
  176         return(EINVAL);
  177   }
  178 
  179   /* Close the device the file system lives on. */
  180   dev_close(dev);
  181 
  182   /* Finish off the unmount. */
  183   sp->s_imount->i_mount = NO_MOUNT;     /* inode returns to normal */
  184   put_inode(sp->s_imount);      /* release the inode mounted on */
  185   put_inode(sp->s_isup);        /* release the root inode of the mounted fs */
  186   sp->s_imount = NIL_INODE;
  187   sp->s_dev = NO_DEV;
  188   return(OK);
  189 }
  190 
  191 /*===========================================================================*
  192  *                              name_to_dev                                  *
  193  *===========================================================================*/
  194 PRIVATE dev_t name_to_dev(path)
  195 char *path;                     /* pointer to path name */
  196 {
  197 /* Convert the block special file 'path' to a device number.  If 'path'
  198  * is not a block special file, return error code in 'err_code'.
  199  */
  200 
  201   register struct inode *rip;
  202   register dev_t dev;
  203 
  204   /* If 'path' can't be opened, give up immediately. */
  205   if ( (rip = eat_path(path)) == NIL_INODE) return(NO_DEV);
  206 
  207   /* If 'path' is not a block special file, return error. */
  208   if ( (rip->i_mode & I_TYPE) != I_BLOCK_SPECIAL) {
  209         err_code = ENOTBLK;
  210         put_inode(rip);
  211         return(NO_DEV);
  212   }
  213 
  214   /* Extract the device number. */
  215   dev = (dev_t) rip->i_zone[0];
  216   put_inode(rip);
  217   return(dev);
  218 }

Cache object: fa59a218cc8e7347251efa0ff12455a7


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