]> git.baikalelectronics.ru Git - kernel.git/commitdiff
block: do not reverse request order when flushing plug list
authorJan Kara <jack@suse.cz>
Mon, 13 Mar 2023 09:30:02 +0000 (10:30 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 22 Mar 2023 12:33:46 +0000 (13:33 +0100)
[ Upstream commit c7c29194de217df21ff011508aafdddaec4c3b82 ]

Commit b72f965ca95b ("block: flush plug based on hardware and software
queue order") changed flushing of plug list to submit requests one
device at a time. However while doing that it also started using
list_add_tail() instead of list_add() used previously thus effectively
submitting requests in reverse order. Also when forming a rq_list with
remaining requests (in case two or more devices are used), we
effectively reverse the ordering of the plug list for each device we
process. Submitting requests in reverse order has negative impact on
performance for rotational disks (when BFQ is not in use). We observe
10-25% regression in random 4k write throughput, as well as ~20%
regression in MariaDB OLTP benchmark on rotational storage on btrfs
filesystem.

Fix the problem by preserving ordering of the plug list when inserting
requests into the queuelist as well as by appending to requeue_list
instead of prepending to it.

Fixes: b72f965ca95b ("block: flush plug based on hardware and software queue order")
Signed-off-by: Jan Kara <jack@suse.cz>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Link: https://lore.kernel.org/r/20230313093002.11756-1-jack@suse.cz
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Sasha Levin <sashal@kernel.org>
block/blk-mq.c
include/linux/blk-mq.h

index fe0a3a882f465bfe803551df72e38d1b5c033822..aa67a52c5a0699c60e39faead973746aecf3a58d 100644 (file)
@@ -2711,6 +2711,7 @@ static void blk_mq_dispatch_plug_list(struct blk_plug *plug, bool from_sched)
        struct blk_mq_hw_ctx *this_hctx = NULL;
        struct blk_mq_ctx *this_ctx = NULL;
        struct request *requeue_list = NULL;
+       struct request **requeue_lastp = &requeue_list;
        unsigned int depth = 0;
        LIST_HEAD(list);
 
@@ -2721,10 +2722,10 @@ static void blk_mq_dispatch_plug_list(struct blk_plug *plug, bool from_sched)
                        this_hctx = rq->mq_hctx;
                        this_ctx = rq->mq_ctx;
                } else if (this_hctx != rq->mq_hctx || this_ctx != rq->mq_ctx) {
-                       rq_list_add(&requeue_list, rq);
+                       rq_list_add_tail(&requeue_lastp, rq);
                        continue;
                }
-               list_add_tail(&rq->queuelist, &list);
+               list_add(&rq->queuelist, &list);
                depth++;
        } while (!rq_list_empty(plug->mq_list));
 
index d6119c5d1069bc768eed9f7c518a6fa6172c71fd..a9764cbf7f8d24ab26367fd80aec7045d41f865d 100644 (file)
@@ -228,6 +228,12 @@ static inline unsigned short req_get_ioprio(struct request *req)
        *(listptr) = rq;                                \
 } while (0)
 
+#define rq_list_add_tail(lastpptr, rq) do {            \
+       (rq)->rq_next = NULL;                           \
+       **(lastpptr) = rq;                              \
+       *(lastpptr) = &rq->rq_next;                     \
+} while (0)
+
 #define rq_list_pop(listptr)                           \
 ({                                                     \
        struct request *__req = NULL;                   \