diff options
author | Ming Lei <ming.lei@redhat.com> | 2020-08-17 17:52:39 +0800 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2020-09-03 11:26:54 +0200 |
commit | cc3a73f245cb408c2856b6a286cae3681643b9d8 (patch) | |
tree | 9da887e2b9b348546443dfe4a4f7fa2224168af4 /block | |
parent | 8f409e764c4b2ad611fa5ec2ecdce54ab337f11e (diff) | |
download | linux-stable-cc3a73f245cb408c2856b6a286cae3681643b9d8.tar.gz linux-stable-cc3a73f245cb408c2856b6a286cae3681643b9d8.tar.bz2 linux-stable-cc3a73f245cb408c2856b6a286cae3681643b9d8.zip |
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: 69840466086d ("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>
Diffstat (limited to 'block')
-rw-r--r-- | block/blk-merge.c | 11 |
1 files changed, 9 insertions, 2 deletions
diff --git a/block/blk-merge.c b/block/blk-merge.c index 93cff719b066..c874931bae6b 100644 --- a/block/blk-merge.c +++ b/block/blk-merge.c @@ -553,10 +553,17 @@ int blk_rq_map_sg(struct request_queue *q, struct request *rq, } 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, 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; 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; 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; if (blk_integrity_merge_rq(q, req, next) == false) |