Allow biodone() to be used as a completion routine.
An ordered series of BIO_READ and BIO_WRITE operations are typically done as: while (work to do) { setup bp for I/O g_io_request(bp, consumer); biowait(bp); } Here you need to have biodone() called at the completion of the I/O to set the BIO_DONE flag and awaken the biowait(). The obvious way to do this would be to set bio_done = biodone, but biodone() will only take the desired action if bio_done == NULL. The relevant code at the end of biodone() is: done = bp->bio_done; if (done == NULL) { mtxp = mtx_pool_find(mtxpool_sleep, bp); mtx_lock(mtxp); bp->bio_flags |= BIO_DONE; wakeup(bp); mtx_unlock(mtxp); } else done(bp); This code would infinitely recurse if biodone() is specified as the routine to use at completion. So before this change, a wrapper done function had to be written: static void g_io_done(struct bio *bp) { bp->bio_done = NULL; biodone(bp); bp->bio_done = g_io_done; } This commit changes if (done == NULL) to if (done == NULL || done == biodone) which eliminates the need for the wrapper function. Reviewed by: kib Sponsored by: Netflix
This commit is contained in:
parent
311b95bbcd
commit
dfd704b7fb
@ -4384,7 +4384,11 @@ biodone(struct bio *bp)
|
||||
atomic_add_int(&inflight_transient_maps, -1);
|
||||
}
|
||||
done = bp->bio_done;
|
||||
if (done == NULL) {
|
||||
/*
|
||||
* The check for done == biodone is to allow biodone to be
|
||||
* used as a bio_done routine.
|
||||
*/
|
||||
if (done == NULL || done == biodone) {
|
||||
mtxp = mtx_pool_find(mtxpool_sleep, bp);
|
||||
mtx_lock(mtxp);
|
||||
bp->bio_flags |= BIO_DONE;
|
||||
|
Loading…
Reference in New Issue
Block a user