From 3833976d1250bf118a46939f409012d87e558de6 Mon Sep 17 00:00:00 2001 From: phk Date: Thu, 21 Oct 2004 15:53:54 +0000 Subject: [PATCH] Move the VI_BWAIT flag into no bo_flag element of bufobj and call it BO_WWAIT Add bufobj_wref(), bufobj_wdrop() and bufobj_wwait() to handle the write count on a bufobj. Bufobj_wdrop() replaces vwakeup(). Use these functions all relevant places except in ffs_softdep.c where the use if interlocked_sleep() makes this impossible. Rename b_vnbufs to b_bobufs now that we touch all the relevant files anyway. --- sys/kern/vfs_bio.c | 74 +++++++++++++++++++++++++++++++---- sys/kern/vfs_cluster.c | 4 +- sys/kern/vfs_default.c | 16 ++++---- sys/kern/vfs_subr.c | 77 +++++++++++-------------------------- sys/nfs4client/nfs4_vnops.c | 24 +++++------- sys/nfsclient/nfs_subs.c | 2 +- sys/nfsclient/nfs_vnops.c | 24 +++++------- sys/sys/buf.h | 3 +- sys/sys/bufobj.h | 7 ++++ sys/sys/vnode.h | 1 - sys/ufs/ffs/ffs_rawread.c | 7 +--- sys/ufs/ffs/ffs_softdep.c | 13 ++++--- sys/ufs/ffs/ffs_vnops.c | 10 ++--- sys/vm/swap_pager.c | 15 ++------ 14 files changed, 138 insertions(+), 139 deletions(-) diff --git a/sys/kern/vfs_bio.c b/sys/kern/vfs_bio.c index 5d4f170f2b1..170cffb0572 100644 --- a/sys/kern/vfs_bio.c +++ b/sys/kern/vfs_bio.c @@ -880,9 +880,7 @@ ibwrite(struct buf *bp) bp->b_flags |= B_CACHE; bp->b_iocmd = BIO_WRITE; - VI_LOCK(bp->b_vp); - bp->b_vp->v_numoutput++; - VI_UNLOCK(bp->b_vp); + bufobj_wref(&bp->b_vp->v_bufobj); vfs_busy_pages(bp, 1); /* @@ -965,7 +963,7 @@ vfs_backgroundwritedone(struct buf *bp) /* * This buffer is marked B_NOCACHE, so when it is released * by biodone, it will be tossed. We mark it with BIO_READ - * to avoid biodone doing a second vwakeup. + * to avoid biodone doing a second bufobj_wakeup. */ bp->b_flags |= B_NOCACHE; bp->b_iocmd = BIO_READ; @@ -1020,7 +1018,7 @@ bdwrite(struct buf *bp) /* * Try to find a buffer to flush. */ - TAILQ_FOREACH(nbp, &vp->v_dirtyblkhd, b_vnbufs) { + TAILQ_FOREACH(nbp, &vp->v_dirtyblkhd, b_bobufs) { if ((nbp->b_vflags & BV_BKGRDINPROG) || buf_countdeps(nbp, 0) || BUF_LOCK(nbp, LK_EXCLUSIVE | LK_NOWAIT, NULL)) @@ -3155,9 +3153,8 @@ bufdone(struct buf *bp) bp->b_flags |= B_DONE; runningbufwakeup(bp); - if (bp->b_iocmd == BIO_WRITE) { - vwakeup(bp); - } + if (bp->b_iocmd == BIO_WRITE && bp->b_vp != NULL) + bufobj_wdrop(&bp->b_vp->v_bufobj); /* call optional completion function if requested */ if (bp->b_iodone != NULL) { @@ -3795,6 +3792,67 @@ bwait(struct buf *bp, u_char pri, const char *wchan) mtx_unlock(&bdonelock); } +#if 0 /* this is here to unconfuse p4 diff */ + +void +bufstrategy(struct bufobj *bo, struct buf *bp) +{ + int i = 0; + struct vnode *vp; + + vp = bp->b_vp; + KASSERT(vp == bo->bo_vnode, ("Inconsistent vnode bufstrategy")); + KASSERT(vp->v_type != VCHR && vp->v_type != VBLK, + ("Wrong vnode in bufstrategy(bp=%p, vp=%p)", bp, vp)); + i = VOP_STRATEGY(vp, bp); + KASSERT(i == 0, ("VOP_STRATEGY failed bp=%p vp=%p", bp, bp->b_vp)); +} + +#endif + +void +bufobj_wref(struct bufobj *bo) +{ + + KASSERT(bo != NULL, ("NULL bo in bufobj_wref")); + BO_LOCK(bo); + bo->bo_numoutput++; + BO_UNLOCK(bo); +} + +void +bufobj_wdrop(struct bufobj *bo) +{ + + KASSERT(bo != NULL, ("NULL bo in bufobj_wdrop")); + BO_LOCK(bo); + KASSERT(bo->bo_numoutput > 0, ("bufobj_wdrop non-positive count")); + if ((--bo->bo_numoutput == 0) && (bo->bo_flag & BO_WWAIT)) { + bo->bo_flag &= ~BO_WWAIT; + wakeup(&bo->bo_numoutput); + } + BO_UNLOCK(bo); +} + +int +bufobj_wwait(struct bufobj *bo, int slpflag, int timeo) +{ + int error; + + KASSERT(bo != NULL, ("NULL bo in bufobj_wwait")); + ASSERT_BO_LOCKED(bo); + error = 0; + while (bo->bo_numoutput) { + bo->bo_flag |= BO_WWAIT; + error = msleep(&bo->bo_numoutput, BO_MTX(bo), + slpflag | (PRIBIO + 1), "bo_wwait", timeo); + if (error) + break; + } + return (error); +} + + #include "opt_ddb.h" #ifdef DDB #include diff --git a/sys/kern/vfs_cluster.c b/sys/kern/vfs_cluster.c index 3eadf00acc3..2372c1e8596 100644 --- a/sys/kern/vfs_cluster.c +++ b/sys/kern/vfs_cluster.c @@ -965,9 +965,7 @@ cluster_wbuild(vp, size, start_lbn, len) tbp->b_flags |= B_ASYNC; tbp->b_iocmd = BIO_WRITE; reassignbuf(tbp); /* put on clean list */ - VI_LOCK(tbp->b_vp); - ++tbp->b_vp->v_numoutput; - VI_UNLOCK(tbp->b_vp); + bufobj_wref(&tbp->b_vp->v_bufobj); splx(s); BUF_KERNPROC(tbp); TAILQ_INSERT_TAIL(&bp->b_cluster.cluster_head, diff --git a/sys/kern/vfs_default.c b/sys/kern/vfs_default.c index 08f2953130d..72e03bf3399 100644 --- a/sys/kern/vfs_default.c +++ b/sys/kern/vfs_default.c @@ -539,6 +539,7 @@ vop_stdfsync(ap) { struct vnode *vp = ap->a_vp; struct buf *bp; + struct bufobj *bo; struct buf *nbp; int s, error = 0; int maxretry = 100; /* large, arbitrarily chosen */ @@ -549,7 +550,7 @@ vop_stdfsync(ap) * MARK/SCAN initialization to avoid infinite loops. */ s = splbio(); - TAILQ_FOREACH(bp, &vp->v_dirtyblkhd, b_vnbufs) { + TAILQ_FOREACH(bp, &vp->v_dirtyblkhd, b_bobufs) { bp->b_vflags &= ~BV_SCANNED; bp->b_error = 0; } @@ -561,7 +562,7 @@ vop_stdfsync(ap) loop2: s = splbio(); for (bp = TAILQ_FIRST(&vp->v_dirtyblkhd); bp != NULL; bp = nbp) { - nbp = TAILQ_NEXT(bp, b_vnbufs); + nbp = TAILQ_NEXT(bp, b_bobufs); if ((bp->b_vflags & BV_SCANNED) != 0) continue; bp->b_vflags |= BV_SCANNED; @@ -589,18 +590,15 @@ vop_stdfsync(ap) * retry if dirty blocks still exist. */ if (ap->a_waitfor == MNT_WAIT) { - while (vp->v_numoutput) { - vp->v_iflag |= VI_BWAIT; - msleep((caddr_t)&vp->v_numoutput, VI_MTX(vp), - PRIBIO + 1, "fsync", 0); - } - if (!TAILQ_EMPTY(&vp->v_dirtyblkhd)) { + bo = &vp->v_bufobj; + bufobj_wwait(bo, 0, 0); + if (bo->bo_dirty.bv_cnt > 0) { /* * If we are unable to write any of these buffers * then we fail now rather than trying endlessly * to write them out. */ - TAILQ_FOREACH(bp, &vp->v_dirtyblkhd, b_vnbufs) + TAILQ_FOREACH(bp, &bo->bo_dirty.bv_hd, b_bobufs) if ((error = bp->b_error) == 0) continue; if (error == 0 && --maxretry >= 0) { diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c index 04b483420ba..910c318d09b 100644 --- a/sys/kern/vfs_subr.c +++ b/sys/kern/vfs_subr.c @@ -903,28 +903,6 @@ insmntque(struct vnode *vp, struct mount *mp) MNT_IUNLOCK(vp->v_mount); } -/* - * Update outstanding I/O count and do wakeup if requested. - */ -void -vwakeup(bp) - register struct buf *bp; -{ - register struct vnode *vp; - - if ((vp = bp->b_vp)) { - VI_LOCK(vp); - vp->v_numoutput--; - if (vp->v_numoutput < 0) - panic("vwakeup: neg numoutput"); - if ((vp->v_numoutput == 0) && (vp->v_iflag & VI_BWAIT)) { - vp->v_iflag &= ~VI_BWAIT; - wakeup(&vp->v_numoutput); - } - VI_UNLOCK(vp); - } -} - /* * Flush out and invalidate all buffers associated with a vnode. * Called with the underlying object locked. @@ -940,23 +918,21 @@ vinvalbuf(vp, flags, cred, td, slpflag, slptimeo) struct buf *blist; int error; vm_object_t object; + struct bufobj *bo; GIANT_REQUIRED; ASSERT_VOP_LOCKED(vp, "vinvalbuf"); VI_LOCK(vp); + bo = &vp->v_bufobj; if (flags & V_SAVE) { - while (vp->v_numoutput) { - vp->v_iflag |= VI_BWAIT; - error = msleep(&vp->v_numoutput, VI_MTX(vp), - slpflag | (PRIBIO + 1), "vinvlbuf", slptimeo); - if (error) { - VI_UNLOCK(vp); - return (error); - } + error = bufobj_wwait(bo, slpflag, slptimeo); + if (error) { + VI_UNLOCK(vp); + return (error); } - if (!TAILQ_EMPTY(&vp->v_dirtyblkhd)) { + if (bo->bo_dirty.bv_cnt > 0) { VI_UNLOCK(vp); if ((error = VOP_FSYNC(vp, cred, MNT_WAIT, td)) != 0) return (error); @@ -965,8 +941,7 @@ vinvalbuf(vp, flags, cred, td, slpflag, slptimeo) * enabled under INVARIANTS */ VI_LOCK(vp); - if (vp->v_numoutput > 0 || - !TAILQ_EMPTY(&vp->v_dirtyblkhd)) + if (bo->bo_numoutput > 0 || bo->bo_dirty.bv_cnt > 0) panic("vinvalbuf: dirty bufs"); } } @@ -1001,10 +976,7 @@ vinvalbuf(vp, flags, cred, td, slpflag, slptimeo) * VM object can also have read-I/O in-progress. */ do { - while (vp->v_numoutput > 0) { - vp->v_iflag |= VI_BWAIT; - msleep(&vp->v_numoutput, VI_MTX(vp), PVM, "vnvlbv", 0); - } + bufobj_wwait(bo, 0, 0); VI_UNLOCK(vp); if (VOP_GETVOBJECT(vp, &object) == 0) { VM_OBJECT_LOCK(object); @@ -1054,7 +1026,7 @@ flushbuflist(blist, flags, vp, slpflag, slptimeo, errorp) ASSERT_VI_LOCKED(vp, "flushbuflist"); for (found = 0, bp = blist; bp; bp = nbp) { - nbp = TAILQ_NEXT(bp, b_vnbufs); + nbp = TAILQ_NEXT(bp, b_bobufs); if (((flags & V_NORMAL) && (bp->b_xflags & BX_ALTDATA)) || ((flags & V_ALT) && (bp->b_xflags & BX_ALTDATA) == 0)) { continue; @@ -1130,7 +1102,7 @@ vtruncbuf(struct vnode *vp, struct ucred *cred, struct thread *td, off_t length, anyfreed = 1; for (;anyfreed;) { anyfreed = 0; - TAILQ_FOREACH_SAFE(bp, &bo->bo_clean.bv_hd, b_vnbufs, nbp) { + TAILQ_FOREACH_SAFE(bp, &bo->bo_clean.bv_hd, b_bobufs, nbp) { if (bp->b_lblkno < trunclbn) continue; if (BUF_LOCK(bp, @@ -1153,7 +1125,7 @@ vtruncbuf(struct vnode *vp, struct ucred *cred, struct thread *td, off_t length, VI_LOCK(vp); } - TAILQ_FOREACH_SAFE(bp, &bo->bo_dirty.bv_hd, b_vnbufs, nbp) { + TAILQ_FOREACH_SAFE(bp, &bo->bo_dirty.bv_hd, b_bobufs, nbp) { if (bp->b_lblkno < trunclbn) continue; if (BUF_LOCK(bp, @@ -1177,7 +1149,7 @@ vtruncbuf(struct vnode *vp, struct ucred *cred, struct thread *td, off_t length, if (length > 0) { restartsync: - TAILQ_FOREACH_SAFE(bp, &bo->bo_dirty.bv_hd, b_vnbufs, nbp) { + TAILQ_FOREACH_SAFE(bp, &bo->bo_dirty.bv_hd, b_bobufs, nbp) { if (bp->b_lblkno > 0) continue; /* @@ -1199,10 +1171,7 @@ vtruncbuf(struct vnode *vp, struct ucred *cred, struct thread *td, off_t length, } } - while (vp->v_numoutput > 0) { - vp->v_iflag |= VI_BWAIT; - msleep(&vp->v_numoutput, VI_MTX(vp), PVM, "vbtrunc", 0); - } + bufobj_wwait(bo, 0, 0); VI_UNLOCK(vp); vnode_pager_setsize(vp, length); @@ -1302,7 +1271,7 @@ buf_vlist_remove(struct buf *bp) root->b_right = bp->b_right; } bv->bv_root = root; - TAILQ_REMOVE(&bv->bv_hd, bp, b_vnbufs); + TAILQ_REMOVE(&bv->bv_hd, bp, b_bobufs); bv->bv_cnt--; bp->b_xflags &= ~(BX_VNDIRTY | BX_VNCLEAN); } @@ -1326,20 +1295,20 @@ buf_vlist_add(struct buf *bp, struct vnode *vp, b_xflags_t xflags) if (root == NULL) { bp->b_left = NULL; bp->b_right = NULL; - TAILQ_INSERT_TAIL(&vp->v_dirtyblkhd, bp, b_vnbufs); + TAILQ_INSERT_TAIL(&vp->v_dirtyblkhd, bp, b_bobufs); } else if (bp->b_lblkno < root->b_lblkno || (bp->b_lblkno == root->b_lblkno && (bp->b_xflags & BX_BKGRDMARKER) < (root->b_xflags & BX_BKGRDMARKER))) { bp->b_left = root->b_left; bp->b_right = root; root->b_left = NULL; - TAILQ_INSERT_BEFORE(root, bp, b_vnbufs); + TAILQ_INSERT_BEFORE(root, bp, b_bobufs); } else { bp->b_right = root->b_right; bp->b_left = root; root->b_right = NULL; TAILQ_INSERT_AFTER(&vp->v_dirtyblkhd, - root, bp, b_vnbufs); + root, bp, b_bobufs); } vp->v_dirtybufcnt++; vp->v_dirtyblkroot = bp; @@ -1349,20 +1318,20 @@ buf_vlist_add(struct buf *bp, struct vnode *vp, b_xflags_t xflags) if (root == NULL) { bp->b_left = NULL; bp->b_right = NULL; - TAILQ_INSERT_TAIL(&vp->v_cleanblkhd, bp, b_vnbufs); + TAILQ_INSERT_TAIL(&vp->v_cleanblkhd, bp, b_bobufs); } else if (bp->b_lblkno < root->b_lblkno || (bp->b_lblkno == root->b_lblkno && (bp->b_xflags & BX_BKGRDMARKER) < (root->b_xflags & BX_BKGRDMARKER))) { bp->b_left = root->b_left; bp->b_right = root; root->b_left = NULL; - TAILQ_INSERT_BEFORE(root, bp, b_vnbufs); + TAILQ_INSERT_BEFORE(root, bp, b_bobufs); } else { bp->b_right = root->b_right; bp->b_left = root; root->b_right = NULL; TAILQ_INSERT_AFTER(&vp->v_cleanblkhd, - root, bp, b_vnbufs); + root, bp, b_bobufs); } vp->v_cleanbufcnt++; vp->v_cleanblkroot = bp; @@ -1760,7 +1729,7 @@ pbrelvp(bp) /* XXX REMOVE ME */ VI_LOCK(bp->b_vp); - if (TAILQ_NEXT(bp, b_vnbufs) != NULL) { + if (TAILQ_NEXT(bp, b_bobufs) != NULL) { panic( "relpbuf(): b_vp was probably reassignbuf()d %p %x", bp, @@ -2790,8 +2759,6 @@ vprint(label, vp) strcat(buf, "|VI_XLOCK"); if (vp->v_iflag & VI_XWANT) strcat(buf, "|VI_XWANT"); - if (vp->v_iflag & VI_BWAIT) - strcat(buf, "|VI_BWAIT"); if (vp->v_iflag & VI_DOOMED) strcat(buf, "|VI_DOOMED"); if (vp->v_iflag & VI_FREE) diff --git a/sys/nfs4client/nfs4_vnops.c b/sys/nfs4client/nfs4_vnops.c index 937db83e334..33dde9d1c73 100644 --- a/sys/nfs4client/nfs4_vnops.c +++ b/sys/nfs4client/nfs4_vnops.c @@ -2642,7 +2642,7 @@ nfs4_flush(struct vnode *vp, struct ucred *cred, int waitfor, struct thread *td, bveccount = 0; VI_LOCK(vp); for (bp = TAILQ_FIRST(&vp->v_dirtyblkhd); bp; bp = nbp) { - nbp = TAILQ_NEXT(bp, b_vnbufs); + nbp = TAILQ_NEXT(bp, b_bobufs); if (BUF_REFCNT(bp) == 0 && (bp->b_flags & (B_DELWRI | B_NEEDCOMMIT)) == (B_DELWRI | B_NEEDCOMMIT)) @@ -2677,13 +2677,13 @@ nfs4_flush(struct vnode *vp, struct ucred *cred, int waitfor, struct thread *td, if (bvecpos >= bvecsize) break; if (BUF_LOCK(bp, LK_EXCLUSIVE | LK_NOWAIT, NULL)) { - nbp = TAILQ_NEXT(bp, b_vnbufs); + nbp = TAILQ_NEXT(bp, b_bobufs); continue; } if ((bp->b_flags & (B_DELWRI | B_NEEDCOMMIT)) != (B_DELWRI | B_NEEDCOMMIT)) { BUF_UNLOCK(bp); - nbp = TAILQ_NEXT(bp, b_vnbufs); + nbp = TAILQ_NEXT(bp, b_bobufs); continue; } VI_UNLOCK(vp); @@ -2711,7 +2711,7 @@ nfs4_flush(struct vnode *vp, struct ucred *cred, int waitfor, struct thread *td, * and vfs_busy_pages() may sleep. We have to * recalculate nbp. */ - nbp = TAILQ_NEXT(bp, b_vnbufs); + nbp = TAILQ_NEXT(bp, b_bobufs); /* * A list of these buffers is kept so that the @@ -2783,9 +2783,7 @@ nfs4_flush(struct vnode *vp, struct ucred *cred, int waitfor, struct thread *td, * into bundirty(). XXX */ s = splbio(); - VI_LOCK(vp); - vp->v_numoutput++; - VI_UNLOCK(vp); + bufobj_wref(&vp->v_bufobj); bp->b_flags |= B_ASYNC; bundirty(bp); bp->b_flags &= ~B_DONE; @@ -2804,7 +2802,7 @@ nfs4_flush(struct vnode *vp, struct ucred *cred, int waitfor, struct thread *td, s = splbio(); VI_LOCK(vp); for (bp = TAILQ_FIRST(&vp->v_dirtyblkhd); bp; bp = nbp) { - nbp = TAILQ_NEXT(bp, b_vnbufs); + nbp = TAILQ_NEXT(bp, b_bobufs); if (BUF_LOCK(bp, LK_EXCLUSIVE | LK_NOWAIT, NULL)) { if (waitfor != MNT_WAIT || passone) continue; @@ -2850,10 +2848,8 @@ nfs4_flush(struct vnode *vp, struct ucred *cred, int waitfor, struct thread *td, goto again; } if (waitfor == MNT_WAIT) { - while (vp->v_numoutput) { - vp->v_iflag |= VI_BWAIT; - error = msleep((caddr_t)&vp->v_numoutput, VI_MTX(vp), - slpflag | (PRIBIO + 1), "nfsfsync", slptimeo); + while (vp->v_bufobj.bo_numoutput) { + error = bufobj_wwait(&vp->v_bufobj, slpflag, slptimeo); if (error) { VI_UNLOCK(vp); if (nfs4_sigintr(nmp, NULL, td)) { @@ -2950,9 +2946,7 @@ nfs4_writebp(struct buf *bp, int force __unused, struct thread *td) bp->b_ioflags &= ~BIO_ERROR; bp->b_iocmd = BIO_WRITE; - VI_LOCK(bp->b_vp); - bp->b_vp->v_numoutput++; - VI_UNLOCK(bp->b_vp); + bufobj_wref(&bp->b_vp->v_bufobj); curthread->td_proc->p_stats->p_ru.ru_oublock++; splx(s); diff --git a/sys/nfsclient/nfs_subs.c b/sys/nfsclient/nfs_subs.c index a325c82cc1e..f9869c2728f 100644 --- a/sys/nfsclient/nfs_subs.c +++ b/sys/nfsclient/nfs_subs.c @@ -814,7 +814,7 @@ nfs_clearcommit(struct mount *mp) } MNT_IUNLOCK(mp); for (bp = TAILQ_FIRST(&vp->v_dirtyblkhd); bp; bp = nbp) { - nbp = TAILQ_NEXT(bp, b_vnbufs); + nbp = TAILQ_NEXT(bp, b_bobufs); if (BUF_REFCNT(bp) == 0 && (bp->b_flags & (B_DELWRI | B_NEEDCOMMIT)) == (B_DELWRI | B_NEEDCOMMIT)) diff --git a/sys/nfsclient/nfs_vnops.c b/sys/nfsclient/nfs_vnops.c index 8fbdb51a5e8..efc2e61be0d 100644 --- a/sys/nfsclient/nfs_vnops.c +++ b/sys/nfsclient/nfs_vnops.c @@ -2619,7 +2619,7 @@ nfs_flush(struct vnode *vp, struct ucred *cred, int waitfor, struct thread *td, bveccount = 0; VI_LOCK(vp); for (bp = TAILQ_FIRST(&vp->v_dirtyblkhd); bp; bp = nbp) { - nbp = TAILQ_NEXT(bp, b_vnbufs); + nbp = TAILQ_NEXT(bp, b_bobufs); if (BUF_REFCNT(bp) == 0 && (bp->b_flags & (B_DELWRI | B_NEEDCOMMIT)) == (B_DELWRI | B_NEEDCOMMIT)) @@ -2654,13 +2654,13 @@ nfs_flush(struct vnode *vp, struct ucred *cred, int waitfor, struct thread *td, if (bvecpos >= bvecsize) break; if (BUF_LOCK(bp, LK_EXCLUSIVE | LK_NOWAIT, NULL)) { - nbp = TAILQ_NEXT(bp, b_vnbufs); + nbp = TAILQ_NEXT(bp, b_bobufs); continue; } if ((bp->b_flags & (B_DELWRI | B_NEEDCOMMIT)) != (B_DELWRI | B_NEEDCOMMIT)) { BUF_UNLOCK(bp); - nbp = TAILQ_NEXT(bp, b_vnbufs); + nbp = TAILQ_NEXT(bp, b_bobufs); continue; } VI_UNLOCK(vp); @@ -2688,7 +2688,7 @@ nfs_flush(struct vnode *vp, struct ucred *cred, int waitfor, struct thread *td, * and vfs_busy_pages() may sleep. We have to * recalculate nbp. */ - nbp = TAILQ_NEXT(bp, b_vnbufs); + nbp = TAILQ_NEXT(bp, b_bobufs); /* * A list of these buffers is kept so that the @@ -2760,9 +2760,7 @@ nfs_flush(struct vnode *vp, struct ucred *cred, int waitfor, struct thread *td, * into bundirty(). XXX */ s = splbio(); - VI_LOCK(vp); - vp->v_numoutput++; - VI_UNLOCK(vp); + bufobj_wref(&vp->v_bufobj); bp->b_flags |= B_ASYNC; bundirty(bp); bp->b_flags &= ~B_DONE; @@ -2781,7 +2779,7 @@ nfs_flush(struct vnode *vp, struct ucred *cred, int waitfor, struct thread *td, s = splbio(); VI_LOCK(vp); for (bp = TAILQ_FIRST(&vp->v_dirtyblkhd); bp; bp = nbp) { - nbp = TAILQ_NEXT(bp, b_vnbufs); + nbp = TAILQ_NEXT(bp, b_bobufs); if (BUF_LOCK(bp, LK_EXCLUSIVE | LK_NOWAIT, NULL)) { if (waitfor != MNT_WAIT || passone) continue; @@ -2826,10 +2824,8 @@ nfs_flush(struct vnode *vp, struct ucred *cred, int waitfor, struct thread *td, goto again; } if (waitfor == MNT_WAIT) { - while (vp->v_numoutput) { - vp->v_iflag |= VI_BWAIT; - error = msleep((caddr_t)&vp->v_numoutput, VI_MTX(vp), - slpflag | (PRIBIO + 1), "nfsfsync", slptimeo); + while (vp->v_bufobj.bo_numoutput) { + error = bufobj_wwait(&vp->v_bufobj, slpflag, slptimeo); if (error) { VI_UNLOCK(vp); error = nfs_sigintr(nmp, NULL, td); @@ -2924,9 +2920,7 @@ nfs_writebp(struct buf *bp, int force __unused, struct thread *td) bp->b_ioflags &= ~BIO_ERROR; bp->b_iocmd = BIO_WRITE; - VI_LOCK(bp->b_vp); - bp->b_vp->v_numoutput++; - VI_UNLOCK(bp->b_vp); + bufobj_wref(&bp->b_vp->v_bufobj); curthread->td_proc->p_stats->p_ru.ru_oublock++; splx(s); diff --git a/sys/sys/buf.h b/sys/sys/buf.h index c88f6f58d5b..bd8bc6c15fb 100644 --- a/sys/sys/buf.h +++ b/sys/sys/buf.h @@ -116,7 +116,7 @@ struct buf { void (*b_iodone)(struct buf *); daddr_t b_blkno; /* Underlying physical block number. */ off_t b_offset; /* Offset into file. */ - TAILQ_ENTRY(buf) b_vnbufs; /* (V) Buffer's associated vnode. */ + TAILQ_ENTRY(buf) b_bobufs; /* (V) Buffer's associated vnode. */ struct buf *b_left; /* (V) splay tree link */ struct buf *b_right; /* (V) splay tree link */ uint32_t b_vflags; /* (V) BV_* flags */ @@ -512,7 +512,6 @@ void vfs_bio_set_validclean(struct buf *, int base, int size); void vfs_bio_clrbuf(struct buf *); void vfs_busy_pages(struct buf *, int clear_modify); void vfs_unbusy_pages(struct buf *); -void vwakeup(struct buf *); int vmapbuf(struct buf *); void vunmapbuf(struct buf *); void relpbuf(struct buf *, int *); diff --git a/sys/sys/bufobj.h b/sys/sys/bufobj.h index 62ac91f5f1d..1fd61ef28d7 100644 --- a/sys/sys/bufobj.h +++ b/sys/sys/bufobj.h @@ -67,8 +67,11 @@ struct bufobj { struct bufv bo_clean; /* i Clean buffers */ struct bufv bo_dirty; /* i Dirty buffers */ long bo_numoutput; /* i Writes in progress */ + u_int bo_flag; /* i Flags */ }; +#define BO_WWAIT (1 << 1) /* Wait for output to complete */ + #define BO_LOCK(bo) \ do { \ KASSERT (bo->bo_mtx != NULL, ("No lock in bufobj")); \ @@ -85,6 +88,10 @@ struct bufobj { #define ASSERT_BO_LOCKED(bo) mtx_assert(bo->bo_mtx, MA_OWNED) #define ASSERT_BO_UNLOCKED(bo) mtx_assert(bo->bo_mtx, MA_NOTOWNED) +void bufobj_wdrop(struct bufobj *bo); +void bufobj_wref(struct bufobj *bo); +int bufobj_wwait(struct bufobj *bo, int slpflag, int timeo); + #endif /* defined(_KERNEL) || defined(_KVM_VNODE) */ #endif /* _SYS_BUFOBJ_H_ */ diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h index 66b370659fe..5f0dd38be02 100644 --- a/sys/sys/vnode.h +++ b/sys/sys/vnode.h @@ -224,7 +224,6 @@ struct xvnode { */ #define VI_XLOCK 0x0001 /* vnode is locked to change vtype */ #define VI_XWANT 0x0002 /* thread is waiting for vnode */ -#define VI_BWAIT 0x0004 /* waiting for output to complete */ #define VI_OLOCK 0x0008 /* vnode is locked waiting for an object */ #define VI_OWANT 0x0010 /* a thread is waiting for VOLOCK */ #define VI_MOUNT 0x0020 /* Mount in progress */ diff --git a/sys/ufs/ffs/ffs_rawread.c b/sys/ufs/ffs/ffs_rawread.c index fcc6193f8bc..e5cc03ed20d 100644 --- a/sys/ufs/ffs/ffs_rawread.c +++ b/sys/ufs/ffs/ffs_rawread.c @@ -137,12 +137,9 @@ ffs_rawread_sync(struct vnode *vp, struct thread *td) /* Wait for pending writes to complete */ spl = splbio(); while (vp->v_numoutput) { - vp->v_iflag |= VI_BWAIT; - error = msleep((caddr_t)&vp->v_numoutput, - VI_MTX(vp), - PRIBIO + 1, - "rawrdfls", 0); + error = bufobj_wwait(&vp->v_bufobj, 0, 0); if (error != 0) { + /* XXX: can't happen with a zero timeout ??? */ splx(spl); VI_UNLOCK(vp); if (upgraded != 0) diff --git a/sys/ufs/ffs/ffs_softdep.c b/sys/ufs/ffs/ffs_softdep.c index 435e32d3a71..aeaa8677b7a 100644 --- a/sys/ufs/ffs/ffs_softdep.c +++ b/sys/ufs/ffs/ffs_softdep.c @@ -2068,7 +2068,7 @@ softdep_setup_freeblocks(ip, length, flags) VI_LOCK(vp); drain_output(vp, 1); restart: - TAILQ_FOREACH(bp, &vp->v_dirtyblkhd, b_vnbufs) { + TAILQ_FOREACH(bp, &vp->v_dirtyblkhd, b_bobufs) { if (((flags & IO_EXT) == 0 && (bp->b_xflags & BX_ALTDATA)) || ((flags & IO_NORMAL) == 0 && (bp->b_xflags & BX_ALTDATA) == 0)) @@ -4925,7 +4925,7 @@ softdep_fsync_mountdev(vp) ACQUIRE_LOCK(&lk); VI_LOCK(vp); for (bp = TAILQ_FIRST(&vp->v_dirtyblkhd); bp; bp = nbp) { - nbp = TAILQ_NEXT(bp, b_vnbufs); + nbp = TAILQ_NEXT(bp, b_bobufs); /* * If it is already scheduled, skip to the next buffer. */ @@ -5185,7 +5185,7 @@ softdep_sync_metadata(ap) return (error); } VI_LOCK(vp); - nbp = getdirtybuf(&TAILQ_NEXT(bp, b_vnbufs), VI_MTX(vp), MNT_WAIT); + nbp = getdirtybuf(&TAILQ_NEXT(bp, b_bobufs), VI_MTX(vp), MNT_WAIT); if (nbp == NULL) VI_UNLOCK(vp); FREE_LOCK(&lk); @@ -5926,9 +5926,10 @@ drain_output(vp, islocked) if (!islocked) ACQUIRE_LOCK(&lk); - while (vp->v_numoutput) { - vp->v_iflag |= VI_BWAIT; - interlocked_sleep(&lk, SLEEP, (caddr_t)&vp->v_numoutput, + while (vp->v_bufobj.bo_numoutput) { + vp->v_bufobj.bo_flag |= BO_WWAIT; + interlocked_sleep(&lk, SLEEP, + (caddr_t)&vp->v_bufobj.bo_numoutput, VI_MTX(vp), PRIBIO + 1, "drainvp", 0); } if (!islocked) diff --git a/sys/ufs/ffs/ffs_vnops.c b/sys/ufs/ffs/ffs_vnops.c index f087e5e31dd..153267424a2 100644 --- a/sys/ufs/ffs/ffs_vnops.c +++ b/sys/ufs/ffs/ffs_vnops.c @@ -197,10 +197,10 @@ ffs_fsync(ap) s = splbio(); VI_LOCK(vp); loop: - TAILQ_FOREACH(bp, &vp->v_dirtyblkhd, b_vnbufs) + TAILQ_FOREACH(bp, &vp->v_dirtyblkhd, b_bobufs) bp->b_vflags &= ~BV_SCANNED; for (bp = TAILQ_FIRST(&vp->v_dirtyblkhd); bp; bp = nbp) { - nbp = TAILQ_NEXT(bp, b_vnbufs); + nbp = TAILQ_NEXT(bp, b_bobufs); /* * Reasons to skip this buffer: it has already been considered * on this pass, this pass is the first time through on a @@ -285,11 +285,7 @@ ffs_fsync(ap) } if (wait) { - while (vp->v_numoutput) { - vp->v_iflag |= VI_BWAIT; - msleep((caddr_t)&vp->v_numoutput, VI_MTX(vp), - PRIBIO + 4, "ffsfsn", 0); - } + bufobj_wwait(&vp->v_bufobj, 3, 0); VI_UNLOCK(vp); /* diff --git a/sys/vm/swap_pager.c b/sys/vm/swap_pager.c index 41992896fb5..22487ddb62c 100644 --- a/sys/vm/swap_pager.c +++ b/sys/vm/swap_pager.c @@ -2545,18 +2545,9 @@ swapdev_strategy(struct buf *bp, struct swdevt *sp) s = splvm(); if (bp->b_iocmd == BIO_WRITE) { vp = bp->b_vp; - if (vp) { - VI_LOCK(vp); - vp->v_numoutput--; - if ((vp->v_iflag & VI_BWAIT) && vp->v_numoutput <= 0) { - vp->v_iflag &= ~VI_BWAIT; - wakeup(&vp->v_numoutput); - } - VI_UNLOCK(vp); - } - VI_LOCK(vp2); - vp2->v_numoutput++; - VI_UNLOCK(vp2); + if (vp) + bufobj_wdrop(&vp->v_bufobj); + bufobj_wref(&vp2->v_bufobj); } bp->b_vp = vp2; splx(s); -- 2.45.2