summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/kern/vfs_bio.c74
-rw-r--r--sys/kern/vfs_cluster.c4
-rw-r--r--sys/kern/vfs_default.c16
-rw-r--r--sys/kern/vfs_subr.c77
-rw-r--r--sys/nfs4client/nfs4_vnops.c24
-rw-r--r--sys/nfsclient/nfs_subs.c2
-rw-r--r--sys/nfsclient/nfs_vnops.c24
-rw-r--r--sys/sys/buf.h3
-rw-r--r--sys/sys/bufobj.h7
-rw-r--r--sys/sys/vnode.h1
-rw-r--r--sys/ufs/ffs/ffs_rawread.c7
-rw-r--r--sys/ufs/ffs/ffs_softdep.c13
-rw-r--r--sys/ufs/ffs/ffs_vnops.c10
-rw-r--r--sys/vm/swap_pager.c15
14 files changed, 138 insertions, 139 deletions
diff --git a/sys/kern/vfs_bio.c b/sys/kern/vfs_bio.c
index 5d4f170..170cffb 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 <ddb/ddb.h>
diff --git a/sys/kern/vfs_cluster.c b/sys/kern/vfs_cluster.c
index 3eadf00..2372c1e 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 08f2953..72e03bf 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 @@ loop1:
* 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 @@ loop1:
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 @@ loop2:
* 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 04b4834..910c318 100644
--- a/sys/kern/vfs_subr.c
+++ b/sys/kern/vfs_subr.c
@@ -904,28 +904,6 @@ insmntque(struct vnode *vp, struct mount *mp)
}
/*
- * 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 @@ restart:
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 @@ restart:
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 @@ restart:
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 @@ restartsync:
}
}
- 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 937db83..33dde9d 100644
--- a/sys/nfs4client/nfs4_vnops.c
+++ b/sys/nfs4client/nfs4_vnops.c
@@ -2642,7 +2642,7 @@ again:
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 @@ again:
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 @@ again:
* 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 @@ again:
* 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 @@ loop:
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 @@ loop:
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 a325c82..f9869c2 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 8fbdb51..efc2e61 100644
--- a/sys/nfsclient/nfs_vnops.c
+++ b/sys/nfsclient/nfs_vnops.c
@@ -2619,7 +2619,7 @@ again:
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 @@ again:
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 @@ again:
* 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 @@ again:
* 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 @@ loop:
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 @@ loop:
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 c88f6f5..bd8bc6c 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 62ac91f..1fd61ef 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 66b3706..5f0dd38 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 fcc6193..e5cc03e 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 435e32d..aeaa867 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 @@ loop:
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 f087e5e..1532674 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 @@ loop:
}
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 4199289..22487dd 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);
OpenPOWER on IntegriCloud