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.
This commit is contained in:
Thomas Veerman 2012-11-14 13:18:16 +00:00
parent badec36b33
commit ed23a7a7d2
3 changed files with 27 additions and 7 deletions

View 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 */);
}
/*===========================================================================*

View 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();

View 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);