aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRyan Libby <rlibby@FreeBSD.org>2024-05-21 17:21:50 +0000
committerRyan Libby <rlibby@FreeBSD.org>2024-05-21 17:21:50 +0000
commita332ba32d4a26e20c959db14afa11ccfa25cf76c (patch)
tree5ab32354e72286dee8c3832d7a59072a1cb60c14
parentbd56aad33c2533615f76c17795f0aa70b7686309 (diff)
downloadsrc-a332ba32d4a26e20c959db14afa11ccfa25cf76c.tar.gz
src-a332ba32d4a26e20c959db14afa11ccfa25cf76c.zip
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
-rw-r--r--sys/kern/vfs_bio.c21
1 files changed, 20 insertions, 1 deletions
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);