git: 83d203e3d7f4 - stable/13 - ffs: lock buffers after snaplk with LK_NOWITNESS

From: Konstantin Belousov <kib_at_FreeBSD.org>
Date: Mon, 07 Feb 2022 09:50:58 UTC
The branch stable/13 has been updated by kib:

URL: https://cgit.FreeBSD.org/src/commit/?id=83d203e3d7f4103526bb68d0b0b5d470ea31061b

commit 83d203e3d7f4103526bb68d0b0b5d470ea31061b
Author:     Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2022-01-28 04:42:33 +0000
Commit:     Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2022-02-07 09:38:50 +0000

    ffs: lock buffers after snaplk with LK_NOWITNESS
    
    (cherry picked from commit 99aa3b731caa252e94d92add8cb02d077a24a256)
---
 sys/ufs/ffs/ffs_alloc.c  |  4 ++++
 sys/ufs/ffs/ffs_balloc.c | 23 +++++++++++++++--------
 sys/ufs/ffs/ffs_vnops.c  | 12 ++++++++----
 3 files changed, 27 insertions(+), 12 deletions(-)

diff --git a/sys/ufs/ffs/ffs_alloc.c b/sys/ufs/ffs/ffs_alloc.c
index 13c508fde646..50b176b262f4 100644
--- a/sys/ufs/ffs/ffs_alloc.c
+++ b/sys/ufs/ffs/ffs_alloc.c
@@ -80,6 +80,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/mount.h>
 #include <sys/priv.h>
 #include <sys/proc.h>
+#include <sys/stat.h>
 #include <sys/syscallsubr.h>
 #include <sys/sysctl.h>
 #include <sys/syslog.h>
@@ -270,6 +271,9 @@ ffs_realloccg(ip, lbprev, bprev, bpref, osize, nsize, flags, cred, bpp)
 	fs = ump->um_fs;
 	bp = NULL;
 	gbflags = (flags & BA_UNMAPPED) != 0 ? GB_UNMAPPED : 0;
+#ifdef WITNESS
+	gbflags |= IS_SNAPSHOT(ip) ? GB_NOWITNESS : 0;
+#endif
 
 	mtx_assert(UFS_MTX(ump), MA_OWNED);
 #ifdef INVARIANTS
diff --git a/sys/ufs/ffs/ffs_balloc.c b/sys/ufs/ffs/ffs_balloc.c
index d7718e56dd87..af20258081d5 100644
--- a/sys/ufs/ffs/ffs_balloc.c
+++ b/sys/ufs/ffs/ffs_balloc.c
@@ -70,6 +70,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/buf.h>
 #include <sys/lock.h>
 #include <sys/mount.h>
+#include <sys/stat.h>
 #include <sys/vnode.h>
 #include <sys/vmmeter.h>
 
