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@xxxxxxxxxxxxxxx # v5.16 Reported-by: Larkin Lowrey <llowrey@xxxxxxxxxxxxxxxxx> Reported-by: Wilson Jonathan <i400sjon@xxxxxxxxx> Reported-by: Roger Heflin <rogerheflin@xxxxxxxxx> Signed-off-by: Song Liu <song@xxxxxxxxxx> --- 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; } -- 2.30.2