- 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.
This commit is contained in:
Jeff Roberson 2005-01-28 17:48:58 +00:00
parent 0479aa4bad
commit bd8d684fd7
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=140946

View file

@ -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);
}