git: 2c8caa4b3925 - main - vfs_subr: optimize inval_buf_range
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Mon, 14 Oct 2024 17:12:21 UTC
The branch main has been updated by dougm:
URL: https://cgit.FreeBSD.org/src/commit/?id=2c8caa4b3925aa73350d687cd13876c275f35889
commit 2c8caa4b3925aa73350d687cd13876c275f35889
Author: Doug Moore <dougm@FreeBSD.org>
AuthorDate: 2024-10-14 17:07:59 +0000
Commit: Doug Moore <dougm@FreeBSD.org>
CommitDate: 2024-10-14 17:07:59 +0000
vfs_subr: optimize inval_buf_range
Use a pctrie_lookup to avoid walking over low out-of-range buf list
entries, and an early break to avoid the high out-of-range
entries. Avoid writing almost identical loops for the dirty and clean
lists.
Because pctries are built for unsigned keys, and these are signed
values, handle the wraparound problem the same way that bnoreuselist()
does.
Reviewed by: kib
Tested by: pho
Differential Revision: https://reviews.freebsd.org/D46963
---
sys/kern/vfs_subr.c | 50 ++++++++++++++++++--------------------------------
1 file changed, 18 insertions(+), 32 deletions(-)
diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c
index f192c6798858..ff18c50546dd 100644
--- a/sys/kern/vfs_subr.c
+++ b/sys/kern/vfs_subr.c
@@ -2616,17 +2616,25 @@ static int
v_inval_buf_range_locked(struct vnode *vp, struct bufobj *bo,
daddr_t startlbn, daddr_t endlbn)
{
+ struct bufv *bv;
struct buf *bp, *nbp;
- bool anyfreed;
+ uint8_t anyfreed;
+ bool clean;
ASSERT_VOP_LOCKED(vp, "v_inval_buf_range_locked");
ASSERT_BO_LOCKED(bo);
+ anyfreed = 1;
+ clean = true;
do {
- anyfreed = false;
- TAILQ_FOREACH_SAFE(bp, &bo->bo_clean.bv_hd, b_bobufs, nbp) {
- if (bp->b_lblkno < startlbn || bp->b_lblkno >= endlbn)
- continue;
+ bv = clean ? &bo->bo_clean : &bo->bo_dirty;
+ bp = BUF_PCTRIE_LOOKUP_GE(&bv->bv_root, startlbn);
+ if (bp == NULL || bp->b_lblkno >= endlbn ||
+ bp->b_lblkno < startlbn)
+ continue;
+ TAILQ_FOREACH_FROM_SAFE(bp, &bv->bv_hd, b_bobufs, nbp) {
+ if (bp->b_lblkno >= endlbn)
+ break;
if (BUF_LOCK(bp,
LK_EXCLUSIVE | LK_SLEEPFAIL | LK_INTERLOCK,
BO_LOCKPTR(bo)) == ENOLCK) {
@@ -2638,39 +2646,17 @@ v_inval_buf_range_locked(struct vnode *vp, struct bufobj *bo,
bp->b_flags |= B_INVAL | B_RELBUF;
bp->b_flags &= ~B_ASYNC;
brelse(bp);
- anyfreed = true;
+ anyfreed = 2;
BO_LOCK(bo);
if (nbp != NULL &&
- (((nbp->b_xflags & BX_VNCLEAN) == 0) ||
+ (((nbp->b_xflags &
+ (clean ? BX_VNCLEAN : BX_VNDIRTY)) == 0) ||
nbp->b_vp != vp ||
- (nbp->b_flags & B_DELWRI) != 0))
- return (EAGAIN);
- }
-
- TAILQ_FOREACH_SAFE(bp, &bo->bo_dirty.bv_hd, b_bobufs, nbp) {
- if (bp->b_lblkno < startlbn || bp->b_lblkno >= endlbn)
- continue;
- if (BUF_LOCK(bp,
- LK_EXCLUSIVE | LK_SLEEPFAIL | LK_INTERLOCK,
- BO_LOCKPTR(bo)) == ENOLCK) {
- BO_LOCK(bo);
- return (EAGAIN);
- }
- bremfree(bp);
- bp->b_flags |= B_INVAL | B_RELBUF;
- bp->b_flags &= ~B_ASYNC;
- brelse(bp);
- anyfreed = true;
-
- BO_LOCK(bo);
- if (nbp != NULL &&
- (((nbp->b_xflags & BX_VNDIRTY) == 0) ||
- (nbp->b_vp != vp) ||
- (nbp->b_flags & B_DELWRI) == 0))
+ (nbp->b_flags & B_DELWRI) == (clean? B_DELWRI: 0)))
return (EAGAIN);
}
- } while (anyfreed);
+ } while (clean = !clean, anyfreed-- > 0);
return (0);
}