@@ -612,7 +613,7 @@ ffs_balloc_ufs2(struct vnode *vp, off_t startoffset, int size,
 	int deallocated, osize, nsize, num, i, error;
 	int unwindidx = -1;
 	int saved_inbdflush;
-	int gbflags, reclaimed;
+	int gbflags, gbwflag, reclaimed;
 
 	ip = VTOI(vp);
 	dp = ip->i_din2;
@@ -628,6 +629,12 @@ ffs_balloc_ufs2(struct vnode *vp, off_t startoffset, int size,
 	if (lbn < 0)
 		return (EFBIG);
 	gbflags = (flags & BA_UNMAPPED) != 0 ? GB_UNMAPPED : 0;
+#ifdef WITNESS
+	gbwflag = IS_SNAPSHOT(ip) ? GB_NOWITNESS : 0;
+	gbflags |= gbwflag;
+#else
+	gbwflag = 0;
+#endif
 
 	vn_seqc_write_begin(vp);
 
@@ -889,7 +896,7 @@ ffs_balloc_ufs2(struct vnode *vp, off_t startoffset, int size,
 		*allocblk++ = nb;
 		*lbns_remfree++ = indirs[1].in_lbn;
 		bp = getblk(vp, indirs[1].in_lbn, fs->fs_bsize, 0, 0,
-		    GB_UNMAPPED);
+		    GB_UNMAPPED | gbwflag);
 		bp->b_blkno = fsbtodb(fs, nb);
 		vfs_bio_clrbuf(bp);
 		if (DOINGSOFTDEP(vp)) {
@@ -914,8 +921,8 @@ ffs_balloc_ufs2(struct vnode *vp, off_t startoffset, int size,
 	 */
 retry:
 	for (i = 1;;) {
-		error = bread(vp,
-		    indirs[i].in_lbn, (int)fs->fs_bsize, NOCRED, &bp);
+		error = bread_gb(vp, indirs[i].in_lbn, (int)fs->fs_bsize,
+		    NOCRED, gbwflag, &bp);
 		if (error) {
 			goto fail;
 		}
@@ -1138,7 +1145,7 @@ fail:
 		 * buffer object lists.
 		 */
 		bp = getblk(vp, *lbns_remfree, fs->fs_bsize, 0, 0,
-		    GB_NOCREAT | GB_UNMAPPED);
+		    GB_NOCREAT | GB_UNMAPPED | gbwflag);
 		if (bp != NULL) {
 			KASSERT(bp->b_blkno == fsbtodb(fs, *blkp),
 			    ("mismatch2 l %jd %jd b %ju %ju",
@@ -1156,8 +1163,8 @@ fail:
 	} else if (unwindidx >= 0) {
 		int r;
 
-		r = bread(vp, indirs[unwindidx].in_lbn, 
-		    (int)fs->fs_bsize, NOCRED, &bp);
+		r = bread_gb(vp, indirs[unwindidx].in_lbn,
+		    (int)fs->fs_bsize, NOCRED, gbwflag, &bp);
 		if (r) {
 			panic("Could not unwind indirect block, error %d", r);
 			brelse(bp);
@@ -1193,7 +1200,7 @@ fail:
 		if (blkp == allociblk)
 			lbns_remfree = lbns;
 		bp = getblk(vp, *lbns_remfree, fs->fs_bsize, 0, 0,
-		    GB_NOCREAT | GB_UNMAPPED);
+		    GB_NOCREAT | GB_UNMAPPED | gbwflag);
 		if (bp != NULL) {
 			panic("zombie2 %jd %ju %ju",
 			    (intmax_t)bp->b_lblkno, (uintmax_t)bp->b_blkno,
diff --git a/sys/ufs/ffs/ffs_vnops.c b/sys/ufs/ffs/ffs_vnops.c
index a33699515bc2..c2d6948dd140 100644
--- a/sys/ufs/ffs/ffs_vnops.c
+++ b/sys/ufs/ffs/ffs_vnops.c
@@ -261,12 +261,17 @@ ffs_syncvnode(struct vnode *vp, int waitfor, int flags)
 	struct ufsmount *ump;
 	struct buf *bp, *nbp;
 	ufs_lbn_t lbn;
-	int error, passes;
+	int error, passes, wflag;
 	bool still_dirty, unlocked, wait;
 
 	ip = VTOI(vp);
 	bo = &vp->v_bufobj;
 	ump = VFSTOUFS(vp->v_mount);
+#ifdef WITNESS
+	wflag = IS_SNAPSHOT(ip) ? LK_NOWITNESS : 0;
+#else
+	wflag = 0;
+#endif
 
 	/*
 	 * When doing MNT_WAIT we must first flush all dependencies
@@ -318,9 +323,8 @@ loop:
 		if (BUF_LOCK(bp, LK_EXCLUSIVE | LK_NOWAIT, NULL) == 0) {
 			BO_UNLOCK(bo);
 		} else if (wait) {
-			if (BUF_LOCK(bp,
-			    LK_EXCLUSIVE | LK_SLEEPFAIL | LK_INTERLOCK,
-			    BO_LOCKPTR(bo)) != 0) {
+			if (BUF_LOCK(bp, LK_EXCLUSIVE | LK_SLEEPFAIL |
+			    LK_INTERLOCK | wflag, BO_LOCKPTR(bo)) != 0) {
 				BO_LOCK(bo);
 				bp->b_vflags &= ~BV_SCANNED;
 				goto next_locked;