HomeFreeBSD

Allow biodone() to be used as a completion routine.

Description

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

Details

Provenance
mckusickAuthored on Oct 23 2021, 2:25 PM
Parents
rG311b95bbcda7: sys/mount.h: remove dead prototype
Branches
Unknown
Tags
Unknown