⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mount.c

📁 一个简单的操作系统minix的核心代码
💻 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 + -