git: a332ba32d4a2 - main - getblk: fail faster with GB_LOCK_NOWAIT

From: Ryan Libby <rlibby_at_FreeBSD.org>
Date: Tue, 21 May 2024 18:16:47 UTC
The branch main has been updated by rlibby:

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

commit a332ba32d4a26e20c959db14afa11ccfa25cf76c
Author:     Ryan Libby <rlibby@FreeBSD.org>
AuthorDate: 2024-05-21 17:21:50 +0000
Commit:     Ryan Libby <rlibby@FreeBSD.org>
CommitDate: 2024-05-21 17:21:50 +0000

    getblk: fail faster with GB_LOCK_NOWAIT
    
    If we asked not to wait on a lock, and then we failed to get a buf lock
    because we would have had to wait, then just return the error.  This
    avoids taking the bufobj lock and a second trip to lockmgr.
    
    Reviewed by:    mckusick, kib, markj
    Sponsored by:   Dell EMC Isilon
    Differential Revision:  https://reviews.freebsd.org/D45245
---
 sys/kern/vfs_bio.c | 21 ++++++++++++++++++++-
 1 file changed, 20 insertions(+), 1 deletion(-)

diff --git a/sys/kern/vfs_bio.c b/sys/kern/vfs_bio.c
index b5466fb2cd53..01057072d991 100644
--- a/sys/kern/vfs_bio.c
+++ b/sys/kern/vfs_bio.c
@@ -4010,8 +4010,23 @@ getblkx(struct vnode *vp, daddr_t blkno, daddr_t dblkno, int size, int slpflag,
 
 	error = BUF_TIMELOCK(bp, LK_EXCLUSIVE | LK_NOWAIT, NULL, "getblku", 0,
 	    0);
-	if (error != 0)
+	if (error != 0) {
+		KASSERT(error == EBUSY,
+		    ("getblk: unexpected error %d from buf try-lock", error));
+		/*
+		 * We failed a buf try-lock.
+		 *
+		 * With GB_LOCK_NOWAIT, just return, rather than taking the
+		 * bufobj interlock and trying again, since we would probably
+		 * fail again anyway.  This is okay even if the buf's identity
+		 * changed and we contended on the wrong lock, as changing
+		 * identity itself requires the buf lock, and we could have
+		 * contended on the right lock.
+		 */
+		if ((flags & GB_LOCK_NOWAIT) != 0)
+			return (error);
 		goto loop;
+	}
 
 	/* Verify buf identify has not changed since lookup. */
 	if (bp->b_bufobj == bo && bp->b_lblkno == blkno)
@@ -4020,6 +4035,10 @@ getblkx(struct vnode *vp, daddr_t blkno, daddr_t dblkno, int size, int slpflag,
 	/* It changed, fallback to locked lookup. */
 	BUF_UNLOCK_RAW(bp);
 
+	/* As above, with GB_LOCK_NOWAIT, just return. */
+	if ((flags & GB_LOCK_NOWAIT) != 0)
+		return (EBUSY);
+
 loop:
 	BO_RLOCK(bo);
 	bp = gbincore(bo, blkno);