From owner-svn-src-all@FreeBSD.ORG  Wed Mar 20 21:07:50 2013
Return-Path: <owner-svn-src-all@FreeBSD.ORG>
Delivered-To: svn-src-all@freebsd.org
Received: from mx1.freebsd.org (mx1.freebsd.org
 [IPv6:2001:1900:2254:206a::19:1])
 by hub.freebsd.org (Postfix) with ESMTP id 879A7207;
 Wed, 20 Mar 2013 21:07:50 +0000 (UTC) (envelope-from kib@FreeBSD.org)
Received: from svn.freebsd.org (svn.freebsd.org
 [IPv6:2001:1900:2254:2068::e6a:0])
 by mx1.freebsd.org (Postfix) with ESMTP id 5678F3F4;
 Wed, 20 Mar 2013 21:07:50 +0000 (UTC)
Received: from svn.freebsd.org ([127.0.1.70])
 by svn.freebsd.org (8.14.6/8.14.6) with ESMTP id r2KL7oHe083822;
 Wed, 20 Mar 2013 21:07:50 GMT (envelope-from kib@svn.freebsd.org)
Received: (from kib@localhost)
 by svn.freebsd.org (8.14.6/8.14.5/Submit) id r2KL7oD0083821;
 Wed, 20 Mar 2013 21:07:50 GMT (envelope-from kib@svn.freebsd.org)
Message-Id: <201303202107.r2KL7oD0083821@svn.freebsd.org>
From: Konstantin Belousov <kib@FreeBSD.org>
Date: Wed, 20 Mar 2013 21:07:50 +0000 (UTC)
To: src-committers@freebsd.org, svn-src-all@freebsd.org,
 svn-src-head@freebsd.org
Subject: svn commit: r248562 - head/sys/kern
X-SVN-Group: head
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
X-BeenThere: svn-src-all@freebsd.org
X-Mailman-Version: 2.1.14
Precedence: list
List-Id: "SVN commit messages for the entire src tree \(except for &quot;
 user&quot; and &quot; projects&quot; \)" <svn-src-all.freebsd.org>
List-Unsubscribe: <http://lists.freebsd.org/mailman/options/svn-src-all>,
 <mailto:svn-src-all-request@freebsd.org?subject=unsubscribe>
List-Archive: <http://lists.freebsd.org/pipermail/svn-src-all>
List-Post: <mailto:svn-src-all@freebsd.org>
List-Help: <mailto:svn-src-all-request@freebsd.org?subject=help>
List-Subscribe: <http://lists.freebsd.org/mailman/listinfo/svn-src-all>,
 <mailto:svn-src-all-request@freebsd.org?subject=subscribe>
X-List-Received-Date: Wed, 20 Mar 2013 21:07:50 -0000

Author: kib
Date: Wed Mar 20 21:07:49 2013
New Revision: 248562
URL: http://svnweb.freebsd.org/changeset/base/248562

Log:
  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

Modified:
  head/sys/kern/vfs_mount.c

Modified: head/sys/kern/vfs_mount.c
==============================================================================
--- head/sys/kern/vfs_mount.c	Wed Mar 20 17:57:00 2013	(r248561)
+++ head/sys/kern/vfs_mount.c	Wed Mar 20 21:07:49 2013	(r248562)
@@ -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);