Commit 76af5464 authored by Breno Leitao's avatar Breno Leitao Committed by Tejun Heo
Browse files

workqueue: validate cpumask_first() result in llc_populate_cpu_shard_id()



On uniprocessor (UP) configs such as nios2, NR_CPUS is 1, so
cpu_shard_id[] is a single-element array (int[1]). In
llc_populate_cpu_shard_id(), cpumask_first(sibling_cpus) returns an
unsigned int that the compiler cannot prove is always 0, triggering
a -Warray-bounds warning when the result is used to index
cpu_shard_id[]:

  kernel/workqueue.c:8321:55: warning: array subscript 1 is above
  array bounds of 'int[1]' [-Warray-bounds]
   8321 |  cpu_shard_id[c] = cpu_shard_id[cpumask_first(sibling_cpus)];
        |                    ~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~

This is a false positive: sibling_cpus can never be empty here because
'c' itself is always set in it, so cpumask_first() will always return a
valid CPU. However, the compiler cannot prove this statically, and the
warning only manifests on UP configs where the array size is 1.

Add a bounds check with WARN_ON_ONCE to silence the warning, and store
the result in a local variable to make the code clearer and avoid calling
cpumask_first() twice.

Fixes: 5920d046 ("workqueue: add WQ_AFFN_CACHE_SHARD affinity scope")
Reported-by: default avatarkernel test robot <lkp@intel.com>
Closes: https://lore.kernel.org/oe-kbuild-all/202604022343.GQtkF2vO-lkp@intel.com/


Signed-off-by: default avatarBreno Leitao <leitao@debian.org>
Signed-off-by: default avatarTejun Heo <tj@kernel.org>
parent 034db4dd
Loading
Loading
Loading
Loading
+12 −1
Original line number Diff line number Diff line
@@ -8266,6 +8266,7 @@ static void __init llc_populate_cpu_shard_id(const struct cpumask *pod_cpus,
	const struct cpumask *sibling_cpus;
	/* Count the number of cores in the current shard_id */
	int cores_in_shard = 0;
	unsigned int leader;
	/* This is a cursor for the shards. Go from zero to nr_shards - 1*/
	int shard_id = 0;
	int c;
@@ -8286,7 +8287,17 @@ static void __init llc_populate_cpu_shard_id(const struct cpumask *pod_cpus,
			 * The siblings' shard MUST be the same as the leader.
			 * never split threads in the same core.
			 */
			cpu_shard_id[c] = cpu_shard_id[cpumask_first(sibling_cpus)];
			leader = cpumask_first(sibling_cpus);

			/*
			 * This check silences a Warray-bounds warning on UP
			 * configs where NR_CPUS=1 makes cpu_shard_id[]
			 * a single-element array, and the compiler can't
			 * prove the index is always 0.
			 */
			if (WARN_ON_ONCE(leader >= nr_cpu_ids))
				continue;
			cpu_shard_id[c] = cpu_shard_id[leader];
		}
	}