Re: [PATCH v2 1/7] srcutiny: Do not call synchronize_rcu() from synchronize_srcu_atomic()

From: KunWu Chan

Date: Wed Nov 11 2026 - 22:08:22 EST


Thanks, Mathieu.

Reviewed-by: Kunwu Chan <chentao@xxxxxxxxxx>

On Wed, Nov 11, 2026 at 10:59 PM Mathieu Desnoyers
<mathieu.desnoyers@xxxxxxxxxxxx> wrote:
>
> synchronize_srcu_atomic() never blocks, so that it can be called from
> atomic context. This includes interrupt handlers, and code within
> rcu_read_lock().
>
> With CONFIG_PREEMPTION=y, the Tiny SRCU version first calls
> synchronize_rcu(). Tiny synchronize_rcu() does not wait: it only
> advances rcu_ctrlblk.gp_seq. This is valid where the caller is in a
> quiescent state, in task context and outside of any RCU reader.
>
> The callers of synchronize_srcu_atomic() need not be in a quiescent
> state. An interrupt handler may have interrupted an RCU reader. A
> caller within rcu_read_lock() is itself an RCU reader. In both cases,
> synchronize_rcu() ends an RCU grace period while an RCU reader is still
> in its critical section. poll_state_synchronize_rcu() would then
> report a grace period that did not happen. The caller within
> rcu_read_lock() also gets "Illegal synchronize_rcu() in RCU read-side
> critical section" from lockdep.
>
> srcu_drive_gp() has the same call. There, it makes an RCU Tasks
> Trace grace period imply an RCU grace period. RCU Tasks Trace uses
> call_srcu() and synchronize_srcu(), which are both forbidden on a
> srcu_struct that uses synchronize_srcu_atomic(). And the Tree SRCU
> version of synchronize_srcu_atomic() does not wait for an RCU grace
> period either.
>
> Fix this by removing the call.
>
> This was found by reading the code. An rcutorture test added later in
> this series fails without this change.
>
> Fixes: a48669f0c49c ("srcutiny: Add an atomic Tiny SRCU")
> Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@xxxxxxxxxxxx>
> ---
> kernel/rcu/srcutiny.c | 7 ++++---
> 1 file changed, 4 insertions(+), 3 deletions(-)
>
> diff --git a/kernel/rcu/srcutiny.c b/kernel/rcu/srcutiny.c
> index 63a3f0a8bc53..d58f4160f925 100644
> --- a/kernel/rcu/srcutiny.c
> +++ b/kernel/rcu/srcutiny.c
> @@ -367,9 +367,10 @@ void synchronize_srcu_atomic(struct srcu_struct *ssp)
> if (rcu_scheduler_active == RCU_SCHEDULER_INACTIVE)
> return;
>
> - if (IS_ENABLED(CONFIG_PREEMPTION))
> - synchronize_rcu(); // Needed for RCU Tasks Trace to imply RCU grace period.
> - // And in Tiny RCU, it is near zero cost and doesn't block.
> + // No synchronize_rcu() here, unlike in srcu_drive_gp(). The caller
> + // may be in an interrupt handler or within rcu_read_lock(). Tiny
> + // synchronize_rcu() would then end an RCU grace period that an RCU
> + // reader still holds up.
>
> // Usually, there will be no readers.
> preempt_disable(); // Guard against lazy preemption and some other grace period.
> --
> 2.47.3
>