srcu: Explain why callbacks invocations can't run concurrently
authorFrederic Weisbecker <frederic@kernel.org>
Tue, 3 Oct 2023 23:29:03 +0000 (01:29 +0200)
committerNeeraj Upadhyay (AMD) <neeraj.iitr10@gmail.com>
Mon, 11 Dec 2023 21:11:17 +0000 (02:41 +0530)
If an SRCU barrier is queued while callbacks are running and a new
callbacks invocator for the same sdp were to run concurrently, the
RCU barrier might execute too early. As this requirement is non-obvious,
make sure to keep a record.

Signed-off-by: Frederic Weisbecker <frederic@kernel.org>
Reviewed-by: Joel Fernandes (Google) <joel@joelfernandes.org>
Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
Signed-off-by: Neeraj Upadhyay (AMD) <neeraj.iitr10@gmail.com>
kernel/rcu/srcutree.c

index 2bfc8ed1eed286d66c930538cc03adbaa830718d..0351a4e83529e322f8e96cecb6244f728478fe7b 100644 (file)
@@ -1715,6 +1715,11 @@ static void srcu_invoke_callbacks(struct work_struct *work)
        WARN_ON_ONCE(!rcu_segcblist_segempty(&sdp->srcu_cblist, RCU_NEXT_TAIL));
        rcu_segcblist_advance(&sdp->srcu_cblist,
                              rcu_seq_current(&ssp->srcu_sup->srcu_gp_seq));
+       /*
+        * Although this function is theoretically re-entrant, concurrent
+        * callbacks invocation is disallowed to avoid executing an SRCU barrier
+        * too early.
+        */
        if (sdp->srcu_cblist_invoking ||
            !rcu_segcblist_ready_cbs(&sdp->srcu_cblist)) {
                spin_unlock_irq_rcu_node(sdp);
@@ -1745,6 +1750,7 @@ static void srcu_invoke_callbacks(struct work_struct *work)
        sdp->srcu_cblist_invoking = false;
        more = rcu_segcblist_ready_cbs(&sdp->srcu_cblist);
        spin_unlock_irq_rcu_node(sdp);
+       /* An SRCU barrier or callbacks from previous nesting work pending */
        if (more)
                srcu_schedule_cbs_sdp(sdp, 0);
 }