aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJens Axboe <axboe@fb.com>2016-08-24 17:34:35 -0400
committerJens Axboe <axboe@fb.com>2016-08-24 17:34:35 -0400
commite57690fe009b2ab0cee8a57f53be634540e49c9d (patch)
tree58bbfa1e382f1445e277e9d1833ac131fc0a9ae2
parent4d70dca4eadf2f95abe389116ac02b8439c2d16c (diff)
blk-mq: don't overwrite rq->mq_ctx
We do this in a few places, if the CPU is offline. This isn't allowed, though, since on multi queue hardware, we can't just move a request from one software queue to another, if they map to different hardware queues. The request and tag isn't valid on another hardware queue. This can happen if plugging races with CPU offlining. But it does no harm, since it can only happen in the window where we are currently busy freezing the queue and flushing IO, in preparation for redoing the software <-> hardware queue mappings. Signed-off-by: Jens Axboe <axboe@fb.com>
-rw-r--r--block/blk-mq.c55
1 files changed, 16 insertions, 39 deletions
diff --git a/block/blk-mq.c b/block/blk-mq.c
index e931a0e8e73d..729169d022fc 100644
--- a/block/blk-mq.c
+++ b/block/blk-mq.c
@@ -1036,10 +1036,11 @@ void blk_mq_delay_queue(struct blk_mq_hw_ctx *hctx, unsigned long msecs)
1036EXPORT_SYMBOL(blk_mq_delay_queue); 1036EXPORT_SYMBOL(blk_mq_delay_queue);
1037 1037
1038static inline void __blk_mq_insert_req_list(struct blk_mq_hw_ctx *hctx, 1038static inline void __blk_mq_insert_req_list(struct blk_mq_hw_ctx *hctx,
1039 struct blk_mq_ctx *ctx,
1040 struct request *rq, 1039 struct request *rq,
1041 bool at_head) 1040 bool at_head)
1042{ 1041{
1042 struct blk_mq_ctx *ctx = rq->mq_ctx;
1043
1043 trace_block_rq_insert(hctx->queue, rq); 1044 trace_block_rq_insert(hctx->queue, rq);
1044 1045
1045 if (at_head) 1046 if (at_head)
@@ -1053,20 +1054,16 @@ static void __blk_mq_insert_request(struct blk_mq_hw_ctx *hctx,
1053{ 1054{
1054 struct blk_mq_ctx *ctx = rq->mq_ctx; 1055 struct blk_mq_ctx *ctx = rq->mq_ctx;
1055 1056
1056 __blk_mq_insert_req_list(hctx, ctx, rq, at_head); 1057 __blk_mq_insert_req_list(hctx, rq, at_head);
1057 blk_mq_hctx_mark_pending(hctx, ctx); 1058 blk_mq_hctx_mark_pending(hctx, ctx);
1058} 1059}
1059 1060
1060void blk_mq_insert_request(struct request *rq, bool at_head, bool run_queue, 1061void blk_mq_insert_request(struct request *rq, bool at_head, bool run_queue,
1061 bool async) 1062 bool async)
1062{ 1063{
1064 struct blk_mq_ctx *ctx = rq->mq_ctx;
1063 struct request_queue *q = rq->q; 1065 struct request_queue *q = rq->q;
1064 struct blk_mq_hw_ctx *hctx; 1066 struct blk_mq_hw_ctx *hctx;
1065 struct blk_mq_ctx *ctx = rq->mq_ctx, *current_ctx;
1066
1067 current_ctx = blk_mq_get_ctx(q);
1068 if (!cpu_online(ctx->cpu))
1069 rq->mq_ctx = ctx = current_ctx;
1070 1067
1071 hctx = q->mq_ops->map_queue(q, ctx->cpu); 1068 hctx = q->mq_ops->map_queue(q, ctx->cpu);
1072 1069
@@ -1076,8 +1073,6 @@ void blk_mq_insert_request(struct request *rq, bool at_head, bool run_queue,
1076 1073
1077 if (run_queue) 1074 if (run_queue)
1078 blk_mq_run_hw_queue(hctx, async); 1075 blk_mq_run_hw_queue(hctx, async);
1079
1080 blk_mq_put_ctx(current_ctx);
1081} 1076}
1082 1077
1083static void blk_mq_insert_requests(struct request_queue *q, 1078static void blk_mq_insert_requests(struct request_queue *q,
@@ -1088,14 +1083,9 @@ static void blk_mq_insert_requests(struct request_queue *q,
1088 1083
1089{ 1084{
1090 struct blk_mq_hw_ctx *hctx; 1085 struct blk_mq_hw_ctx *hctx;
1091 struct blk_mq_ctx *current_ctx;
1092 1086
1093 trace_block_unplug(q, depth, !from_schedule); 1087 trace_block_unplug(q, depth, !from_schedule);
1094 1088
1095 current_ctx = blk_mq_get_ctx(q);
1096
1097 if (!cpu_online(ctx->cpu))
1098 ctx = current_ctx;
1099 hctx = q->mq_ops->map_queue(q, ctx->cpu); 1089 hctx = q->mq_ops->map_queue(q, ctx->cpu);
1100 1090
1101 /* 1091 /*
@@ -1107,15 +1097,14 @@ static void blk_mq_insert_requests(struct request_queue *q,
1107 struct request *rq; 1097 struct request *rq;
1108 1098
1109 rq = list_first_entry(list, struct request, queuelist); 1099 rq = list_first_entry(list, struct request, queuelist);
1100 BUG_ON(rq->mq_ctx != ctx);
1110 list_del_init(&rq->queuelist); 1101 list_del_init(&rq->queuelist);
1111 rq->mq_ctx = ctx; 1102 __blk_mq_insert_req_list(hctx, rq, false);
1112 __blk_mq_insert_req_list(hctx, ctx, rq, false);
1113 } 1103 }
1114 blk_mq_hctx_mark_pending(hctx, ctx); 1104 blk_mq_hctx_mark_pending(hctx, ctx);
1115 spin_unlock(&ctx->lock); 1105 spin_unlock(&ctx->lock);
1116 1106
1117 blk_mq_run_hw_queue(hctx, from_schedule); 1107 blk_mq_run_hw_queue(hctx, from_schedule);
1118 blk_mq_put_ctx(current_ctx);
1119} 1108}
1120 1109
1121static int plug_ctx_cmp(void *priv, struct list_head *a, struct list_head *b) 1110static int plug_ctx_cmp(void *priv, struct list_head *a, struct list_head *b)
@@ -1630,16 +1619,17 @@ static int blk_mq_alloc_bitmap(struct blk_mq_ctxmap *bitmap, int node)
1630 return 0; 1619 return 0;
1631} 1620}
1632 1621
1622/*
1623 * 'cpu' is going away. splice any existing rq_list entries from this
1624 * software queue to the hw queue dispatch list, and ensure that it
1625 * gets run.
1626 */
1633static int blk_mq_hctx_cpu_offline(struct blk_mq_hw_ctx *hctx, int cpu) 1627static int blk_mq_hctx_cpu_offline(struct blk_mq_hw_ctx *hctx, int cpu)
1634{ 1628{
1635 struct request_queue *q = hctx->queue;
1636 struct blk_mq_ctx *ctx; 1629 struct blk_mq_ctx *ctx;
1637 LIST_HEAD(tmp); 1630 LIST_HEAD(tmp);
1638 1631
1639 /* 1632 ctx = __blk_mq_get_ctx(hctx->queue, cpu);
1640 * Move ctx entries to new CPU, if this one is going away.
1641 */
1642 ctx = __blk_mq_get_ctx(q, cpu);
1643 1633
1644 spin_lock(&ctx->lock); 1634 spin_lock(&ctx->lock);
1645 if (!list_empty(&ctx->rq_list)) { 1635 if (!list_empty(&ctx->rq_list)) {
@@ -1651,24 +1641,11 @@ static int blk_mq_hctx_cpu_offline(struct blk_mq_hw_ctx *hctx, int cpu)
1651 if (list_empty(&tmp)) 1641 if (list_empty(&tmp))
1652 return NOTIFY_OK; 1642 return NOTIFY_OK;
1653 1643
1654 ctx = blk_mq_get_ctx(q); 1644 spin_lock(&hctx->lock);
1655 spin_lock(&ctx->lock); 1645 list_splice_tail_init(&tmp, &hctx->dispatch);
1656 1646 spin_unlock(&hctx->lock);
1657 while (!list_empty(&tmp)) {
1658 struct request *rq;
1659
1660 rq = list_first_entry(&tmp, struct request, queuelist);
1661 rq->mq_ctx = ctx;
1662 list_move_tail(&rq->queuelist, &ctx->rq_list);
1663 }
1664
1665 hctx = q->mq_ops->map_queue(q, ctx->cpu);
1666 blk_mq_hctx_mark_pending(hctx, ctx);
1667
1668 spin_unlock(&ctx->lock);
1669 1647
1670 blk_mq_run_hw_queue(hctx, true); 1648 blk_mq_run_hw_queue(hctx, true);
1671 blk_mq_put_ctx(ctx);
1672 return NOTIFY_OK; 1649 return NOTIFY_OK;
1673} 1650}
1674 1651