On Mon, Aug 10, 2026 at 05:27:50AM -0700, Puranjay Mohan wrote:
> ---
>  kernel/rcu/Kconfig |   6 +++
>  kernel/rcu/rcu.h   |  11 ++++
>  kernel/rcu/tree.c  | 131 +++++++++++++++++++++++++++++++++++++++++----
>  kernel/rcu/tree.h  |   6 +++
>  4 files changed, 143 insertions(+), 11 deletions(-)
> 
> diff --git a/kernel/rcu/Kconfig b/kernel/rcu/Kconfig
> index f15da8038d0ba..1a5fb3156c062 100644
> --- a/kernel/rcu/Kconfig
> +++ b/kernel/rcu/Kconfig
> @@ -175,6 +175,12 @@ config RCU_STALL_COMMON
>  config RCU_NEED_SEGCBLIST
>       def_bool ( TREE_RCU || TREE_SRCU || TASKS_RCU_GENERIC )
>  
> +# The deferral (and the IRQ_WORK it uses) is only needed where call_rcu() /
> +# call_srcu() can be invoked while a callback-list operation is in flight.
> +config RCU_DEFER
> +     def_bool HAVE_NMI || KPROBES || FUNCTION_TRACER || TRACEPOINTS
> +     select IRQ_WORK

nit: I don't think this config belongs to RCU.
Do we really need this when majority of kernels enable those?

>  config RCU_FANOUT
>       int "Tree-based hierarchical RCU fanout value"
>       range 2 64 if 64BIT
> @@ -3206,6 +3204,103 @@ __call_rcu_common(struct rcu_head *head, 
> rcu_callback_t func, bool lazy_in)
>       local_irq_restore(flags);
>  }
>  
> +/*
> + * Stage @head for this CPU's irq_work to re-issue once interrupts are on.  
> Only
> + * the drain side takes a lock, so this stays safe from NMI.
> + */
> +static void call_rcu_defer(struct rcu_head *head, rcu_callback_t func)
> +{
> +     struct rcu_data *rdp = this_cpu_ptr(&rcu_data);
> +
> +     /*
> +      * Instrumentation on the enqueue path can re-enter here from inside the
> +      * drain.  Re-queuing would livelock it, so drop the callback; an NMI
> +      * cannot loop, so let it through.
> +
> +      */
> +     if (READ_ONCE(rdp->defer_draining) && !in_nmi()) {
> +             WARN_ONCE(IS_ENABLED(CONFIG_PROVE_RCU),
> +                       "call_rcu() re-entered during callback drain; leaking 
> callback\n");
> +             return;
> +     }
> +     head->func = func;
> +     if (llist_add((struct llist_node *)head, &rdp->defer_head))
> +             irq_work_queue(&rdp->defer_work);

Should RCU wait for the IRQ work to be processed during e.g.)
rcu_barrier()?

-- 
Cheers,
Harry / Hyeonggon

Reply via email to