Merge "blk-mq: use static mapping"

This commit is contained in:
Linux Build Service Account 2016-10-03 10:34:53 -07:00 committed by Gerrit - the friendly Code Review server
commit abc3610d33
3 changed files with 39 additions and 85 deletions

View file

@ -31,8 +31,8 @@ static int get_first_sibling(unsigned int cpu)
return cpu; return cpu;
} }
int blk_mq_update_queue_map(unsigned int *map, unsigned int nr_queues, static int blk_mq_update_queue_map(unsigned int *map,
const struct cpumask *online_mask) unsigned int nr_queues, const struct cpumask *online_mask)
{ {
unsigned int i, nr_cpus, nr_uniq_cpus, queue, first_sibling; unsigned int i, nr_cpus, nr_uniq_cpus, queue, first_sibling;
cpumask_var_t cpus; cpumask_var_t cpus;
@ -52,18 +52,14 @@ int blk_mq_update_queue_map(unsigned int *map, unsigned int nr_queues,
queue = 0; queue = 0;
for_each_possible_cpu(i) { for_each_possible_cpu(i) {
if (!cpumask_test_cpu(i, online_mask)) {
map[i] = 0;
continue;
}
/* /*
* Easy case - we have equal or more hardware queues. Or * Easy case - we have equal or more hardware queues. Or
* there are no thread siblings to take into account. Do * there are no thread siblings to take into account. Do
* 1:1 if enough, or sequential mapping if less. * 1:1 if enough, or sequential mapping if less.
*/ */
if (nr_queues >= nr_cpus || nr_cpus == nr_uniq_cpus) { if (nr_queues >= nr_cpu_ids) {
map[i] = cpu_to_queue_index(nr_cpus, nr_queues, queue); map[i] = cpu_to_queue_index(nr_cpu_ids, nr_queues,
queue);
queue++; queue++;
continue; continue;
} }
@ -75,7 +71,7 @@ int blk_mq_update_queue_map(unsigned int *map, unsigned int nr_queues,
*/ */
first_sibling = get_first_sibling(i); first_sibling = get_first_sibling(i);
if (first_sibling == i) { if (first_sibling == i) {
map[i] = cpu_to_queue_index(nr_uniq_cpus, nr_queues, map[i] = cpu_to_queue_index(nr_cpu_ids, nr_queues,
queue); queue);
queue++; queue++;
} else } else

View file

@ -1783,10 +1783,6 @@ static void blk_mq_init_cpu_queues(struct request_queue *q,
INIT_LIST_HEAD(&__ctx->rq_list); INIT_LIST_HEAD(&__ctx->rq_list);
__ctx->queue = q; __ctx->queue = q;
/* If the cpu isn't online, the cpu is mapped to first hctx */
if (!cpu_online(i))
continue;
hctx = q->mq_ops->map_queue(q, i); hctx = q->mq_ops->map_queue(q, i);
/* /*
@ -1820,12 +1816,9 @@ static void blk_mq_map_swqueue(struct request_queue *q,
* Map software to hardware queues * Map software to hardware queues
*/ */
queue_for_each_ctx(q, ctx, i) { queue_for_each_ctx(q, ctx, i) {
/* If the cpu isn't online, the cpu is mapped to first hctx */
if (!cpumask_test_cpu(i, online_mask))
continue;
hctx = q->mq_ops->map_queue(q, i); hctx = q->mq_ops->map_queue(q, i);
cpumask_set_cpu(i, hctx->cpumask); if (cpumask_test_cpu(i, online_mask))
cpumask_set_cpu(i, hctx->cpumask);
ctx->index_hw = hctx->nr_ctx; ctx->index_hw = hctx->nr_ctx;
hctx->ctxs[hctx->nr_ctx++] = ctx; hctx->ctxs[hctx->nr_ctx++] = ctx;
} }
@ -1863,17 +1856,22 @@ static void blk_mq_map_swqueue(struct request_queue *q,
/* /*
* Initialize batch roundrobin counts * Initialize batch roundrobin counts
* Set next_cpu for only those hctxs that have an online CPU
* in their cpumask field. For hctxs that belong to few online
* and few offline CPUs, this will always provide one CPU from
* online ones. For hctxs belonging to all offline CPUs, their
* cpumask will be updated in reinit_notify.
*/ */
hctx->next_cpu = cpumask_first(hctx->cpumask); if (cpumask_first(hctx->cpumask) < nr_cpu_ids) {
hctx->next_cpu_batch = BLK_MQ_CPU_WORK_BATCH; hctx->next_cpu = cpumask_first(hctx->cpumask);
hctx->next_cpu_batch = BLK_MQ_CPU_WORK_BATCH;
}
} }
queue_for_each_ctx(q, ctx, i) { queue_for_each_ctx(q, ctx, i) {
if (!cpumask_test_cpu(i, online_mask))
continue;
hctx = q->mq_ops->map_queue(q, i); hctx = q->mq_ops->map_queue(q, i);
cpumask_set_cpu(i, hctx->tags->cpumask); if (cpumask_test_cpu(i, online_mask))
cpumask_set_cpu(i, hctx->tags->cpumask);
} }
} }
@ -2101,38 +2099,13 @@ void blk_mq_free_queue(struct request_queue *q)
blk_mq_free_hw_queues(q, set); blk_mq_free_hw_queues(q, set);
} }
/* Basically redo blk_mq_init_queue with queue frozen */
static void blk_mq_queue_reinit(struct request_queue *q,
const struct cpumask *online_mask)
{
WARN_ON_ONCE(!atomic_read(&q->mq_freeze_depth));
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
* involves free and re-allocate memory, worthy doing?)
*/
blk_mq_map_swqueue(q, online_mask);
blk_mq_sysfs_register(q);
}
static int blk_mq_queue_reinit_notify(struct notifier_block *nb, static int blk_mq_queue_reinit_notify(struct notifier_block *nb,
unsigned long action, void *hcpu) unsigned long action, void *hcpu)
{ {
struct request_queue *q; struct request_queue *q;
struct blk_mq_hw_ctx *hctx;
int i;
int cpu = (unsigned long)hcpu; int cpu = (unsigned long)hcpu;
/*
* New online cpumask which is going to be set in this hotplug event.
* Declare this cpumasks as global as cpu-hotplug operation is invoked
* one-by-one and dynamically allocating this could result in a failure.
*/
static struct cpumask online_new;
/* /*
* Before hotadded cpu starts handling requests, new mappings must * Before hotadded cpu starts handling requests, new mappings must
@ -2154,44 +2127,31 @@ static int blk_mq_queue_reinit_notify(struct notifier_block *nb,
switch (action & ~CPU_TASKS_FROZEN) { switch (action & ~CPU_TASKS_FROZEN) {
case CPU_DEAD: case CPU_DEAD:
case CPU_UP_CANCELED: case CPU_UP_CANCELED:
cpumask_copy(&online_new, cpu_online_mask); mutex_lock(&all_q_mutex);
list_for_each_entry(q, &all_q_list, all_q_node) {
queue_for_each_hw_ctx(q, hctx, i) {
cpumask_clear_cpu(cpu, hctx->cpumask);
cpumask_clear_cpu(cpu, hctx->tags->cpumask);
}
}
mutex_unlock(&all_q_mutex);
break; break;
case CPU_UP_PREPARE: case CPU_UP_PREPARE:
cpumask_copy(&online_new, cpu_online_mask); /* Update hctx->cpumask for newly onlined CPUs */
cpumask_set_cpu(cpu, &online_new); mutex_lock(&all_q_mutex);
list_for_each_entry(q, &all_q_list, all_q_node) {
queue_for_each_hw_ctx(q, hctx, i) {
cpumask_set_cpu(cpu, hctx->cpumask);
hctx->next_cpu_batch = BLK_MQ_CPU_WORK_BATCH;
cpumask_set_cpu(cpu, hctx->tags->cpumask);
}
}
mutex_unlock(&all_q_mutex);
break; break;
default: default:
return NOTIFY_OK; return NOTIFY_OK;
} }
mutex_lock(&all_q_mutex);
/*
* We need to freeze and reinit all existing queues. Freezing
* involves synchronous wait for an RCU grace period and doing it
* one by one may take a long time. Start freezing all queues in
* one swoop and then wait for the completions so that freezing can
* take place in parallel.
*/
list_for_each_entry(q, &all_q_list, all_q_node)
blk_mq_freeze_queue_start(q);
list_for_each_entry(q, &all_q_list, all_q_node) {
blk_mq_freeze_queue_wait(q);
/*
* timeout handler can't touch hw queue during the
* reinitialization
*/
del_timer_sync(&q->timeout);
}
list_for_each_entry(q, &all_q_list, all_q_node)
blk_mq_queue_reinit(q, &online_new);
list_for_each_entry(q, &all_q_list, all_q_node)
blk_mq_unfreeze_queue(q);
mutex_unlock(&all_q_mutex);
return NOTIFY_OK; return NOTIFY_OK;
} }

View file

@ -48,8 +48,6 @@ void blk_mq_disable_hotplug(void);
* CPU -> queue mappings * CPU -> queue mappings
*/ */
extern unsigned int *blk_mq_make_queue_map(struct blk_mq_tag_set *set); extern unsigned int *blk_mq_make_queue_map(struct blk_mq_tag_set *set);
extern int blk_mq_update_queue_map(unsigned int *map, unsigned int nr_queues,
const struct cpumask *online_mask);
extern int blk_mq_hw_queue_to_node(unsigned int *map, unsigned int); extern int blk_mq_hw_queue_to_node(unsigned int *map, unsigned int);
/* /*