From: Thomas Veerman Date: Wed, 14 Nov 2012 13:18:16 +0000 (+0000) Subject: VFS: fix reboot panic with mounted FUSE FS X-Git-Tag: v3.2.1~230 X-Git-Url: http://zhaoyanbai.com/repos/host.html?a=commitdiff_plain;h=ed23a7a7d28477eda5477d5b0c3a03c46152a4ac;p=minix.git VFS: fix reboot panic with mounted FUSE FS 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. --- diff --git a/servers/vfs/misc.c b/servers/vfs/misc.c index 04c799f71..f32ec88e2 100644 --- a/servers/vfs/misc.c +++ b/servers/vfs/misc.c @@ -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 */); + } /*===========================================================================* diff --git a/servers/vfs/mount.c b/servers/vfs/mount.c index 7956c24fb..7b14b865b 100644 --- a/servers/vfs/mount.c +++ b/servers/vfs/mount.c @@ -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(); diff --git a/servers/vfs/proto.h b/servers/vfs/proto.h index 74b4b8ab8..281200514 100644 --- a/servers/vfs/proto.h +++ b/servers/vfs/proto.h @@ -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);