Re: [PATCH 9/9] rcu-tasks: Detect duplicate callback enqueue
From: Paul E. McKenney
Date: Mon Oct 26 2026 - 19:37:53 EST
On Mon, Oct 26, 2026 at 10:36:02AM +0800, KunWu Chan wrote:
> On Sat, Oct 24, 2026 at 3:31 AM Paul E. McKenney <paulmck@xxxxxxxxxx> wrote:
> >
> > On Fri, Oct 23, 2026 at 06:18:41PM +0800, Kunwu Chan wrote:
> > > Detect duplicate callback enqueue attempts in the generic
> > > RCU Tasks callback registration path.
> > >
> > > Signed-off-by: Kunwu Chan <chentao@xxxxxxxxxx>
> >
> > And the same questions for this patch as well. ;-)
>
> Same changes applied: pr_err_ratelimited() and dump_stack.
Very good, thank you!
Thanx, Paul
> Thanks,
> Kunwu
>
> >
> > Thanx, Paul
> >
> > > ---
> > > kernel/rcu/tasks.h | 15 +++++++++++++++
> > > 1 file changed, 15 insertions(+)
> > >
> > > diff --git a/kernel/rcu/tasks.h b/kernel/rcu/tasks.h
> > > index 5d7f234795b4..49b716feb31d 100644
> > > --- a/kernel/rcu/tasks.h
> > > +++ b/kernel/rcu/tasks.h
> > > @@ -6,6 +6,7 @@
> > > */
> > >
> > > #ifdef CONFIG_TASKS_RCU_GENERIC
> > > +#include <linux/mm.h>
> > > #include "rcu_segcblist.h"
> > >
> > > ////////////////////////////////////////////////////////////////////////
> > > @@ -339,9 +340,12 @@ static void call_rcu_tasks_iw_wakeup(struct irq_work *iwp)
> > > }
> > >
> > > // Enqueue a callback for the specified flavor of Tasks RCU.
> > > +static void rcu_tasks_leak_callback(struct rcu_head *rhp) { }
> > > +
> > > static void call_rcu_tasks_generic(struct rcu_head *rhp, rcu_callback_t func,
> > > struct rcu_tasks *rtp)
> > > {
> > > + static atomic_t doublefrees;
> > > int chosen_cpu;
> > > unsigned long flags;
> > > bool havekthread = smp_load_acquire(&rtp->kthread_ptr);
> > > @@ -358,6 +362,16 @@ static void call_rcu_tasks_generic(struct rcu_head *rhp, rcu_callback_t func,
> > > if (WARN_ON_ONCE(!func))
> > > return;
> > >
> > > + if (debug_rcu_head_queue(rhp)) {
> > > + if (atomic_inc_return(&doublefrees) < 4) {
> > > + pr_err("%s(): Duplicate call_rcu_%s() CB %p->%pS()\n",
> > > + __func__, rtp->name, rhp, rhp->func);
> > > + mem_dump_obj(rhp);
> > > + }
> > > + WRITE_ONCE(rhp->func, rcu_tasks_leak_callback);
> > > + return;
> > > + }
> > > +
> > > rhp->next = NULL;
> > > rhp->func = func;
> > > local_irq_save(flags);
> > > @@ -586,6 +600,7 @@ static void rcu_tasks_invoke_cbs(struct rcu_tasks *rtp, struct rcu_tasks_percpu
> > > raw_spin_unlock_irqrestore_rcu_node(rtpcp, flags);
> > > len = rcl.len;
> > > for (rhp = rcu_cblist_dequeue(&rcl); rhp; rhp = rcu_cblist_dequeue(&rcl)) {
> > > + debug_rcu_head_unqueue(rhp);
> > > debug_rcu_head_callback(rhp);
> > > local_bh_disable();
> > > rhp->func(rhp);
> > > --
> > > 2.43.0
> > >