📄 mount.c
字号:
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/fs/mount.c
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
25100 /* This file performs the MOUNT and UMOUNT system calls.
25101 *
25102 * The entry points into this file are
25103 * do_mount: perform the MOUNT system call
25104 * do_umount: perform the UMOUNT system call
25105 */
25106
25107 #include "fs.h"
25108 #include <fcntl.h>
25109 #include <minix/com.h>
25110 #include <sys/stat.h>
25111 #include "buf.h"
25112 #include "dev.h"
25113 #include "file.h"
25114 #include "fproc.h"
25115 #include "inode.h"
25116 #include "param.h"
25117 #include "super.h"
25118
25119 PRIVATE message dev_mess;
25120
25121 FORWARD _PROTOTYPE( dev_t name_to_dev, (char *path) );
25122
25123 /*===========================================================================*
25124 * do_mount *
25125 *===========================================================================*/
25126 PUBLIC int do_mount()
25127 {
25128 /* Perform the mount(name, mfile, rd_only) system call. */
25129
25130 register struct inode *rip, *root_ip;
25131 struct super_block *xp, *sp;
25132 dev_t dev;
25133 mode_t bits;
25134 int rdir, mdir; /* TRUE iff {root|mount} file is dir */
25135 int r, found, major, task;
25136
25137 /* Only the super-user may do MOUNT. */
25138 if (!super_user) return(EPERM);
25139
25140 /* If 'name' is not for a block special file, return error. */
25141 if (fetch_name(name1, name1_length, M1) != OK) return(err_code);
25142 if ( (dev = name_to_dev(user_path)) == NO_DEV) return(err_code);
25143
25144 /* Scan super block table to see if dev already mounted & find a free slot.*/
25145 sp = NIL_SUPER;
25146 found = FALSE;
25147 for (xp = &super_block[0]; xp < &super_block[NR_SUPERS]; xp++) {
25148 if (xp->s_dev == dev) found = TRUE; /* is it mounted already? */
25149 if (xp->s_dev == NO_DEV) sp = xp; /* record free slot */
25150 }
25151 if (found) return(EBUSY); /* already mounted */
25152 if (sp == NIL_SUPER) return(ENFILE); /* no super block available */
25153
25154 dev_mess.m_type = DEV_OPEN; /* distinguish from close */
25155 dev_mess.DEVICE = dev; /* Touch the device. */
25156 if (rd_only) dev_mess.COUNT = R_BIT;
25157 else dev_mess.COUNT = R_BIT|W_BIT;
25158
25159 major = (dev >> MAJOR) & BYTE;
25160 if (major <= 0 || major >= max_major) return(ENODEV);
25161 task = dmap[major].dmap_task; /* device task nr */
25162 (*dmap[major].dmap_open)(task, &dev_mess);
25163 if (dev_mess.REP_STATUS != OK) return(EINVAL);
25164
25165 /* Fill in the super block. */
25166 sp->s_dev = dev; /* read_super() needs to know which dev */
25167 r = read_super(sp);
25168
25169 /* Is it recognized as a Minix filesystem? */
25170 if (r != OK) {
25171 dev_mess.m_type = DEV_CLOSE;
25172 dev_mess.DEVICE = dev;
25173 (*dmap[major].dmap_close)(task, &dev_mess);
25174 return(r);
25175 }
25176
25177 /* Now get the inode of the file to be mounted on. */
25178 if (fetch_name(name2, name2_length, M1) != OK) {
25179 sp->s_dev = NO_DEV;
25180 dev_mess.m_type = DEV_CLOSE;
25181 dev_mess.DEVICE = dev;
25182 (*dmap[major].dmap_close)(task, &dev_mess);
25183 return(err_code);
25184 }
25185 if ( (rip = eat_path(user_path)) == NIL_INODE) {
25186 sp->s_dev = NO_DEV;
25187 dev_mess.m_type = DEV_CLOSE;
25188 dev_mess.DEVICE = dev;
25189 (*dmap[major].dmap_close)(task, &dev_mess);
25190 return(err_code);
25191 }
25192
25193 /* It may not be busy. */
25194 r = OK;
25195 if (rip->i_count > 1) r = EBUSY;
25196
25197 /* It may not be special. */
25198 bits = rip->i_mode & I_TYPE;
25199 if (bits == I_BLOCK_SPECIAL || bits == I_CHAR_SPECIAL) r = ENOTDIR;
25200
25201 /* Get the root inode of the mounted file system. */
25202 root_ip = NIL_INODE; /* if 'r' not OK, make sure this is defined */
25203 if (r == OK) {
25204 if ( (root_ip = get_inode(dev, ROOT_INODE)) == NIL_INODE) r = err_code;
25205 }
25206 if (root_ip != NIL_INODE && root_ip->i_mode == 0) r = EINVAL;
25207
25208 /* File types of 'rip' and 'root_ip' may not conflict. */
25209 if (r == OK) {
25210 mdir = ((rip->i_mode & I_TYPE) == I_DIRECTORY); /* TRUE iff dir */
25211 rdir = ((root_ip->i_mode & I_TYPE) == I_DIRECTORY);
25212 if (!mdir && rdir) r = EISDIR;
25213 }
25214
25215 /* If error, return the super block and both inodes; release the maps. */
25216 if (r != OK) {
25217 put_inode(rip);
25218 put_inode(root_ip);
25219 (void) do_sync();
25220 invalidate(dev);
25221
25222 sp->s_dev = NO_DEV;
25223 dev_mess.m_type = DEV_CLOSE;
25224 dev_mess.DEVICE = dev;
25225 (*dmap[major].dmap_close)(task, &dev_mess);
25226 return(r);
25227 }
25228
25229 /* Nothing else can go wrong. Perform the mount. */
25230 rip->i_mount = I_MOUNT; /* this bit says the inode is mounted on */
25231 sp->s_imount = rip;
25232 sp->s_isup = root_ip;
25233 sp->s_rd_only = rd_only;
25234 return(OK);
25235 }
25238 /*===========================================================================*
25239 * do_umount *
25240 *===========================================================================*/
25241 PUBLIC int do_umount()
25242 {
25243 /* Perform the umount(name) system call. */
25244
25245 register struct inode *rip;
25246 struct super_block *sp, *sp1;
25247 dev_t dev;
25248 int count;
25249 int major, task;
25250
25251 /* Only the super-user may do UMOUNT. */
25252 if (!super_user) return(EPERM);
25253
25254 /* If 'name' is not for a block special file, return error. */
25255 if (fetch_name(name, name_length, M3) != OK) return(err_code);
25256 if ( (dev = name_to_dev(user_path)) == NO_DEV) return(err_code);
25257
25258 /* See if the mounted device is busy. Only 1 inode using it should be
25259 * open -- the root inode -- and that inode only 1 time.
25260 */
25261 count = 0;
25262 for (rip = &inode[0]; rip< &inode[NR_INODES]; rip++)
25263 if (rip->i_count > 0 && rip->i_dev == dev) count += rip->i_count;
25264 if (count > 1) return(EBUSY); /* can't umount a busy file system */
25265
25266 /* Find the super block. */
25267 sp = NIL_SUPER;
25268 for (sp1 = &super_block[0]; sp1 < &super_block[NR_SUPERS]; sp1++) {
25269 if (sp1->s_dev == dev) {
25270 sp = sp1;
25271 break;
25272 }
25273 }
25274
25275 /* Sync the disk, and invalidate cache. */
25276 (void) do_sync(); /* force any cached blocks out of memory */
25277 invalidate(dev); /* invalidate cache entries for this dev */
25278 if (sp == NIL_SUPER) return(EINVAL);
25279
25280 major = (dev >> MAJOR) & BYTE; /* major device nr */
25281 task = dmap[major].dmap_task; /* device task nr */
25282 dev_mess.m_type = DEV_CLOSE; /* distinguish from open */
25283 dev_mess.DEVICE = dev;
25284 (*dmap[major].dmap_close)(task, &dev_mess);
25285
25286 /* Finish off the unmount. */
25287 sp->s_imount->i_mount = NO_MOUNT; /* inode returns to normal */
25288 put_inode(sp->s_imount); /* release the inode mounted on */
25289 put_inode(sp->s_isup); /* release the root inode of the mounted fs */
25290 sp->s_imount = NIL_INODE;
25291 sp->s_dev = NO_DEV;
25292 return(OK);
25293 }
25296 /*===========================================================================*
25297 * name_to_dev *
25298 *===========================================================================*/
25299 PRIVATE dev_t name_to_dev(path)
25300 char *path; /* pointer to path name */
25301 {
25302 /* Convert the block special file 'path' to a device number. If 'path'
25303 * is not a block special file, return error code in 'err_code'.
25304 */
25305
25306 register struct inode *rip;
25307 register dev_t dev;
25308
25309 /* If 'path' can't be opened, give up immediately. */
25310 if ( (rip = eat_path(path)) == NIL_INODE) return(NO_DEV);
25311
25312 /* If 'path' is not a block special file, return error. */
25313 if ( (rip->i_mode & I_TYPE) != I_BLOCK_SPECIAL) {
25314 err_code = ENOTBLK;
25315 put_inode(rip);
25316 return(NO_DEV);
25317 }
25318
25319 /* Extract the device number. */
25320 dev = (dev_t) rip->i_zone[0];
25321 put_inode(rip);
25322 return(dev);
25323 }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -