block: respect queue limit of max discard segment
[ Upstream commit 943b40c832beb71115e38a1c4d99b640b5342738 ]
When queue_max_discard_segments(q) is 1, blk_discard_mergable() will
return false for discard request, then normal request merge is applied.
However, only queue_max_segments() is checked, so max discard segment
limit isn't respected.
Check max discard segment limit in the request merge code for fixing
the issue.
Discard request failure of virtio_blk is fixed.
Fixes: 6984046608
("block: fix the DISCARD request merge")
Signed-off-by: Ming Lei <ming.lei@redhat.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Cc: Stefano Garzarella <sgarzare@redhat.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
parent
8f409e764c
commit
cc3a73f245
@ -553,10 +553,17 @@ int blk_rq_map_sg(struct request_queue *q, struct request *rq,
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(blk_rq_map_sg);
|
EXPORT_SYMBOL(blk_rq_map_sg);
|
||||||
|
|
||||||
|
static inline unsigned int blk_rq_get_max_segments(struct request *rq)
|
||||||
|
{
|
||||||
|
if (req_op(rq) == REQ_OP_DISCARD)
|
||||||
|
return queue_max_discard_segments(rq->q);
|
||||||
|
return queue_max_segments(rq->q);
|
||||||
|
}
|
||||||
|
|
||||||
static inline int ll_new_hw_segment(struct request *req, struct bio *bio,
|
static inline int ll_new_hw_segment(struct request *req, struct bio *bio,
|
||||||
unsigned int nr_phys_segs)
|
unsigned int nr_phys_segs)
|
||||||
{
|
{
|
||||||
if (req->nr_phys_segments + nr_phys_segs > queue_max_segments(req->q))
|
if (req->nr_phys_segments + nr_phys_segs > blk_rq_get_max_segments(req))
|
||||||
goto no_merge;
|
goto no_merge;
|
||||||
|
|
||||||
if (blk_integrity_merge_bio(req->q, req, bio) == false)
|
if (blk_integrity_merge_bio(req->q, req, bio) == false)
|
||||||
@ -640,7 +647,7 @@ static int ll_merge_requests_fn(struct request_queue *q, struct request *req,
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
total_phys_segments = req->nr_phys_segments + next->nr_phys_segments;
|
total_phys_segments = req->nr_phys_segments + next->nr_phys_segments;
|
||||||
if (total_phys_segments > queue_max_segments(q))
|
if (total_phys_segments > blk_rq_get_max_segments(req))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (blk_integrity_merge_rq(q, req, next) == false)
|
if (blk_integrity_merge_rq(q, req, next) == false)
|
||||||
|
Loading…
Reference in New Issue
Block a user