svn commit: r189287 - head/sys/kern

Alexander Kabaev kan at FreeBSD.org
Mon Mar 2 12:51:40 PST 2009


Author: kan
Date: Mon Mar  2 20:51:39 2009
New Revision: 189287
URL: http://svn.freebsd.org/changeset/base/189287

Log:
  Change vfs_busy to wait until an outcome of pending unmount
  operation is known and to retry or fail accordingly to that
  outcome. This fixes the problem with namespace traversing
  programs failing with random ENOENT errors if someone just
  happened to try to unmount that same filesystem at the same
  time.
  
  Reported by:	dhw
  Reviewed by:	kib, attilio
  Sponsored by:	Juniper Networks, Inc.

Modified:
  head/sys/kern/vfs_subr.c

Modified: head/sys/kern/vfs_subr.c
==============================================================================
--- head/sys/kern/vfs_subr.c	Mon Mar  2 19:42:01 2009	(r189286)
+++ head/sys/kern/vfs_subr.c	Mon Mar  2 20:51:39 2009	(r189287)
@@ -345,7 +345,19 @@ vfs_busy(struct mount *mp, int flags)
 
 	MNT_ILOCK(mp);
 	MNT_REF(mp);
-	if (mp->mnt_kern_flag & MNTK_UNMOUNT) {
+	/*
+	 * If mount point is currenly being unmounted, sleep until the
+	 * mount point fate is decided.  If thread doing the unmounting fails,
+	 * it will clear MNTK_UNMOUNT flag before waking us up, indicating
+	 * that this mount point has survived the unmount attempt and vfs_busy
+	 * should retry.  Otherwise the unmounter thread will set MNTK_REFEXPIRE
+	 * flag in addition to MNTK_UNMOUNT, indicating that mount point is
+	 * about to be really destroyed.  vfs_busy needs to release its
+	 * reference on the mount point in this case and return with ENOENT,
+	 * telling the caller that mount mount it tried to busy is no longer
+	 * valid.
+	 */
+	while (mp->mnt_kern_flag & MNTK_UNMOUNT) {
 		if (flags & MBF_NOWAIT || mp->mnt_kern_flag & MNTK_REFEXPIRE) {
 			MNT_REL(mp);
 			MNT_IUNLOCK(mp);
@@ -357,12 +369,8 @@ vfs_busy(struct mount *mp, int flags)
 			mtx_unlock(&mountlist_mtx);
 		mp->mnt_kern_flag |= MNTK_MWAIT;
 		msleep(mp, MNT_MTX(mp), PVFS, "vfs_busy", 0);
-		MNT_REL(mp);
-		MNT_IUNLOCK(mp);
 		if (flags & MBF_MNTLSTLOCK)
 			mtx_lock(&mountlist_mtx);
-		CTR1(KTR_VFS, "%s: failed busying after sleep", __func__);
-		return (ENOENT);
 	}
 	if (flags & MBF_MNTLSTLOCK)
 		mtx_unlock(&mountlist_mtx);


More information about the svn-src-head mailing list