mirror of
https://github.com/raspberrypi/linux.git
synced 2025-12-06 10:00:17 +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;
|
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)
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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 */
|
||||||
|
|||||||
Reference in New Issue
Block a user