]> Zhao Yanbai Git Server - minix.git/commitdiff
cleanup of vfs shutdown logic; makes clean unmounts easier (but
authorBen Gras <ben@minix3.org>
Wed, 29 Apr 2009 16:59:18 +0000 (16:59 +0000)
committerBen Gras <ben@minix3.org>
Wed, 29 Apr 2009 16:59:18 +0000 (16:59 +0000)
needs checking if fp_wd or fp_rd is NULL before use)

servers/vfs/fproc.h
servers/vfs/main.c
servers/vfs/misc.c
servers/vfs/mount.c
servers/vfs/open.c
servers/vfs/path.c
servers/vfs/stadir.c
servers/vfs/vnode.c

index 961af0014a0bcd1e1a0abfa56115e57933321217..d1052cd93a43124744ac8084b6df2a5fb37ae2f1 100644 (file)
@@ -10,8 +10,8 @@ EXTERN struct fproc {
 
   mode_t fp_umask;             /* mask set by umask system call */
  
-  struct vnode *fp_wd;         /* working directory */
-  struct vnode *fp_rd;         /* root directory */
+  struct vnode *fp_wd;         /* working directory; NULL during reboot */
+  struct vnode *fp_rd;         /* root directory; NULL during reboot */
   
   struct filp *fp_filp[OPEN_MAX];/* the file descriptor table */
 
index f28b497880b372618f4df7fe1852deb1433d1ec0..024f4e92acab9bf493637b9edf8ea1a8b48fa454 100644 (file)
@@ -104,12 +104,12 @@ PUBLIC int main()
 
        /* Check for special control messages first. */
         if ((call_nr & NOTIFY_MESSAGE)) {
-               if (call_nr == PROC_EVENT)
+               if (call_nr == PROC_EVENT && who_e == PM_PROC_NR)
                {
                        /* PM tries to get FS to do something */
                        service_pm();
                }
-               else if (call_nr == SYN_ALARM)
+               else if (call_nr == SYN_ALARM && who_e == CLOCK)
                {
                        /* Alarm timer expired. Used only for select().
                         * Check it.
index 2f391a8f032f2e86a5b1c5971f180e4c2fd01cc2..54f54d8e390555fb59462c61ec7649d95bbad64d 100644 (file)
@@ -298,6 +298,33 @@ PUBLIC int do_fsync()
   return(OK);
 }
 
+void unmount_all(void)
+{
+       int i;
+       int found = 0, worked = 0, remain = 0;
+  /* Unmount all filesystems.  File systems are mounted on other file systems,
+   * so you have to pull off the loose bits repeatedly to get it all undone.
+   */
+  for (i= 0; i < NR_SUPERS; i++) {
+       struct vmnt *vmp;
+       /* Unmount at least one. */
+       worked = remain = 0;
+       for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; vmp++) {
+               if (vmp->m_dev != NO_DEV) {
+                       found++;
+                       CHECK_VREFS;
+                       if(unmount(vmp->m_dev) == OK)
+                               worked++;
+                       else
+                               remain++;
+                       CHECK_VREFS;
+               }
+       }
+  }
+
+         printf("VFS: worked: %d remain: %d\n", worked, remain);
+}
+
 /*===========================================================================*
  *                             pm_reboot                                    *
  *===========================================================================*/
@@ -305,7 +332,6 @@ PUBLIC void pm_reboot()
 {
   /* Perform the FS side of the reboot call. */
   int i;
-  struct vmnt *vmp;
 
   do_sync();
 
@@ -316,27 +342,17 @@ PUBLIC void pm_reboot()
    * will tell us about it).
    */
   for (i = 0; i < NR_PROCS; i++)
-       if((m_in.endpt1 = fproc[i].fp_endpoint) != NONE)
-               free_proc(&fproc[i], FP_EXITING);
+       if((m_in.endpt1 = fproc[i].fp_endpoint) != NONE) {
+               /* No FP_EXITING, just free the resources, otherwise
+                * consistency check for fp_endpoint (set to NONE) will
+                * fail if process wants to do something in the (short)
+                * future.
+                */
+               free_proc(&fproc[i], 0);
+       }
   CHECK_VREFS;
 
-  /* The root file system is mounted onto itself, which keeps it from being
-   * unmounted.  Pull an inode out of thin air and put the root on it.
-   */
-
-  /* Unmount all filesystems.  File systems are mounted on other file systems,
-   * so you have to pull off the loose bits repeatedly to get it all undone.
-   */
-  for (i= 0; i < NR_SUPERS; i++) {
-       /* Unmount at least one. */
-       for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; vmp++) {
-               if (vmp->m_dev != NO_DEV) {
-                       CHECK_VREFS;
-                       (void) unmount(vmp->m_dev);
-                       CHECK_VREFS;
-               }
-       }
-  }
+  unmount_all();
 
   CHECK_VREFS;
 
