~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Minix Cross Reference
Minix/fs/mount.c


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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.