]> Zhao Yanbai Git Server - minix.git/commitdiff
VFS: fix reboot panic with mounted FUSE FS
authorThomas Veerman <thomas@minix3.org>
Wed, 14 Nov 2012 13:18:16 +0000 (13:18 +0000)
committerThomas Veerman <thomas@minix3.org>
Wed, 14 Nov 2012 13:18:16 +0000 (13:18 +0000)
Upon reboot VFS semi-exits all processes and unmounts the file system.
However, upon unmount, exiting FUSE file systems might need service from
the file system (due to libc). As the FUSE process is halfway the exit
procedure, it doesn't have a valid root directory and working directory.
Trying to do system calls then triggers a sanity check in VFS.

This fix first exits normal processes which should then allow for
unmounting FUSE file systems. Then VFS exits all processes including
File Servers and unmounts the rest of the file system.

servers/vfs/misc.c
servers/vfs/mount.c
servers/vfs/proto.h

index 04c799f711f7383f3acf7f1f1b739b1518d9cb63..f32ec88e2ad11825035dc392f6448bb25be5a711 100644 (file)
@@ -348,19 +348,36 @@ int do_fsync()
  *===========================================================================*/
 void pm_reboot()
 {
-  /* Perform the VFS side of the reboot call. */
+/* Perform the VFS side of the reboot call. */
   int i;
   struct fproc *rfp;
 
   do_sync();
 
-  /* Do exit processing for all leftover processes and servers,
-   * but don't actually exit them (if they were really gone, PM
-   * will tell us about it).
+  /* Do exit processing for all leftover processes and servers, but don't
+   * actually exit them (if they were really gone, PM will tell us about it).
+   * Skip processes that handle parts of the file system; we first need to give
+   * them the chance to unmount (which should be possible as all normal
+   * processes have no open files anymore).
    */
   for (i = 0; i < NR_PROCS; i++) {
        rfp = &fproc[i];
 
+       /* Don't just free the proc right away, but let it finish what it was
+        * doing first */
+       lock_proc(rfp, 0);
+       if (rfp->fp_endpoint != NONE && find_vmnt(rfp->fp_endpoint) == NULL)
+               free_proc(rfp, 0);
+       unlock_proc(rfp);
+  }
+
+  do_sync();
+  unmount_all(0 /* Don't force */);
+
+  /* Try to exit all processes again including File Servers */
+  for (i = 0; i < NR_PROCS; i++) {
+       rfp = &fproc[i];
+
        /* Don't just free the proc right away, but let it finish what it was
         * doing first */
        lock_proc(rfp, 0);
@@ -370,7 +387,8 @@ void pm_reboot()
   }
 
   do_sync();
-  unmount_all();
+  unmount_all(1 /* Force */);
+
 }
 
 /*===========================================================================*
index 7956c24fb240256b892a955eec5efda47c24743c..7b14b865b94c51e76b73edec4de330cc788910e2 100644 (file)
@@ -533,7 +533,7 @@ int unmount(
 /*===========================================================================*
  *                             unmount_all                                  *
  *===========================================================================*/
-void unmount_all(void)
+void unmount_all(int force)
 {
 /* 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.
@@ -551,6 +551,8 @@ void unmount_all(void)
        }
   }
 
+  if (!force) return;
+
   /* Verify nothing is locked anymore */
   check_vnode_locks();
   check_vmnt_locks();
index 74b4b8ab89326f5383c1bbaf573773cbaf73cf08..2812005145d6f648ca212406681df3e8b60baa21 100644 (file)
@@ -154,7 +154,7 @@ void mount_pfs(void);
 int mount_fs(dev_t dev, char fullpath[PATH_MAX+1], endpoint_t fs_e, int
        rdonly, char mount_label[LABEL_MAX]);
 int unmount(dev_t dev, char label[LABEL_MAX]);
-void unmount_all(void);
+void unmount_all(int force);
 
 /* open.c */
 int do_close(void);