Skip to content

Commit 82dd841

Browse files
committed
rcu: Warn on for_each_leaf_node_cpu_mask() from non-leaf
The for_each_leaf_node_cpu_mask() and for_each_leaf_node_possible_cpu() macros must be invoked only on leaf rcu_node structures. Failing to abide by this restriction can result in infinite loops on systems with more than 64 CPUs (or for more than 32 CPUs on 32-bit systems). This commit therefore adds WARN_ON_ONCE() calls to make misuse of these two macros easier to debug. Reported-by: Qian Cai <[email protected]> Signed-off-by: Paul E. McKenney <[email protected]>
1 parent 9f01eb5 commit 82dd841

File tree

1 file changed

+4
-2
lines changed

1 file changed

+4
-2
lines changed

kernel/rcu/rcu.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -325,7 +325,8 @@ static inline void rcu_init_levelspread(int *levelspread, const int *levelcnt)
325325
* Iterate over all possible CPUs in a leaf RCU node.
326326
*/
327327
#define for_each_leaf_node_possible_cpu(rnp, cpu) \
328-
for ((cpu) = cpumask_next((rnp)->grplo - 1, cpu_possible_mask); \
328+
for (WARN_ON_ONCE(!rcu_is_leaf_node(rnp)), \
329+
(cpu) = cpumask_next((rnp)->grplo - 1, cpu_possible_mask); \
329330
(cpu) <= rnp->grphi; \
330331
(cpu) = cpumask_next((cpu), cpu_possible_mask))
331332

@@ -335,7 +336,8 @@ static inline void rcu_init_levelspread(int *levelspread, const int *levelcnt)
335336
#define rcu_find_next_bit(rnp, cpu, mask) \
336337
((rnp)->grplo + find_next_bit(&(mask), BITS_PER_LONG, (cpu)))
337338
#define for_each_leaf_node_cpu_mask(rnp, cpu, mask) \
338-
for ((cpu) = rcu_find_next_bit((rnp), 0, (mask)); \
339+
for (WARN_ON_ONCE(!rcu_is_leaf_node(rnp)), \
340+
(cpu) = rcu_find_next_bit((rnp), 0, (mask)); \
339341
(cpu) <= rnp->grphi; \
340342
(cpu) = rcu_find_next_bit((rnp), (cpu) + 1 - (rnp->grplo), (mask)))
341343

0 commit comments

Comments
 (0)