From: Yu Kuai No functional changes are intended, some drivers like mdraid will split bio by internal processing, prepare to unify bio split codes. Signed-off-by: Yu Kuai --- block/blk-merge.c | 60 +++++++++++++++++++++++++++++---------------- include/linux/bio.h | 2 ++ 2 files changed, 41 insertions(+), 21 deletions(-) diff --git a/block/blk-merge.c b/block/blk-merge.c index 70d704615be5..c45d5e43e172 100644 --- a/block/blk-merge.c +++ b/block/blk-merge.c @@ -104,35 +104,49 @@ static unsigned int bio_allowed_max_sectors(const struct queue_limits *lim) return round_down(UINT_MAX, lim->logical_block_size) >> SECTOR_SHIFT; } -static struct bio *bio_submit_split(struct bio *bio, int split_sectors) +/** + * bio_submit_split - Submit a bio, splitting it at a designated sector + * @bio: the original bio to be submitted and split + * @split_sectors: the sector count (from the start of @bio) at which to split + * @bs: the bio set used for allocating the new split bio + * + * The original bio is modified to contain the remaining sectors and submitted. + * The caller is responsible for submitting the returned bio. + * + * If succeed, the newly allocated bio representing the initial part will be + * returned, on failure NULL will be returned and original bio will fail. + */ +struct bio *bio_submit_split(struct bio *bio, int split_sectors, + struct bio_set *bs) { + struct bio *split; + if (unlikely(split_sectors < 0)) goto error; - if (split_sectors) { - struct bio *split; + if (!split_sectors) + return bio; - split = bio_split(bio, split_sectors, GFP_NOIO, - &bio->bi_bdev->bd_disk->bio_split); - if (IS_ERR(split)) { - split_sectors = PTR_ERR(split); - goto error; - } - split->bi_opf |= REQ_NOMERGE; - blkcg_bio_issue_init(split); - bio_chain(split, bio); - trace_block_split(split, bio->bi_iter.bi_sector); - WARN_ON_ONCE(bio_zone_write_plugging(bio)); - submit_bio_noacct(bio); - return split; + split = bio_split(bio, split_sectors, GFP_NOIO, bs); + if (IS_ERR(split)) { + split_sectors = PTR_ERR(split); + goto error; } - return bio; + split->bi_opf |= REQ_NOMERGE; + blkcg_bio_issue_init(split); + bio_chain(split, bio); + trace_block_split(split, bio->bi_iter.bi_sector); + WARN_ON_ONCE(bio_zone_write_plugging(bio)); + submit_bio_noacct(bio); + return split; + error: bio->bi_status = errno_to_blk_status(split_sectors); bio_endio(bio); return NULL; } +EXPORT_SYMBOL_GPL(bio_submit_split); struct bio *bio_split_discard(struct bio *bio, const struct queue_limits *lim, unsigned *nsegs) @@ -167,7 +181,8 @@ struct bio *bio_split_discard(struct bio *bio, const struct queue_limits *lim, if (split_sectors > tmp) split_sectors -= tmp; - return bio_submit_split(bio, split_sectors); + return bio_submit_split(bio, split_sectors, + &bio->bi_bdev->bd_disk->bio_split); } static inline unsigned int blk_boundary_sectors(const struct queue_limits *lim, @@ -357,7 +372,8 @@ struct bio *bio_split_rw(struct bio *bio, const struct queue_limits *lim, { return bio_submit_split(bio, bio_split_rw_at(bio, lim, nr_segs, - get_max_io_size(bio, lim) << SECTOR_SHIFT)); + get_max_io_size(bio, lim) << SECTOR_SHIFT), + &bio->bi_bdev->bd_disk->bio_split); } /* @@ -376,7 +392,8 @@ struct bio *bio_split_zone_append(struct bio *bio, lim->max_zone_append_sectors << SECTOR_SHIFT); if (WARN_ON_ONCE(split_sectors > 0)) split_sectors = -EINVAL; - return bio_submit_split(bio, split_sectors); + return bio_submit_split(bio, split_sectors, + &bio->bi_bdev->bd_disk->bio_split); } struct bio *bio_split_write_zeroes(struct bio *bio, @@ -396,7 +413,8 @@ struct bio *bio_split_write_zeroes(struct bio *bio, return bio; if (bio_sectors(bio) <= max_sectors) return bio; - return bio_submit_split(bio, max_sectors); + return bio_submit_split(bio, max_sectors, + &bio->bi_bdev->bd_disk->bio_split); } /** diff --git a/include/linux/bio.h b/include/linux/bio.h index 46ffac5caab7..2233261be5e8 100644 --- a/include/linux/bio.h +++ b/include/linux/bio.h @@ -324,6 +324,8 @@ extern struct bio *bio_split(struct bio *bio, int sectors, gfp_t gfp, struct bio_set *bs); int bio_split_rw_at(struct bio *bio, const struct queue_limits *lim, unsigned *segs, unsigned max_bytes); +struct bio *bio_submit_split(struct bio *bio, int split_sectors, + struct bio_set *bs); /** * bio_next_split - get next @sectors from a bio, splitting if necessary -- 2.39.2