From: Paul E. McKenney Date: Thu, 6 Sep 2012 04:43:57 +0000 (-0700) Subject: rcu: Handle unbalanced rcu_node configurations with few CPUs X-Git-Tag: next-20120921~38^2~2 X-Git-Url: https://git.karo-electronics.de/?a=commitdiff_plain;h=9303662f1616826c551b6b1e958c9cd785356892;p=karo-tx-linux.git rcu: Handle unbalanced rcu_node configurations with few CPUs If CONFIG_RCU_FANOUT_EXACT=y, if there are not enough CPUs (according to nr_cpu_ids) to require more than a single rcu_node structure, but if NR_CPUS is larger than would fit into a single rcu_node structure, then the current rcu_init_levelspread() code is subject to integer overflow in the eight-bit ->levelspread[] array in the rcu_state structure. In this case, the solution is -not- to increase the size of the elements in this array because the values in that array should be constrained to the number of bits in an unsigned long. Instead, this commit replaces NR_CPUS with nr_cpu_ids in the rcu_init_levelspread() function's initialization of the cprv local variable. This results in all of the arithmetic being consistently based off of the nr_cpu_ids value, thus avoiding the overflow, which was caused by the mixing of nr_cpu_ids and NR_CPUS. Reported-by: Mike Galbraith Signed-off-by: Paul E. McKenney --- diff --git a/kernel/rcutree.c b/kernel/rcutree.c index 7a91dd481dce..5068e5119494 100644 --- a/kernel/rcutree.c +++ b/kernel/rcutree.c @@ -2721,7 +2721,7 @@ static void __init rcu_init_levelspread(struct rcu_state *rsp) int cprv; int i; - cprv = NR_CPUS; + cprv = nr_cpu_ids; for (i = rcu_num_lvls - 1; i >= 0; i--) { ccur = rsp->levelcnt[i]; rsp->levelspread[i] = (cprv + ccur - 1) / ccur;