66 lines
2.3 KiB
Diff
66 lines
2.3 KiB
Diff
From 7fc5a2cbcc8459cab6ae8c5dd1220768027ccb70 Mon Sep 17 00:00:00 2001
|
|
From: Jens Axboe <axboe@kernel.dk>
|
|
Date: Wed, 11 Jun 2025 08:48:46 -0600
|
|
Subject: block: use plug request list tail for one-shot backmerge attempt
|
|
|
|
Previously, the block layer stored the requests in the plug list in
|
|
LIFO order. For this reason, blk_attempt_plug_merge() would check
|
|
just the head entry for a back merge attempt, and abort after that
|
|
unless requests for multiple queues existed in the plug list. If more
|
|
than one request is present in the plug list, this makes the one-shot
|
|
back merging less useful than before, as it'll always fail to find a
|
|
quick merge candidate.
|
|
|
|
Use the tail entry for the one-shot merge attempt, which is the last
|
|
added request in the list. If that fails, abort immediately unless
|
|
there are multiple queues available. If multiple queues are available,
|
|
then scan the list. Ideally the latter scan would be a backwards scan
|
|
of the list, but as it currently stands, the plug list is singly linked
|
|
and hence this isn't easily feasible.
|
|
|
|
Cc: stable@vger.kernel.org
|
|
Link: https://lore.kernel.org/linux-block/20250611121626.7252-1-abuehaze@amazon.com/
|
|
Reported-by: Hazem Mohamed Abuelfotoh <abuehaze@amazon.com>
|
|
Fixes: e70c301faece ("block: don't reorder requests in blk_add_rq_to_plug")
|
|
Signed-off-by: Jens Axboe <axboe@kernel.dk>
|
|
---
|
|
block/blk-merge.c | 26 +++++++++++++-------------
|
|
1 file changed, 13 insertions(+), 13 deletions(-)
|
|
|
|
--- a/block/blk-merge.c
|
|
+++ b/block/blk-merge.c
|
|
@@ -1127,20 +1127,20 @@ bool blk_attempt_plug_merge(struct reque
|
|
if (!plug || rq_list_empty(&plug->mq_list))
|
|
return false;
|
|
|
|
- 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;
|
|
- break;
|
|
- }
|
|
+ rq = plug->mq_list.tail;
|
|
+ if (rq->q == q)
|
|
+ return blk_attempt_bio_merge(q, rq, bio, nr_segs, false) ==
|
|
+ BIO_MERGE_OK;
|
|
+ else if (!plug->multiple_queues)
|
|
+ return false;
|
|
|
|
- /*
|
|
- * Only keep iterating plug list for merges if we have multiple
|
|
- * queues
|
|
- */
|
|
- if (!plug->multiple_queues)
|
|
- break;
|
|
+ rq_list_for_each(&plug->mq_list, rq) {
|
|
+ if (rq->q != q)
|
|
+ continue;
|
|
+ if (blk_attempt_bio_merge(q, rq, bio, nr_segs, false) ==
|
|
+ BIO_MERGE_OK)
|
|
+ return true;
|
|
+ break;
|
|
}
|
|
return false;
|
|
}
|