]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
block: add a bio_reuse helper
authorChristoph Hellwig <hch@lst.de>
Wed, 14 Jan 2026 13:06:41 +0000 (14:06 +0100)
committerCarlos Maiolino <cem@kernel.org>
Wed, 21 Jan 2026 11:57:16 +0000 (12:57 +0100)
Add a helper to allow an existing bio to be resubmitted without
having to re-add the payload.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Jens Axboe <axboe@kernel.dk>
Reviewed-by: Hans Holmberg <hans.holmberg@wdc.com>
Reviewed-by: Carlos Maiolino <cmaiolino@redhat.com>
Reviewed-by: Damien Le Moal <dlemoal@kernel.org>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
block/bio.c
include/linux/bio.h

index e726c0e280a8dc85ef823511f1c59547ada5b3bd..40f690985bfb6ee25233be5a1feed2ae1ef1dabe 100644 (file)
@@ -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;
index c75a9b3672aa414589970a3b59f07a756d5707fe..6156f2d66d4acc2950520ef0fd22e5924a5cc41e 100644 (file)
@@ -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,