blk-mq: improve plug list sorting
authorJens Axboe <axboe@kernel.dk>
Tue, 30 Oct 2018 18:24:04 +0000 (12:24 -0600)
committerJens Axboe <axboe@kernel.dk>
Wed, 7 Nov 2018 20:45:00 +0000 (13:45 -0700)
Currently we only look at the software queue, but with support
for multiple maps, we should also look at the hardware queue.
This is important since we'll flush out the request list if
either the software queue or hardware queue don't match.

This sorts by software queue first, then hardware queue if
that differs. Finally we sort by request location like before.
This minimizes the flush points per plug list.

Reviewed-by: Keith Busch <keith.busch@intel.com>
Reviewed-by: Sagi Grimberg <sagi@grimberg.me>
Reviewed-by: Hannes Reinecke <hare@suse.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
block/blk-mq.c

index 271726d48003481e7a6f969475d8561aac0cb343..45c92b8d4795d29569cd58dd08b34f62f15aa697 100644 (file)
@@ -1612,14 +1612,21 @@ void blk_mq_insert_requests(struct blk_mq_hw_ctx *hctx, struct blk_mq_ctx *ctx,
        spin_unlock(&ctx->lock);
 }
 
-static int plug_ctx_cmp(void *priv, struct list_head *a, struct list_head *b)
+static int plug_rq_cmp(void *priv, struct list_head *a, struct list_head *b)
 {
        struct request *rqa = container_of(a, struct request, queuelist);
        struct request *rqb = container_of(b, struct request, queuelist);
 
-       return !(rqa->mq_ctx < rqb->mq_ctx ||
-                (rqa->mq_ctx == rqb->mq_ctx &&
-                 blk_rq_pos(rqa) < blk_rq_pos(rqb)));
+       if (rqa->mq_ctx < rqb->mq_ctx)
+               return -1;
+       else if (rqa->mq_ctx > rqb->mq_ctx)
+               return 1;
+       else if (rqa->mq_hctx < rqb->mq_hctx)
+               return -1;
+       else if (rqa->mq_hctx > rqb->mq_hctx)
+               return 1;
+
+       return blk_rq_pos(rqa) > blk_rq_pos(rqb);
 }
 
 void blk_mq_flush_plug_list(struct blk_plug *plug, bool from_schedule)
@@ -1634,7 +1641,7 @@ void blk_mq_flush_plug_list(struct blk_plug *plug, bool from_schedule)
 
        list_splice_init(&plug->mq_list, &list);
 
-       list_sort(NULL, &list, plug_ctx_cmp);
+       list_sort(NULL, &list, plug_rq_cmp);
 
        this_q = NULL;
        this_hctx = NULL;