Skip to content

Commit b35243a

Browse files
Christoph Hellwigaxboe
authored andcommitted
block: rework bio splitting
The current setup with bio_may_exceed_limit and __bio_split_to_limits is a bit of a mess. Change it so that __bio_split_to_limits does all the work and is just a variant of bio_split_to_limits that returns nr_segs. This is done by inlining it and instead have the various bio_split_* helpers directly submit the potentially split bios. To support btrfs, the rw version has a lower level helper split out that just returns the offset to split. This turns out to nicely clean up the btrfs flow as well. Signed-off-by: Christoph Hellwig <[email protected]> Acked-by: David Sterba <[email protected]> Reviewed-by: Damien Le Moal <[email protected]> Tested-by: Hans Holmberg <[email protected]> Reviewed-by: Hans Holmberg <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jens Axboe <[email protected]>
1 parent f6f84be commit b35243a

File tree

5 files changed

+125
-129
lines changed

5 files changed

+125
-129
lines changed

block/blk-merge.c

Lines changed: 56 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -105,9 +105,33 @@ static unsigned int bio_allowed_max_sectors(const struct queue_limits *lim)
105105
return round_down(UINT_MAX, lim->logical_block_size) >> SECTOR_SHIFT;
106106
}
107107

108-
static struct bio *bio_split_discard(struct bio *bio,
109-
const struct queue_limits *lim,
110-
unsigned *nsegs, struct bio_set *bs)
108+
static struct bio *bio_submit_split(struct bio *bio, int split_sectors)
109+
{
110+
if (unlikely(split_sectors < 0)) {
111+
bio->bi_status = errno_to_blk_status(split_sectors);
112+
bio_endio(bio);
113+
return NULL;
114+
}
115+
116+
if (split_sectors) {
117+
struct bio *split;
118+
119+
split = bio_split(bio, split_sectors, GFP_NOIO,
120+
&bio->bi_bdev->bd_disk->bio_split);
121+
split->bi_opf |= REQ_NOMERGE;
122+
blkcg_bio_issue_init(split);
123+
bio_chain(split, bio);
124+
trace_block_split(split, bio->bi_iter.bi_sector);
125+
WARN_ON_ONCE(bio_zone_write_plugging(bio));
126+
submit_bio_noacct(bio);
127+
return split;
128+
}
129+
130+
return bio;
131+
}
132+
133+
struct bio *bio_split_discard(struct bio *bio, const struct queue_limits *lim,
134+
unsigned *nsegs)
111135
{
112136
unsigned int max_discard_sectors, granularity;
113137
sector_t tmp;
@@ -121,10 +145,10 @@ static struct bio *bio_split_discard(struct bio *bio,
121145
min(lim->max_discard_sectors, bio_allowed_max_sectors(lim));
122146
max_discard_sectors -= max_discard_sectors % granularity;
123147
if (unlikely(!max_discard_sectors))
124-
return NULL;
148+
return bio;
125149

126150
if (bio_sectors(bio) <= max_discard_sectors)
127-
return NULL;
151+
return bio;
128152

129153
split_sectors = max_discard_sectors;
130154

@@ -139,19 +163,18 @@ static struct bio *bio_split_discard(struct bio *bio,
139163
if (split_sectors > tmp)
140164
split_sectors -= tmp;
141165

142-
return bio_split(bio, split_sectors, GFP_NOIO, bs);
166+
return bio_submit_split(bio, split_sectors);
143167
}
144168

145-
static struct bio *bio_split_write_zeroes(struct bio *bio,
146-
const struct queue_limits *lim,
147-
unsigned *nsegs, struct bio_set *bs)
169+
struct bio *bio_split_write_zeroes(struct bio *bio,
170+
const struct queue_limits *lim, unsigned *nsegs)
148171
{
149172
*nsegs = 0;
150173
if (!lim->max_write_zeroes_sectors)
151-
return NULL;
174+
return bio;
152175
if (bio_sectors(bio) <= lim->max_write_zeroes_sectors)
153-
return NULL;
154-
return bio_split(bio, lim->max_write_zeroes_sectors, GFP_NOIO, bs);
176+
return bio;
177+
return bio_submit_split(bio, lim->max_write_zeroes_sectors);
155178
}
156179

157180
static inline unsigned int blk_boundary_sectors(const struct queue_limits *lim,
@@ -274,27 +297,19 @@ static bool bvec_split_segs(const struct queue_limits *lim,
274297
}
275298

276299
/**
277-
* bio_split_rw - split a bio in two bios
300+
* bio_split_rw_at - check if and where to split a read/write bio
278301
* @bio: [in] bio to be split
279302
* @lim: [in] queue limits to split based on
280303
* @segs: [out] number of segments in the bio with the first half of the sectors
281-
* @bs: [in] bio set to allocate the clone from
282304
* @max_bytes: [in] maximum number of bytes per bio
283305
*
284-
* Clone @bio, update the bi_iter of the clone to represent the first sectors
285-
* of @bio and update @bio->bi_iter to represent the remaining sectors. The
286-
* following is guaranteed for the cloned bio:
287-
* - That it has at most @max_bytes worth of data
288-
* - That it has at most queue_max_segments(@q) segments.
289-
*
290-
* Except for discard requests the cloned bio will point at the bi_io_vec of
291-
* the original bio. It is the responsibility of the caller to ensure that the
292-
* original bio is not freed before the cloned bio. The caller is also
293-
* responsible for ensuring that @bs is only destroyed after processing of the
294-
* split bio has finished.
306+
* Find out if @bio needs to be split to fit the queue limits in @lim and a
307+
* maximum size of @max_bytes. Returns a negative error number if @bio can't be
308+
* split, 0 if the bio doesn't have to be split, or a positive sector offset if
309+
* @bio needs to be split.
295310
*/
296-
struct bio *bio_split_rw(struct bio *bio, const struct queue_limits *lim,
297-
unsigned *segs, struct bio_set *bs, unsigned max_bytes)
311+
int bio_split_rw_at(struct bio *bio, const struct queue_limits *lim,
312+
unsigned *segs, unsigned max_bytes)
298313
{
299314
struct bio_vec bv, bvprv, *bvprvp = NULL;
300315
struct bvec_iter iter;
@@ -324,22 +339,17 @@ struct bio *bio_split_rw(struct bio *bio, const struct queue_limits *lim,
324339
}
325340

326341
*segs = nsegs;
327-
return NULL;
342+
return 0;
328343
split:
329-
if (bio->bi_opf & REQ_ATOMIC) {
330-
bio->bi_status = BLK_STS_INVAL;
331-
bio_endio(bio);
332-
return ERR_PTR(-EINVAL);
333-
}
344+
if (bio->bi_opf & REQ_ATOMIC)
345+
return -EINVAL;
346+
334347
/*
335348
* We can't sanely support splitting for a REQ_NOWAIT bio. End it
336349
* with EAGAIN if splitting is required and return an error pointer.
337350
*/
338-
if (bio->bi_opf & REQ_NOWAIT) {
339-
bio->bi_status = BLK_STS_AGAIN;
340-
bio_endio(bio);
341-
return ERR_PTR(-EAGAIN);
342-
}
351+
if (bio->bi_opf & REQ_NOWAIT)
352+
return -EAGAIN;
343353

344354
*segs = nsegs;
345355

@@ -356,58 +366,16 @@ struct bio *bio_split_rw(struct bio *bio, const struct queue_limits *lim,
356366
* big IO can be trival, disable iopoll when split needed.
357367
*/
358368
bio_clear_polled(bio);
359-
return bio_split(bio, bytes >> SECTOR_SHIFT, GFP_NOIO, bs);
369+
return bytes >> SECTOR_SHIFT;
360370
}
361-
EXPORT_SYMBOL_GPL(bio_split_rw);
371+
EXPORT_SYMBOL_GPL(bio_split_rw_at);
362372

363-
/**
364-
* __bio_split_to_limits - split a bio to fit the queue limits
365-
* @bio: bio to be split
366-
* @lim: queue limits to split based on
367-
* @nr_segs: returns the number of segments in the returned bio
368-
*
369-
* Check if @bio needs splitting based on the queue limits, and if so split off
370-
* a bio fitting the limits from the beginning of @bio and return it. @bio is
371-
* shortened to the remainder and re-submitted.
372-
*
373-
* The split bio is allocated from @q->bio_split, which is provided by the
374-
* block layer.
375-
*/
376-
struct bio *__bio_split_to_limits(struct bio *bio,
377-
const struct queue_limits *lim,
378-
unsigned int *nr_segs)
373+
struct bio *bio_split_rw(struct bio *bio, const struct queue_limits *lim,
374+
unsigned *nr_segs)
379375
{
380-
struct bio_set *bs = &bio->bi_bdev->bd_disk->bio_split;
381-
struct bio *split;
382-
383-
switch (bio_op(bio)) {
384-
case REQ_OP_DISCARD:
385-
case REQ_OP_SECURE_ERASE:
386-
split = bio_split_discard(bio, lim, nr_segs, bs);
387-
break;
388-
case REQ_OP_WRITE_ZEROES:
389-
split = bio_split_write_zeroes(bio, lim, nr_segs, bs);
390-
break;
391-
default:
392-
split = bio_split_rw(bio, lim, nr_segs, bs,
393-
get_max_io_size(bio, lim) << SECTOR_SHIFT);
394-
if (IS_ERR(split))
395-
return NULL;
396-
break;
397-
}
398-
399-
if (split) {
400-
/* there isn't chance to merge the split bio */
401-
split->bi_opf |= REQ_NOMERGE;
402-
403-
blkcg_bio_issue_init(split);
404-
bio_chain(split, bio);
405-
trace_block_split(split, bio->bi_iter.bi_sector);
406-
WARN_ON_ONCE(bio_zone_write_plugging(bio));
407-
submit_bio_noacct(bio);
408-
return split;
409-
}
410-
return bio;
376+
return bio_submit_split(bio,
377+
bio_split_rw_at(bio, lim, nr_segs,
378+
get_max_io_size(bio, lim) << SECTOR_SHIFT));
411379
}
412380

413381
/**
@@ -426,9 +394,7 @@ struct bio *bio_split_to_limits(struct bio *bio)
426394
const struct queue_limits *lim = &bdev_get_queue(bio->bi_bdev)->limits;
427395
unsigned int nr_segs;
428396

429-
if (bio_may_exceed_limits(bio, lim))
430-
return __bio_split_to_limits(bio, lim, &nr_segs);
431-
return bio;
397+
return __bio_split_to_limits(bio, lim, &nr_segs);
432398
}
433399
EXPORT_SYMBOL(bio_split_to_limits);
434400

block/blk-mq.c

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2939,7 +2939,7 @@ void blk_mq_submit_bio(struct bio *bio)
29392939
struct blk_plug *plug = current->plug;
29402940
const int is_sync = op_is_sync(bio->bi_opf);
29412941
struct blk_mq_hw_ctx *hctx;
2942-
unsigned int nr_segs = 1;
2942+
unsigned int nr_segs;
29432943
struct request *rq;
29442944
blk_status_t ret;
29452945

@@ -2981,11 +2981,10 @@ void blk_mq_submit_bio(struct bio *bio)
29812981
goto queue_exit;
29822982
}
29832983

2984-
if (unlikely(bio_may_exceed_limits(bio, &q->limits))) {
2985-
bio = __bio_split_to_limits(bio, &q->limits, &nr_segs);
2986-
if (!bio)
2987-
goto queue_exit;
2988-
}
2984+
bio = __bio_split_to_limits(bio, &q->limits, &nr_segs);
2985+
if (!bio)
2986+
goto queue_exit;
2987+
29892988
if (!bio_integrity_prep(bio))
29902989
goto queue_exit;
29912990

block/blk.h

Lines changed: 44 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -331,33 +331,58 @@ ssize_t part_timeout_show(struct device *, struct device_attribute *, char *);
331331
ssize_t part_timeout_store(struct device *, struct device_attribute *,
332332
const char *, size_t);
333333

334-
static inline bool bio_may_exceed_limits(struct bio *bio,
335-
const struct queue_limits *lim)
334+
struct bio *bio_split_discard(struct bio *bio, const struct queue_limits *lim,
335+
unsigned *nsegs);
336+
struct bio *bio_split_write_zeroes(struct bio *bio,
337+
const struct queue_limits *lim, unsigned *nsegs);
338+
struct bio *bio_split_rw(struct bio *bio, const struct queue_limits *lim,
339+
unsigned *nr_segs);
340+
341+
/*
342+
* All drivers must accept single-segments bios that are smaller than PAGE_SIZE.
343+
*
344+
* This is a quick and dirty check that relies on the fact that bi_io_vec[0] is
345+
* always valid if a bio has data. The check might lead to occasional false
346+
* positives when bios are cloned, but compared to the performance impact of
347+
* cloned bios themselves the loop below doesn't matter anyway.
348+
*/
349+
static inline bool bio_may_need_split(struct bio *bio,
350+
const struct queue_limits *lim)
351+
{
352+
return lim->chunk_sectors || bio->bi_vcnt != 1 ||
353+
bio->bi_io_vec->bv_len + bio->bi_io_vec->bv_offset > PAGE_SIZE;
354+
}
355+
356+
/**
357+
* __bio_split_to_limits - split a bio to fit the queue limits
358+
* @bio: bio to be split
359+
* @lim: queue limits to split based on
360+
* @nr_segs: returns the number of segments in the returned bio
361+
*
362+
* Check if @bio needs splitting based on the queue limits, and if so split off
363+
* a bio fitting the limits from the beginning of @bio and return it. @bio is
364+
* shortened to the remainder and re-submitted.
365+
*
366+
* The split bio is allocated from @q->bio_split, which is provided by the
367+
* block layer.
368+
*/
369+
static inline struct bio *__bio_split_to_limits(struct bio *bio,
370+
const struct queue_limits *lim, unsigned int *nr_segs)
336371
{
337372
switch (bio_op(bio)) {
373+
default:
374+
if (bio_may_need_split(bio, lim))
375+
return bio_split_rw(bio, lim, nr_segs);
376+
*nr_segs = 1;
377+
return bio;
338378
case REQ_OP_DISCARD:
339379
case REQ_OP_SECURE_ERASE:
380+
return bio_split_discard(bio, lim, nr_segs);
340381
case REQ_OP_WRITE_ZEROES:
341-
return true; /* non-trivial splitting decisions */
342-
default:
343-
break;
382+
return bio_split_write_zeroes(bio, lim, nr_segs);
344383
}
345-
346-
/*
347-
* All drivers must accept single-segments bios that are <= PAGE_SIZE.
348-
* This is a quick and dirty check that relies on the fact that
349-
* bi_io_vec[0] is always valid if a bio has data. The check might
350-
* lead to occasional false negatives when bios are cloned, but compared
351-
* to the performance impact of cloned bios themselves the loop below
352-
* doesn't matter anyway.
353-
*/
354-
return lim->chunk_sectors || bio->bi_vcnt != 1 ||
355-
bio->bi_io_vec->bv_len + bio->bi_io_vec->bv_offset > PAGE_SIZE;
356384
}
357385

358-
struct bio *__bio_split_to_limits(struct bio *bio,
359-
const struct queue_limits *lim,
360-
unsigned int *nr_segs);
361386
int ll_back_merge_fn(struct request *req, struct bio *bio,
362387
unsigned int nr_segs);
363388
bool blk_attempt_req_merge(struct request_queue *q, struct request *rq,

fs/btrfs/bio.c

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -73,20 +73,13 @@ struct btrfs_bio *btrfs_bio_alloc(unsigned int nr_vecs, blk_opf_t opf,
7373

7474
static struct btrfs_bio *btrfs_split_bio(struct btrfs_fs_info *fs_info,
7575
struct btrfs_bio *orig_bbio,
76-
u64 map_length, bool use_append)
76+
u64 map_length)
7777
{
7878
struct btrfs_bio *bbio;
7979
struct bio *bio;
8080

81-
if (use_append) {
82-
unsigned int nr_segs;
83-
84-
bio = bio_split_rw(&orig_bbio->bio, &fs_info->limits, &nr_segs,
85-
&btrfs_clone_bioset, map_length);
86-
} else {
87-
bio = bio_split(&orig_bbio->bio, map_length >> SECTOR_SHIFT,
88-
GFP_NOFS, &btrfs_clone_bioset);
89-
}
81+
bio = bio_split(&orig_bbio->bio, map_length >> SECTOR_SHIFT, GFP_NOFS,
82+
&btrfs_clone_bioset);
9083
bbio = btrfs_bio(bio);
9184
btrfs_bio_init(bbio, fs_info, NULL, orig_bbio);
9285
bbio->inode = orig_bbio->inode;
@@ -664,6 +657,19 @@ static bool btrfs_wq_submit_bio(struct btrfs_bio *bbio,
664657
return true;
665658
}
666659

660+
static u64 btrfs_append_map_length(struct btrfs_bio *bbio, u64 map_length)
661+
{
662+
unsigned int nr_segs;
663+
int sector_offset;
664+
665+
map_length = min(map_length, bbio->fs_info->max_zone_append_size);
666+
sector_offset = bio_split_rw_at(&bbio->bio, &bbio->fs_info->limits,
667+
&nr_segs, map_length);
668+
if (sector_offset)
669+
return sector_offset << SECTOR_SHIFT;
670+
return map_length;
671+
}
672+
667673
static bool btrfs_submit_chunk(struct btrfs_bio *bbio, int mirror_num)
668674
{
669675
struct btrfs_inode *inode = bbio->inode;
@@ -691,10 +697,10 @@ static bool btrfs_submit_chunk(struct btrfs_bio *bbio, int mirror_num)
691697

692698
map_length = min(map_length, length);
693699
if (use_append)
694-
map_length = min(map_length, fs_info->max_zone_append_size);
700+
map_length = btrfs_append_map_length(bbio, map_length);
695701

696702
if (map_length < length) {
697-
bbio = btrfs_split_bio(fs_info, bbio, map_length, use_append);
703+
bbio = btrfs_split_bio(fs_info, bbio, map_length);
698704
bio = &bbio->bio;
699705
}
700706

include/linux/bio.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -324,8 +324,8 @@ static inline void bio_next_folio(struct folio_iter *fi, struct bio *bio)
324324
void bio_trim(struct bio *bio, sector_t offset, sector_t size);
325325
extern struct bio *bio_split(struct bio *bio, int sectors,
326326
gfp_t gfp, struct bio_set *bs);
327-
struct bio *bio_split_rw(struct bio *bio, const struct queue_limits *lim,
328-
unsigned *segs, struct bio_set *bs, unsigned max_bytes);
327+
int bio_split_rw_at(struct bio *bio, const struct queue_limits *lim,
328+
unsigned *segs, unsigned max_bytes);
329329

330330
/**
331331
* bio_next_split - get next @sectors from a bio, splitting if necessary

0 commit comments

Comments
 (0)