block: factor out a bio_await helper

Add a new helper to wait for a bio and anything chained off it to
complete synchronously after submitting it.  This factors common code out
of submit_bio_wait and bio_await_chain and will also be useful for
file system code and thus is exported.

Note that this will now set REQ_SYNC also for the bio_await case for
consistency.  Nothing should look at the flag in the end_io handler,
but if something does having the flag set makes more sense.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Damien Le Moal <dlemoal@kernel.org>
Link: https://patch.msgid.link/20260407140538.633364-4-hch@lst.de
Signed-off-by: Jens Axboe <axboe@kernel.dk>
This commit is contained in:
Christoph Hellwig 2026-04-07 16:05:26 +02:00 committed by Jens Axboe
parent 65565ca5f9
commit 6fa747550e
2 changed files with 39 additions and 16 deletions

View File

@ -1467,6 +1467,36 @@ static void bio_wait_end_io(struct bio *bio)
complete(bio->bi_private);
}
/**
* bio_await - call a function on a bio, and wait until it completes
* @bio: the bio which describes the I/O
* @submit: function called to submit the bio
* @priv: private data passed to @submit
*
* Wait for the bio as well as any bio chained off it after executing the
* passed in callback @submit. The wait for the bio is set up before calling
* @submit to ensure that the completion is captured. If @submit is %NULL,
* submit_bio() is used instead to submit the bio.
*
* Note: this overrides the bi_private and bi_end_io fields in the bio.
*/
void bio_await(struct bio *bio, void *priv,
void (*submit)(struct bio *bio, void *priv))
{
DECLARE_COMPLETION_ONSTACK_MAP(done,
bio->bi_bdev->bd_disk->lockdep_map);
bio->bi_private = &done;
bio->bi_end_io = bio_wait_end_io;
bio->bi_opf |= REQ_SYNC;
if (submit)
submit(bio, priv);
else
submit_bio(bio);
blk_wait_io(&done);
}
EXPORT_SYMBOL_GPL(bio_await);
/**
* submit_bio_wait - submit a bio, and wait until it completes
* @bio: The &struct bio which describes the I/O
@ -1480,19 +1510,16 @@ static void bio_wait_end_io(struct bio *bio)
*/
int submit_bio_wait(struct bio *bio)
{
DECLARE_COMPLETION_ONSTACK_MAP(done,
bio->bi_bdev->bd_disk->lockdep_map);
bio->bi_private = &done;
bio->bi_end_io = bio_wait_end_io;
bio->bi_opf |= REQ_SYNC;
submit_bio(bio);
blk_wait_io(&done);
bio_await(bio, NULL, NULL);
return blk_status_to_errno(bio->bi_status);
}
EXPORT_SYMBOL(submit_bio_wait);
static void bio_endio_cb(struct bio *bio, void *priv)
{
bio_endio(bio);
}
/**
* bdev_rw_virt - synchronously read into / write from kernel mapping
* @bdev: block device to access
@ -1528,13 +1555,7 @@ EXPORT_SYMBOL_GPL(bdev_rw_virt);
*/
void bio_await_chain(struct bio *bio)
{
DECLARE_COMPLETION_ONSTACK_MAP(done,
bio->bi_bdev->bd_disk->lockdep_map);
bio->bi_private = &done;
bio->bi_end_io = bio_wait_end_io;
bio_endio(bio);
blk_wait_io(&done);
bio_await(bio, NULL, bio_endio_cb);
bio_put(bio);
}

View File

@ -432,6 +432,8 @@ extern void bio_uninit(struct bio *);
void bio_reset(struct bio *bio, struct block_device *bdev, blk_opf_t opf);
void bio_reuse(struct bio *bio, blk_opf_t opf);
void bio_chain(struct bio *, struct bio *);
void bio_await(struct bio *bio, void *priv,
void (*submit)(struct bio *bio, void *priv));
int __must_check bio_add_page(struct bio *bio, struct page *page, unsigned len,
unsigned off);