block: factor out a helper bio_submit_split_bioset()

[ Upstream commit e37b5596a1 ]

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 <yukuai3@huawei.com>
Reviewed-by: Bart Van Assche <bvanassche@acm.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Stable-dep-of: b2f5974079 ("block: fix ordering of recursive split IO")
Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
Yu Kuai 2025-09-10 14:30:46 +08:00 committed by Greg Kroah-Hartman
parent 8668afa4d6
commit 9f7b1537e3
2 changed files with 42 additions and 19 deletions

View File

@ -104,33 +104,54 @@ static unsigned int bio_allowed_max_sectors(const struct queue_limits *lim)
return round_down(UINT_MAX, lim->logical_block_size) >> SECTOR_SHIFT;
}
/*
* bio_submit_split_bioset - Submit a bio, splitting it at a designated sector
* @bio: the original bio to be submitted and split
* @split_sectors: the sector count 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_bioset(struct bio *bio, unsigned int split_sectors,
struct bio_set *bs)
{
struct bio *split = bio_split(bio, split_sectors, GFP_NOIO, bs);
if (IS_ERR(split)) {
bio->bi_status = errno_to_blk_status(PTR_ERR(split));
bio_endio(bio);
return NULL;
}
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;
}
EXPORT_SYMBOL_GPL(bio_submit_split_bioset);
static struct bio *bio_submit_split(struct bio *bio, int split_sectors)
{
if (unlikely(split_sectors < 0))
goto error;
if (unlikely(split_sectors < 0)) {
bio->bi_status = errno_to_blk_status(split_sectors);
bio_endio(bio);
return NULL;
}
if (split_sectors) {
struct bio *split;
split = bio_split(bio, split_sectors, GFP_NOIO,
bio = bio_submit_split_bioset(bio, split_sectors,
&bio->bi_bdev->bd_disk->bio_split);
if (IS_ERR(split)) {
split_sectors = PTR_ERR(split);
goto error;
}
split->bi_opf |= REQ_NOMERGE;
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;
if (bio)
bio->bi_opf |= REQ_NOMERGE;
}
return bio;
error:
bio->bi_status = errno_to_blk_status(split_sectors);
bio_endio(bio);
return NULL;
}
struct bio *bio_split_discard(struct bio *bio, const struct queue_limits *lim,

View File

@ -999,6 +999,8 @@ extern int blk_register_queue(struct gendisk *disk);
extern void blk_unregister_queue(struct gendisk *disk);
void submit_bio_noacct(struct bio *bio);
struct bio *bio_split_to_limits(struct bio *bio);
struct bio *bio_submit_split_bioset(struct bio *bio, unsigned int split_sectors,
struct bio_set *bs);
extern int blk_lld_busy(struct request_queue *q);
extern int blk_queue_enter(struct request_queue *q, blk_mq_req_flags_t flags);