From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
To: Puranjay Mohan <puranjay12@gmail.com>
Cc: "Lai Jiangshan" <jiangshanlai@gmail.com>,
"Paul E. McKenney" <paulmck@kernel.org>,
"Josh Triplett" <josh@joshtriplett.org>,
"Onur Özkan" <work@onurozkan.dev>,
"Frederic Weisbecker" <frederic@kernel.org>,
"Neeraj Upadhyay" <neeraj.upadhyay@kernel.org>,
"Joel Fernandes" <joelagnelf@nvidia.com>,
"Boqun Feng" <boqun@kernel.org>,
"Uladzislau Rezki" <urezki@gmail.com>,
"Davidlohr Bueso" <dave@stgolabs.net>,
"Andrii Nakryiko" <andrii@kernel.org>,
"Eduard Zingerman" <eddyz87@gmail.com>,
"Alexei Starovoitov" <ast@kernel.org>,
"Daniel Borkmann" <daniel@iogearbox.net>,
"Kumar Kartikeya Dwivedi" <memxor@gmail.com>,
"Steven Rostedt" <rostedt@goodmis.org>,
"Mathieu Desnoyers" <mathieu.desnoyers@efficios.com>,
Zqiang <qiang.zhang@linux.dev>,
"Martin KaFai Lau" <martin.lau@linux.dev>,
"Song Liu" <song@kernel.org>,
"Yonghong Song" <yonghong.song@linux.dev>,
"Jiri Olsa" <jolsa@kernel.org>,
"Emil Tsalapatis" <emil@etsalapatis.com>,
"Matt Fleming" <mfleming@cloudflare.com>,
"Harry Yoo (Oracle)" <harry@kernel.org>,
linux-kernel@vger.kernel.org, rcu@vger.kernel.org,
bpf@vger.kernel.org, linux-rt-devel@lists.linux.dev
Subject: Re: [PATCH v4 1/6] rcu: Make call_rcu() safe to call from any context
Date: Thu, 10 Sep 2026 11:05:57 +0200 [thread overview]
Message-ID: <20260910090557.zz62jtMt@linutronix.de> (raw)
In-Reply-To: <CANk7y0gMh6McuLnFwxGO-nH_g3TnstwTK2rtT5pq=b8qq9ykKQ@mail.gmail.com>
On 2026-09-02 15:14:20 [+0100], Puranjay Mohan wrote:
> >
> > But it is wrong to talk about NMI and do this for other reasons not
> > mentioning why this was needed/ made sense.
> > Can this be fixed?
> > Also what is the reasoning for doing it from any IRQ disabled region?
>
> So, the main reason for this patchset is to make call_(s)rcu() work
> from BPF programs, and these BPF programs can run from any context
> like an NMI perf event interrupt or maybe attached to a function
> through ftrace which is in the call chain of call_rcu() itself.
This I expected.
> call_rcu() takes locks with irqs disabled or it modifies lists
> non-atomically with irqs disabled. This means that a BPF program that
> runs from NMI with the lock already taken will deadlock, or if it runs
> between these non-atomic list modifications, it will corrupt the
> lists. A BPF program can also synchronously re-enter call_rcu() if it
> is attached to a function in the call chain of call_rcu() that is
> called with a lock taken. So, all these cases are detected with
> irqs_disabled() and on detection we do stuff that doesn't require
> taking any locks and is safe even if re-entered.
Attaching a BPF program to call_rcu() and re-entering sounds great. But
there is nothing unique about call_rcu(), is there? We do have certain
amount of functions which can be invoked from NMI and their usage is
limited.
Anyway. If this is the sole reason for stunt then it _has_ to be part of
the commit message. Now it looks like an ooopsie where you talk about
NMI and do hardirq check.
> > > > > +static void __rcu_defer_drain(struct rcu_data *rdp)
> > > > > +{
> > > > > + struct llist_node *node, *next;
> > > > > + unsigned long flags;
> > > > > +
> > > > > + if (!IS_ENABLED(CONFIG_RCU_DEFER))
> > > > > + return;
> > > > > +
> > > > > + raw_spin_lock_irqsave(&rdp->defer_lock, flags);
> > > > > + llist_for_each_safe(node, next, llist_del_all(&rdp->defer_head)) {
> > > > > + struct rcu_head *head = (struct rcu_head *)node;
> > > >
> > > > Why do you need the lock. This is still not clear to me despite the
> > > > comment. You can do llist_del_all() towards another list and then feed
> > > > it into rcu_do_enqueue() one by one. And you use the LAZY part.
> > >
> > > Because rcu_barrier() can call this for each cpu and at the same time
> > > rcu_defer_drain() can call it too, so this would cause a race where
> > > the irq work can remove the callbacks (llist_del_all) and before it
> > > can enqueue them, rcu_barrier will see that the list is already empty
> > > and will not wait for these callbacks. We want the llist_del_all() and
> > > rcu_do_enqueue() to happen atomically so rcu_barrier() can work
> > > correctly.
> >
> > So you collect a bunch of callbacks and spent time re-arranging
> > everything with irqs off.
> > What is wrong with keeping it in the llist and consuming it like the
> > regular rcu_segcblist?
>
> I don't understand your last point, all the collection and delayed
> addition into rcu_segcblist is because it is not safe to do it
> directly as I explained above.
That is correct. My point is the more callbacks you add, the more time
you spend to re-add them here. It is not just the one NMI callback
injected from NMI, it is everyone within interrupts disabled region.
After each one you trigger an IRQ. And with LAZY-irq-work or on
architectures which don't have an IRQ-work interrupt, you accumulate
every callback from IRQ disabled region since the last HZ tick.
The question is why not have an additional list which is handled the
same way in terms of grace period like the current one?
> > It does not look like you defer them for long at all. Every callback
> > enqueued in an IRQ-off region will be immediately re-enqueued to the
> > regular list the moment interrupts are enabled again.
> > Except on architectures which don't implement irq-work interrupts where
> > it will be delayed to the next HZ tick. And the next HZ tick does not
> > sound like a long time either.
>
> Yeah, I get your point, and when a CPU goes offline will its LAZY irq
> works be drained or left in the queue? Because we want to make sure
> this irq work is executed before a CPU goes offline.
Hmm. There is smpcfd_dying_cpu() running before rcutree_dying_cpu().
smpcfd_dying_cpu() flushes irq-work near the end. On PREEMPT_RT we have
this thread handling them and this one is parked smpboot_park_threads()
a bit earlier. So here smpcfd_dying_cpu() will wake the parked thread
which then waits until the CPU comes back on.
We can't run the work directly due to the IRQ-off context. We could move
them to another CPU but then the irq-work might expect to be run on the
other CPU…
But we could flush the queue before parking at the very least I suppose…
Sebastian
next prev parent reply other threads:[~2026-09-10 9:06 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-10 12:27 [PATCH v4 0/6] rcu,srcu: Make call_rcu()/call_srcu() safe " Puranjay Mohan
2026-08-10 12:27 ` [PATCH v4 1/6] rcu: Make call_rcu() safe to call " Puranjay Mohan
2026-08-10 12:43 ` sashiko-bot
2026-08-10 12:48 ` Puranjay Mohan
2026-08-26 14:46 ` Sebastian Andrzej Siewior
2026-09-01 12:53 ` Puranjay Mohan
2026-09-02 8:26 ` Sebastian Andrzej Siewior
2026-09-02 14:14 ` Puranjay Mohan
2026-09-10 9:05 ` Sebastian Andrzej Siewior [this message]
2026-09-09 14:26 ` Harry Yoo
2026-09-09 14:30 ` Puranjay Mohan
2026-08-10 12:27 ` [PATCH v4 2/6] rcu: Make Tiny " Puranjay Mohan
2026-08-10 12:42 ` sashiko-bot
2026-08-10 12:45 ` Puranjay Mohan
2026-08-10 12:27 ` [PATCH v4 3/6] srcu: Make call_srcu() " Puranjay Mohan
2026-08-10 12:27 ` [PATCH v4 4/6] srcu: Make Tiny " Puranjay Mohan
2026-08-10 12:27 ` [PATCH v4 5/6] rcutorture: Exercise ->call() from NMI context Puranjay Mohan
2026-08-10 12:27 ` [PATCH v4 6/6] selftests/bpf: Add a call_srcu() re-entry reproducer Puranjay Mohan
2026-08-12 0:10 ` [PATCH v4 0/6] rcu,srcu: Make call_rcu()/call_srcu() safe from any context Paul E. McKenney
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260910090557.zz62jtMt@linutronix.de \
--to=bigeasy@linutronix.de \
--cc=andrii@kernel.org \
--cc=ast@kernel.org \
--cc=boqun@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=daniel@iogearbox.net \
--cc=dave@stgolabs.net \
--cc=eddyz87@gmail.com \
--cc=emil@etsalapatis.com \
--cc=frederic@kernel.org \
--cc=harry@kernel.org \
--cc=jiangshanlai@gmail.com \
--cc=joelagnelf@nvidia.com \
--cc=jolsa@kernel.org \
--cc=josh@joshtriplett.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-rt-devel@lists.linux.dev \
--cc=martin.lau@linux.dev \
--cc=mathieu.desnoyers@efficios.com \
--cc=memxor@gmail.com \
--cc=mfleming@cloudflare.com \
--cc=neeraj.upadhyay@kernel.org \
--cc=paulmck@kernel.org \
--cc=puranjay12@gmail.com \
--cc=qiang.zhang@linux.dev \
--cc=rcu@vger.kernel.org \
--cc=rostedt@goodmis.org \
--cc=song@kernel.org \
--cc=urezki@gmail.com \
--cc=work@onurozkan.dev \
--cc=yonghong.song@linux.dev \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®