Re: [GIT PULL] workqueue fixes for v4.13-rc3

From: Tejun Heo
Date: Wed Aug 23 2017 - 13:08:16 EST


Hello, Geert.

On Wed, Aug 23, 2017 at 04:47:41PM +0200, Geert Uytterhoeven wrote:
> Some code is mixing up multiple memory nodes with multiple cpu nodes.
> M68k uses DISCONTIGMEM, but not NUMA (no SMP):
>
> config NEED_MULTIPLE_NODES
> def_bool y
> depends on DISCONTIGMEM || NUMA
>
> The (virtual) Atari has 2 memory nodes:
> - node0: start 0x00000000 size 0x00e00000
> - node1: start 0x01000000 size 0x10000000
> Both are tied to the same (single) CPU node, of course.

Ah, okay, so it has multiple nodes but not NUMA. The generic numa
topology code assumes that there's only one node if !NUMA and reports
all online cpus regardless of the node number, which makes the same
CPUs to be reported for all nodes on the system. I think something
like the following (completely untested) should work.

Thanks.

diff --git a/include/asm-generic/topology.h b/include/asm-generic/topology.h
index fc824e2..b31e84a 100644
--- a/include/asm-generic/topology.h
+++ b/include/asm-generic/topology.h
@@ -48,7 +48,11 @@
#define parent_node(node) ((void)(node),0)
#endif
#ifndef cpumask_of_node
-#define cpumask_of_node(node) ((void)node, cpu_online_mask)
+ #ifdef CONFIG_NEED_MULTIPLE_NODES
+ #define cpumask_of_node(node) ((node) == 0 ? cpu_online_mask : cpu_empty_mask)
+ #else
+ #define cpumask_of_node(node) ((void)node, cpu_online_mask)
+ #endif
#endif
#ifndef pcibus_to_node
#define pcibus_to_node(bus) ((void)(bus), -1)
diff --git a/include/linux/cpumask.h b/include/linux/cpumask.h
index 4bf4479..4d41d3b 100644
--- a/include/linux/cpumask.h
+++ b/include/linux/cpumask.h
@@ -89,10 +89,12 @@ extern struct cpumask __cpu_possible_mask;
extern struct cpumask __cpu_online_mask;
extern struct cpumask __cpu_present_mask;
extern struct cpumask __cpu_active_mask;
+extern struct cpumask __cpu_empty_mask;
#define cpu_possible_mask ((const struct cpumask *)&__cpu_possible_mask)
#define cpu_online_mask ((const struct cpumask *)&__cpu_online_mask)
#define cpu_present_mask ((const struct cpumask *)&__cpu_present_mask)
#define cpu_active_mask ((const struct cpumask *)&__cpu_active_mask)
+#define cpu_empty_mask ((const struct cpumask *)&__cpu_empty_mask)

#if NR_CPUS > 1
#define num_online_cpus() cpumask_weight(cpu_online_mask)
diff --git a/kernel/cpu.c b/kernel/cpu.c
index ab86045..eeed945 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -1741,6 +1741,9 @@ EXPORT_SYMBOL(__cpu_present_mask);
struct cpumask __cpu_active_mask __read_mostly;
EXPORT_SYMBOL(__cpu_active_mask);

+struct cpumask __cpu_empty_mask __read_mostly;
+EXPORT_SYMBOL(__cpu_empty_mask);
+
void init_cpu_present(const struct cpumask *src)
{
cpumask_copy(&__cpu_present_mask, src);