blk-mq: kill unused blk_mq_create_mq_map()
[cascardo/linux.git] / block / blk-mq.c
index e931a0e..f1c5263 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/sched/sysctl.h>
 #include <linux/delay.h>
 #include <linux/crash_dump.h>
+#include <linux/prefetch.h>
 
 #include <trace/events/block.h>
 
@@ -244,7 +245,7 @@ struct request *blk_mq_alloc_request(struct request_queue *q, int rw,
                return ERR_PTR(ret);
 
        ctx = blk_mq_get_ctx(q);
-       hctx = q->mq_ops->map_queue(q, ctx->cpu);
+       hctx = blk_mq_map_queue(q, ctx->cpu);
        blk_mq_set_alloc_data(&alloc_data, q, flags, ctx, hctx);
 
        rq = __blk_mq_alloc_request(&alloc_data, rw, 0);
@@ -253,7 +254,7 @@ struct request *blk_mq_alloc_request(struct request_queue *q, int rw,
                blk_mq_put_ctx(ctx);
 
                ctx = blk_mq_get_ctx(q);
-               hctx = q->mq_ops->map_queue(q, ctx->cpu);
+               hctx = blk_mq_map_queue(q, ctx->cpu);
                blk_mq_set_alloc_data(&alloc_data, q, flags, ctx, hctx);
                rq =  __blk_mq_alloc_request(&alloc_data, rw, 0);
                ctx = alloc_data.ctx;
@@ -337,11 +338,7 @@ EXPORT_SYMBOL_GPL(blk_mq_free_hctx_request);
 
 void blk_mq_free_request(struct request *rq)
 {
-       struct blk_mq_hw_ctx *hctx;
-       struct request_queue *q = rq->q;
-
-       hctx = q->mq_ops->map_queue(q, rq->mq_ctx->cpu);
-       blk_mq_free_hctx_request(hctx, rq);
+       blk_mq_free_hctx_request(blk_mq_map_queue(rq->q, rq->mq_ctx->cpu), rq);
 }
 EXPORT_SYMBOL_GPL(blk_mq_free_request);
 
@@ -501,7 +498,7 @@ EXPORT_SYMBOL(blk_mq_requeue_request);
 static void blk_mq_requeue_work(struct work_struct *work)
 {
        struct request_queue *q =
-               container_of(work, struct request_queue, requeue_work);
+               container_of(work, struct request_queue, requeue_work.work);
        LIST_HEAD(rq_list);
        struct request *rq, *next;
        unsigned long flags;
@@ -556,16 +553,24 @@ EXPORT_SYMBOL(blk_mq_add_to_requeue_list);
 
 void blk_mq_cancel_requeue_work(struct request_queue *q)
 {
-       cancel_work_sync(&q->requeue_work);
+       cancel_delayed_work_sync(&q->requeue_work);
 }
 EXPORT_SYMBOL_GPL(blk_mq_cancel_requeue_work);
 
 void blk_mq_kick_requeue_list(struct request_queue *q)
 {
-       kblockd_schedule_work(&q->requeue_work);
+       kblockd_schedule_delayed_work(&q->requeue_work, 0);
 }
 EXPORT_SYMBOL(blk_mq_kick_requeue_list);
 
+void blk_mq_delay_kick_requeue_list(struct request_queue *q,
+                                   unsigned long msecs)
+{
+       kblockd_schedule_delayed_work(&q->requeue_work,
+                                     msecs_to_jiffies(msecs));
+}
+EXPORT_SYMBOL(blk_mq_delay_kick_requeue_list);
+
 void blk_mq_abort_requeue_list(struct request_queue *q)
 {
        unsigned long flags;
@@ -588,8 +593,10 @@ EXPORT_SYMBOL(blk_mq_abort_requeue_list);
 
 struct request *blk_mq_tag_to_rq(struct blk_mq_tags *tags, unsigned int tag)
 {
-       if (tag < tags->nr_tags)
+       if (tag < tags->nr_tags) {
+               prefetch(tags->rqs[tag]);
                return tags->rqs[tag];
+       }
 
        return NULL;
 }
@@ -793,11 +800,12 @@ static void __blk_mq_run_hw_queue(struct blk_mq_hw_ctx *hctx)
        struct list_head *dptr;
        int queued;
 
-       WARN_ON(!cpumask_test_cpu(raw_smp_processor_id(), hctx->cpumask));
-
        if (unlikely(test_bit(BLK_MQ_S_STOPPED, &hctx->state)))
                return;
 
+       WARN_ON(!cpumask_test_cpu(raw_smp_processor_id(), hctx->cpumask) &&
+               cpu_online(hctx->next_cpu));
+
        hctx->run++;
 
        /*
@@ -935,8 +943,7 @@ void blk_mq_run_hw_queue(struct blk_mq_hw_ctx *hctx, bool async)
                put_cpu();
        }
 
-       kblockd_schedule_delayed_work_on(blk_mq_hctx_next_cpu(hctx),
-                       &hctx->run_work, 0);
+       kblockd_schedule_work_on(blk_mq_hctx_next_cpu(hctx), &hctx->run_work);
 }
 
 void blk_mq_run_hw_queues(struct request_queue *q, bool async)
@@ -957,7 +964,7 @@ EXPORT_SYMBOL(blk_mq_run_hw_queues);
 
 void blk_mq_stop_hw_queue(struct blk_mq_hw_ctx *hctx)
 {
-       cancel_delayed_work(&hctx->run_work);
+       cancel_work(&hctx->run_work);
        cancel_delayed_work(&hctx->delay_work);
        set_bit(BLK_MQ_S_STOPPED, &hctx->state);
 }
@@ -1010,7 +1017,7 @@ static void blk_mq_run_work_fn(struct work_struct *work)
 {
        struct blk_mq_hw_ctx *hctx;
 
-       hctx = container_of(work, struct blk_mq_hw_ctx, run_work.work);
+       hctx = container_of(work, struct blk_mq_hw_ctx, run_work);
 
        __blk_mq_run_hw_queue(hctx);
 }
@@ -1036,10 +1043,11 @@ void blk_mq_delay_queue(struct blk_mq_hw_ctx *hctx, unsigned long msecs)
 EXPORT_SYMBOL(blk_mq_delay_queue);
 
 static inline void __blk_mq_insert_req_list(struct blk_mq_hw_ctx *hctx,
-                                           struct blk_mq_ctx *ctx,
                                            struct request *rq,
                                            bool at_head)
 {
+       struct blk_mq_ctx *ctx = rq->mq_ctx;
+
        trace_block_rq_insert(hctx->queue, rq);
 
        if (at_head)
@@ -1053,22 +1061,16 @@ static void __blk_mq_insert_request(struct blk_mq_hw_ctx *hctx,
 {
        struct blk_mq_ctx *ctx = rq->mq_ctx;
 
-       __blk_mq_insert_req_list(hctx, ctx, rq, at_head);
+       __blk_mq_insert_req_list(hctx, rq, at_head);
        blk_mq_hctx_mark_pending(hctx, ctx);
 }
 
 void blk_mq_insert_request(struct request *rq, bool at_head, bool run_queue,
-               bool async)
+                          bool async)
 {
+       struct blk_mq_ctx *ctx = rq->mq_ctx;
        struct request_queue *q = rq->q;
-       struct blk_mq_hw_ctx *hctx;
-       struct blk_mq_ctx *ctx = rq->mq_ctx, *current_ctx;
-
-       current_ctx = blk_mq_get_ctx(q);
-       if (!cpu_online(ctx->cpu))
-               rq->mq_ctx = ctx = current_ctx;
-
-       hctx = q->mq_ops->map_queue(q, ctx->cpu);
+       struct blk_mq_hw_ctx *hctx = blk_mq_map_queue(q, ctx->cpu);
 
        spin_lock(&ctx->lock);
        __blk_mq_insert_request(hctx, rq, at_head);
@@ -1076,8 +1078,6 @@ void blk_mq_insert_request(struct request *rq, bool at_head, bool run_queue,
 
        if (run_queue)
                blk_mq_run_hw_queue(hctx, async);
-
-       blk_mq_put_ctx(current_ctx);
 }
 
 static void blk_mq_insert_requests(struct request_queue *q,
@@ -1087,17 +1087,10 @@ static void blk_mq_insert_requests(struct request_queue *q,
                                     bool from_schedule)
 
 {
-       struct blk_mq_hw_ctx *hctx;
-       struct blk_mq_ctx *current_ctx;
+       struct blk_mq_hw_ctx *hctx = blk_mq_map_queue(q, ctx->cpu);
 
        trace_block_unplug(q, depth, !from_schedule);
 
-       current_ctx = blk_mq_get_ctx(q);
-
-       if (!cpu_online(ctx->cpu))
-               ctx = current_ctx;
-       hctx = q->mq_ops->map_queue(q, ctx->cpu);
-
        /*
         * preemption doesn't flush plug list, so it's possible ctx->cpu is
         * offline now
@@ -1107,15 +1100,14 @@ static void blk_mq_insert_requests(struct request_queue *q,
                struct request *rq;
 
                rq = list_first_entry(list, struct request, queuelist);
+               BUG_ON(rq->mq_ctx != ctx);
                list_del_init(&rq->queuelist);
-               rq->mq_ctx = ctx;
-               __blk_mq_insert_req_list(hctx, ctx, rq, false);
+               __blk_mq_insert_req_list(hctx, rq, false);
        }
        blk_mq_hctx_mark_pending(hctx, ctx);
        spin_unlock(&ctx->lock);
 
        blk_mq_run_hw_queue(hctx, from_schedule);
-       blk_mq_put_ctx(current_ctx);
 }
 
 static int plug_ctx_cmp(void *priv, struct list_head *a, struct list_head *b)
@@ -1232,7 +1224,7 @@ static struct request *blk_mq_map_request(struct request_queue *q,
 
        blk_queue_enter_live(q);
        ctx = blk_mq_get_ctx(q);
-       hctx = q->mq_ops->map_queue(q, ctx->cpu);
+       hctx = blk_mq_map_queue(q, ctx->cpu);
 
        if (rw_is_sync(bio_op(bio), bio->bi_opf))
                op_flags |= REQ_SYNC;
@@ -1246,7 +1238,7 @@ static struct request *blk_mq_map_request(struct request_queue *q,
                trace_block_sleeprq(q, bio, op);
 
                ctx = blk_mq_get_ctx(q);
-               hctx = q->mq_ops->map_queue(q, ctx->cpu);
+               hctx = blk_mq_map_queue(q, ctx->cpu);
                blk_mq_set_alloc_data(&alloc_data, q, 0, ctx, hctx);
                rq = __blk_mq_alloc_request(&alloc_data, op, op_flags);
                ctx = alloc_data.ctx;
@@ -1263,8 +1255,7 @@ static int blk_mq_direct_issue_request(struct request *rq, blk_qc_t *cookie)
 {
        int ret;
        struct request_queue *q = rq->q;
-       struct blk_mq_hw_ctx *hctx = q->mq_ops->map_queue(q,
-                       rq->mq_ctx->cpu);
+       struct blk_mq_hw_ctx *hctx = blk_mq_map_queue(q, rq->mq_ctx->cpu);
        struct blk_mq_queue_data bd = {
                .rq = rq,
                .list = NULL,
@@ -1468,15 +1459,6 @@ run_queue:
        return cookie;
 }
 
-/*
- * Default mapping to a software queue, since we use one per CPU.
- */
-struct blk_mq_hw_ctx *blk_mq_map_queue(struct request_queue *q, const int cpu)
-{
-       return q->queue_hw_ctx[q->mq_map[cpu]];
-}
-EXPORT_SYMBOL(blk_mq_map_queue);
-
 static void blk_mq_free_rq_map(struct blk_mq_tag_set *set,
                struct blk_mq_tags *tags, unsigned int hctx_idx)
 {
@@ -1630,16 +1612,17 @@ static int blk_mq_alloc_bitmap(struct blk_mq_ctxmap *bitmap, int node)
        return 0;
 }
 
+/*
+ * 'cpu' is going away. splice any existing rq_list entries from this
+ * software queue to the hw queue dispatch list, and ensure that it
+ * gets run.
+ */
 static int blk_mq_hctx_cpu_offline(struct blk_mq_hw_ctx *hctx, int cpu)
 {
-       struct request_queue *q = hctx->queue;
        struct blk_mq_ctx *ctx;
        LIST_HEAD(tmp);
 
-       /*
-        * Move ctx entries to new CPU, if this one is going away.
-        */
-       ctx = __blk_mq_get_ctx(q, cpu);
+       ctx = __blk_mq_get_ctx(hctx->queue, cpu);
 
        spin_lock(&ctx->lock);
        if (!list_empty(&ctx->rq_list)) {
@@ -1651,24 +1634,11 @@ static int blk_mq_hctx_cpu_offline(struct blk_mq_hw_ctx *hctx, int cpu)
        if (list_empty(&tmp))
                return NOTIFY_OK;
 
-       ctx = blk_mq_get_ctx(q);
-       spin_lock(&ctx->lock);
-
-       while (!list_empty(&tmp)) {
-               struct request *rq;
-
-               rq = list_first_entry(&tmp, struct request, queuelist);
-               rq->mq_ctx = ctx;
-               list_move_tail(&rq->queuelist, &ctx->rq_list);
-       }
-
-       hctx = q->mq_ops->map_queue(q, ctx->cpu);
-       blk_mq_hctx_mark_pending(hctx, ctx);
-
-       spin_unlock(&ctx->lock);
+       spin_lock(&hctx->lock);
+       list_splice_tail_init(&tmp, &hctx->dispatch);
+       spin_unlock(&hctx->lock);
 
        blk_mq_run_hw_queue(hctx, true);
-       blk_mq_put_ctx(ctx);
        return NOTIFY_OK;
 }
 
@@ -1744,7 +1714,7 @@ static int blk_mq_init_hctx(struct request_queue *q,
        if (node == NUMA_NO_NODE)
                node = hctx->numa_node = set->numa_node;
 
-       INIT_DELAYED_WORK(&hctx->run_work, blk_mq_run_work_fn);
+       INIT_WORK(&hctx->run_work, blk_mq_run_work_fn);
        INIT_DELAYED_WORK(&hctx->delay_work, blk_mq_delay_work_fn);
        spin_lock_init(&hctx->lock);
        INIT_LIST_HEAD(&hctx->dispatch);
@@ -1822,7 +1792,7 @@ static void blk_mq_init_cpu_queues(struct request_queue *q,
                if (!cpu_online(i))
                        continue;
 
-               hctx = q->mq_ops->map_queue(q, i);
+               hctx = blk_mq_map_queue(q, i);
 
                /*
                 * Set local node, IFF we have more than one hw queue. If
@@ -1860,7 +1830,7 @@ static void blk_mq_map_swqueue(struct request_queue *q,
                        continue;
 
                ctx = per_cpu_ptr(q->queue_ctx, i);
-               hctx = q->mq_ops->map_queue(q, i);
+               hctx = blk_mq_map_queue(q, i);
 
                cpumask_set_cpu(i, hctx->cpumask);
                ctx->index_hw = hctx->nr_ctx;
@@ -1891,7 +1861,6 @@ static void blk_mq_map_swqueue(struct request_queue *q,
                hctx->tags = set->tags[i];
                WARN_ON(!hctx->tags);
 
-               cpumask_copy(hctx->tags->cpumask, hctx->cpumask);
                /*
                 * Set the map size to the number of mapped software queues.
                 * This is more accurate and more efficient than looping
@@ -1985,7 +1954,6 @@ void blk_mq_release(struct request_queue *q)
                kfree(hctx);
        }
 
-       kfree(q->mq_map);
        q->mq_map = NULL;
 
        kfree(q->queue_hw_ctx);
@@ -2084,9 +2052,7 @@ struct request_queue *blk_mq_init_allocated_queue(struct blk_mq_tag_set *set,
        if (!q->queue_hw_ctx)
                goto err_percpu;
 
-       q->mq_map = blk_mq_make_queue_map(set);
-       if (!q->mq_map)
-               goto err_map;
+       q->mq_map = set->mq_map;
 
        blk_mq_realloc_hw_ctxs(set, q);
        if (!q->nr_hw_queues)
@@ -2104,7 +2070,7 @@ struct request_queue *blk_mq_init_allocated_queue(struct blk_mq_tag_set *set,
 
        q->sg_reserved_size = INT_MAX;
 
-       INIT_WORK(&q->requeue_work, blk_mq_requeue_work);
+       INIT_DELAYED_WORK(&q->requeue_work, blk_mq_requeue_work);
        INIT_LIST_HEAD(&q->requeue_list);
        spin_lock_init(&q->requeue_lock);
 
@@ -2136,8 +2102,6 @@ struct request_queue *blk_mq_init_allocated_queue(struct blk_mq_tag_set *set,
        return q;
 
 err_hctxs:
-       kfree(q->mq_map);
-err_map:
        kfree(q->queue_hw_ctx);
 err_percpu:
        free_percpu(q->queue_ctx);
@@ -2169,8 +2133,6 @@ static void blk_mq_queue_reinit(struct request_queue *q,
 
        blk_mq_sysfs_unregister(q);
 
-       blk_mq_update_queue_map(q->mq_map, q->nr_hw_queues, online_mask);
-
        /*
         * redo blk_mq_init_cpu_queues and blk_mq_init_hw_queues. FIXME: maybe
         * we should change hctx numa_node according to new topology (this
@@ -2309,12 +2271,6 @@ static int blk_mq_alloc_rq_maps(struct blk_mq_tag_set *set)
        return 0;
 }
 
-struct cpumask *blk_mq_tags_cpumask(struct blk_mq_tags *tags)
-{
-       return tags->cpumask;
-}
-EXPORT_SYMBOL_GPL(blk_mq_tags_cpumask);
-
 /*
  * Alloc a tag set to be associated with one or more request queues.
  * May fail with EINVAL for various error conditions. May adjust the
@@ -2323,6 +2279,8 @@ EXPORT_SYMBOL_GPL(blk_mq_tags_cpumask);
  */
 int blk_mq_alloc_tag_set(struct blk_mq_tag_set *set)
 {
+       int ret;
+
        BUILD_BUG_ON(BLK_MQ_MAX_DEPTH > 1 << BLK_MQ_UNIQUE_TAG_BITS);
 
        if (!set->nr_hw_queues)
@@ -2332,7 +2290,7 @@ int blk_mq_alloc_tag_set(struct blk_mq_tag_set *set)
        if (set->queue_depth < set->reserved_tags + BLK_MQ_TAG_MIN)
                return -EINVAL;
 
-       if (!set->ops->queue_rq || !set->ops->map_queue)
+       if (!set->ops->queue_rq)
                return -EINVAL;
 
        if (set->queue_depth > BLK_MQ_MAX_DEPTH) {
@@ -2361,17 +2319,35 @@ int blk_mq_alloc_tag_set(struct blk_mq_tag_set *set)
        if (!set->tags)
                return -ENOMEM;
 
-       if (blk_mq_alloc_rq_maps(set))
-               goto enomem;
+       ret = -ENOMEM;
+       set->mq_map = kzalloc_node(sizeof(*set->mq_map) * nr_cpu_ids,
+                       GFP_KERNEL, set->numa_node);
+       if (!set->mq_map)
+               goto out_free_tags;
+
+       if (set->ops->map_queues)
+               ret = set->ops->map_queues(set);
+       else
+               ret = blk_mq_map_queues(set);
+       if (ret)
+               goto out_free_mq_map;
+
+       ret = blk_mq_alloc_rq_maps(set);
+       if (ret)
+               goto out_free_mq_map;
 
        mutex_init(&set->tag_list_lock);
        INIT_LIST_HEAD(&set->tag_list);
 
        return 0;
-enomem:
+
+out_free_mq_map:
+       kfree(set->mq_map);
+       set->mq_map = NULL;
+out_free_tags:
        kfree(set->tags);
        set->tags = NULL;
-       return -ENOMEM;
+       return ret;
 }
 EXPORT_SYMBOL(blk_mq_alloc_tag_set);
 
@@ -2384,6 +2360,9 @@ void blk_mq_free_tag_set(struct blk_mq_tag_set *set)
                        blk_mq_free_rq_map(set, set->tags[i], i);
        }
 
+       kfree(set->mq_map);
+       set->mq_map = NULL;
+
        kfree(set->tags);
        set->tags = NULL;
 }