block: Reduce the amount of memory required per request queue
authorBart Van Assche <bvanassche@acm.org>
Fri, 25 Oct 2019 16:50:09 +0000 (09:50 -0700)
committerJens Axboe <axboe@kernel.dk>
Fri, 25 Oct 2019 20:12:18 +0000 (14:12 -0600)
Instead of always allocating at least nr_cpu_ids hardware queues per request
queue, reallocate q->queue_hw_ctx if it has to grow. This patch improves
behavior that was introduced by commit 868f2f0b7206 ("blk-mq: dynamic h/w
context count").

Cc: Keith Busch <keith.busch@intel.com>
Cc: Christoph Hellwig <hch@infradead.org>
Cc: Ming Lei <ming.lei@redhat.com>
Cc: Hannes Reinecke <hare@suse.com>
Cc: Johannes Thumshirn <jthumshirn@suse.de>
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
block/blk-mq.c

index 7528678ef41fc8fe65ba9fa95fc30f5b7bf951fe..ba09cda49953fee5a92e713f1de1544dd509857f 100644 (file)
@@ -2761,6 +2761,23 @@ static void blk_mq_realloc_hw_ctxs(struct blk_mq_tag_set *set,
        int i, j, end;
        struct blk_mq_hw_ctx **hctxs = q->queue_hw_ctx;
 
+       if (q->nr_hw_queues < set->nr_hw_queues) {
+               struct blk_mq_hw_ctx **new_hctxs;
+
+               new_hctxs = kcalloc_node(set->nr_hw_queues,
+                                      sizeof(*new_hctxs), GFP_KERNEL,
+                                      set->numa_node);
+               if (!new_hctxs)
+                       return;
+               if (hctxs)
+                       memcpy(new_hctxs, hctxs, q->nr_hw_queues *
+                              sizeof(*hctxs));
+               q->queue_hw_ctx = new_hctxs;
+               q->nr_hw_queues = set->nr_hw_queues;
+               kfree(hctxs);
+               hctxs = new_hctxs;
+       }
+
        /* protect against switching io scheduler  */
        mutex_lock(&q->sysfs_lock);
        for (i = 0; i < set->nr_hw_queues; i++) {
@@ -2848,12 +2865,6 @@ struct request_queue *blk_mq_init_allocated_queue(struct blk_mq_tag_set *set,
        /* init q->mq_kobj and sw queues' kobjects */
        blk_mq_sysfs_init(q);
 
-       q->queue_hw_ctx = kcalloc_node(nr_hw_queues(set),
-                                      sizeof(*(q->queue_hw_ctx)), GFP_KERNEL,
-                                      set->numa_node);
-       if (!q->queue_hw_ctx)
-               goto err_sys_init;
-
        INIT_LIST_HEAD(&q->unused_hctx_list);
        spin_lock_init(&q->unused_hctx_lock);
 
@@ -2901,7 +2912,6 @@ struct request_queue *blk_mq_init_allocated_queue(struct blk_mq_tag_set *set,
 err_hctxs:
        kfree(q->queue_hw_ctx);
        q->nr_hw_queues = 0;
-err_sys_init:
        blk_mq_sysfs_deinit(q);
 err_poll:
        blk_stat_free_callback(q->poll_cb);