Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

rcu: Tighten rcu_advance_cbs_nowake() checks

Currently, rcu_advance_cbs_nowake() checks that a grace period is in
progress, however, that grace period could end just after the check.
This commit rechecks that a grace period is still in progress while
holding the rcu_node structure's lock. The grace period cannot end while
the current CPU's rcu_node structure's ->lock is held, thus avoiding
false positives from the WARN_ON_ONCE().

As Daniel Vacek noted, it is not necessary for the rcu_node structure
to have a CPU that has not yet passed through its quiescent state.

Tested-by: Guillaume Morin <guillaume@morinfr.org>
Signed-off-by: Paul E. McKenney <paulmck@kernel.org>

+4 -3
+4 -3
kernel/rcu/tree.c
··· 1590 1590 struct rcu_data *rdp) 1591 1591 { 1592 1592 rcu_lockdep_assert_cblist_protected(rdp); 1593 - if (!rcu_seq_state(rcu_seq_current(&rnp->gp_seq)) || 1594 - !raw_spin_trylock_rcu_node(rnp)) 1593 + if (!rcu_seq_state(rcu_seq_current(&rnp->gp_seq)) || !raw_spin_trylock_rcu_node(rnp)) 1595 1594 return; 1596 - WARN_ON_ONCE(rcu_advance_cbs(rnp, rdp)); 1595 + // The grace period cannot end while we hold the rcu_node lock. 1596 + if (rcu_seq_state(rcu_seq_current(&rnp->gp_seq))) 1597 + WARN_ON_ONCE(rcu_advance_cbs(rnp, rdp)); 1597 1598 raw_spin_unlock_rcu_node(rnp); 1598 1599 } 1599 1600