@@ -378,6 +394,7 @@ int cpid;   /* Child process id */
   /* Increase the counters in the 'filp' table. */
   cp = &fproc[childno];
   fp = &fproc[parentno];
+
   for (i = 0; i < OPEN_MAX; i++)
        if (cp->fp_filp[i] != NIL_FILP) cp->fp_filp[i]->filp_count++;
 
@@ -404,8 +421,8 @@ int cpid;   /* Child process id */
   cp->fp_execced = 0;
 
   /* Record the fact that both root and working dir have another user. */
-  dup_vnode(cp->fp_rd);
-  dup_vnode(cp->fp_wd);
+  if(cp->fp_rd) dup_vnode(cp->fp_rd);
+  if(cp->fp_wd) dup_vnode(cp->fp_wd);
 }
 
 /*===========================================================================*
@@ -421,6 +438,10 @@ PRIVATE void free_proc(struct fproc *exiter, int flags)
 
   fp = exiter;         /* get_filp() needs 'fp' */
 
+  if(fp->fp_endpoint == NONE) {
+       panic(__FILE__, "free_proc: already free", NO_NUM);
+  }
+
   if (fp->fp_suspended == SUSPENDED) {
        task = -fp->fp_task;
        if (task == XPIPE || task == XPOPEN) susp_count--;
@@ -432,12 +453,6 @@ PRIVATE void free_proc(struct fproc *exiter, int flags)
   for (i = 0; i < OPEN_MAX; i++) {
        (void) close_fd(fp, i);
   }
-
-  /* Release root and working directories. */
-  put_vnode(fp->fp_rd);
-  put_vnode(fp->fp_wd);
-  fp->fp_rd = NIL_VNODE;
-  fp->fp_wd = NIL_VNODE;
   
   /* Check if any process is SUSPENDed on this driver.
    * If a driver exits, unmap its entries in the dmap table.
@@ -446,6 +461,12 @@ PRIVATE void free_proc(struct fproc *exiter, int flags)
    */
   unsuspend_by_endpt(fp->fp_endpoint);
 
+  /* Release root and working directories. */
+  if(fp->fp_rd) { put_vnode(fp->fp_rd); fp->fp_rd = NIL_VNODE; }
+  if(fp->fp_wd) { put_vnode(fp->fp_wd); fp->fp_wd = NIL_VNODE; }
+
+ CHECK_VREFS;
+
   /* The rest of these actions is only done when processes actually
    * exit.
    */
index 8fd1cbbd4310f041902ce2363c5f4258879ac943..871c67266e464d44860a4e0a7ee0c4bbadc6c2d9 100644 (file)
@@ -327,18 +327,14 @@ PRIVATE int mount_fs(endpoint_t fs_e)
           if (tfp->fp_pid == PID_FREE)
               continue;
 
-          if (tfp->fp_rd == NULL)
-              panic("fs", "do_mount: null rootdir", i);
-          if (tfp->fp_wd == NULL)
-              panic("fs", "do_mount: null workdir", i);
-
-          put_vnode(tfp->fp_rd);
-          dup_vnode(root_node);
-          tfp->fp_rd = root_node;
-
-          put_vnode(tfp->fp_wd);
-          dup_vnode(root_node);
-          tfp->fp_wd = root_node;
+#define MAKEROOT(what) {               \
+               put_vnode(what);        \
+               dup_vnode(root_node);   \
+               what = root_node;       \
+         }
+
+         if(tfp->fp_rd) MAKEROOT(tfp->fp_rd);
+         if(tfp->fp_wd) MAKEROOT(tfp->fp_wd);
       }
 
        CHECK_VREFS;
