Skip to content

Commit 1e8a7f6

Browse files
Christoph Hellwigaxboe
authored andcommitted
block: properly handle REQ_OP_ZONE_APPEND in __bio_split_to_limits
Currently REQ_OP_ZONE_APPEND is handled by the bio_split_rw case in __bio_split_to_limits. This is harmful because REQ_OP_ZONE_APPEND bios do not adhere to the soft max_limits value but instead use their own capped version of max_hw_sectors, leading to incorrect splits that later blow up in bio_split. We still need the bio_split_rw logic to count nr_segs for blk-mq code, so add a new wrapper that passes in the right limit, and turns any bio that would need a split into an error as an additional debugging aid. Signed-off-by: Christoph Hellwig <[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 379b122 commit 1e8a7f6

File tree

2 files changed

+24
-0
lines changed

2 files changed

+24
-0
lines changed

block/blk-merge.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,26 @@ struct bio *bio_split_rw(struct bio *bio, const struct queue_limits *lim,
378378
get_max_io_size(bio, lim) << SECTOR_SHIFT));
379379
}
380380

381+
/*
382+
* REQ_OP_ZONE_APPEND bios must never be split by the block layer.
383+
*
384+
* But we want the nr_segs calculation provided by bio_split_rw_at, and having
385+
* a good sanity check that the submitter built the bio correctly is nice to
386+
* have as well.
387+
*/
388+
struct bio *bio_split_zone_append(struct bio *bio,
389+
const struct queue_limits *lim, unsigned *nr_segs)
390+
{
391+
unsigned int max_sectors = queue_limits_max_zone_append_sectors(lim);
392+
int split_sectors;
393+
394+
split_sectors = bio_split_rw_at(bio, lim, nr_segs,
395+
max_sectors << SECTOR_SHIFT);
396+
if (WARN_ON_ONCE(split_sectors > 0))
397+
split_sectors = -EINVAL;
398+
return bio_submit_split(bio, split_sectors);
399+
}
400+
381401
/**
382402
* bio_split_to_limits - split a bio to fit the queue limits
383403
* @bio: bio to be split

block/blk.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,8 @@ struct bio *bio_split_write_zeroes(struct bio *bio,
337337
const struct queue_limits *lim, unsigned *nsegs);
338338
struct bio *bio_split_rw(struct bio *bio, const struct queue_limits *lim,
339339
unsigned *nr_segs);
340+
struct bio *bio_split_zone_append(struct bio *bio,
341+
const struct queue_limits *lim, unsigned *nr_segs);
340342

341343
/*
342344
* All drivers must accept single-segments bios that are smaller than PAGE_SIZE.
@@ -375,6 +377,8 @@ static inline struct bio *__bio_split_to_limits(struct bio *bio,
375377
return bio_split_rw(bio, lim, nr_segs);
376378
*nr_segs = 1;
377379
return bio;
380+
case REQ_OP_ZONE_APPEND:
381+
return bio_split_zone_append(bio, lim, nr_segs);
378382
case REQ_OP_DISCARD:
379383
case REQ_OP_SECURE_ERASE:
380384
return bio_split_discard(bio, lim, nr_segs);

0 commit comments

Comments
 (0)