From: Ming Lin <ming.l@xxxxxxxxxxxxxxx> Suppose that a system has 8 logical CPUs(4 cores with hyperthread) and that 5 hardware queues are provided by a block driver. With the current algorithm this will lead to the following assignment of logical CPU to hardware queue: HWQ 0: 0 1 HWQ 1: 2 3 HWQ 2: 4 5 HWQ 3: 6 7 HWQ 4: (none) One way to fix it is to change the algorithm so the assignment may be: HWQ 0: 0 1 HWQ 1: 2 3 HWQ 2: 4 5 HWQ 3: 6 HWQ 4: 7 This patch only checks if all HW queues are mapped to cpu. blk_mq_init_queue() will fail if not all HW queues are mapped. And it also fails when hardware queue numbers > cpu numbers. Signed-off-by: Ming Lin <ming.l@xxxxxxxxxxxxxxxx> --- block/blk-mq-cpumap.c | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/block/blk-mq-cpumap.c b/block/blk-mq-cpumap.c index 8764c24..5a88ac4 100644 --- a/block/blk-mq-cpumap.c +++ b/block/blk-mq-cpumap.c @@ -36,10 +36,17 @@ int blk_mq_update_queue_map(unsigned int *map, unsigned int nr_queues, { unsigned int i, nr_cpus, nr_uniq_cpus, queue, first_sibling; cpumask_var_t cpus; + int *queue_map; - if (!alloc_cpumask_var(&cpus, GFP_ATOMIC)) + queue_map = kzalloc(sizeof(int) * nr_queues, GFP_KERNEL); + if (!queue_map) return 1; + if (!alloc_cpumask_var(&cpus, GFP_ATOMIC)) { + kfree(queue_map); + return 1; + } + cpumask_clear(cpus); nr_cpus = nr_uniq_cpus = 0; for_each_cpu(i, online_mask) { @@ -54,7 +61,7 @@ int blk_mq_update_queue_map(unsigned int *map, unsigned int nr_queues, for_each_possible_cpu(i) { if (!cpumask_test_cpu(i, online_mask)) { map[i] = 0; - continue; + goto mapped; } /* @@ -65,7 +72,7 @@ int blk_mq_update_queue_map(unsigned int *map, unsigned int nr_queues, if (nr_queues >= nr_cpus || nr_cpus == nr_uniq_cpus) { map[i] = cpu_to_queue_index(nr_cpus, nr_queues, queue); queue++; - continue; + goto mapped; } /* @@ -80,10 +87,22 @@ int blk_mq_update_queue_map(unsigned int *map, unsigned int nr_queues, queue++; } else map[i] = map[first_sibling]; + +mapped: + /* i is cpu, map[i] is queue index */ + queue_map[map[i]] = 1; } free_cpumask_var(cpus); - return 0; + + /* check if all queues are mapped to cpu */ + for (i = 0; i < nr_queues; i++) + if (!queue_map[i]) + break; + + kfree(queue_map); + + return i != nr_queues; } unsigned int *blk_mq_make_queue_map(struct blk_mq_tag_set *set) -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-block" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html