Need to force sync(2) before umounting UFS1 filesystems?

Kirk McKusick mckusick at mckusick.com
Fri Sep 30 18:20:27 UTC 2011


> Date: Fri, 30 Sep 2011 15:31:56 +0200
> Subject: Re: Need to force sync(2) before umounting UFS1 filesystems?
> From: Attilio Rao <attilio at freebsd.org>
> To: Kirk McKusick <mckusick at mckusick.com>
> Cc: Konstantin Belousov <kib at freebsd.org>,
>     Garrett Cooper <yanegomi at gmail.com>,
>     freebsd-fs at freebsd.org, Xin LI <delphij at freebsd.org>
> 
> 2011/9/30 Kirk McKusick <mckusick at mckusick.com>:
> 
> > Here is my proposed fix. It does the unroll originally found in the
> > non-FORCE case before sleeping waiting for the vfs_busy to clear.
> > Is it acceptable to hold the mount mutex while calling VOP_UNLOCK?
> > If not, then it needs to be released before the unlock, reacquired
> > afterwards, and the check to see if the sleep is needed redone.
> 
> I thought about this approach when sending the e-mail, but there is a
> problem: you need to handle the MNTK_UNMOUNT flag checking and
> subsequent setting after coveredvnode is held, otherwise at the first
> looping you will just return EBUSY.
> 
> You can avoid the unlock by passing PVFS | PDROP.
> 
> Attilio

Problem noted. I have updated the patch to clear the MNTK_UNMOUNT
(and other flags set above it) after it returns from the sleep.
Which means I cannot use the PDROP flag now, but it is good to
know about it for future reference.

Still not clear to me if it is acceptable to hold the mount mutex
while calling VOP_UNLOCK. Should I drop the mount mutex around the
VOP_UNLOCK(coveredvp)? Other than that possible problem, this patch
appears to solve the EBUSY problem and avoid possible deadlocks.

	Kirk McKusick

Index: sys/kern/vfs_mount.c
===================================================================
--- sys/kern/vfs_mount.c	(revision 225884)
+++ sys/kern/vfs_mount.c	(working copy)
@@ -1187,6 +1187,7 @@
 
 	mtx_assert(&Giant, MA_OWNED);
 
+top:
 	if ((coveredvp = mp->mnt_vnodecovered) != NULL) {
 		mnt_gen_r = mp->mnt_gen;
 		VI_LOCK(coveredvp);
@@ -1227,21 +1228,19 @@
 		mp->mnt_kern_flag |= MNTK_UNMOUNTF;
 	error = 0;
 	if (mp->mnt_lockref) {
-		if ((flags & MNT_FORCE) == 0) {
-			mp->mnt_kern_flag &= ~(MNTK_UNMOUNT | MNTK_NOINSMNTQ |
-			    MNTK_UNMOUNTF);
-			if (mp->mnt_kern_flag & MNTK_MWAIT) {
-				mp->mnt_kern_flag &= ~MNTK_MWAIT;
-				wakeup(mp);
-			}
-			MNT_IUNLOCK(mp);
-			if (coveredvp)
-				VOP_UNLOCK(coveredvp, 0);
-			return (EBUSY);
+		if (mp->mnt_kern_flag & MNTK_MWAIT) {
+			mp->mnt_kern_flag &= ~MNTK_MWAIT;
+			wakeup(mp);
 		}
+		if (coveredvp)
+			VOP_UNLOCK(coveredvp, 0);
 		mp->mnt_kern_flag |= MNTK_DRAINING;
 		error = msleep(&mp->mnt_lockref, MNT_MTX(mp), PVFS,
 		    "mount drain", 0);
+		mp->mnt_kern_flag &= ~(MNTK_UNMOUNT | MNTK_NOINSMNTQ |
+		    MNTK_UNMOUNTF);
+		MNT_IUNLOCK(mp);
+		goto top;
 	}
 	MNT_IUNLOCK(mp);
 	KASSERT(mp->mnt_lockref == 0,


More information about the freebsd-fs mailing list