[PATCH v2 7/7] rcutorture: Check an atomic SRCU wait within an RCU reader
From: Mathieu Desnoyers
Date: Wed Nov 11 2026 - 10:11:19 EST
synchronize_srcu_atomic() may be called within rcu_read_lock(). It must
then not end an RCU grace period, because its caller still holds it up.
Tiny SRCU did end one, by calling synchronize_rcu().
Check this once, when a torture type starts with atomic SRCU readers.
Take a cookie from get_state_synchronize_rcu() within rcu_read_lock(),
call synchronize_srcu_atomic(), and warn if
poll_state_synchronize_rcu() then reports the cookie as completed. The
cookie is taken within the reader, so no RCU grace period can complete
it before rcu_read_unlock().
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@xxxxxxxxxxxx>
---
kernel/rcu/rcutorture.c | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
diff --git a/kernel/rcu/rcutorture.c b/kernel/rcu/rcutorture.c
index 2ec461414263..d9c9ff653cb6 100644
--- a/kernel/rcu/rcutorture.c
+++ b/kernel/rcu/rcutorture.c
@@ -799,6 +799,24 @@ static void srcu_torture_read_unlock_atomic(int idx)
srcu_read_unlock_atomic_irqrestore(srcu_ctlp, idx, flags);
}
+/*
+ * Wait for an atomic SRCU grace period within an RCU reader. The wait must
+ * not end an RCU grace period: this reader still holds it up. The cookie is
+ * taken within the reader, so no RCU grace period can complete it there.
+ */
+static void srcu_torture_check_atomic_in_rcu_reader(void)
+{
+ unsigned long cookie;
+
+ rcu_read_lock();
+ cookie = get_state_synchronize_rcu();
+ synchronize_srcu_atomic(srcu_ctlp);
+ WARN_ONCE(poll_state_synchronize_rcu(cookie),
+ "%s: synchronize_srcu_atomic() ended an RCU grace period within an RCU reader\n",
+ __func__);
+ rcu_read_unlock();
+}
+
static void srcu_torture_init(void)
{
rcu_sync_torture_init();
@@ -819,6 +837,7 @@ static void srcu_torture_init(void)
VERBOSE_TOROUT_STRING("srcu_torture_init atomic SRCU");
srcu_torture_init_forbidden_apis();
srcu_torture_init_irqsave();
+ srcu_torture_check_atomic_in_rcu_reader();
}
}
@@ -1093,6 +1112,8 @@ static void srcud_torture_init(void)
WARN_ON(init_srcu_struct(&srcu_ctld));
}
srcu_ctlp = &srcu_ctld;
+ if (reader_flavor & SRCU_READ_FLAVOR_ATOMIC)
+ srcu_torture_check_atomic_in_rcu_reader();
}
static void srcu_torture_cleanup(void)
--
2.47.3