On Thu, May 25, 2017 at 11:03:53AM -0400, Tejun Heo wrote: > wq_update_unbound_numa() should have never called into > alloc_unbound_pwq() w/ empty node cpu mask. It should have fallen > back to the dfl_pwq. It looks like I just messed up the logic there > from the initial commit of the feature. Can you please see whether > the following fixes the problem?
Can you please try the following instead. On the second thought, I don't think the current logic is wrong. If this fixes the issue, somehow your setup is having a situation where online cpumask for a node is a proper superset of possible cpumask for the node. Thanks. diff --git a/kernel/workqueue.c b/kernel/workqueue.c index c74bf39ef764..4da5ff649ff8 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -3559,13 +3559,13 @@ static struct pool_workqueue *alloc_unbound_pwq(struct workqueue_struct *wq, * stable. * * Return: %true if the resulting @cpumask is different from @attrs->cpumask, - * %false if equal. + * %false if equal. On %false return, the content of @cpumask is undefined. */ static bool wq_calc_node_cpumask(const struct workqueue_attrs *attrs, int node, int cpu_going_down, cpumask_t *cpumask) { if (!wq_numa_enabled || attrs->no_numa) - goto use_dfl; + return false; /* does @node have any online CPUs @attrs wants? */ cpumask_and(cpumask, cpumask_of_node(node), attrs->cpumask); @@ -3573,15 +3573,13 @@ static bool wq_calc_node_cpumask(const struct workqueue_attrs *attrs, int node, cpumask_clear_cpu(cpu_going_down, cpumask); if (cpumask_empty(cpumask)) - goto use_dfl; + return false; /* yeap, return possible CPUs in @node that @attrs wants */ cpumask_and(cpumask, attrs->cpumask, wq_numa_possible_cpumask[node]); - return !cpumask_equal(cpumask, attrs->cpumask); -use_dfl: - cpumask_copy(cpumask, attrs->cpumask); - return false; + return !cpumask_empty(cpumask) && + !cpumask_equal(cpumask, attrs->cpumask); } /* install @pwq into @wq's numa_pwq_tbl[] for @node and return the old pwq */