rcu: Tighten rcu_advance_cbs_nowake() checks
authorPaul E. McKenney <paulmck@kernel.org>
Fri, 17 Sep 2021 22:04:48 +0000 (15:04 -0700)
committerPaul E. McKenney <paulmck@kernel.org>
Wed, 8 Dec 2021 00:23:03 +0000 (16:23 -0800)
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>
kernel/rcu/tree.c

index ef8d36f..8706b30 100644 (file)
@@ -1590,10 +1590,11 @@ static void __maybe_unused rcu_advance_cbs_nowake(struct rcu_node *rnp,
                                                  struct rcu_data *rdp)
 {
        rcu_lockdep_assert_cblist_protected(rdp);
-       if (!rcu_seq_state(rcu_seq_current(&rnp->gp_seq)) ||
-           !raw_spin_trylock_rcu_node(rnp))
+       if (!rcu_seq_state(rcu_seq_current(&rnp->gp_seq)) || !raw_spin_trylock_rcu_node(rnp))
                return;
-       WARN_ON_ONCE(rcu_advance_cbs(rnp, rdp));
+       // The grace period cannot end while we hold the rcu_node lock.
+       if (rcu_seq_state(rcu_seq_current(&rnp->gp_seq)))
+               WARN_ON_ONCE(rcu_advance_cbs(rnp, rdp));
        raw_spin_unlock_rcu_node(rnp);
 }