mirror of
https://github.com/raspberrypi/linux.git
synced 2025-12-06 01:49:46 +00:00
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:
committed by
Greg Kroah-Hartman
parent
bac3bc3550
commit
fb03efa169
@@ -443,7 +443,7 @@ int blk_rq_append_bio(struct request *rq, struct bio *bio)
|
||||
int ret;
|
||||
|
||||
/* 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 we would have to split the bio, copy instead */
|
||||
if (ret > 0)
|
||||
|
||||
@@ -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
|
||||
* @lim: [in] queue limits to split based on
|
||||
* @segs: [out] number of segments in the bio with the first half of the sectors
|
||||
* @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
|
||||
* 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
|
||||
* @bio needs to be split.
|
||||
*/
|
||||
int bio_split_rw_at(struct bio *bio, const struct queue_limits *lim,
|
||||
unsigned *segs, unsigned max_bytes)
|
||||
int bio_split_io_at(struct bio *bio, const struct queue_limits *lim,
|
||||
unsigned *segs, unsigned max_bytes, unsigned len_align_mask)
|
||||
{
|
||||
struct bio_vec bv, bvprv, *bvprvp = NULL;
|
||||
struct bvec_iter iter;
|
||||
unsigned nsegs = 0, bytes = 0;
|
||||
|
||||
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
|
||||
* offset would create a gap, disallow it.
|
||||
@@ -363,8 +368,16 @@ split:
|
||||
* Individual bvecs might not be logical block aligned. Round down the
|
||||
* split size so that each bio is properly block size aligned, even if
|
||||
* 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));
|
||||
if (!bytes)
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* Bio splitting may cause subtle trouble such as hang when doing sync
|
||||
@@ -374,7 +387,7 @@ split:
|
||||
bio_clear_polled(bio);
|
||||
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,
|
||||
unsigned *nr_segs)
|
||||
|
||||
@@ -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);
|
||||
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);
|
||||
int bio_split_io_at(struct bio *bio, const struct queue_limits *lim,
|
||||
unsigned *segs, unsigned max_bytes, unsigned len_align);
|
||||
|
||||
/**
|
||||
* bio_next_split - get next @sectors from a bio, splitting if necessary
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
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 = { }
|
||||
|
||||
#endif /* _LINUX_BLKDEV_H */
|
||||
|
||||
Reference in New Issue
Block a user