block: check for valid bio while splitting

[ Upstream commit fec2e70572 ]

We're already iterating every segment, so check these for a valid IO
lengths at the same time. Individual segment lengths will not be checked
on passthrough commands. The read/write command segments must be sized
to the dma alignment.

Signed-off-by: Keith Busch <kbusch@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
Keith Busch
2025-08-27 07:12:51 -07:00
committed by Greg Kroah-Hartman
parent bac3bc3550
commit fb03efa169
4 changed files with 27 additions and 7 deletions

View File

@@ -443,7 +443,7 @@ int blk_rq_append_bio(struct request *rq, struct bio *bio)
int ret; int ret;
/* check that the data layout matches the hardware restrictions */ /* check that the data layout matches the hardware restrictions */
ret = bio_split_rw_at(bio, lim, &nr_segs, max_bytes); ret = bio_split_io_at(bio, lim, &nr_segs, max_bytes, 0);
if (ret) { if (ret) {
/* if we would have to split the bio, copy instead */ /* if we would have to split the bio, copy instead */
if (ret > 0) if (ret > 0)

View File

@@ -303,25 +303,30 @@ static unsigned int bio_split_alignment(struct bio *bio,
} }
/** /**
* bio_split_rw_at - check if and where to split a read/write bio * bio_split_io_at - check if and where to split a bio
* @bio: [in] bio to be split * @bio: [in] bio to be split
* @lim: [in] queue limits to split based on * @lim: [in] queue limits to split based on
* @segs: [out] number of segments in the bio with the first half of the sectors * @segs: [out] number of segments in the bio with the first half of the sectors
* @max_bytes: [in] maximum number of bytes per bio * @max_bytes: [in] maximum number of bytes per bio
* @len_align_mask: [in] length alignment mask for each vector
* *
* Find out if @bio needs to be split to fit the queue limits in @lim and a * Find out if @bio needs to be split to fit the queue limits in @lim and a
* maximum size of @max_bytes. Returns a negative error number if @bio can't be * maximum size of @max_bytes. Returns a negative error number if @bio can't be
* split, 0 if the bio doesn't have to be split, or a positive sector offset if * split, 0 if the bio doesn't have to be split, or a positive sector offset if
* @bio needs to be split. * @bio needs to be split.
*/ */
int bio_split_rw_at(struct bio *bio, const struct queue_limits *lim, int bio_split_io_at(struct bio *bio, const struct queue_limits *lim,
unsigned *segs, unsigned max_bytes) unsigned *segs, unsigned max_bytes, unsigned len_align_mask)
{ {
struct bio_vec bv, bvprv, *bvprvp = NULL; struct bio_vec bv, bvprv, *bvprvp = NULL;
struct bvec_iter iter; struct bvec_iter iter;
unsigned nsegs = 0, bytes = 0; unsigned nsegs = 0, bytes = 0;
bio_for_each_bvec(bv, bio, iter) { bio_for_each_bvec(bv, bio, iter) {
if (bv.bv_offset & lim->dma_alignment ||
bv.bv_len & len_align_mask)
return -EINVAL;
/* /*
* If the queue doesn't support SG gaps and adding this * If the queue doesn't support SG gaps and adding this
* offset would create a gap, disallow it. * offset would create a gap, disallow it.
@@ -363,8 +368,16 @@ split:
* Individual bvecs might not be logical block aligned. Round down the * Individual bvecs might not be logical block aligned. Round down the
* split size so that each bio is properly block size aligned, even if * split size so that each bio is properly block size aligned, even if
* we do not use the full hardware limits. * we do not use the full hardware limits.
*
* It is possible to submit a bio that can't be split into a valid io:
* there may either be too many discontiguous vectors for the max
* segments limit, or contain virtual boundary gaps without having a
* valid block sized split. A zero byte result means one of those
* conditions occured.
*/ */
bytes = ALIGN_DOWN(bytes, bio_split_alignment(bio, lim)); bytes = ALIGN_DOWN(bytes, bio_split_alignment(bio, lim));
if (!bytes)
return -EINVAL;
/* /*
* Bio splitting may cause subtle trouble such as hang when doing sync * Bio splitting may cause subtle trouble such as hang when doing sync
@@ -374,7 +387,7 @@ split:
bio_clear_polled(bio); bio_clear_polled(bio);
return bytes >> SECTOR_SHIFT; return bytes >> SECTOR_SHIFT;
} }
EXPORT_SYMBOL_GPL(bio_split_rw_at); EXPORT_SYMBOL_GPL(bio_split_io_at);
struct bio *bio_split_rw(struct bio *bio, const struct queue_limits *lim, struct bio *bio_split_rw(struct bio *bio, const struct queue_limits *lim,
unsigned *nr_segs) unsigned *nr_segs)

View File

@@ -322,8 +322,8 @@ static inline void bio_next_folio(struct folio_iter *fi, struct bio *bio)
void bio_trim(struct bio *bio, sector_t offset, sector_t size); void bio_trim(struct bio *bio, sector_t offset, sector_t size);
extern struct bio *bio_split(struct bio *bio, int sectors, extern struct bio *bio_split(struct bio *bio, int sectors,
gfp_t gfp, struct bio_set *bs); gfp_t gfp, struct bio_set *bs);
int bio_split_rw_at(struct bio *bio, const struct queue_limits *lim, int bio_split_io_at(struct bio *bio, const struct queue_limits *lim,
unsigned *segs, unsigned max_bytes); unsigned *segs, unsigned max_bytes, unsigned len_align);
/** /**
* bio_next_split - get next @sectors from a bio, splitting if necessary * bio_next_split - get next @sectors from a bio, splitting if necessary

View File

@@ -1872,6 +1872,13 @@ bdev_atomic_write_unit_max_bytes(struct block_device *bdev)
return queue_atomic_write_unit_max_bytes(bdev_get_queue(bdev)); return queue_atomic_write_unit_max_bytes(bdev_get_queue(bdev));
} }
static inline int bio_split_rw_at(struct bio *bio,
const struct queue_limits *lim,
unsigned *segs, unsigned max_bytes)
{
return bio_split_io_at(bio, lim, segs, max_bytes, lim->dma_alignment);
}
#define DEFINE_IO_COMP_BATCH(name) struct io_comp_batch name = { } #define DEFINE_IO_COMP_BATCH(name) struct io_comp_batch name = { }
#endif /* _LINUX_BLKDEV_H */ #endif /* _LINUX_BLKDEV_H */