Now __irq_build_affinity_masks() spreads vectors evenly per node, and all vectors may not be spread in case that each numa node has different CPU number, then the following warning in irq_build_affinity_masks() can be triggered:
if (nr_present < numvecs) WARN_ON(nr_present + nr_others < numvecs); Improve current spreading algorithm by assigning vectors according to the ratio of node's nr_cpu to nr_remaining_cpus. Meantime the reported warning can be fixed. Cc: Christoph Hellwig <h...@lst.de> Cc: Keith Busch <kbu...@kernel.org> Cc: linux-n...@lists.infradead.org, Cc: Jon Derrick <jonathan.derr...@intel.com> Reported-by: Jon Derrick <jonathan.derr...@intel.com> Signed-off-by: Ming Lei <ming....@redhat.com> --- kernel/irq/affinity.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/kernel/irq/affinity.c b/kernel/irq/affinity.c index bc3652a2c61b..76f3d1b27d00 100644 --- a/kernel/irq/affinity.c +++ b/kernel/irq/affinity.c @@ -106,6 +106,7 @@ static int __irq_build_affinity_masks(unsigned int startvec, unsigned int last_affv = firstvec + numvecs; unsigned int curvec = startvec; nodemask_t nodemsk = NODE_MASK_NONE; + unsigned remaining_cpus = 0; if (!cpumask_weight(cpu_mask)) return 0; @@ -126,6 +127,11 @@ static int __irq_build_affinity_masks(unsigned int startvec, return numvecs; } + for_each_node_mask(n, nodemsk) { + cpumask_and(nmsk, cpu_mask, node_to_cpumask[n]); + remaining_cpus += cpumask_weight(nmsk); + } + for_each_node_mask(n, nodemsk) { unsigned int ncpus, v, vecs_to_assign, vecs_per_node; @@ -135,17 +141,22 @@ static int __irq_build_affinity_masks(unsigned int startvec, if (!ncpus) continue; + if (remaining_cpus == 0) + break; + /* * Calculate the number of cpus per vector * - * Spread the vectors evenly per node. If the requested - * vector number has been reached, simply allocate one - * vector for each remaining node so that all nodes can - * be covered + * Spread the vectors among CPUs on this node according + * to the ratio of 'ncpus' to 'remaining_cpus'. If the + * requested vector number has been reached, simply + * spread one vector for each remaining node so that all + * nodes can be covered */ if (numvecs > done) vecs_per_node = max_t(unsigned, - (numvecs - done) / nodes, 1); + (numvecs - done) * ncpus / + remaining_cpus, 1); else vecs_per_node = 1; @@ -169,7 +180,7 @@ static int __irq_build_affinity_masks(unsigned int startvec, } done += v; - --nodes; + remaining_cpus -= ncpus; } return done < numvecs ? done : numvecs; } -- 2.20.1