@@ -435,13 +431,11 @@ Dev_t dev;
   for (vp = &vnode[0]; vp < &vnode[NR_VNODES]; vp++) {
       if (vp->v_ref_count > 0 && vp->v_dev == dev) {
 
-#if 1
+#if 0
        int i;
                struct fproc *tfp;
-         if(!(vp->v_inode_nr == 1 && vp->v_ref_count == 1)) {
                  printf("unmount: vnode 0x%x/%d in use %d times\n",
                        dev, vp->v_inode_nr, vp->v_ref_count);
-         }
              for (i= 0, tfp= fproc; i<NR_PROCS; i++, tfp++) {
                int n;
                   if (tfp->fp_pid == PID_FREE)
@@ -465,7 +459,7 @@ Dev_t dev;
                                printf("\tvnode %d: is a mount point\n",
                                        vp->v_inode_nr);
                          }
-#if 0
+#if 1
                          if(vmp_i->m_root_node == vp) {
                                printf("\tvnode %d: is a root node\n",
                                        vp->v_inode_nr);
index 4050f89a3751ed6c096e739c0c496915c1f47ca0..7af05c83f94dc4de1234623843f80464cf6175d4 100644 (file)
@@ -251,6 +251,11 @@ int *created;
        struct node_details res;
        char lastc[PATH_MAX+1];
 
+       if(!fp->fp_rd || !fp->fp_wd) {
+               printf("VFS: %d: no rd/wd\n", fp->fp_endpoint);
+               return ENOENT;
+       }
+
        start_vp = (user_fullpath[0] == '/' ? fp->fp_rd : fp->fp_wd);
        dup_vnode(start_vp);
 
index 6828b78711a54b648bcfc4a4112308e70e6ed701..dc3006afba312a591e5ecd54ecb49b4efb05c872 100644 (file)
@@ -109,6 +109,11 @@ struct vnode **vpp;
    */
   struct vnode *vp;
 
+  if(!fp->fp_rd || !fp->fp_wd) {
+       printf("VFS: lookup_vp %d: no rd/wd\n", fp->fp_endpoint);
+       return ENOENT;
+  }
+
   vp= (user_fullpath[0] == '/' ? fp->fp_rd : fp->fp_wd);
 
   return lookup_rel_vp(vp, flags, use_realuid, vpp);
@@ -207,6 +212,11 @@ struct vnode **vpp;
         */
        struct vnode *vp;
 
+  if(!fp->fp_rd || !fp->fp_wd) {
+       printf("VFS: lookup_lastdir %d: no rd/wd\n", fp->fp_endpoint);
+       return ENOENT;
+  }
+
        vp= (user_fullpath[0] == '/' ? fp->fp_rd : fp->fp_wd);
        return lookup_lastdir_rel(vp, use_realuid, vpp);
 }
@@ -239,6 +249,11 @@ node_details_t *node;
        return ENOENT;
   }
 
+  if(!fp->fp_rd || !fp->fp_wd) {
+       printf("VFS: lookup_rel %d: no rd/wd\n", fp->fp_endpoint);
+       return ENOENT;
+  }
+
   fs_e = start_node->v_fs_e;
   path_off = 0;
   dir_ino = start_node->v_inode_nr;
index 975f4a333832c1d9ff6da89d13064f5fe7e79c1d..d894900af2cb9047e282a0d6e9e377846f5375ae 100644 (file)
@@ -39,6 +39,12 @@ PUBLIC int do_fchdir()
   struct filp *rfilp;
   int r;
 
+  if(!fp->fp_wd || !fp->fp_rd) {
+       printf("VFS: do_fchdir: %d: no rd/wd\n",
+               fp->fp_endpoint);
+       return ENOENT;
+  }
+
   /* Is the file descriptor valid? */
   if ( (rfilp = get_filp(m_in.fd)) == NIL_FILP) return(err_code);
 
@@ -67,11 +73,22 @@ PUBLIC int do_chdir()
   int r;
   register struct fproc *rfp;
 
+  if(!fp->fp_wd || !fp->fp_rd) {
+       printf("VFS: do_chdir: %d: no rd/wd\n",
+               fp->fp_endpoint);
+       return ENOENT;
+  }
+
   if (who_e == PM_PROC_NR) {
        int slot;
        if(isokendpt(m_in.endpt1, &slot) != OK)
                return EINVAL;
        rfp = &fproc[slot];
+
+       if(!rfp->fp_wd || !rfp->fp_rd) {
+               printf("VFS: do_chdir: %d: no other rd/wd\n", fp->fp_endpoint);
+               return ENOENT;
+       }
         
         put_vnode(fp->fp_rd);
         dup_vnode(fp->fp_rd = rfp->fp_rd);
@@ -106,6 +123,12 @@ PUBLIC int do_chroot()
   register int r;
 
   if (!super_user) return(EPERM);      /* only su may chroot() */
+
+  if(!fp->fp_wd || !fp->fp_rd) {
+       printf("VFS: do_chroot: %d: no rd/wd\n",
+               fp->fp_endpoint);
+       return ENOENT;
+  }
   
   r = change(&fp->fp_rd, m_in.name, m_in.name_length);
   return(r);
index 7d28a05022d9c1c68b35793994d2a32a7540e2ec..286f3689a5e3e6d2ed784bb14caae9266fe120a2 100644 (file)
@@ -189,8 +189,8 @@ PUBLIC int check_vrefs()
        for (rfp=&fproc[0]; rfp < &fproc[NR_PROCS]; rfp++) {
                if (rfp->fp_pid == PID_FREE)
                        continue;
-               REFVP(rfp->fp_rd);
-                REFVP(rfp->fp_wd);
+               if(rfp->fp_rd) REFVP(rfp->fp_rd);
+                if(rfp->fp_wd) REFVP(rfp->fp_wd);
        }
 
        /* Count references from filedescriptors */