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:
Alan Cox 2005-07-20 19:06:06 +00:00
parent de864c8710
commit ec9c9e7363
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=148200
4 changed files with 2 additions and 4 deletions

View file

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

View file

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

View file

@ -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);
/*

View file

@ -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
*/