RAID arrays check/repair operations benefit a lot from merging requests. If we only check the previous entry for merge attempt, many merge will be missed. As a result, significant regression is observed for RAID check and repair.
Fix this by checking more than just the previous entry when plug->multiple_queues == true.
This improves the check/repair speed of a 20-HDD raid6 from 19 MB/s to 103 MB/s.
Fixes: d38a9c04c0d5 ("block: only check previous entry for plug merge attempt") Cc: stable@vger.kernel.org # v5.16 Reported-by: Larkin Lowrey llowrey@nuclearwinter.com Reported-by: Wilson Jonathan i400sjon@gmail.com Reported-by: Roger Heflin rogerheflin@gmail.com Signed-off-by: Song Liu song@kernel.org --- block/blk-merge.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-)
diff --git a/block/blk-merge.c b/block/blk-merge.c index 4de34a332c9f..57e2075fb2f4 100644 --- a/block/blk-merge.c +++ b/block/blk-merge.c @@ -1089,12 +1089,14 @@ bool blk_attempt_plug_merge(struct request_queue *q, struct bio *bio, if (!plug || rq_list_empty(plug->mq_list)) return false;
- /* check the previously added entry for a quick merge attempt */ - rq = rq_list_peek(&plug->mq_list); - if (rq->q == q) { - if (blk_attempt_bio_merge(q, rq, bio, nr_segs, false) == - BIO_MERGE_OK) - return true; + rq_list_for_each(&plug->mq_list, rq) { + if (rq->q == q) { + if (blk_attempt_bio_merge(q, rq, bio, nr_segs, false) == + BIO_MERGE_OK) + return true; + } + if (!plug->multiple_queues) + break; } return false; }