rcu: Remove duplicate RCU exp QS report from rcu_report_dead()
authorZqiang <qiang1.zhang@intel.com>
Tue, 30 Aug 2022 08:31:51 +0000 (16:31 +0800)
committerPaul E. McKenney <paulmck@kernel.org>
Tue, 18 Oct 2022 21:59:57 +0000 (14:59 -0700)
The rcu_report_dead() function invokes rcu_report_exp_rdp() in order
to force an immediate expedited quiescent state on the outgoing
CPU, and then it invokes rcu_preempt_deferred_qs() to provide any
required deferred quiescent state of either sort.  Because the call to
rcu_preempt_deferred_qs() provides the expedited RCU quiescent state if
requested, the call to rcu_report_exp_rdp() is potentially redundant.

One possible issue is a concurrent start of a new expedited RCU
grace period, but this situation is already handled correctly
by __sync_rcu_exp_select_node_cpus().  This function will detect
that the CPU is going offline via the error return from its call
to smp_call_function_single().  In that case, it will retry, and
eventually stop retrying due to rcu_report_exp_rdp() clearing the
->qsmaskinitnext bit corresponding to the target CPU.  As a result,
__sync_rcu_exp_select_node_cpus() will report the necessary quiescent
state after dealing with any remaining CPU.

This change assumes that control does not enter rcu_report_dead() within
an RCU read-side critical section, but then again, the surviving call
to rcu_preempt_deferred_qs() has always made this assumption.

This commit therefore removes the call to rcu_report_exp_rdp(), thus
relying on rcu_preempt_deferred_qs() to handle both normal and expedited
quiescent states.

Signed-off-by: Zqiang <qiang1.zhang@intel.com>
Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
kernel/rcu/tree.c

index 6bb8e72bc8151ef2eb4093f2464f32c225672f88..0ca21ac0f0648af61d531604599a04d84de07499 100644 (file)
@@ -4276,8 +4276,6 @@ void rcu_report_dead(unsigned int cpu)
        // Do any dangling deferred wakeups.
        do_nocb_deferred_wakeup(rdp);
 
-       /* QS for any half-done expedited grace period. */
-       rcu_report_exp_rdp(rdp);
        rcu_preempt_deferred_qs(current);
 
        /* Remove outgoing CPU from mask in the leaf rcu_node structure. */