On Wed, Sep 9, 2026 at 3:26 PM Harry Yoo <[email protected]> wrote:
>
> 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?
Paul was worried about some embedded systems paying a performance
penalty as they might not enable these but would still use RCU.
>
> > 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()?
Yes it should and it does, rcu_barrier() now enqueues these deferred
callbacks from this list before doing the other barrier logic.
Thanks