svn commit: r352426 - in head/sys: kern ufs/ffs

Mateusz Guzik mjg at FreeBSD.org
Mon Sep 16 21:33:17 UTC 2019


Author: mjg
Date: Mon Sep 16 21:33:16 2019
New Revision: 352426
URL: https://svnweb.freebsd.org/changeset/base/352426

Log:
  vfs: manage mnt_writeopcount with atomics
  
  See r352424.
  
  Reviewed by:	kib, jeff
  Tested by:	pho
  Sponsored by:	The FreeBSD Foundation
  Differential Revision:	https://reviews.freebsd.org/D21575

Modified:
  head/sys/kern/vfs_vnops.c
  head/sys/ufs/ffs/ffs_softdep.c

Modified: head/sys/kern/vfs_vnops.c
==============================================================================
--- head/sys/kern/vfs_vnops.c	Mon Sep 16 21:32:21 2019	(r352425)
+++ head/sys/kern/vfs_vnops.c	Mon Sep 16 21:33:16 2019	(r352426)
@@ -1621,11 +1621,23 @@ vn_suspendable(struct mount *mp)
  * suspension is over, and then proceed.
  */
 static int
-vn_start_write_locked(struct mount *mp, int flags)
+vn_start_write_refed(struct mount *mp, int flags, bool mplocked)
 {
 	int error, mflags;
 
-	mtx_assert(MNT_MTX(mp), MA_OWNED);
+	if (__predict_true(!mplocked) && (flags & V_XSLEEP) == 0 &&
+	    vfs_op_thread_enter(mp)) {
+		MPASS((mp->mnt_kern_flag & MNTK_SUSPEND) == 0);
+		atomic_add_int(&mp->mnt_writeopcount, 1);
+		vfs_op_thread_exit(mp);
+		return (0);
+	}
+
+	if (mplocked)
+		mtx_assert(MNT_MTX(mp), MA_OWNED);
+	else
+		MNT_ILOCK(mp);
+
 	error = 0;
 
 	/*
@@ -1648,7 +1660,7 @@ vn_start_write_locked(struct mount *mp, int flags)
 	}
 	if (flags & V_XSLEEP)
 		goto unlock;
-	mp->mnt_writeopcount++;
+	atomic_add_int(&mp->mnt_writeopcount, 1);
 unlock:
 	if (error != 0 || (flags & V_XSLEEP) != 0)
 		MNT_REL(mp);
@@ -1694,11 +1706,10 @@ vn_start_write(struct vnode *vp, struct mount **mpp, i
 	 * refcount for the provided mountpoint too, in order to
 	 * emulate a vfs_ref().
 	 */
-	MNT_ILOCK(mp);
 	if (vp == NULL && (flags & V_MNTREF) == 0)
-		MNT_REF(mp);
+		vfs_ref(mp);
 
-	return (vn_start_write_locked(mp, flags));
+	return (vn_start_write_refed(mp, flags, false));
 }
 
 /*
@@ -1780,15 +1791,26 @@ vn_start_secondary_write(struct vnode *vp, struct moun
 void
 vn_finished_write(struct mount *mp)
 {
+	int c;
+
 	if (mp == NULL || !vn_suspendable(mp))
 		return;
+
+	if (vfs_op_thread_enter(mp)) {
+		c = atomic_fetchadd_int(&mp->mnt_writeopcount, -1) - 1;
+		if (c < 0)
+			panic("vn_finished_write: invalid writeopcount %d", c);
+		MNT_REL_UNLOCKED(mp);
+		vfs_op_thread_exit(mp);
+		return;
+	}
+
 	MNT_ILOCK(mp);
 	MNT_REL(mp);
-	mp->mnt_writeopcount--;
-	if (mp->mnt_writeopcount < 0)
-		panic("vn_finished_write: neg cnt");
-	if ((mp->mnt_kern_flag & MNTK_SUSPEND) != 0 &&
-	    mp->mnt_writeopcount <= 0)
+	c = atomic_fetchadd_int(&mp->mnt_writeopcount, -1) - 1;
+	if (c < 0)
+		panic("vn_finished_write: invalid writeopcount %d", c);
+	if ((mp->mnt_kern_flag & MNTK_SUSPEND) != 0 && c == 0)
 		wakeup(&mp->mnt_writeopcount);
 	MNT_IUNLOCK(mp);
 }
@@ -1827,8 +1849,11 @@ vfs_write_suspend(struct mount *mp, int flags)
 
 	MPASS(vn_suspendable(mp));
 
+	vfs_op_enter(mp);
+
 	MNT_ILOCK(mp);
 	if (mp->mnt_susp_owner == curthread) {
+		vfs_op_exit_locked(mp);
 		MNT_IUNLOCK(mp);
 		return (EALREADY);
 	}
@@ -1845,6 +1870,7 @@ vfs_write_suspend(struct mount *mp, int flags)
 	 */
 	if ((flags & VS_SKIP_UNMOUNT) != 0 &&
 	    (mp->mnt_kern_flag & MNTK_UNMOUNT) != 0) {
+		vfs_op_exit_locked(mp);
 		MNT_IUNLOCK(mp);
 		return (EBUSY);
 	}
