svn commit: r245282 - in stable/9/sys: kern sys ufs/ffs

Konstantin Belousov kib at FreeBSD.org
Fri Jan 11 05:35:05 UTC 2013


Author: kib
Date: Fri Jan 11 05:35:04 2013
New Revision: 245282
URL: http://svnweb.freebsd.org/changeset/base/245282

Log:
  MFC r244795:
  Make it possible to atomically resume writes on the mount and account
  the write start, by adding a variation of the vfs_write_resume(9) which
  accepts flags.
  
  Use the new function to prevent a deadlock between parallel suspension
  and snapshotting a UFS mount.

Modified:
  stable/9/sys/kern/vfs_vnops.c
  stable/9/sys/sys/vnode.h
  stable/9/sys/ufs/ffs/ffs_snapshot.c
Directory Properties:
  stable/9/sys/   (props changed)

Modified: stable/9/sys/kern/vfs_vnops.c
==============================================================================
--- stable/9/sys/kern/vfs_vnops.c	Fri Jan 11 02:25:39 2013	(r245281)
+++ stable/9/sys/kern/vfs_vnops.c	Fri Jan 11 05:35:04 2013	(r245282)
@@ -1408,6 +1408,40 @@ vn_closefile(fp, td)
  * proceed. If a suspend request is in progress, we wait until the
  * suspension is over, and then proceed.
  */
+static int
+vn_start_write_locked(struct mount *mp, int flags)
+{
+	int error;
+
+	mtx_assert(MNT_MTX(mp), MA_OWNED);
+	error = 0;
+
+	/*
+	 * Check on status of suspension.
+	 */
+	if ((curthread->td_pflags & TDP_IGNSUSP) == 0 ||
+	    mp->mnt_susp_owner != curthread) {
+		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);
+			if (error)
+				goto unlock;
+		}
+	}
+	if (flags & V_XSLEEP)
+		goto unlock;
+	mp->mnt_writeopcount++;
+unlock:
+	if (error != 0 || (flags & V_XSLEEP) != 0)
+		MNT_REL(mp);
+	MNT_IUNLOCK(mp);
+	return (error);
+}
+
 int
 vn_start_write(vp, mpp, flags)
 	struct vnode *vp;
@@ -1444,30 +1478,7 @@ vn_start_write(vp, mpp, flags)
 	if (vp == NULL)
 		MNT_REF(mp);
 
-	/*
-	 * Check on status of suspension.
-	 */
-	if ((curthread->td_pflags & TDP_IGNSUSP) == 0 ||
-	    mp->mnt_susp_owner != curthread) {
-		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);
-			if (error)
-				goto unlock;
-		}
-	}
-	if (flags & V_XSLEEP)
-		goto unlock;
-	mp->mnt_writeopcount++;
-unlock:
-	if (error != 0 || (flags & V_XSLEEP) != 0)
-		MNT_REL(mp);
-	MNT_IUNLOCK(mp);
-	return (error);
+	return (vn_start_write_locked(mp, flags));
 }
 
 /*
@@ -1613,8 +1624,7 @@ vfs_write_suspend(mp)
  * Request a filesystem to resume write operations.
  */
 void
-vfs_write_resume(mp)
-	struct mount *mp;
+vfs_write_resume_flags(struct mount *mp, int flags)
 {
 
 	MNT_ILOCK(mp);
@@ -1626,10 +1636,25 @@ vfs_write_resume(mp)
 		wakeup(&mp->mnt_writeopcount);
 		wakeup(&mp->mnt_flag);
 		curthread->td_pflags &= ~TDP_IGNSUSP;
+		if ((flags & VR_START_WRITE) != 0) {
+			MNT_REF(mp);
+			mp->mnt_writeopcount++;
+		}
 		MNT_IUNLOCK(mp);
 		VFS_SUSP_CLEAN(mp);
-	} else
+	} else if ((flags & VR_START_WRITE) != 0) {
+		MNT_REF(mp);
+		vn_start_write_locked(mp, 0);
+	} else {
 		MNT_IUNLOCK(mp);
+	}
+}
+
+void
+vfs_write_resume(struct mount *mp)
+{
+
+	vfs_write_resume_flags(mp, 0);
 }
 
 /*

Modified: stable/9/sys/sys/vnode.h
==============================================================================
--- stable/9/sys/sys/vnode.h	Fri Jan 11 02:25:39 2013	(r245281)
+++ stable/9/sys/sys/vnode.h	Fri Jan 11 05:35:04 2013	(r245282)
@@ -393,6 +393,8 @@ extern int		vttoif_tab[];
 #define	V_NOWAIT	0x0002	/* vn_start_write: don't sleep for suspend */
 #define	V_XSLEEP	0x0004	/* vn_start_write: just return after sleep */
 
+#define	VR_START_WRITE	0x0001	/* vfs_write_resume: start write atomically */
+
 #define	VREF(vp)	vref(vp)
 
 #ifdef DIAGNOSTIC
@@ -701,6 +703,7 @@ int	vn_io_fault_uiomove(char *data, int 
 int	vfs_cache_lookup(struct vop_lookup_args *ap);
 void	vfs_timestamp(struct timespec *);
 void	vfs_write_resume(struct mount *mp);
+void	vfs_write_resume_flags(struct mount *mp, int flags);
 int	vfs_write_suspend(struct mount *mp);
 int	vop_stdbmap(struct vop_bmap_args *);
 int	vop_stdfsync(struct vop_fsync_args *);

Modified: stable/9/sys/ufs/ffs/ffs_snapshot.c
==============================================================================
--- stable/9/sys/ufs/ffs/ffs_snapshot.c	Fri Jan 11 02:25:39 2013	(r245281)
+++ stable/9/sys/ufs/ffs/ffs_snapshot.c	Fri Jan 11 05:35:04 2013	(r245282)
@@ -686,8 +686,7 @@ out1:
 	/*
 	 * Resume operation on filesystem.
 	 */
-	vfs_write_resume(vp->v_mount);
-	vn_start_write(NULL, &wrtmp, V_WAIT);
+	vfs_write_resume_flags(vp->v_mount, VR_START_WRITE);
 	if (collectsnapstats && starttime.tv_sec > 0) {
 		nanotime(&endtime);
 		timespecsub(&endtime, &starttime);


More information about the svn-src-stable-9 mailing list