aboutsummaryrefslogtreecommitdiff
path: root/sys/kern/vfs_bio.c
diff options
context:
space:
mode:
authorJeff Roberson <jeff@FreeBSD.org>2005-01-28 17:48:58 +0000
committerJeff Roberson <jeff@FreeBSD.org>2005-01-28 17:48:58 +0000
commitbd8d684fd7ce07258bacb16e01c65fb5b0954a9d (patch)
tree17ce7797ccdf13f98be78a5dc720ed28d35071d9 /sys/kern/vfs_bio.c
parent0479aa4bad01976ed8a5fb20df88be5f89aeb412 (diff)
downloadsrc-bd8d684fd7ce07258bacb16e01c65fb5b0954a9d.tar.gz
src-bd8d684fd7ce07258bacb16e01c65fb5b0954a9d.zip
- Don't drop the wref on the bufobj until after bufdone() has completed.
Without this, threads waiting in bufobj_wwait() may wakeup prior to bufdone() completing. Sponsored by: Isilon Systems, Inc.
Notes
Notes: svn path=/head/; revision=140946
Diffstat (limited to 'sys/kern/vfs_bio.c')
-rw-r--r--sys/kern/vfs_bio.c17
1 files changed, 10 insertions, 7 deletions
diff --git a/sys/kern/vfs_bio.c b/sys/kern/vfs_bio.c
index 1cdb6e57e101..044e7e15c4d2 100644
--- a/sys/kern/vfs_bio.c
+++ b/sys/kern/vfs_bio.c
@@ -3178,21 +3178,21 @@ dev_strategy(struct cdev *dev, struct buf *bp)
void
bufdone(struct buf *bp)
{
+ struct bufobj *dropobj;
int s;
void (*biodone)(struct buf *);
CTR3(KTR_BUF, "bufdone(%p) vp %p flags %X", bp, bp->b_vp, bp->b_flags);
s = splbio();
+ dropobj = NULL;
KASSERT(BUF_REFCNT(bp) > 0, ("biodone: bp %p not busy %d", bp, BUF_REFCNT(bp)));
KASSERT(!(bp->b_flags & B_DONE), ("biodone: bp %p already done", bp));
runningbufwakeup(bp);
-
- if (bp->b_iocmd == BIO_WRITE && bp->b_bufobj != NULL)
- bufobj_wdrop(bp->b_bufobj);
-
+ if (bp->b_iocmd == BIO_WRITE)
+ dropobj = bp->b_bufobj;
/* call optional completion function if requested */
if (bp->b_iodone != NULL) {
biodone = bp->b_iodone;
@@ -3202,9 +3202,11 @@ bufdone(struct buf *bp)
* if we're calling into unknown code.
*/
mtx_lock(&Giant);
- bp->b_flags |= B_DONE; /* XXX Should happen after biodone? */
+ bp->b_flags |= B_DONE;
(*biodone) (bp);
mtx_unlock(&Giant);
+ if (dropobj)
+ bufobj_wdrop(dropobj);
splx(s);
return;
}
@@ -3338,9 +3340,10 @@ bufdone(struct buf *bp)
brelse(bp);
else
bqrelse(bp);
- } else {
+ } else
bdone(bp);
- }
+ if (dropobj)
+ bufobj_wdrop(dropobj);
splx(s);
}