|
@@ -1870,7 +1870,7 @@ static void blk_mq_init_cpu_queues(struct request_queue *q,
|
|
|
static void blk_mq_map_swqueue(struct request_queue *q,
|
|
|
const struct cpumask *online_mask)
|
|
|
{
|
|
|
- unsigned int i;
|
|
|
+ unsigned int i, hctx_idx;
|
|
|
struct blk_mq_hw_ctx *hctx;
|
|
|
struct blk_mq_ctx *ctx;
|
|
|
struct blk_mq_tag_set *set = q->tag_set;
|
|
@@ -1893,6 +1893,21 @@ static void blk_mq_map_swqueue(struct request_queue *q,
|
|
|
if (!cpumask_test_cpu(i, online_mask))
|
|
|
continue;
|
|
|
|
|
|
+ hctx_idx = q->mq_map[i];
|
|
|
+ /* unmapped hw queue can be remapped after CPU topo changed */
|
|
|
+ if (!set->tags[hctx_idx]) {
|
|
|
+ set->tags[hctx_idx] = blk_mq_init_rq_map(set, hctx_idx);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * If tags initialization fail for some hctx,
|
|
|
+ * that hctx won't be brought online. In this
|
|
|
+ * case, remap the current ctx to hctx[0] which
|
|
|
+ * is guaranteed to always have tags allocated
|
|
|
+ */
|
|
|
+ if (!set->tags[hctx_idx])
|
|
|
+ q->mq_map[i] = 0;
|
|
|
+ }
|
|
|
+
|
|
|
ctx = per_cpu_ptr(q->queue_ctx, i);
|
|
|
hctx = blk_mq_map_queue(q, i);
|
|
|
|
|
@@ -1909,7 +1924,11 @@ static void blk_mq_map_swqueue(struct request_queue *q,
|
|
|
* disable it and free the request entries.
|
|
|
*/
|
|
|
if (!hctx->nr_ctx) {
|
|
|
- if (set->tags[i]) {
|
|
|
+ /* Never unmap queue 0. We need it as a
|
|
|
+ * fallback in case of a new remap fails
|
|
|
+ * allocation
|
|
|
+ */
|
|
|
+ if (i && set->tags[i]) {
|
|
|
blk_mq_free_rq_map(set, set->tags[i], i);
|
|
|
set->tags[i] = NULL;
|
|
|
}
|
|
@@ -1917,9 +1936,6 @@ static void blk_mq_map_swqueue(struct request_queue *q,
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
- /* unmapped hw queue can be remapped after CPU topo changed */
|
|
|
- if (!set->tags[i])
|
|
|
- set->tags[i] = blk_mq_init_rq_map(set, i);
|
|
|
hctx->tags = set->tags[i];
|
|
|
WARN_ON(!hctx->tags);
|
|
|
|