From: Christoph Hellwig Date: Wed, 14 Jan 2026 13:06:41 +0000 (+0100) Subject: block: add a bio_reuse helper X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7ca44303f9f6160a2f87ae3d5d2326d9127cd61c;p=thirdparty%2Fkernel%2Flinux.git block: add a bio_reuse helper Add a helper to allow an existing bio to be resubmitted without having to re-add the payload. Signed-off-by: Christoph Hellwig Reviewed-by: Jens Axboe Reviewed-by: Hans Holmberg Reviewed-by: Carlos Maiolino Reviewed-by: Damien Le Moal Reviewed-by: Darrick J. Wong Signed-off-by: Carlos Maiolino --- diff --git a/block/bio.c b/block/bio.c index e726c0e280a8d..40f690985bfb6 100644 --- a/block/bio.c +++ b/block/bio.c @@ -311,6 +311,40 @@ void bio_reset(struct bio *bio, struct block_device *bdev, blk_opf_t opf) } EXPORT_SYMBOL(bio_reset); +/** + * bio_reuse - reuse a bio with the payload left intact + * @bio: bio to reuse + * @opf: operation and flags for the next I/O + * + * Allow reusing an existing bio for another operation with all set up + * fields including the payload, device and end_io handler left intact. + * + * Typically used when @bio is first used to read data which is then written + * to another location without modification. @bio must not be in-flight and + * owned by the caller. Can't be used for cloned bios. + * + * Note: Can't be used when @bio has integrity or blk-crypto contexts for now. + * Feel free to add that support when you need it, though. + */ +void bio_reuse(struct bio *bio, blk_opf_t opf) +{ + unsigned short vcnt = bio->bi_vcnt, i; + bio_end_io_t *end_io = bio->bi_end_io; + void *private = bio->bi_private; + + WARN_ON_ONCE(bio_flagged(bio, BIO_CLONED)); + WARN_ON_ONCE(bio_integrity(bio)); + WARN_ON_ONCE(bio_has_crypt_ctx(bio)); + + bio_reset(bio, bio->bi_bdev, opf); + for (i = 0; i < vcnt; i++) + bio->bi_iter.bi_size += bio->bi_io_vec[i].bv_len; + bio->bi_vcnt = vcnt; + bio->bi_private = private; + bio->bi_end_io = end_io; +} +EXPORT_SYMBOL_GPL(bio_reuse); + static struct bio *__bio_chain_endio(struct bio *bio) { struct bio *parent = bio->bi_private; diff --git a/include/linux/bio.h b/include/linux/bio.h index c75a9b3672aa4..6156f2d66d4ac 100644 --- a/include/linux/bio.h +++ b/include/linux/bio.h @@ -414,6 +414,7 @@ static inline void bio_init_inline(struct bio *bio, struct block_device *bdev, } 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 *); int __must_check bio_add_page(struct bio *bio, struct page *page, unsigned len,