From: "Zqiang" <qiang.zhang@linux.dev>
To: "Sunho Park" <shpark061104@gmail.com>, paulmck@kernel.org
Cc: jiangshanlai@gmail.com, josh@joshtriplett.org,
work@onurozkan.dev, rostedt@goodmis.org,
mathieu.desnoyers@efficios.com, frederic@kernel.org,
rcu@vger.kernel.org, linux-kernel@vger.kernel.org,
"Sunho Park" <shpark061104@gmail.com>,
syzbot+d4faf7db59e11f6fd1ab@syzkaller.appspotmail.com
Subject: Re: [PATCH] srcu: Fix WARN_ON() for rcu_segcblist_n_cbs() in cleanup_srcu_struct()
Date: Sat, 29 Aug 2026 13:19:20 +0000 [thread overview]
Message-ID: <1b9d3ddaa26ba6a8ac2ad4c586c2d19a5c1f927e@linux.dev> (raw)
In-Reply-To: <20260827150208.2166775-1-shpark061104@gmail.com>
>
> The WARN_ON() added by commit 78a38cbf6f20 ("srcu: Queue sdp->work
> when the delay timer is successfully deleted") uses rcu_segcblist_n_cbs()
> to detect callbacks that srcu_barrier() failed to wait for. However, the
> ->len counter is decremented only at the end of srcu_invoke_callbacks(),
> after the invoking loop has finished. Since srcu_barrier() can return
> right after the barrier callback is invoked, cleanup_srcu_struct() can see
> a non-zero n_cbs even though the cblist is already physically empty,
> falsely triggering the WARN_ON() together with a still-pending delay_work
> timer.
>
> Use rcu_segcblist_empty(), which checks the actual head of the cblist.
> Callbacks that have genuinely not been invoked yet still leave the list
> non-empty, so the WARN_ON() still catches callers that skip srcu_barrier()
> or queue callbacks after it.
You should describe in detail how this scene was triggered like this:
1. call_srcu(&kvm->srcu, &bus->rcu, __free_bus) start a SRCU GP1.
2. The SRCU GP1 end, arms a timer and queue sdp->work, but this sdp->work not yet run.
3. Another call_srcu(&kvm->srcu, &bus->rcu, __free_bus) invoke srcu_segcblist_advance()
to push step1 srcu callback to RCU_DONE_TAIL and start a SRCU GP2.
4. srcu_barrier() is called and queues barrier callbacks after step3 srcu callback,
waits for srcu_invoke_callbacks() to invoke them.
5. The SRCU GP2 end, also arms a timer, and the sdp->work by step2 queued begin run,
the srcu_invoke_callbacks() invoke srcu_segcblist_advance() also push step3 and step4
srcu callback to RCU_DONE_TAIL, all srcu callback execution completed,
but the not yet invoke rcu_segcblist_add_len() to update srcu_cblist's len.
6. The srcu_barrier() return, cleanup_srcu_struct() begin run, after then, find
the step5 timer still pending and the srcu_cblist's len not zero, trigger
WARN_ON()
Thanks
Zqiang
>
> Link: https://lore.kernel.org/rcu/e6350377085ddd85d6ef00d8e9a67bd50c762d3c@linux.dev/T/#t
> Reported-by: syzbot+d4faf7db59e11f6fd1ab@syzkaller.appspotmail.com
> Closes: https://syzkaller.appspot.com/bug?extid=d4faf7db59e11f6fd1ab
> Fixes: 78a38cbf6f20 ("srcu: Queue sdp->work when the delay timer is successfully deleted")
> Signed-off-by: Sunho Park <shpark061104@gmail.com>
> ---
> kernel/rcu/srcutree.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/kernel/rcu/srcutree.c b/kernel/rcu/srcutree.c
> index ed204b3f4b84..ad27880dd690 100644
> --- a/kernel/rcu/srcutree.c
> +++ b/kernel/rcu/srcutree.c
> @@ -704,7 +704,7 @@ void cleanup_srcu_struct(struct srcu_struct *ssp)
> // Call srcu_barrier() before this cleanup_srcu_struct()
> // to avoid triggering this WARN_ON().
> if (WARN_ON(timer_delete_sync(&sdp->delay_work) &&
> - rcu_segcblist_n_cbs(&sdp->srcu_cblist)) &&
> + !rcu_segcblist_empty(&sdp->srcu_cblist)) &&
> rcu_cpu_beenfullyonline(sdp->cpu))
> queue_work_on(sdp->cpu, rcu_gp_wq, &sdp->work);
> flush_work(&sdp->work);
> --
> 2.43.0
>
prev parent reply other threads:[~2026-08-29 13:19 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-27 15:02 [PATCH] srcu: Fix WARN_ON() for rcu_segcblist_n_cbs() in cleanup_srcu_struct() Sunho Park
2026-08-29 13:19 ` Zqiang [this message]
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=1b9d3ddaa26ba6a8ac2ad4c586c2d19a5c1f927e@linux.dev \
--to=qiang.zhang@linux.dev \
--cc=frederic@kernel.org \
--cc=jiangshanlai@gmail.com \
--cc=josh@joshtriplett.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mathieu.desnoyers@efficios.com \
--cc=paulmck@kernel.org \
--cc=rcu@vger.kernel.org \
--cc=rostedt@goodmis.org \
--cc=shpark061104@gmail.com \
--cc=syzbot+d4faf7db59e11f6fd1ab@syzkaller.appspotmail.com \
--cc=work@onurozkan.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.