Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 13 Dec 2014 16:07:01 +0000 (UTC)
From:      Konstantin Belousov <kib@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r275744 - head/sys/kern
Message-ID:  <201412131607.sBDG72ru045596@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: kib
Date: Sat Dec 13 16:07:01 2014
New Revision: 275744
URL: https://svnweb.freebsd.org/changeset/base/275744

Log:
  Only sleep interruptible while waiting for suspension end when
  filesystem specified VFCF_SBDRY flag, i.e. for NFS.
  
  There are two issues with the sleeps.  First, applications may get
  unexpected EINTR from the disk i/o syscalls.  Second, interruptible
  sleep allows the stop of the process, and since mount point is
  referenced while thread sleeps, unmount cannot free mount point
  structure' memory, blocking unmount indefinitely.
  
  Even for NFS, it is probably only reasonable to enable PCATCH for intr
  mounts, but this information is currently not available at VFS level.
  
  Reported and tested by:	pho (previous version)
  Sponsored by:	The FreeBSD Foundation
  MFC after:	1 week

Modified:
  head/sys/kern/vfs_vnops.c

Modified: head/sys/kern/vfs_vnops.c
==============================================================================
--- head/sys/kern/vfs_vnops.c	Sat Dec 13 16:02:37 2014	(r275743)
+++ head/sys/kern/vfs_vnops.c	Sat Dec 13 16:07:01 2014	(r275744)
@@ -1600,7 +1600,7 @@ vn_suspendable(struct vnode *vp, struct 
 static int
 vn_start_write_locked(struct mount *mp, int flags)
 {
-	int error;
+	int error, mflags;
 
 	mtx_assert(MNT_MTX(mp), MA_OWNED);
 	error = 0;
@@ -1610,13 +1610,15 @@ vn_start_write_locked(struct mount *mp, 
 	 */
 	if ((curthread->td_pflags & TDP_IGNSUSP) == 0 ||
 	    mp->mnt_susp_owner != curthread) {
+		mflags = ((mp->mnt_vfc->vfc_flags & VFCF_SBDRY) != 0 ?
+		    (flags & PCATCH) : 0) | (PUSER - 1);
 		while ((mp->mnt_kern_flag & MNTK_SUSPEND) != 0) {
 			if (flags & V_NOWAIT) {
 				error = EWOULDBLOCK;
 				goto unlock;
 			}
-			error = msleep(&mp->mnt_flag, MNT_MTX(mp),
-			    (PUSER - 1) | (flags & PCATCH), "suspfs", 0);
+			error = msleep(&mp->mnt_flag, MNT_MTX(mp), mflags,
+			    "suspfs", 0);
 			if (error)
 				goto unlock;
 		}
@@ -1732,8 +1734,9 @@ vn_start_secondary_write(vp, mpp, flags)
 	/*
 	 * Wait for the suspension to finish.
 	 */
-	error = msleep(&mp->mnt_flag, MNT_MTX(mp),
-		       (PUSER - 1) | (flags & PCATCH) | PDROP, "suspfs", 0);
+	error = msleep(&mp->mnt_flag, MNT_MTX(mp), (PUSER - 1) | PDROP |
+	    ((mp->mnt_vfc->vfc_flags & VFCF_SBDRY) != 0 ? (flags & PCATCH) : 0),
+	    "suspfs", 0);
 	vfs_rel(mp);
 	if (error == 0)
 		goto retry;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201412131607.sBDG72ru045596>