Eliminate inconsistency in the setting of the B_DONE flag. Specifically,
make the b_iodone callback responsible for setting it if it is needed. Previously, it was set unconditionally by bufdone() without holding whichever lock is shared by the b_iodone callback and the corresponding top-half function. Consequently, in a race, the top-half function could conclude that operation was done before the b_iodone callback finished. See, for example, aio_physwakeup() and aio_fphysio(). Note: I don't believe that the other, more widely-used b_iodone callbacks are affected. Discussed with: jeff Reviewed by: phk MFC after: 2 weeks
This commit is contained in:
parent
de864c8710
commit
ec9c9e7363
@ -2107,6 +2107,7 @@ aio_physwakeup(struct buf *bp)
|
||||
struct aio_liojob *lj;
|
||||
|
||||
mtx_lock(&Giant);
|
||||
bp->b_flags |= B_DONE;
|
||||
wakeup(bp);
|
||||
|
||||
aiocbe = (struct aiocblist *)bp->b_caller1;
|
||||
|
@ -3046,7 +3046,6 @@ bufdone(struct buf *bp)
|
||||
if (bp->b_iodone != NULL) {
|
||||
biodone = bp->b_iodone;
|
||||
bp->b_iodone = NULL;
|
||||
bp->b_flags |= B_DONE;
|
||||
(*biodone) (bp);
|
||||
if (dropobj)
|
||||
bufobj_wdrop(dropobj);
|
||||
|
@ -1534,7 +1534,7 @@ ffs_backgroundwritedone(struct buf *bp)
|
||||
* by biodone it will be tossed.
|
||||
*/
|
||||
bp->b_flags |= B_NOCACHE;
|
||||
bp->b_flags &= ~(B_CACHE | B_DONE);
|
||||
bp->b_flags &= ~B_CACHE;
|
||||
bufdone(bp);
|
||||
BO_LOCK(bufobj);
|
||||
/*
|
||||
|
@ -1363,8 +1363,6 @@ swp_pager_async_iodone(struct buf *bp)
|
||||
int i;
|
||||
vm_object_t object = NULL;
|
||||
|
||||
bp->b_flags |= B_DONE;
|
||||
|
||||
/*
|
||||
* report error
|
||||
*/
|
||||
|
Loading…
x
Reference in New Issue
Block a user