I sprinkled some printfs to narrow down the problem, but that had the
unfortunate effect of making the bug dissapear.
I am no expert here, but I wonder if a delay() is needed somewhere or if
my printfs are just stopping a race.
Here's the diff I used.
Index: kern/vfs_subr.c
===================================================================
RCS file: /cvs/src/sys/kern/vfs_subr.c,v
retrieving revision 1.249
diff -u -p -u -p -r1.249 vfs_subr.c
--- kern/vfs_subr.c 22 Jul 2016 09:54:09 -0000 1.249
+++ kern/vfs_subr.c 10 Aug 2016 13:33:02 -0000
@@ -1573,11 +1573,14 @@ vfs_unmountall(void)
struct mount *mp, *nmp;
int allerror, error, again = 1;
+ printf("\nvfs_unmountall ");
retry:
allerror = 0;
TAILQ_FOREACH_REVERSE_SAFE(mp, &mountlist, mntlist, mnt_list, nmp) {
+ printf("1");
if ((vfs_busy(mp, VB_WRITE|VB_NOWAIT)) != 0)
continue;
+ printf("2");
if ((error = dounmount(mp, MNT_FORCE, curproc, NULL)) != 0) {
printf("unmount of %s failed with error %d\n",
mp->mnt_stat.f_mntonname, error);
@@ -1585,6 +1588,7 @@ vfs_unmountall(void)
}
}
+ printf("3");
if (allerror) {
printf("WARNING: some file systems would not unmount\n");
if (again) {
@@ -1593,6 +1597,7 @@ vfs_unmountall(void)
goto retry;
}
}
+ printf("4");
}
/*
@@ -1612,12 +1617,15 @@ vfs_shutdown(void)
if (panicstr == 0) {
/* Sync before unmount, in case we hang on something. */
+ printf("1");
sys_sync(&proc0, NULL, NULL);
/* Unmount file systems. */
+ printf("2");
vfs_unmountall();
}
+ printf("3");
if (vfs_syncwait(1))
printf("giving up\n");
else
Index: kern/vfs_syscalls.c
===================================================================
RCS file: /cvs/src/sys/kern/vfs_syscalls.c,v
retrieving revision 1.263
diff -u -p -u -p -r1.263 vfs_syscalls.c
--- kern/vfs_syscalls.c 14 Jul 2016 15:39:40 -0000 1.263
+++ kern/vfs_syscalls.c 10 Aug 2016 13:33:02 -0000
@@ -474,20 +474,28 @@ sys_sync(struct proc *p, void *v, regist
struct mount *mp, *nmp;
int asyncflag;
+ printf("\nsys_sync ");
TAILQ_FOREACH_REVERSE_SAFE(mp, &mountlist, mntlist, mnt_list, nmp) {
+ printf("1");
if (vfs_busy(mp, VB_READ|VB_NOWAIT))
continue;
+ printf("2");
+ printf("%s", mp->mnt_stat.f_mntonname);
if ((mp->mnt_flag & MNT_RDONLY) == 0) {
+ printf("3");
asyncflag = mp->mnt_flag & MNT_ASYNC;
mp->mnt_flag &= ~MNT_ASYNC;
uvm_vnp_sync(mp);
+ printf("4");
VFS_SYNC(mp, MNT_NOWAIT, p->p_ucred, p);
if (asyncflag)
mp->mnt_flag |= MNT_ASYNC;
}
+ printf("5");
vfs_unbusy(mp);
}
+ printf("6");
return (0);
}