From: Joel Fernandes <joelagnelf@nvidia.com>
To: linux-kernel@vger.kernel.org
Cc: "Paul E . McKenney" <paulmck@kernel.org>,
Frederic Weisbecker <frederic@kernel.org>,
Neeraj Upadhyay <neeraj.upadhyay@kernel.org>,
Josh Triplett <josh@joshtriplett.org>,
Boqun Feng <boqun@kernel.org>,
Uladzislau Rezki <urezki@gmail.com>,
Steven Rostedt <rostedt@goodmis.org>,
Mathieu Desnoyers <mathieu.desnoyers@efficios.com>,
Lai Jiangshan <jiangshanlai@gmail.com>,
Zqiang <qiang.zhang@linux.dev>,
Davidlohr Bueso <dave@stgolabs.net>,
Joel Fernandes <joelagnelf@nvidia.com>,
rcu@vger.kernel.org
Subject: [PATCH v3 14/14] [TEST COMMIT] rcu: detect stuck defer_qs_pending at GP cleanup
Date: Thu, 18 Jun 2026 14:50:30 -0400 [thread overview]
Message-ID: <20260618185030.376450-15-joelagnelf@nvidia.com> (raw)
In-Reply-To: <20260618185030.376450-1-joelagnelf@nvidia.com>
Debug-only stuck-state detector for upstream review. This commit is
NOT for merge; it is a review aid. Reviewers can enable
CONFIG_RCU_GP_CLEANUP_STALE_CHECK to gain runtime confidence in the
preceding fix commits.
Signed-off-by: Joel Fernandes <joelagnelf@nvidia.com>
---
kernel/rcu/Kconfig.debug | 11 ++++++++++
kernel/rcu/tree.c | 47 ++++++++++++++++++++++++++++++++++++++++
kernel/rcu/tree.h | 8 +++++++
3 files changed, 66 insertions(+)
diff --git a/kernel/rcu/Kconfig.debug b/kernel/rcu/Kconfig.debug
index 35218ba74eb5..5a40c4fe544c 100644
--- a/kernel/rcu/Kconfig.debug
+++ b/kernel/rcu/Kconfig.debug
@@ -98,6 +98,17 @@ config RCU_TORTURE_TEST_LOG_GP
Say Y here if you want grace-period sequence numbers logged.
Say N if you are unsure.
+config RCU_GP_CLEANUP_STALE_CHECK
+ bool "Detect stuck defer_qs_pending state at GP cleanup"
+ depends on RCU_TORTURE_TEST
+ default n
+ help
+ This option adds a per-CPU instrumentation counter on every
+ PENDING -> IDLE transition of rdp->defer_qs_pending, and a
+ detector in rcu_gp_cleanup().
+
+ Say N if you are unsure.
+
config RCU_REF_SCALE_TEST
tristate "Scalability tests for read-side synchronization (RCU and others)"
depends on DEBUG_KERNEL
diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c
index 8fd62775c176..67d51990427d 100644
--- a/kernel/rcu/tree.c
+++ b/kernel/rcu/tree.c
@@ -2147,6 +2147,52 @@ static noinline_for_stack void rcu_gp_fqs_loop(void)
}
}
+#ifdef CONFIG_RCU_GP_CLEANUP_STALE_CHECK
+/*
+ * Threshold of consecutive GPs with rdp->defer_qs_pending stuck at
+ * PENDING and no observed PENDING -> IDLE transition before WARN.
+ */
+#define RCU_DEFER_QS_STUCK_GPS_THRESHOLD 5
+
+static void rcu_gp_cleanup_stale_check(void)
+{
+ int cpu;
+ unsigned long cur_gp_seq = READ_ONCE(rcu_state.gp_seq);
+
+ for_each_online_cpu(cpu) {
+ struct rcu_data *rdp = per_cpu_ptr(&rcu_data, cpu);
+ s64 clears_now;
+ int p_now;
+
+ if (READ_ONCE(rdp->gp_seq) != cur_gp_seq) {
+ rdp->defer_qs_pending_stuck_gps = 0;
+ rdp->defer_qs_pending_clears_snap =
+ atomic64_read(&rdp->defer_qs_pending_clears);
+ continue;
+ }
+
+ clears_now = atomic64_read(&rdp->defer_qs_pending_clears);
+ p_now = READ_ONCE(rdp->defer_qs_pending);
+
+ if (p_now != DEFER_QS_PENDING ||
+ clears_now != rdp->defer_qs_pending_clears_snap) {
+ rdp->defer_qs_pending_stuck_gps = 0;
+ rdp->defer_qs_pending_clears_snap = clears_now;
+ continue;
+ }
+
+ rdp->defer_qs_pending_stuck_gps++;
+ WARN_ONCE(rdp->defer_qs_pending_stuck_gps >=
+ RCU_DEFER_QS_STUCK_GPS_THRESHOLD,
+ "RCU: defer_qs_pending STUCK on CPU %d for %u GPs (gp_seq=%lu, clears=%lld)\n",
+ cpu, rdp->defer_qs_pending_stuck_gps,
+ cur_gp_seq, clears_now);
+ }
+}
+#else
+static inline void rcu_gp_cleanup_stale_check(void) { }
+#endif /* CONFIG_RCU_GP_CLEANUP_STALE_CHECK */
+
/*
* Clean up after the old grace period.
*/
@@ -2221,6 +2267,7 @@ static noinline void rcu_gp_cleanup(void)
/* Declare grace period done, trace first to use old GP number. */
trace_rcu_grace_period(rcu_state.name, rcu_state.gp_seq, TPS("end"));
+ rcu_gp_cleanup_stale_check();
rcu_seq_end(&rcu_state.gp_seq);
ASSERT_EXCLUSIVE_WRITER(rcu_state.gp_seq);
WRITE_ONCE(rcu_state.gp_state, RCU_GP_IDLE);
diff --git a/kernel/rcu/tree.h b/kernel/rcu/tree.h
index 3da43935f5e0..010052a55477 100644
--- a/kernel/rcu/tree.h
+++ b/kernel/rcu/tree.h
@@ -205,6 +205,11 @@ struct rcu_data {
struct irq_work defer_qs_iw; /* Obtain later scheduler attention. */
struct hrtimer defer_qs_iw_rescue;/* Rescue timer for deferred-QS. */
int defer_qs_pending; /* irqwork or softirq pending? */
+#ifdef CONFIG_RCU_GP_CLEANUP_STALE_CHECK
+ atomic64_t defer_qs_pending_clears;
+ s64 defer_qs_pending_clears_snap;
+ unsigned int defer_qs_pending_stuck_gps;
+#endif
struct work_struct strict_work; /* Schedule readers for strict GPs. */
/* 2) batch handling */
@@ -300,6 +305,9 @@ struct rcu_data {
static inline void rcu_defer_qs_clear(struct rcu_data *rdp)
{
WRITE_ONCE(rdp->defer_qs_pending, DEFER_QS_IDLE);
+#ifdef CONFIG_RCU_GP_CLEANUP_STALE_CHECK
+ atomic64_inc(&rdp->defer_qs_pending_clears);
+#endif
}
/* Values for nocb_defer_wakeup field in struct rcu_data. */
--
2.34.1
prev parent reply other threads:[~2026-06-18 18:51 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-06-18 18:50 [PATCH v3 00/14] rcu: fix stuck defer_qs_pending state, add rescue timer and torture tests Joel Fernandes
2026-06-18 18:50 ` [PATCH v3 01/14] rcu: introduce rcu_defer_qs_clear() helper Joel Fernandes
2026-06-18 18:50 ` [PATCH v3 02/14] rcu: clear defer_qs_pending when notifying GP changes Joel Fernandes
2026-06-18 18:50 ` [PATCH v3 03/14] rcu: clear defer_qs_pending in handler for compounded sections Joel Fernandes
2026-06-18 18:50 ` [PATCH v3 04/14] rcu: drop redundant defer_qs_pending clear in irqrestore handler Joel Fernandes
2026-06-18 18:50 ` [PATCH v3 05/14] rcu: clear defer_qs_pending at expedited IPI entry Joel Fernandes
2026-06-18 18:50 ` [PATCH v3 06/14] rcu: set need_resched on softirq deferred-QS arming path Joel Fernandes
2026-06-18 18:50 ` [PATCH v3 07/14] rcu: clear defer_qs_pending in deferred-QS bail when nesting > 0 Joel Fernandes
2026-06-18 18:50 ` [PATCH v3 08/14] rcu: add per-CPU rescue hrtimer for deferred-QS reporting Joel Fernandes
2026-06-18 18:50 ` [PATCH v3 09/14] rcutorture: Abstract reader-segment dump into rcu_torture_dump_read_segs() Joel Fernandes
2026-06-18 18:50 ` [PATCH v3 10/14] rcutorture: Check for immediate deboosting at reader end Joel Fernandes
2026-06-18 18:50 ` [PATCH v3 11/14] rcutorture: Test RCU readers from hardware interrupt handlers Joel Fernandes
2026-06-18 18:50 ` [PATCH v3 12/14] rcutorture: tighten boost-WARN to exclude any implicit-reader context Joel Fernandes
2026-06-18 18:50 ` [PATCH v3 13/14] rcutorture: give async deboost mechanisms up to 500us before WARN Joel Fernandes
2026-06-18 18:50 ` Joel Fernandes [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=20260618185030.376450-15-joelagnelf@nvidia.com \
--to=joelagnelf@nvidia.com \
--cc=boqun@kernel.org \
--cc=dave@stgolabs.net \
--cc=frederic@kernel.org \
--cc=jiangshanlai@gmail.com \
--cc=josh@joshtriplett.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mathieu.desnoyers@efficios.com \
--cc=neeraj.upadhyay@kernel.org \
--cc=paulmck@kernel.org \
--cc=qiang.zhang@linux.dev \
--cc=rcu@vger.kernel.org \
--cc=rostedt@goodmis.org \
--cc=urezki@gmail.com \
/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
Powered by JetHome