Skip to content

Commit 14b06a2

Browse files
Christoph Hellwigkawasaki
authored andcommitted
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 <[email protected]> Reviewed-by: Jens Axboe <[email protected]> Reviewed-by: Hans Holmberg <[email protected]> Reviewed-by: Carlos Maiolino <[email protected]> Reviewed-by: Damien Le Moal <[email protected]> Reviewed-by: "Darrick J. Wong" <[email protected]>
1 parent 06634b5 commit 14b06a2

File tree

2 files changed

+35
-0
lines changed

2 files changed

+35
-0
lines changed

block/bio.c

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,40 @@ void bio_reset(struct bio *bio, struct block_device *bdev, blk_opf_t opf)
311311
}
312312
EXPORT_SYMBOL(bio_reset);
313313

314+
/**
315+
* bio_reuse - reuse a bio with the payload left intact
316+
* @bio: bio to reuse
317+
* @opf: operation and flags for the next I/O
318+
*
319+
* Allow reusing an existing bio for another operation with all set up
320+
* fields including the payload, device and end_io handler left intact.
321+
*
322+
* Typically used when @bio is first used to read data which is then written
323+
* to another location without modification. @bio must not be in-flight and
324+
* owned by the caller. Can't be used for cloned bios.
325+
*
326+
* Note: Can't be used when @bio has integrity or blk-crypto contexts for now.
327+
* Feel free to add that support when you need it, though.
328+
*/
329+
void bio_reuse(struct bio *bio, blk_opf_t opf)
330+
{
331+
unsigned short vcnt = bio->bi_vcnt, i;
332+
bio_end_io_t *end_io = bio->bi_end_io;
333+
void *private = bio->bi_private;
334+
335+
WARN_ON_ONCE(bio_flagged(bio, BIO_CLONED));
336+
WARN_ON_ONCE(bio_integrity(bio));
337+
WARN_ON_ONCE(bio_has_crypt_ctx(bio));
338+
339+
bio_reset(bio, bio->bi_bdev, opf);
340+
for (i = 0; i < vcnt; i++)
341+
bio->bi_iter.bi_size += bio->bi_io_vec[i].bv_len;
342+
bio->bi_vcnt = vcnt;
343+
bio->bi_private = private;
344+
bio->bi_end_io = end_io;
345+
}
346+
EXPORT_SYMBOL_GPL(bio_reuse);
347+
314348
static struct bio *__bio_chain_endio(struct bio *bio)
315349
{
316350
struct bio *parent = bio->bi_private;

include/linux/bio.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,7 @@ static inline void bio_init_inline(struct bio *bio, struct block_device *bdev,
414414
}
415415
extern void bio_uninit(struct bio *);
416416
void bio_reset(struct bio *bio, struct block_device *bdev, blk_opf_t opf);
417+
void bio_reuse(struct bio *bio, blk_opf_t opf);
417418
void bio_chain(struct bio *, struct bio *);
418419

419420
int __must_check bio_add_page(struct bio *bio, struct page *page, unsigned len,

0 commit comments

Comments
 (0)