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
This commit is contained in:
+20
-1
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user