summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2013-03-20 21:07:49 +0000
committerkib <kib@FreeBSD.org>2013-03-20 21:07:49 +0000
commit6fbc70a0bc5387f75b59d76d9857ee9aceab716a (patch)
treeb70af796e14ffb314315311c8bff02276a3d09e0 /sys
parent9904f3d96892171a40469b83d51181e130737660 (diff)
downloadFreeBSD-src-6fbc70a0bc5387f75b59d76d9857ee9aceab716a.zip
FreeBSD-src-6fbc70a0bc5387f75b59d76d9857ee9aceab716a.tar.gz
When the journaled FFS volume is suspended due to the journal space
becoming too low, the softdep flush thread processes the workitems, which frees the space in journal, and then unsuspends the fs. The softdep_flush() and other workitem processing functions busy the filesystem before iterating over the worklist, to prevent the parallel unmount from freeing the mount data. The vfs_busy() is called with MBF_NOWAIT flag. Now, if the unmount is already started and the filesystem is suspended due to low journal space, the journal is never flushed and filesystem is never unsuspended, because vfs_busy(MBF_NOWAIT) call cannot succeed for the unmounting fs, and softdep_flush() does not process the workitems. Unmount needs to write metadata, where it hangs in the "suspfs" state. Move the vn_start_write() call in the dounmount() before setting the MNTK_UNMOUNT flag. This practically ensures that softdep_flush() processed the pending journal writes by making dounmount() wait for the lift of the suspension. Sponsored by: The FreeBSD Foundation Reported and tested by: pho MFC after: 2 weeks
Diffstat (limited to 'sys')
-rw-r--r--sys/kern/vfs_mount.c3
1 files changed, 2 insertions, 1 deletions
diff --git a/sys/kern/vfs_mount.c b/sys/kern/vfs_mount.c
index 3f10669..c1ed6c9 100644
--- a/sys/kern/vfs_mount.c
+++ b/sys/kern/vfs_mount.c
@@ -1256,12 +1256,14 @@ dounmount(mp, flags, td)
return (error);
}
+ vn_start_write(NULL, &mp, V_WAIT);
MNT_ILOCK(mp);
if ((mp->mnt_kern_flag & MNTK_UNMOUNT) != 0 ||
!TAILQ_EMPTY(&mp->mnt_uppers)) {
MNT_IUNLOCK(mp);
if (coveredvp)
VOP_UNLOCK(coveredvp, 0);
+ vn_finished_write(mp);
return (EBUSY);
}
mp->mnt_kern_flag |= MNTK_UNMOUNT | MNTK_NOINSMNTQ;
@@ -1281,7 +1283,6 @@ dounmount(mp, flags, td)
KASSERT(error == 0,
("%s: invalid return value for msleep in the drain path @ %s:%d",
__func__, __FILE__, __LINE__));
- vn_start_write(NULL, &mp, V_WAIT);
if (mp->mnt_flag & MNT_EXPUBLIC)
vfs_setpublicfs(NULL, NULL, NULL);
OpenPOWER on IntegriCloud