From bd8d684fd7ce07258bacb16e01c65fb5b0954a9d Mon Sep 17 00:00:00 2001 From: Jeff Roberson Date: Fri, 28 Jan 2005 17:48:58 +0000 Subject: - 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. --- sys/kern/vfs_bio.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) (limited to 'sys/kern/vfs_bio.c') 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); } -- cgit v1.2.3