@@ -1856,8 +1882,10 @@ vfs_write_suspend(struct mount *mp, int flags)
 		    MNT_MTX(mp), (PUSER - 1)|PDROP, "suspwt", 0);
 	else
 		MNT_IUNLOCK(mp);
-	if ((error = VFS_SYNC(mp, MNT_SUSPEND)) != 0)
+	if ((error = VFS_SYNC(mp, MNT_SUSPEND)) != 0) {
 		vfs_write_resume(mp, 0);
+		vfs_op_exit(mp);
+	}
 	return (error);
 }
 
@@ -1881,14 +1909,15 @@ vfs_write_resume(struct mount *mp, int flags)
 		curthread->td_pflags &= ~TDP_IGNSUSP;
 		if ((flags & VR_START_WRITE) != 0) {
 			MNT_REF(mp);
-			mp->mnt_writeopcount++;
+			atomic_add_int(&mp->mnt_writeopcount, 1);
 		}
 		MNT_IUNLOCK(mp);
 		if ((flags & VR_NO_SUSPCLR) == 0)
 			VFS_SUSP_CLEAN(mp);
+		vfs_op_exit(mp);
 	} else if ((flags & VR_START_WRITE) != 0) {
 		MNT_REF(mp);
-		vn_start_write_locked(mp, 0);
+		vn_start_write_refed(mp, 0, true);
 	} else {
 		MNT_IUNLOCK(mp);
 	}

Modified: head/sys/ufs/ffs/ffs_softdep.c
==============================================================================
--- head/sys/ufs/ffs/ffs_softdep.c	Mon Sep 16 21:32:21 2019	(r352425)
+++ head/sys/ufs/ffs/ffs_softdep.c	Mon Sep 16 21:33:16 2019	(r352426)
@@ -2954,17 +2954,26 @@ journal_suspend(ump)
 {
 	struct jblocks *jblocks;
 	struct mount *mp;
+	bool set;
 
 	mp = UFSTOVFS(ump);
+	if ((mp->mnt_kern_flag & MNTK_SUSPEND) != 0)
+		return;
+
 	jblocks = ump->softdep_jblocks;
+	vfs_op_enter(mp);
+	set = false;
 	MNT_ILOCK(mp);
 	if ((mp->mnt_kern_flag & MNTK_SUSPEND) == 0) {
 		stat_journal_min++;
 		mp->mnt_kern_flag |= MNTK_SUSPEND;
 		mp->mnt_susp_owner = ump->softdep_flushtd;
+		set = true;
 	}
 	jblocks->jb_suspended = 1;
 	MNT_IUNLOCK(mp);
+	if (!set)
+		vfs_op_exit(mp);
 }
 
 static int


More information about the svn-src-all mailing list