* [PATCH rcu 00/15] RCU torture changes for v6.17
@ 2025-07-09 10:42 neeraj.upadhyay
2025-07-09 10:42 ` [PATCH rcu 01/15] rcutorture: Print only one rtort_pipe_count splat neeraj.upadhyay
` (14 more replies)
0 siblings, 15 replies; 16+ messages in thread
From: neeraj.upadhyay @ 2025-07-09 10:42 UTC (permalink / raw)
To: rcu
Cc: linux-kernel, paulmck, joelagnelf, frederic, boqun.feng, urezki,
rostedt, mathieu.desnoyers, jiangshanlai, qiang.zhang1211,
neeraj.iitr10, neeraj.upadhyay, Neeraj Upadhyay (AMD)
From: "Neeraj Upadhyay (AMD)" <neeraj.upadhyay@kernel.org>
Hello,
This patch series contains following updates to the RCU torture code
(rebased on v6.16-rc3):
Paul E. McKenney (14):
rcutorture: Print only one rtort_pipe_count splat
rcutorture: Start rcu_torture_writer() after rcu_torture_reader()
rcutorture: Make rcutorture_one_extend_check() account for hard IRQs
rcutorture: Add tests for SRCU up/down reader primitives
rcutorture: Pull rcu_torture_updown() loop body into new function
rcutorture: Complain if an ->up_read() is delayed more than 10 seconds
rcutorture: Check for ->up_read() without matching ->down_read()
rcutorture: Check for no up/down readers at task level
rcutorture: Print number of RCU up/down readers and migrations
rcutorture: Drop redundant "insoftirq" parameters
rcutorture: Make Trivial RCU ignore onoff_interval and
shuffle_interval
rcutorture: Make BUSTED scenario check and log readers
rcutorture: Remove SRCU-lite scenarios
rcutorture: Remove support for SRCU-lite
Zqiang (1):
rcutorture: Fix rcutorture_one_extend_check() splat in RT kernels
include/linux/srcu.h | 2 +-
kernel/rcu/rcutorture.c | 356 +++++++++++++++---
.../selftests/rcutorture/configs/rcu/BUSTED | 3 +
.../selftests/rcutorture/configs/rcu/CFLIST | 1 -
.../selftests/rcutorture/configs/rcu/SRCU-L | 10 -
.../rcutorture/configs/rcu/SRCU-L.boot | 3 -
6 files changed, 302 insertions(+), 73 deletions(-)
delete mode 100644 tools/testing/selftests/rcutorture/configs/rcu/SRCU-L
delete mode 100644 tools/testing/selftests/rcutorture/configs/rcu/SRCU-L.boot
--
2.40.1
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH rcu 01/15] rcutorture: Print only one rtort_pipe_count splat
2025-07-09 10:42 [PATCH rcu 00/15] RCU torture changes for v6.17 neeraj.upadhyay
@ 2025-07-09 10:42 ` neeraj.upadhyay
2025-07-09 10:42 ` [PATCH rcu 02/15] rcutorture: Start rcu_torture_writer() after rcu_torture_reader() neeraj.upadhyay
` (13 subsequent siblings)
14 siblings, 0 replies; 16+ messages in thread
From: neeraj.upadhyay @ 2025-07-09 10:42 UTC (permalink / raw)
To: rcu
Cc: linux-kernel, paulmck, joelagnelf, frederic, boqun.feng, urezki,
rostedt, mathieu.desnoyers, jiangshanlai, qiang.zhang1211,
neeraj.iitr10, neeraj.upadhyay, Neeraj Upadhyay (AMD)
From: "Paul E. McKenney" <paulmck@kernel.org>
The rcu_torture_writer() function scans the memory blocks after a stutter
(or forced idle) interval, complaining about any that have not passed
through ten grace periods since the start of the stutter interval.
But one splat suffices, so this commit therefore stops at the first splat.
Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
Signed-off-by: Joel Fernandes <joelagnelf@nvidia.com>
Signed-off-by: Neeraj Upadhyay (AMD) <neeraj.upadhyay@kernel.org>
---
kernel/rcu/rcutorture.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/kernel/rcu/rcutorture.c b/kernel/rcu/rcutorture.c
index 70ec0f21abc3..d1e0d61d8815 100644
--- a/kernel/rcu/rcutorture.c
+++ b/kernel/rcu/rcutorture.c
@@ -1722,6 +1722,7 @@ rcu_torture_writer(void *arg)
cur_ops->gp_kthread_dbg();
WARN(1, "%s: rtort_pipe_count: %d\n", __func__, rcu_tortures[i].rtort_pipe_count);
rcu_ftrace_dump(DUMP_ALL);
+ break;
}
if (stutter_waited)
sched_set_normal(current, oldnice);
--
2.40.1
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH rcu 02/15] rcutorture: Start rcu_torture_writer() after rcu_torture_reader()
2025-07-09 10:42 [PATCH rcu 00/15] RCU torture changes for v6.17 neeraj.upadhyay
2025-07-09 10:42 ` [PATCH rcu 01/15] rcutorture: Print only one rtort_pipe_count splat neeraj.upadhyay
@ 2025-07-09 10:42 ` neeraj.upadhyay
2025-07-09 10:42 ` [PATCH rcu 03/15] rcutorture: Make rcutorture_one_extend_check() account for hard IRQs neeraj.upadhyay
` (12 subsequent siblings)
14 siblings, 0 replies; 16+ messages in thread
From: neeraj.upadhyay @ 2025-07-09 10:42 UTC (permalink / raw)
To: rcu
Cc: linux-kernel, paulmck, joelagnelf, frederic, boqun.feng, urezki,
rostedt, mathieu.desnoyers, jiangshanlai, qiang.zhang1211,
neeraj.iitr10, neeraj.upadhyay, Neeraj Upadhyay (AMD)
From: "Paul E. McKenney" <paulmck@kernel.org>
Testing of rcutorture's SRCU-P scenario on a large arm64 system resulted
in rcu_torture_writer() forward-progress failures, but these same tests
passed on x86. After some off-list discussion of possible memory-ordering
causes for these failures, Boqun showed that these were in fact due to
reordering, but by the scheduler, not by the memory system. On x86,
rcu_torture_writer() would have run quickly enough that by the time
the rcu_torture_updown() kthread started, the rcu_torture_current
variable would already be initialized, thus avoiding a bug in which
a NULL value would cause rcu_torture_updown() to do an extra call to
srcu_up_read_fast().
This commit therefore moves creation of the rcu_torture_writer() kthread
after that of the rcu_torture_reader() kthreads. This results in
deterministic failures on x86.
What about the double-srcu_up_read_fast() bug? Boqun has the fix.
But let's also fix the test while we are at it!
Reported-by: Joel Fernandes <joelagnelf@nvidia.com>
Reported-by: Boqun Feng <boqun.feng@gmail.com>
Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
Signed-off-by: Joel Fernandes <joelagnelf@nvidia.com>
Signed-off-by: Neeraj Upadhyay (AMD) <neeraj.upadhyay@kernel.org>
---
kernel/rcu/rcutorture.c | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/kernel/rcu/rcutorture.c b/kernel/rcu/rcutorture.c
index d1e0d61d8815..a209d2419cfd 100644
--- a/kernel/rcu/rcutorture.c
+++ b/kernel/rcu/rcutorture.c
@@ -4246,11 +4246,6 @@ rcu_torture_init(void)
/* Start up the kthreads. */
rcu_torture_write_types();
- firsterr = torture_create_kthread(rcu_torture_writer, NULL,
- writer_task);
- if (torture_init_error(firsterr))
- goto unwind;
-
if (nrealfakewriters > 0) {
fakewriter_tasks = kcalloc(nrealfakewriters,
sizeof(fakewriter_tasks[0]),
@@ -4283,6 +4278,12 @@ rcu_torture_init(void)
if (torture_init_error(firsterr))
goto unwind;
}
+
+ firsterr = torture_create_kthread(rcu_torture_writer, NULL,
+ writer_task);
+ if (torture_init_error(firsterr))
+ goto unwind;
+
nrealnocbers = nocbs_nthreads;
if (WARN_ON(nrealnocbers < 0))
nrealnocbers = 1;
--
2.40.1
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH rcu 03/15] rcutorture: Make rcutorture_one_extend_check() account for hard IRQs
2025-07-09 10:42 [PATCH rcu 00/15] RCU torture changes for v6.17 neeraj.upadhyay
2025-07-09 10:42 ` [PATCH rcu 01/15] rcutorture: Print only one rtort_pipe_count splat neeraj.upadhyay
2025-07-09 10:42 ` [PATCH rcu 02/15] rcutorture: Start rcu_torture_writer() after rcu_torture_reader() neeraj.upadhyay
@ 2025-07-09 10:42 ` neeraj.upadhyay
2025-07-09 10:42 ` [PATCH rcu 04/15] rcutorture: Add tests for SRCU up/down reader primitives neeraj.upadhyay
` (11 subsequent siblings)
14 siblings, 0 replies; 16+ messages in thread
From: neeraj.upadhyay @ 2025-07-09 10:42 UTC (permalink / raw)
To: rcu
Cc: linux-kernel, paulmck, joelagnelf, frederic, boqun.feng, urezki,
rostedt, mathieu.desnoyers, jiangshanlai, qiang.zhang1211,
neeraj.iitr10, neeraj.upadhyay, Neeraj Upadhyay (AMD),
kernel test robot
From: "Paul E. McKenney" <paulmck@kernel.org>
This commit retrospectively prepares for testing of RCU readers invoked
from hardware interrupt handlers (for example, HRTIMER_MODE_HARD hrtimer
handlers) in kernels built with CONFIG_RCU_TORTURE_TEST_CHK_RDR_STATE=y,
which is rarely used but sometimes extremely useful. This preparation
involves taking early exits if in_hardirq(), and, while we are in the
area, a very early exit if in_nmi().
This means that a number of insoftirq parameters are no longer needed,
but that is the subject of a later commit.
Reported-by: kernel test robot <oliver.sang@intel.com>
Closes: https://lore.kernel.org/oe-lkp/202505140917.8ee62cc6-lkp@intel.com
Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
Tested-by: kernel test robot <oliver.sang@intel.com>
Signed-off-by: Neeraj Upadhyay (AMD) <neeraj.upadhyay@kernel.org>
---
kernel/rcu/rcutorture.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/kernel/rcu/rcutorture.c b/kernel/rcu/rcutorture.c
index a209d2419cfd..7944cc69321d 100644
--- a/kernel/rcu/rcutorture.c
+++ b/kernel/rcu/rcutorture.c
@@ -1920,10 +1920,10 @@ static void rcutorture_one_extend_check(char *s, int curstate, int new, int old,
{
int mask;
- if (!IS_ENABLED(CONFIG_RCU_TORTURE_TEST_CHK_RDR_STATE))
+ if (!IS_ENABLED(CONFIG_RCU_TORTURE_TEST_CHK_RDR_STATE) || in_nmi())
return;
- WARN_ONCE(!(curstate & RCUTORTURE_RDR_IRQ) && irqs_disabled(), ROEC_ARGS);
+ WARN_ONCE(!(curstate & RCUTORTURE_RDR_IRQ) && irqs_disabled() && !in_hardirq(), ROEC_ARGS);
WARN_ONCE((curstate & RCUTORTURE_RDR_IRQ) && !irqs_disabled(), ROEC_ARGS);
// If CONFIG_PREEMPT_COUNT=n, further checks are unreliable.
@@ -1938,9 +1938,9 @@ static void rcutorture_one_extend_check(char *s, int curstate, int new, int old,
(curstate & (RCUTORTURE_RDR_RCU_1 | RCUTORTURE_RDR_RCU_2)) &&
cur_ops->readlock_nesting() == 0, ROEC_ARGS);
- // Timer handlers have all sorts of stuff disabled, so ignore
+ // Interrupt handlers have all sorts of stuff disabled, so ignore
// unintended disabling.
- if (insoftirq)
+ if (in_serving_softirq() || in_hardirq())
return;
WARN_ONCE(cur_ops->extendables &&
--
2.40.1
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH rcu 04/15] rcutorture: Add tests for SRCU up/down reader primitives
2025-07-09 10:42 [PATCH rcu 00/15] RCU torture changes for v6.17 neeraj.upadhyay
` (2 preceding siblings ...)
2025-07-09 10:42 ` [PATCH rcu 03/15] rcutorture: Make rcutorture_one_extend_check() account for hard IRQs neeraj.upadhyay
@ 2025-07-09 10:42 ` neeraj.upadhyay
2025-07-09 10:42 ` [PATCH rcu 05/15] rcutorture: Pull rcu_torture_updown() loop body into new function neeraj.upadhyay
` (10 subsequent siblings)
14 siblings, 0 replies; 16+ messages in thread
From: neeraj.upadhyay @ 2025-07-09 10:42 UTC (permalink / raw)
To: rcu
Cc: linux-kernel, paulmck, joelagnelf, frederic, boqun.feng, urezki,
rostedt, mathieu.desnoyers, jiangshanlai, qiang.zhang1211,
neeraj.iitr10, neeraj.upadhyay, Neeraj Upadhyay (AMD),
kernel test robot
From: "Paul E. McKenney" <paulmck@kernel.org>
This commit adds a new rcutorture.n_up_down kernel boot parameter
that specifies the number of outstanding SRCU up/down readers, which
begin in kthread context and end in an hrtimer handler. There is a new
kthread ("rcu_torture_updown") that scans an per-reader array looking
for elements whose readers have ended. This kthread sleeps between one
and two milliseconds between consecutive scans.
[ paulmck: Apply kernel test robot feedback. ]
[ paulmck: Apply Z qiang feedback. ]
[ joel: Fix build error: hrtimer_init is replaced by hrtimer_setup. ]
[ joel: Apply Boqun bug fix to drop extra up_read() call in
rcu_torture_updown()].
Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
Signed-off-by: Joel Fernandes <joelagnelf@nvidia.com>
Tested-by: kernel test robot <oliver.sang@intel.com>
Signed-off-by: Neeraj Upadhyay (AMD) <neeraj.upadhyay@kernel.org>
---
kernel/rcu/rcutorture.c | 225 ++++++++++++++++++++++++++++++++++++----
1 file changed, 206 insertions(+), 19 deletions(-)
diff --git a/kernel/rcu/rcutorture.c b/kernel/rcu/rcutorture.c
index 7944cc69321d..bf87c0c4e77e 100644
--- a/kernel/rcu/rcutorture.c
+++ b/kernel/rcu/rcutorture.c
@@ -55,22 +55,24 @@ MODULE_DESCRIPTION("Read-Copy Update module-based torture test facility");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Paul E. McKenney <paulmck@linux.ibm.com> and Josh Triplett <josh@joshtriplett.org>");
-/* Bits for ->extendables field, extendables param, and related definitions. */
-#define RCUTORTURE_RDR_SHIFT_1 8 /* Put SRCU index in upper bits. */
-#define RCUTORTURE_RDR_MASK_1 (0xff << RCUTORTURE_RDR_SHIFT_1)
-#define RCUTORTURE_RDR_SHIFT_2 16 /* Put SRCU index in upper bits. */
-#define RCUTORTURE_RDR_MASK_2 (0xff << RCUTORTURE_RDR_SHIFT_2)
-#define RCUTORTURE_RDR_BH 0x01 /* Extend readers by disabling bh. */
-#define RCUTORTURE_RDR_IRQ 0x02 /* ... disabling interrupts. */
-#define RCUTORTURE_RDR_PREEMPT 0x04 /* ... disabling preemption. */
-#define RCUTORTURE_RDR_RBH 0x08 /* ... rcu_read_lock_bh(). */
-#define RCUTORTURE_RDR_SCHED 0x10 /* ... rcu_read_lock_sched(). */
-#define RCUTORTURE_RDR_RCU_1 0x20 /* ... entering another RCU reader. */
-#define RCUTORTURE_RDR_RCU_2 0x40 /* ... entering another RCU reader. */
-#define RCUTORTURE_RDR_NBITS 7 /* Number of bits defined above. */
-#define RCUTORTURE_MAX_EXTEND \
+// Bits for ->extendables field, extendables param, and related definitions.
+#define RCUTORTURE_RDR_SHIFT_1 8 // Put SRCU index in upper bits.
+#define RCUTORTURE_RDR_MASK_1 (0xff << RCUTORTURE_RDR_SHIFT_1)
+#define RCUTORTURE_RDR_SHIFT_2 16 // Put SRCU index in upper bits.
+#define RCUTORTURE_RDR_MASK_2 (0xff << RCUTORTURE_RDR_SHIFT_2)
+#define RCUTORTURE_RDR_BH 0x01 // Extend readers by disabling bh.
+#define RCUTORTURE_RDR_IRQ 0x02 // ... disabling interrupts.
+#define RCUTORTURE_RDR_PREEMPT 0x04 // ... disabling preemption.
+#define RCUTORTURE_RDR_RBH 0x08 // ... rcu_read_lock_bh().
+#define RCUTORTURE_RDR_SCHED 0x10 // ... rcu_read_lock_sched().
+#define RCUTORTURE_RDR_RCU_1 0x20 // ... entering another RCU reader.
+#define RCUTORTURE_RDR_RCU_2 0x40 // ... entering another RCU reader.
+#define RCUTORTURE_RDR_UPDOWN 0x80 // ... up-read from task, down-read from timer.
+ // Note: Manual start, automatic end.
+#define RCUTORTURE_RDR_NBITS 8 // Number of bits defined above.
+#define RCUTORTURE_MAX_EXTEND \
(RCUTORTURE_RDR_BH | RCUTORTURE_RDR_IRQ | RCUTORTURE_RDR_PREEMPT | \
- RCUTORTURE_RDR_RBH | RCUTORTURE_RDR_SCHED)
+ RCUTORTURE_RDR_RBH | RCUTORTURE_RDR_SCHED) // Intentionally omit RCUTORTURE_RDR_UPDOWN.
#define RCUTORTURE_RDR_ALLBITS \
(RCUTORTURE_MAX_EXTEND | RCUTORTURE_RDR_RCU_1 | RCUTORTURE_RDR_RCU_2 | \
RCUTORTURE_RDR_MASK_1 | RCUTORTURE_RDR_MASK_2)
@@ -110,6 +112,7 @@ torture_param(bool, gp_sync, false, "Use synchronous GP wait primitives");
torture_param(int, irqreader, 1, "Allow RCU readers from irq handlers");
torture_param(int, leakpointer, 0, "Leak pointer dereferences from readers");
torture_param(int, n_barrier_cbs, 0, "# of callbacks/kthreads for barrier testing");
+torture_param(int, n_up_down, 32, "# of concurrent up/down hrtimer-based RCU readers");
torture_param(int, nfakewriters, 4, "Number of RCU fake writer threads");
torture_param(int, nreaders, -1, "Number of RCU reader threads");
torture_param(int, object_debug, 0, "Enable debug-object double call_rcu() testing");
@@ -156,6 +159,7 @@ static int nrealfakewriters;
static struct task_struct *writer_task;
static struct task_struct **fakewriter_tasks;
static struct task_struct **reader_tasks;
+static struct task_struct *updown_task;
static struct task_struct **nocb_tasks;
static struct task_struct *stats_task;
static struct task_struct *fqs_task;
@@ -378,6 +382,8 @@ struct rcu_torture_ops {
void (*readunlock)(int idx);
int (*readlock_held)(void); // lockdep.
int (*readlock_nesting)(void); // actual nesting, if available, -1 if not.
+ int (*down_read)(void);
+ void (*up_read)(int idx);
unsigned long (*get_gp_seq)(void);
unsigned long (*gp_diff)(unsigned long new, unsigned long old);
void (*deferred_free)(struct rcu_torture *p);
@@ -427,6 +433,7 @@ struct rcu_torture_ops {
int no_pi_lock;
int debug_objects;
int start_poll_irqsoff;
+ int have_up_down;
const char *name;
};
@@ -762,6 +769,50 @@ static int torture_srcu_read_lock_held(void)
return srcu_read_lock_held(srcu_ctlp);
}
+static bool srcu_torture_have_up_down(void)
+{
+ int rf = reader_flavor;
+
+ if (!rf)
+ rf = SRCU_READ_FLAVOR_NORMAL;
+ return !!(cur_ops->have_up_down & rf);
+}
+
+static int srcu_torture_down_read(void)
+{
+ int idx;
+ struct srcu_ctr __percpu *scp;
+
+ WARN_ON_ONCE(reader_flavor & ~SRCU_READ_FLAVOR_ALL);
+ WARN_ON_ONCE(reader_flavor & (reader_flavor - 1));
+
+ if ((reader_flavor & SRCU_READ_FLAVOR_NORMAL) || !(reader_flavor & SRCU_READ_FLAVOR_ALL)) {
+ idx = srcu_down_read(srcu_ctlp);
+ WARN_ON_ONCE(idx & ~0x1);
+ return idx;
+ }
+ if (reader_flavor & SRCU_READ_FLAVOR_FAST) {
+ scp = srcu_down_read_fast(srcu_ctlp);
+ idx = __srcu_ptr_to_ctr(srcu_ctlp, scp);
+ WARN_ON_ONCE(idx & ~0x1);
+ return idx << 3;
+ }
+ WARN_ON_ONCE(1);
+ return 0;
+}
+
+static void srcu_torture_up_read(int idx)
+{
+ WARN_ON_ONCE((reader_flavor && (idx & ~reader_flavor)) || (!reader_flavor && (idx & ~0x1)));
+ if (reader_flavor & SRCU_READ_FLAVOR_FAST)
+ srcu_up_read_fast(srcu_ctlp, __srcu_ctr_to_ptr(srcu_ctlp, (idx & 0x8) >> 3));
+ else if ((reader_flavor & SRCU_READ_FLAVOR_NORMAL) ||
+ !(reader_flavor & SRCU_READ_FLAVOR_ALL))
+ srcu_up_read(srcu_ctlp, idx & 0x1);
+ else
+ WARN_ON_ONCE(1);
+}
+
static unsigned long srcu_torture_completed(void)
{
return srcu_batches_completed(srcu_ctlp);
@@ -819,6 +870,8 @@ static struct rcu_torture_ops srcu_ops = {
.readlock = srcu_torture_read_lock,
.read_delay = srcu_read_delay,
.readunlock = srcu_torture_read_unlock,
+ .down_read = srcu_torture_down_read,
+ .up_read = srcu_torture_up_read,
.readlock_held = torture_srcu_read_lock_held,
.get_gp_seq = srcu_torture_completed,
.gp_diff = rcu_seq_diff,
@@ -839,6 +892,8 @@ static struct rcu_torture_ops srcu_ops = {
.irq_capable = 1,
.no_pi_lock = IS_ENABLED(CONFIG_TINY_SRCU),
.debug_objects = 1,
+ .have_up_down = IS_ENABLED(CONFIG_TINY_SRCU)
+ ? 0 : SRCU_READ_FLAVOR_NORMAL | SRCU_READ_FLAVOR_FAST,
.name = "srcu"
};
@@ -864,6 +919,8 @@ static struct rcu_torture_ops srcud_ops = {
.read_delay = srcu_read_delay,
.readunlock = srcu_torture_read_unlock,
.readlock_held = torture_srcu_read_lock_held,
+ .down_read = srcu_torture_down_read,
+ .up_read = srcu_torture_up_read,
.get_gp_seq = srcu_torture_completed,
.gp_diff = rcu_seq_diff,
.deferred_free = srcu_torture_deferred_free,
@@ -883,6 +940,8 @@ static struct rcu_torture_ops srcud_ops = {
.irq_capable = 1,
.no_pi_lock = IS_ENABLED(CONFIG_TINY_SRCU),
.debug_objects = 1,
+ .have_up_down = IS_ENABLED(CONFIG_TINY_SRCU)
+ ? 0 : SRCU_READ_FLAVOR_NORMAL | SRCU_READ_FLAVOR_FAST,
.name = "srcud"
};
@@ -1994,7 +2053,7 @@ static void rcutorture_one_extend(int *readstate, int newstate, bool insoftirq,
first = idxold1 == 0;
WARN_ON_ONCE(idxold2 < 0);
- WARN_ON_ONCE(idxold2 & ~RCUTORTURE_RDR_ALLBITS);
+ WARN_ON_ONCE(idxold2 & ~(RCUTORTURE_RDR_ALLBITS | RCUTORTURE_RDR_UPDOWN));
rcutorture_one_extend_check("before change", idxold1, statesnew, statesold, insoftirq);
rtrsp->rt_readstate = newstate;
@@ -2070,6 +2129,11 @@ static void rcutorture_one_extend(int *readstate, int newstate, bool insoftirq,
if (lockit)
raw_spin_unlock_irqrestore(¤t->pi_lock, flags);
}
+ if (statesold & RCUTORTURE_RDR_UPDOWN) {
+ cur_ops->up_read((idxold1 & RCUTORTURE_RDR_MASK_1) >> RCUTORTURE_RDR_SHIFT_1);
+ WARN_ON_ONCE(idxnew1 != -1);
+ idxold1 = 0;
+ }
/* Delay if neither beginning nor end and there was a change. */
if ((statesnew || statesold) && *readstate && newstate)
@@ -2210,7 +2274,8 @@ static bool rcu_torture_one_read_start(struct rcu_torture_one_read_state *rtorsp
rtorsp->started = cur_ops->get_gp_seq();
rtorsp->ts = rcu_trace_clock_local();
rtorsp->p = rcu_dereference_check(rcu_torture_current,
- !cur_ops->readlock_held || cur_ops->readlock_held());
+ !cur_ops->readlock_held || cur_ops->readlock_held() ||
+ (rtorsp->readstate & RCUTORTURE_RDR_UPDOWN));
if (rtorsp->p == NULL) {
/* Wait for rcu_torture_writer to get underway */
rcutorture_one_extend(&rtorsp->readstate, 0, myid < 0, trsp, rtorsp->rtrsp);
@@ -2379,6 +2444,121 @@ rcu_torture_reader(void *arg)
return 0;
}
+struct rcu_torture_one_read_state_updown {
+ struct hrtimer rtorsu_hrt;
+ bool rtorsu_inuse;
+ struct torture_random_state rtorsu_trs;
+ struct rcu_torture_one_read_state rtorsu_rtors;
+};
+
+static struct rcu_torture_one_read_state_updown *updownreaders;
+static DEFINE_TORTURE_RANDOM(rcu_torture_updown_rand);
+static int rcu_torture_updown(void *arg);
+
+static enum hrtimer_restart rcu_torture_updown_hrt(struct hrtimer *hrtp)
+{
+ struct rcu_torture_one_read_state_updown *rtorsup;
+
+ rtorsup = container_of(hrtp, struct rcu_torture_one_read_state_updown, rtorsu_hrt);
+ rcu_torture_one_read_end(&rtorsup->rtorsu_rtors, &rtorsup->rtorsu_trs, -1);
+ smp_store_release(&rtorsup->rtorsu_inuse, false);
+ return HRTIMER_NORESTART;
+}
+
+static int rcu_torture_updown_init(void)
+{
+ int i;
+ struct torture_random_state *rand = &rcu_torture_updown_rand;
+ int ret;
+
+ if (n_up_down < 0)
+ return 0;
+ if (!srcu_torture_have_up_down()) {
+ VERBOSE_TOROUT_STRING("rcu_torture_updown_init: Disabling up/down reader tests due to lack of primitives");
+ return 0;
+ }
+ updownreaders = kcalloc(n_up_down, sizeof(*updownreaders), GFP_KERNEL);
+ if (!updownreaders) {
+ VERBOSE_TOROUT_STRING("rcu_torture_updown_init: Out of memory, disabling up/down reader tests");
+ return -ENOMEM;
+ }
+ for (i = 0; i < n_up_down; i++) {
+ init_rcu_torture_one_read_state(&updownreaders[i].rtorsu_rtors, rand);
+ hrtimer_setup(&updownreaders[i].rtorsu_hrt, rcu_torture_updown_hrt, CLOCK_MONOTONIC,
+ HRTIMER_MODE_REL | HRTIMER_MODE_SOFT);
+ torture_random_init(&updownreaders[i].rtorsu_trs);
+ init_rcu_torture_one_read_state(&updownreaders[i].rtorsu_rtors,
+ &updownreaders[i].rtorsu_trs);
+ }
+ ret = torture_create_kthread(rcu_torture_updown, rand, updown_task);
+ if (ret) {
+ kfree(updownreaders);
+ updownreaders = NULL;
+ }
+ return ret;
+}
+
+static void rcu_torture_updown_cleanup(void)
+{
+ struct rcu_torture_one_read_state_updown *rtorsup;
+
+ for (rtorsup = updownreaders; rtorsup < &updownreaders[n_up_down]; rtorsup++) {
+ if (!smp_load_acquire(&rtorsup->rtorsu_inuse))
+ continue;
+ if (!hrtimer_cancel(&rtorsup->rtorsu_hrt))
+ WARN_ON_ONCE(rtorsup->rtorsu_inuse);
+
+ }
+ kfree(updownreaders);
+ updownreaders = NULL;
+}
+
+/*
+ * RCU torture up/down reader kthread, starting RCU readers in kthread
+ * context and ending them in hrtimer handlers. Otherwise similar to
+ * rcu_torture_reader().
+ */
+static int
+rcu_torture_updown(void *arg)
+{
+ int idx;
+ int rawidx;
+ struct rcu_torture_one_read_state_updown *rtorsup;
+ ktime_t t;
+
+ VERBOSE_TOROUT_STRING("rcu_torture_updown task started");
+ do {
+ for (rtorsup = updownreaders; rtorsup < &updownreaders[n_up_down]; rtorsup++) {
+ if (torture_must_stop())
+ break;
+ if (smp_load_acquire(&rtorsup->rtorsu_inuse))
+ continue;
+ init_rcu_torture_one_read_state(&rtorsup->rtorsu_rtors,
+ &rtorsup->rtorsu_trs);
+ rawidx = cur_ops->down_read();
+ idx = (rawidx << RCUTORTURE_RDR_SHIFT_1) & RCUTORTURE_RDR_MASK_1;
+ rtorsup->rtorsu_rtors.readstate = idx | RCUTORTURE_RDR_UPDOWN;
+ rtorsup->rtorsu_rtors.rtrsp++;
+ if (!rcu_torture_one_read_start(&rtorsup->rtorsu_rtors,
+ &rtorsup->rtorsu_trs, -1)) {
+ schedule_timeout_idle(HZ);
+ continue;
+ }
+ smp_store_release(&rtorsup->rtorsu_inuse, true);
+ t = torture_random(&rtorsup->rtorsu_trs) & 0xfffff; // One per million.
+ if (t < 10 * 1000)
+ t = 200 * 1000 * 1000;
+ hrtimer_start(&rtorsup->rtorsu_hrt, t,
+ HRTIMER_MODE_REL | HRTIMER_MODE_SOFT);
+ }
+ torture_hrtimeout_ms(1, 1000, &rcu_torture_updown_rand);
+ stutter_wait("rcu_torture_updown");
+ } while (!torture_must_stop());
+ rcu_torture_updown_cleanup();
+ torture_kthread_stopping("rcu_torture_updown");
+ return 0;
+}
+
/*
* Randomly Toggle CPUs' callback-offload state. This uses hrtimers to
* increase race probabilities and fuzzes the interval between toggling.
@@ -2633,7 +2813,7 @@ rcu_torture_print_module_parms(struct rcu_torture_ops *cur_ops, const char *tag)
"reader_flavor=%x "
"nocbs_nthreads=%d nocbs_toggle=%d "
"test_nmis=%d "
- "preempt_duration=%d preempt_interval=%d\n",
+ "preempt_duration=%d preempt_interval=%d n_up_down=%d\n",
torture_type, tag, nrealreaders, nrealfakewriters,
stat_interval, verbose, test_no_idle_hz, shuffle_interval,
stutter, irqreader, fqs_duration, fqs_holdoff, fqs_stutter,
@@ -2647,7 +2827,7 @@ rcu_torture_print_module_parms(struct rcu_torture_ops *cur_ops, const char *tag)
reader_flavor,
nocbs_nthreads, nocbs_toggle,
test_nmis,
- preempt_duration, preempt_interval);
+ preempt_duration, preempt_interval, n_up_down);
}
static int rcutorture_booster_cleanup(unsigned int cpu)
@@ -3750,6 +3930,10 @@ rcu_torture_cleanup(void)
nocb_tasks = NULL;
}
+ if (updown_task) {
+ torture_stop_kthread(rcu_torture_updown, updown_task);
+ updown_task = NULL;
+ }
if (reader_tasks) {
for (i = 0; i < nrealreaders; i++)
torture_stop_kthread(rcu_torture_reader,
@@ -4284,6 +4468,9 @@ rcu_torture_init(void)
if (torture_init_error(firsterr))
goto unwind;
+ firsterr = rcu_torture_updown_init();
+ if (torture_init_error(firsterr))
+ goto unwind;
nrealnocbers = nocbs_nthreads;
if (WARN_ON(nrealnocbers < 0))
nrealnocbers = 1;
--
2.40.1
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH rcu 05/15] rcutorture: Pull rcu_torture_updown() loop body into new function
2025-07-09 10:42 [PATCH rcu 00/15] RCU torture changes for v6.17 neeraj.upadhyay
` (3 preceding siblings ...)
2025-07-09 10:42 ` [PATCH rcu 04/15] rcutorture: Add tests for SRCU up/down reader primitives neeraj.upadhyay
@ 2025-07-09 10:42 ` neeraj.upadhyay
2025-07-09 10:42 ` [PATCH rcu 06/15] rcutorture: Complain if an ->up_read() is delayed more than 10 seconds neeraj.upadhyay
` (9 subsequent siblings)
14 siblings, 0 replies; 16+ messages in thread
From: neeraj.upadhyay @ 2025-07-09 10:42 UTC (permalink / raw)
To: rcu
Cc: linux-kernel, paulmck, joelagnelf, frederic, boqun.feng, urezki,
rostedt, mathieu.desnoyers, jiangshanlai, qiang.zhang1211,
neeraj.iitr10, neeraj.upadhyay, Neeraj Upadhyay (AMD)
From: "Paul E. McKenney" <paulmck@kernel.org>
This is strictly a code-movement commit, pulling that part of
the rcu_torture_updown() function's loop body that processes
one rcu_torture_one_read_state_updown structure into a new
rcu_torture_updown_one() function. The checks for the end of the
torture test and the current structure being in use remain in the
rcu_torture_updown() function.
Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
Signed-off-by: Joel Fernandes <joelagnelf@nvidia.com>
Signed-off-by: Neeraj Upadhyay (AMD) <neeraj.upadhyay@kernel.org>
---
kernel/rcu/rcutorture.c | 44 ++++++++++++++++++++++-------------------
1 file changed, 24 insertions(+), 20 deletions(-)
diff --git a/kernel/rcu/rcutorture.c b/kernel/rcu/rcutorture.c
index bf87c0c4e77e..13cf0e472868 100644
--- a/kernel/rcu/rcutorture.c
+++ b/kernel/rcu/rcutorture.c
@@ -2513,6 +2513,29 @@ static void rcu_torture_updown_cleanup(void)
updownreaders = NULL;
}
+// Do one reader for rcu_torture_updown().
+static void rcu_torture_updown_one(struct rcu_torture_one_read_state_updown *rtorsup)
+{
+ int idx;
+ int rawidx;
+ ktime_t t;
+
+ init_rcu_torture_one_read_state(&rtorsup->rtorsu_rtors, &rtorsup->rtorsu_trs);
+ rawidx = cur_ops->down_read();
+ idx = (rawidx << RCUTORTURE_RDR_SHIFT_1) & RCUTORTURE_RDR_MASK_1;
+ rtorsup->rtorsu_rtors.readstate = idx | RCUTORTURE_RDR_UPDOWN;
+ rtorsup->rtorsu_rtors.rtrsp++;
+ if (!rcu_torture_one_read_start(&rtorsup->rtorsu_rtors, &rtorsup->rtorsu_trs, -1)) {
+ schedule_timeout_idle(HZ);
+ return;
+ }
+ smp_store_release(&rtorsup->rtorsu_inuse, true);
+ t = torture_random(&rtorsup->rtorsu_trs) & 0xfffff; // One per million.
+ if (t < 10 * 1000)
+ t = 200 * 1000 * 1000;
+ hrtimer_start(&rtorsup->rtorsu_hrt, t, HRTIMER_MODE_REL | HRTIMER_MODE_SOFT);
+}
+
/*
* RCU torture up/down reader kthread, starting RCU readers in kthread
* context and ending them in hrtimer handlers. Otherwise similar to
@@ -2521,10 +2544,7 @@ static void rcu_torture_updown_cleanup(void)
static int
rcu_torture_updown(void *arg)
{
- int idx;
- int rawidx;
struct rcu_torture_one_read_state_updown *rtorsup;
- ktime_t t;
VERBOSE_TOROUT_STRING("rcu_torture_updown task started");
do {
@@ -2533,23 +2553,7 @@ rcu_torture_updown(void *arg)
break;
if (smp_load_acquire(&rtorsup->rtorsu_inuse))
continue;
- init_rcu_torture_one_read_state(&rtorsup->rtorsu_rtors,
- &rtorsup->rtorsu_trs);
- rawidx = cur_ops->down_read();
- idx = (rawidx << RCUTORTURE_RDR_SHIFT_1) & RCUTORTURE_RDR_MASK_1;
- rtorsup->rtorsu_rtors.readstate = idx | RCUTORTURE_RDR_UPDOWN;
- rtorsup->rtorsu_rtors.rtrsp++;
- if (!rcu_torture_one_read_start(&rtorsup->rtorsu_rtors,
- &rtorsup->rtorsu_trs, -1)) {
- schedule_timeout_idle(HZ);
- continue;
- }
- smp_store_release(&rtorsup->rtorsu_inuse, true);
- t = torture_random(&rtorsup->rtorsu_trs) & 0xfffff; // One per million.
- if (t < 10 * 1000)
- t = 200 * 1000 * 1000;
- hrtimer_start(&rtorsup->rtorsu_hrt, t,
- HRTIMER_MODE_REL | HRTIMER_MODE_SOFT);
+ rcu_torture_updown_one(rtorsup);
}
torture_hrtimeout_ms(1, 1000, &rcu_torture_updown_rand);
stutter_wait("rcu_torture_updown");
--
2.40.1
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH rcu 06/15] rcutorture: Complain if an ->up_read() is delayed more than 10 seconds
2025-07-09 10:42 [PATCH rcu 00/15] RCU torture changes for v6.17 neeraj.upadhyay
` (4 preceding siblings ...)
2025-07-09 10:42 ` [PATCH rcu 05/15] rcutorture: Pull rcu_torture_updown() loop body into new function neeraj.upadhyay
@ 2025-07-09 10:42 ` neeraj.upadhyay
2025-07-09 10:42 ` [PATCH rcu 07/15] rcutorture: Check for ->up_read() without matching ->down_read() neeraj.upadhyay
` (8 subsequent siblings)
14 siblings, 0 replies; 16+ messages in thread
From: neeraj.upadhyay @ 2025-07-09 10:42 UTC (permalink / raw)
To: rcu
Cc: linux-kernel, paulmck, joelagnelf, frederic, boqun.feng, urezki,
rostedt, mathieu.desnoyers, jiangshanlai, qiang.zhang1211,
neeraj.iitr10, neeraj.upadhyay, Neeraj Upadhyay (AMD),
kernel test robot
From: "Paul E. McKenney" <paulmck@kernel.org>
The down/up SRCU reader testing uses an hrtimer handler to exit the SRCU
read-side critical section. This might be delayed, and if delayed for
too long, it can prevent the rcutorture run from completing. This commit
therefore complains if the hrtimer handler is delayed for more than
ten seconds.
[ paulmck, joel: Apply kernel test robot feedback to avoid
false-positive complaint of excessive ->up_read() delays by using
HRTIMER_MODE_HARD ]
Tested-by: kernel test robot <oliver.sang@intel.com>
Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
Signed-off-by: Joel Fernandes <joelagnelf@nvidia.com>
Signed-off-by: Neeraj Upadhyay (AMD) <neeraj.upadhyay@kernel.org>
---
kernel/rcu/rcutorture.c | 16 +++++++++++++---
1 file changed, 13 insertions(+), 3 deletions(-)
diff --git a/kernel/rcu/rcutorture.c b/kernel/rcu/rcutorture.c
index 13cf0e472868..22288efc8c67 100644
--- a/kernel/rcu/rcutorture.c
+++ b/kernel/rcu/rcutorture.c
@@ -2447,6 +2447,8 @@ rcu_torture_reader(void *arg)
struct rcu_torture_one_read_state_updown {
struct hrtimer rtorsu_hrt;
bool rtorsu_inuse;
+ ktime_t rtorsu_kt;
+ unsigned long rtorsu_j;
struct torture_random_state rtorsu_trs;
struct rcu_torture_one_read_state rtorsu_rtors;
};
@@ -2485,7 +2487,7 @@ static int rcu_torture_updown_init(void)
for (i = 0; i < n_up_down; i++) {
init_rcu_torture_one_read_state(&updownreaders[i].rtorsu_rtors, rand);
hrtimer_setup(&updownreaders[i].rtorsu_hrt, rcu_torture_updown_hrt, CLOCK_MONOTONIC,
- HRTIMER_MODE_REL | HRTIMER_MODE_SOFT);
+ HRTIMER_MODE_REL | HRTIMER_MODE_HARD);
torture_random_init(&updownreaders[i].rtorsu_trs);
init_rcu_torture_one_read_state(&updownreaders[i].rtorsu_rtors,
&updownreaders[i].rtorsu_trs);
@@ -2533,7 +2535,10 @@ static void rcu_torture_updown_one(struct rcu_torture_one_read_state_updown *rto
t = torture_random(&rtorsup->rtorsu_trs) & 0xfffff; // One per million.
if (t < 10 * 1000)
t = 200 * 1000 * 1000;
- hrtimer_start(&rtorsup->rtorsu_hrt, t, HRTIMER_MODE_REL | HRTIMER_MODE_SOFT);
+ hrtimer_start(&rtorsup->rtorsu_hrt, t, HRTIMER_MODE_REL | HRTIMER_MODE_HARD);
+ smp_mb(); // Sample jiffies after posting hrtimer.
+ rtorsup->rtorsu_j = jiffies; // Not used by hrtimer handler.
+ rtorsup->rtorsu_kt = t;
}
/*
@@ -2544,6 +2549,7 @@ static void rcu_torture_updown_one(struct rcu_torture_one_read_state_updown *rto
static int
rcu_torture_updown(void *arg)
{
+ unsigned long j;
struct rcu_torture_one_read_state_updown *rtorsup;
VERBOSE_TOROUT_STRING("rcu_torture_updown task started");
@@ -2551,8 +2557,12 @@ rcu_torture_updown(void *arg)
for (rtorsup = updownreaders; rtorsup < &updownreaders[n_up_down]; rtorsup++) {
if (torture_must_stop())
break;
- if (smp_load_acquire(&rtorsup->rtorsu_inuse))
+ j = smp_load_acquire(&jiffies); // Time before ->rtorsu_inuse.
+ if (smp_load_acquire(&rtorsup->rtorsu_inuse)) {
+ WARN_ONCE(time_after(j, rtorsup->rtorsu_j + 1 + HZ * 10),
+ "hrtimer queued at jiffies %lu for %lld ns took %lu jiffies\n", rtorsup->rtorsu_j, rtorsup->rtorsu_kt, j - rtorsup->rtorsu_j);
continue;
+ }
rcu_torture_updown_one(rtorsup);
}
torture_hrtimeout_ms(1, 1000, &rcu_torture_updown_rand);
--
2.40.1
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH rcu 07/15] rcutorture: Check for ->up_read() without matching ->down_read()
2025-07-09 10:42 [PATCH rcu 00/15] RCU torture changes for v6.17 neeraj.upadhyay
` (5 preceding siblings ...)
2025-07-09 10:42 ` [PATCH rcu 06/15] rcutorture: Complain if an ->up_read() is delayed more than 10 seconds neeraj.upadhyay
@ 2025-07-09 10:42 ` neeraj.upadhyay
2025-07-09 10:42 ` [PATCH rcu 08/15] rcutorture: Check for no up/down readers at task level neeraj.upadhyay
` (7 subsequent siblings)
14 siblings, 0 replies; 16+ messages in thread
From: neeraj.upadhyay @ 2025-07-09 10:42 UTC (permalink / raw)
To: rcu
Cc: linux-kernel, paulmck, joelagnelf, frederic, boqun.feng, urezki,
rostedt, mathieu.desnoyers, jiangshanlai, qiang.zhang1211,
neeraj.iitr10, neeraj.upadhyay, Neeraj Upadhyay (AMD),
kernel test robot
From: "Paul E. McKenney" <paulmck@kernel.org>
This commit creates counters in the rcu_torture_one_read_state_updown
structure that check for a call to ->up_read() that lacks a matching
call to ->down_read().
While in the area, add end-of-run cleanup code that prevents calls to
rcu_torture_updown_hrt() from happening after the test has moved on. Yes,
the srcu_barrier() at the end of the test will wait for them, but this
could result in confusing states, statistics, and diagnostic information.
So explicitly wait for them before we get to the end-of-test output.
[ paulmck: Apply kernel test robot feedback. ]
[ joel: Apply Boqun's fix for counter increment ordering. ]
Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
Tested-by: kernel test robot <oliver.sang@intel.com>
Signed-off-by: Joel Fernandes <joelagnelf@nvidia.com>
Signed-off-by: Neeraj Upadhyay (AMD) <neeraj.upadhyay@kernel.org>
---
kernel/rcu/rcutorture.c | 15 +++++++++++++--
1 file changed, 13 insertions(+), 2 deletions(-)
diff --git a/kernel/rcu/rcutorture.c b/kernel/rcu/rcutorture.c
index 22288efc8c67..f773d4f8f2ae 100644
--- a/kernel/rcu/rcutorture.c
+++ b/kernel/rcu/rcutorture.c
@@ -2449,6 +2449,8 @@ struct rcu_torture_one_read_state_updown {
bool rtorsu_inuse;
ktime_t rtorsu_kt;
unsigned long rtorsu_j;
+ unsigned long rtorsu_ndowns;
+ unsigned long rtorsu_nups;
struct torture_random_state rtorsu_trs;
struct rcu_torture_one_read_state rtorsu_rtors;
};
@@ -2463,6 +2465,8 @@ static enum hrtimer_restart rcu_torture_updown_hrt(struct hrtimer *hrtp)
rtorsup = container_of(hrtp, struct rcu_torture_one_read_state_updown, rtorsu_hrt);
rcu_torture_one_read_end(&rtorsup->rtorsu_rtors, &rtorsup->rtorsu_trs, -1);
+ WARN_ONCE(rtorsup->rtorsu_nups >= rtorsup->rtorsu_ndowns, "%s: Up without matching down #%zu.\n", __func__, rtorsup - updownreaders);
+ rtorsup->rtorsu_nups++;
smp_store_release(&rtorsup->rtorsu_inuse, false);
return HRTIMER_NORESTART;
}
@@ -2507,8 +2511,12 @@ static void rcu_torture_updown_cleanup(void)
for (rtorsup = updownreaders; rtorsup < &updownreaders[n_up_down]; rtorsup++) {
if (!smp_load_acquire(&rtorsup->rtorsu_inuse))
continue;
- if (!hrtimer_cancel(&rtorsup->rtorsu_hrt))
- WARN_ON_ONCE(rtorsup->rtorsu_inuse);
+ if (hrtimer_cancel(&rtorsup->rtorsu_hrt) || WARN_ON_ONCE(rtorsup->rtorsu_inuse)) {
+ rcu_torture_one_read_end(&rtorsup->rtorsu_rtors, &rtorsup->rtorsu_trs, -1);
+ WARN_ONCE(rtorsup->rtorsu_nups >= rtorsup->rtorsu_ndowns, "%s: Up without matching down #%zu.\n", __func__, rtorsup - updownreaders);
+ rtorsup->rtorsu_nups++;
+ smp_store_release(&rtorsup->rtorsu_inuse, false);
+ }
}
kfree(updownreaders);
@@ -2524,10 +2532,13 @@ static void rcu_torture_updown_one(struct rcu_torture_one_read_state_updown *rto
init_rcu_torture_one_read_state(&rtorsup->rtorsu_rtors, &rtorsup->rtorsu_trs);
rawidx = cur_ops->down_read();
+ rtorsup->rtorsu_ndowns++;
idx = (rawidx << RCUTORTURE_RDR_SHIFT_1) & RCUTORTURE_RDR_MASK_1;
rtorsup->rtorsu_rtors.readstate = idx | RCUTORTURE_RDR_UPDOWN;
rtorsup->rtorsu_rtors.rtrsp++;
if (!rcu_torture_one_read_start(&rtorsup->rtorsu_rtors, &rtorsup->rtorsu_trs, -1)) {
+ WARN_ONCE(rtorsup->rtorsu_nups >= rtorsup->rtorsu_ndowns, "%s: Up without matching down #%zu.\n", __func__, rtorsup - updownreaders);
+ rtorsup->rtorsu_nups++;
schedule_timeout_idle(HZ);
return;
}
--
2.40.1
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH rcu 08/15] rcutorture: Check for no up/down readers at task level
2025-07-09 10:42 [PATCH rcu 00/15] RCU torture changes for v6.17 neeraj.upadhyay
` (6 preceding siblings ...)
2025-07-09 10:42 ` [PATCH rcu 07/15] rcutorture: Check for ->up_read() without matching ->down_read() neeraj.upadhyay
@ 2025-07-09 10:42 ` neeraj.upadhyay
2025-07-09 10:42 ` [PATCH rcu 09/15] rcutorture: Print number of RCU up/down readers and migrations neeraj.upadhyay
` (6 subsequent siblings)
14 siblings, 0 replies; 16+ messages in thread
From: neeraj.upadhyay @ 2025-07-09 10:42 UTC (permalink / raw)
To: rcu
Cc: linux-kernel, paulmck, joelagnelf, frederic, boqun.feng, urezki,
rostedt, mathieu.desnoyers, jiangshanlai, qiang.zhang1211,
neeraj.iitr10, neeraj.upadhyay, Neeraj Upadhyay (AMD)
From: "Paul E. McKenney" <paulmck@kernel.org>
The design of testing of up/down readers such as srcu_down_read()
and srcu_up_read() assumes that these are tested only by the
rcu_torture_updown() kthread, and never by the rcu_torture_reader()
kthread. Because we all know which road is paved with good intentions,
this commit adds WARN_ON_ONCE() to verify that things are going to plan.
Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
Signed-off-by: Neeraj Upadhyay (AMD) <neeraj.upadhyay@kernel.org>
---
kernel/rcu/rcutorture.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/kernel/rcu/rcutorture.c b/kernel/rcu/rcutorture.c
index f773d4f8f2ae..10f3cc4861ee 100644
--- a/kernel/rcu/rcutorture.c
+++ b/kernel/rcu/rcutorture.c
@@ -2232,6 +2232,7 @@ rcutorture_loop_extend(int *readstate, bool insoftirq, struct torture_random_sta
i = ((i | (i >> 3)) & RCUTORTURE_RDR_MAX_LOOPS) + 1;
for (j = 0; j < i; j++) {
mask = rcutorture_extend_mask(*readstate, trsp);
+ WARN_ON_ONCE(mask & RCUTORTURE_RDR_UPDOWN);
rcutorture_one_extend(readstate, mask, insoftirq, trsp, &rtrsp[j]);
}
return &rtrsp[j];
@@ -2368,6 +2369,7 @@ static bool rcu_torture_one_read(struct torture_random_state *trsp, long myid)
WARN_ON_ONCE(!rcu_is_watching());
init_rcu_torture_one_read_state(&rtors, trsp);
newstate = rcutorture_extend_mask(rtors.readstate, trsp);
+ WARN_ON_ONCE(newstate & RCUTORTURE_RDR_UPDOWN);
rcutorture_one_extend(&rtors.readstate, newstate, myid < 0, trsp, rtors.rtrsp++);
if (!rcu_torture_one_read_start(&rtors, trsp, myid)) {
rcutorture_one_extend(&rtors.readstate, 0, myid < 0, trsp, rtors.rtrsp);
--
2.40.1
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH rcu 09/15] rcutorture: Print number of RCU up/down readers and migrations
2025-07-09 10:42 [PATCH rcu 00/15] RCU torture changes for v6.17 neeraj.upadhyay
` (7 preceding siblings ...)
2025-07-09 10:42 ` [PATCH rcu 08/15] rcutorture: Check for no up/down readers at task level neeraj.upadhyay
@ 2025-07-09 10:42 ` neeraj.upadhyay
2025-07-09 10:42 ` [PATCH rcu 10/15] rcutorture: Drop redundant "insoftirq" parameters neeraj.upadhyay
` (5 subsequent siblings)
14 siblings, 0 replies; 16+ messages in thread
From: neeraj.upadhyay @ 2025-07-09 10:42 UTC (permalink / raw)
To: rcu
Cc: linux-kernel, paulmck, joelagnelf, frederic, boqun.feng, urezki,
rostedt, mathieu.desnoyers, jiangshanlai, qiang.zhang1211,
neeraj.iitr10, neeraj.upadhyay, Neeraj Upadhyay (AMD)
From: "Paul E. McKenney" <paulmck@kernel.org>
This commit prints the number of RCU up/down readers and the number
of such readers that migrated from one CPU to another, along
with the rest of the periodic rcu_torture_stats_print() output.
These statistics are currently used only by srcu_down_read{,_fast}()
and srcu_up_read(,_fast)().
Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
Signed-off-by: Neeraj Upadhyay (AMD) <neeraj.upadhyay@kernel.org>
---
kernel/rcu/rcutorture.c | 30 +++++++++++++++++++++++++-----
1 file changed, 25 insertions(+), 5 deletions(-)
diff --git a/kernel/rcu/rcutorture.c b/kernel/rcu/rcutorture.c
index 10f3cc4861ee..3f644b1f5823 100644
--- a/kernel/rcu/rcutorture.c
+++ b/kernel/rcu/rcutorture.c
@@ -2450,9 +2450,11 @@ struct rcu_torture_one_read_state_updown {
struct hrtimer rtorsu_hrt;
bool rtorsu_inuse;
ktime_t rtorsu_kt;
+ int rtorsu_cpu;
unsigned long rtorsu_j;
unsigned long rtorsu_ndowns;
unsigned long rtorsu_nups;
+ unsigned long rtorsu_nmigrates;
struct torture_random_state rtorsu_trs;
struct rcu_torture_one_read_state rtorsu_rtors;
};
@@ -2463,12 +2465,15 @@ static int rcu_torture_updown(void *arg);
static enum hrtimer_restart rcu_torture_updown_hrt(struct hrtimer *hrtp)
{
+ int cpu = raw_smp_processor_id();
struct rcu_torture_one_read_state_updown *rtorsup;
rtorsup = container_of(hrtp, struct rcu_torture_one_read_state_updown, rtorsu_hrt);
rcu_torture_one_read_end(&rtorsup->rtorsu_rtors, &rtorsup->rtorsu_trs, -1);
WARN_ONCE(rtorsup->rtorsu_nups >= rtorsup->rtorsu_ndowns, "%s: Up without matching down #%zu.\n", __func__, rtorsup - updownreaders);
- rtorsup->rtorsu_nups++;
+ WRITE_ONCE(rtorsup->rtorsu_nups, rtorsup->rtorsu_nups + 1);
+ WRITE_ONCE(rtorsup->rtorsu_nmigrates,
+ rtorsup->rtorsu_nmigrates + (cpu != rtorsup->rtorsu_cpu));
smp_store_release(&rtorsup->rtorsu_inuse, false);
return HRTIMER_NORESTART;
}
@@ -2516,7 +2521,7 @@ static void rcu_torture_updown_cleanup(void)
if (hrtimer_cancel(&rtorsup->rtorsu_hrt) || WARN_ON_ONCE(rtorsup->rtorsu_inuse)) {
rcu_torture_one_read_end(&rtorsup->rtorsu_rtors, &rtorsup->rtorsu_trs, -1);
WARN_ONCE(rtorsup->rtorsu_nups >= rtorsup->rtorsu_ndowns, "%s: Up without matching down #%zu.\n", __func__, rtorsup - updownreaders);
- rtorsup->rtorsu_nups++;
+ WRITE_ONCE(rtorsup->rtorsu_nups, rtorsup->rtorsu_nups + 1);
smp_store_release(&rtorsup->rtorsu_inuse, false);
}
@@ -2534,13 +2539,14 @@ static void rcu_torture_updown_one(struct rcu_torture_one_read_state_updown *rto
init_rcu_torture_one_read_state(&rtorsup->rtorsu_rtors, &rtorsup->rtorsu_trs);
rawidx = cur_ops->down_read();
- rtorsup->rtorsu_ndowns++;
+ WRITE_ONCE(rtorsup->rtorsu_ndowns, rtorsup->rtorsu_ndowns + 1);
idx = (rawidx << RCUTORTURE_RDR_SHIFT_1) & RCUTORTURE_RDR_MASK_1;
rtorsup->rtorsu_rtors.readstate = idx | RCUTORTURE_RDR_UPDOWN;
rtorsup->rtorsu_rtors.rtrsp++;
+ rtorsup->rtorsu_cpu = raw_smp_processor_id();
if (!rcu_torture_one_read_start(&rtorsup->rtorsu_rtors, &rtorsup->rtorsu_trs, -1)) {
WARN_ONCE(rtorsup->rtorsu_nups >= rtorsup->rtorsu_ndowns, "%s: Up without matching down #%zu.\n", __func__, rtorsup - updownreaders);
- rtorsup->rtorsu_nups++;
+ WRITE_ONCE(rtorsup->rtorsu_nups, rtorsup->rtorsu_nups + 1);
schedule_timeout_idle(HZ);
return;
}
@@ -2649,6 +2655,10 @@ rcu_torture_stats_print(void)
long pipesummary[RCU_TORTURE_PIPE_LEN + 1] = { 0 };
long batchsummary[RCU_TORTURE_PIPE_LEN + 1] = { 0 };
long n_gpwraps = 0;
+ unsigned long ndowns = 0;
+ unsigned long nunexpired = 0;
+ unsigned long nmigrates = 0;
+ unsigned long nups = 0;
struct rcu_torture *rtcp;
static unsigned long rtcv_snap = ULONG_MAX;
static bool splatted;
@@ -2662,10 +2672,18 @@ rcu_torture_stats_print(void)
if (cur_ops->get_gpwrap_count)
n_gpwraps += cur_ops->get_gpwrap_count(cpu);
}
+ if (updownreaders) {
+ for (i = 0; i < n_up_down; i++) {
+ ndowns += READ_ONCE(updownreaders[i].rtorsu_ndowns);
+ nups += READ_ONCE(updownreaders[i].rtorsu_nups);
+ nunexpired += READ_ONCE(updownreaders[i].rtorsu_inuse);
+ nmigrates += READ_ONCE(updownreaders[i].rtorsu_nmigrates);
+ }
+ }
for (i = RCU_TORTURE_PIPE_LEN; i >= 0; i--) {
if (pipesummary[i] != 0)
break;
- }
+ } // The value of variable "i" is used later, so don't clobber it!
pr_alert("%s%s ", torture_type, TORTURE_FLAG);
rtcp = rcu_access_pointer(rcu_torture_current);
@@ -2686,6 +2704,8 @@ rcu_torture_stats_print(void)
n_rcu_torture_boost_failure,
n_rcu_torture_boosts,
atomic_long_read(&n_rcu_torture_timers));
+ if (updownreaders)
+ pr_cont("ndowns: %lu nups: %lu nhrt: %lu nmigrates: %lu ", ndowns, nups, nunexpired, nmigrates);
torture_onoff_stats();
pr_cont("barrier: %ld/%ld:%ld ",
data_race(n_barrier_successes),
--
2.40.1
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH rcu 10/15] rcutorture: Drop redundant "insoftirq" parameters
2025-07-09 10:42 [PATCH rcu 00/15] RCU torture changes for v6.17 neeraj.upadhyay
` (8 preceding siblings ...)
2025-07-09 10:42 ` [PATCH rcu 09/15] rcutorture: Print number of RCU up/down readers and migrations neeraj.upadhyay
@ 2025-07-09 10:42 ` neeraj.upadhyay
2025-07-09 10:42 ` [PATCH rcu 11/15] rcutorture: Make Trivial RCU ignore onoff_interval and shuffle_interval neeraj.upadhyay
` (4 subsequent siblings)
14 siblings, 0 replies; 16+ messages in thread
From: neeraj.upadhyay @ 2025-07-09 10:42 UTC (permalink / raw)
To: rcu
Cc: linux-kernel, paulmck, joelagnelf, frederic, boqun.feng, urezki,
rostedt, mathieu.desnoyers, jiangshanlai, qiang.zhang1211,
neeraj.iitr10, neeraj.upadhyay, Neeraj Upadhyay (AMD),
kernel test robot
From: "Paul E. McKenney" <paulmck@kernel.org>
Given that the rcutorture_one_extend_check() function now uses
in_serving_softirq() and in_hardirq(), it is no longer necessary to pass
insoftirq flags down the function-call stack. This commit therefore
removes those flags, and, while in the area, does a bit of whitespace
cleanup.
Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
Tested-by: kernel test robot <oliver.sang@intel.com>
Signed-off-by: Neeraj Upadhyay (AMD) <neeraj.upadhyay@kernel.org>
---
kernel/rcu/rcutorture.c | 35 ++++++++++++++++-------------------
1 file changed, 16 insertions(+), 19 deletions(-)
diff --git a/kernel/rcu/rcutorture.c b/kernel/rcu/rcutorture.c
index 3f644b1f5823..470b5a117602 100644
--- a/kernel/rcu/rcutorture.c
+++ b/kernel/rcu/rcutorture.c
@@ -1975,7 +1975,7 @@ static void rcu_torture_reader_do_mbchk(long myid, struct rcu_torture *rtp,
// Verify the specified RCUTORTURE_RDR* state.
#define ROEC_ARGS "%s %s: Current %#x To add %#x To remove %#x preempt_count() %#x\n", __func__, s, curstate, new, old, preempt_count()
-static void rcutorture_one_extend_check(char *s, int curstate, int new, int old, bool insoftirq)
+static void rcutorture_one_extend_check(char *s, int curstate, int new, int old)
{
int mask;
@@ -2038,8 +2038,7 @@ static void rcutorture_one_extend_check(char *s, int curstate, int new, int old,
* beginning or end of the critical section and if there was actually a
* change, do a ->read_delay().
*/
-static void rcutorture_one_extend(int *readstate, int newstate, bool insoftirq,
- struct torture_random_state *trsp,
+static void rcutorture_one_extend(int *readstate, int newstate, struct torture_random_state *trsp,
struct rt_read_seg *rtrsp)
{
bool first;
@@ -2054,7 +2053,7 @@ static void rcutorture_one_extend(int *readstate, int newstate, bool insoftirq,
first = idxold1 == 0;
WARN_ON_ONCE(idxold2 < 0);
WARN_ON_ONCE(idxold2 & ~(RCUTORTURE_RDR_ALLBITS | RCUTORTURE_RDR_UPDOWN));
- rcutorture_one_extend_check("before change", idxold1, statesnew, statesold, insoftirq);
+ rcutorture_one_extend_check("before change", idxold1, statesnew, statesold);
rtrsp->rt_readstate = newstate;
/* First, put new protection in place to avoid critical-section gap. */
@@ -2074,8 +2073,7 @@ static void rcutorture_one_extend(int *readstate, int newstate, bool insoftirq,
idxnew2 = (cur_ops->readlock() << RCUTORTURE_RDR_SHIFT_2) & RCUTORTURE_RDR_MASK_2;
// Complain unless both the old and the new protection is in place.
- rcutorture_one_extend_check("during change",
- idxold1 | statesnew, statesnew, statesold, insoftirq);
+ rcutorture_one_extend_check("during change", idxold1 | statesnew, statesnew, statesold);
// Sample CPU under both sets of protections to reduce confusion.
if (IS_ENABLED(CONFIG_RCU_TORTURE_TEST_LOG_CPU)) {
@@ -2150,7 +2148,7 @@ static void rcutorture_one_extend(int *readstate, int newstate, bool insoftirq,
WARN_ON_ONCE(*readstate < 0);
if (WARN_ON_ONCE(*readstate & ~RCUTORTURE_RDR_ALLBITS))
pr_info("Unexpected readstate value of %#x\n", *readstate);
- rcutorture_one_extend_check("after change", *readstate, statesnew, statesold, insoftirq);
+ rcutorture_one_extend_check("after change", *readstate, statesnew, statesold);
}
/* Return the biggest extendables mask given current RCU and boot parameters. */
@@ -2217,8 +2215,7 @@ rcutorture_extend_mask(int oldmask, struct torture_random_state *trsp)
* critical section.
*/
static struct rt_read_seg *
-rcutorture_loop_extend(int *readstate, bool insoftirq, struct torture_random_state *trsp,
- struct rt_read_seg *rtrsp)
+rcutorture_loop_extend(int *readstate, struct torture_random_state *trsp, struct rt_read_seg *rtrsp)
{
int i;
int j;
@@ -2233,7 +2230,7 @@ rcutorture_loop_extend(int *readstate, bool insoftirq, struct torture_random_sta
for (j = 0; j < i; j++) {
mask = rcutorture_extend_mask(*readstate, trsp);
WARN_ON_ONCE(mask & RCUTORTURE_RDR_UPDOWN);
- rcutorture_one_extend(readstate, mask, insoftirq, trsp, &rtrsp[j]);
+ rcutorture_one_extend(readstate, mask, trsp, &rtrsp[j]);
}
return &rtrsp[j];
}
@@ -2279,7 +2276,7 @@ static bool rcu_torture_one_read_start(struct rcu_torture_one_read_state *rtorsp
(rtorsp->readstate & RCUTORTURE_RDR_UPDOWN));
if (rtorsp->p == NULL) {
/* Wait for rcu_torture_writer to get underway */
- rcutorture_one_extend(&rtorsp->readstate, 0, myid < 0, trsp, rtorsp->rtrsp);
+ rcutorture_one_extend(&rtorsp->readstate, 0, trsp, rtorsp->rtrsp);
return false;
}
if (rtorsp->p->rtort_mbtest == 0)
@@ -2293,7 +2290,7 @@ static bool rcu_torture_one_read_start(struct rcu_torture_one_read_state *rtorsp
* critical sections and check for errors.
*/
static void rcu_torture_one_read_end(struct rcu_torture_one_read_state *rtorsp,
- struct torture_random_state *trsp, long myid)
+ struct torture_random_state *trsp)
{
int i;
unsigned long completed;
@@ -2340,7 +2337,7 @@ static void rcu_torture_one_read_end(struct rcu_torture_one_read_state *rtorsp,
}
if (cur_ops->reader_blocked)
preempted = cur_ops->reader_blocked();
- rcutorture_one_extend(&rtorsp->readstate, 0, myid < 0, trsp, rtorsp->rtrsp);
+ rcutorture_one_extend(&rtorsp->readstate, 0, trsp, rtorsp->rtrsp);
WARN_ON_ONCE(rtorsp->readstate);
// This next splat is expected behavior if leakpointer, especially
// for CONFIG_RCU_STRICT_GRACE_PERIOD=y kernels.
@@ -2370,13 +2367,13 @@ static bool rcu_torture_one_read(struct torture_random_state *trsp, long myid)
init_rcu_torture_one_read_state(&rtors, trsp);
newstate = rcutorture_extend_mask(rtors.readstate, trsp);
WARN_ON_ONCE(newstate & RCUTORTURE_RDR_UPDOWN);
- rcutorture_one_extend(&rtors.readstate, newstate, myid < 0, trsp, rtors.rtrsp++);
+ rcutorture_one_extend(&rtors.readstate, newstate, trsp, rtors.rtrsp++);
if (!rcu_torture_one_read_start(&rtors, trsp, myid)) {
- rcutorture_one_extend(&rtors.readstate, 0, myid < 0, trsp, rtors.rtrsp);
+ rcutorture_one_extend(&rtors.readstate, 0, trsp, rtors.rtrsp);
return false;
}
- rtors.rtrsp = rcutorture_loop_extend(&rtors.readstate, myid < 0, trsp, rtors.rtrsp);
- rcu_torture_one_read_end(&rtors, trsp, myid);
+ rtors.rtrsp = rcutorture_loop_extend(&rtors.readstate, trsp, rtors.rtrsp);
+ rcu_torture_one_read_end(&rtors, trsp);
return true;
}
@@ -2469,7 +2466,7 @@ static enum hrtimer_restart rcu_torture_updown_hrt(struct hrtimer *hrtp)
struct rcu_torture_one_read_state_updown *rtorsup;
rtorsup = container_of(hrtp, struct rcu_torture_one_read_state_updown, rtorsu_hrt);
- rcu_torture_one_read_end(&rtorsup->rtorsu_rtors, &rtorsup->rtorsu_trs, -1);
+ rcu_torture_one_read_end(&rtorsup->rtorsu_rtors, &rtorsup->rtorsu_trs);
WARN_ONCE(rtorsup->rtorsu_nups >= rtorsup->rtorsu_ndowns, "%s: Up without matching down #%zu.\n", __func__, rtorsup - updownreaders);
WRITE_ONCE(rtorsup->rtorsu_nups, rtorsup->rtorsu_nups + 1);
WRITE_ONCE(rtorsup->rtorsu_nmigrates,
@@ -2519,7 +2516,7 @@ static void rcu_torture_updown_cleanup(void)
if (!smp_load_acquire(&rtorsup->rtorsu_inuse))
continue;
if (hrtimer_cancel(&rtorsup->rtorsu_hrt) || WARN_ON_ONCE(rtorsup->rtorsu_inuse)) {
- rcu_torture_one_read_end(&rtorsup->rtorsu_rtors, &rtorsup->rtorsu_trs, -1);
+ rcu_torture_one_read_end(&rtorsup->rtorsu_rtors, &rtorsup->rtorsu_trs);
WARN_ONCE(rtorsup->rtorsu_nups >= rtorsup->rtorsu_ndowns, "%s: Up without matching down #%zu.\n", __func__, rtorsup - updownreaders);
WRITE_ONCE(rtorsup->rtorsu_nups, rtorsup->rtorsu_nups + 1);
smp_store_release(&rtorsup->rtorsu_inuse, false);
--
2.40.1
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH rcu 11/15] rcutorture: Make Trivial RCU ignore onoff_interval and shuffle_interval
2025-07-09 10:42 [PATCH rcu 00/15] RCU torture changes for v6.17 neeraj.upadhyay
` (9 preceding siblings ...)
2025-07-09 10:42 ` [PATCH rcu 10/15] rcutorture: Drop redundant "insoftirq" parameters neeraj.upadhyay
@ 2025-07-09 10:42 ` neeraj.upadhyay
2025-07-09 10:42 ` [PATCH rcu 12/15] rcutorture: Fix rcutorture_one_extend_check() splat in RT kernels neeraj.upadhyay
` (3 subsequent siblings)
14 siblings, 0 replies; 16+ messages in thread
From: neeraj.upadhyay @ 2025-07-09 10:42 UTC (permalink / raw)
To: rcu
Cc: linux-kernel, paulmck, joelagnelf, frederic, boqun.feng, urezki,
rostedt, mathieu.desnoyers, jiangshanlai, qiang.zhang1211,
neeraj.iitr10, neeraj.upadhyay, Neeraj Upadhyay (AMD),
kernel test robot
From: "Paul E. McKenney" <paulmck@kernel.org>
Trivial RCU is a textbook implementation that is not used in the
Linux kernel, but tested to keep textbooks (and presentations) honest.
It is so trivial that it cannot deal with either CPU hotplug or external
migration from one CPU to another. This commit therefore splats whenever
onoff_interval or shuffle_interval are non-zero, and then sets them to
zero in order to avoid false-positive failures.
Those wishing to set these module parameters in order to force failures
in Trivial RCU are free to revert this commit. Just don't expect me to
be sympathetic to any resulting bug reports!
Reported-by: kernel test robot <oliver.sang@intel.com>
Closes: https://lore.kernel.org/oe-lkp/202505131651.af6e81d7-lkp@intel.com
Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
Signed-off-by: Neeraj Upadhyay (AMD) <neeraj.upadhyay@kernel.org>
---
kernel/rcu/rcutorture.c | 15 +++++++++++++--
1 file changed, 13 insertions(+), 2 deletions(-)
diff --git a/kernel/rcu/rcutorture.c b/kernel/rcu/rcutorture.c
index 470b5a117602..7a07b2590c27 100644
--- a/kernel/rcu/rcutorture.c
+++ b/kernel/rcu/rcutorture.c
@@ -969,7 +969,8 @@ static struct rcu_torture_ops busted_srcud_ops = {
/*
* Definitions for trivial CONFIG_PREEMPT=n-only torture testing.
- * This implementation does not necessarily work well with CPU hotplug.
+ * This implementation does not work well with CPU hotplug nor
+ * with rcutorture's shuffling.
*/
static void synchronize_rcu_trivial(void)
@@ -982,6 +983,16 @@ static void synchronize_rcu_trivial(void)
}
}
+static void rcu_sync_torture_init_trivial(void)
+{
+ rcu_sync_torture_init();
+ // if (onoff_interval || shuffle_interval) {
+ if (WARN_ONCE(onoff_interval || shuffle_interval, "%s: Non-zero onoff_interval (%d) or shuffle_interval (%d) breaks trivial RCU, resetting to zero", __func__, onoff_interval, shuffle_interval)) {
+ onoff_interval = 0;
+ shuffle_interval = 0;
+ }
+}
+
static int rcu_torture_read_lock_trivial(void)
{
preempt_disable();
@@ -995,7 +1006,7 @@ static void rcu_torture_read_unlock_trivial(int idx)
static struct rcu_torture_ops trivial_ops = {
.ttype = RCU_TRIVIAL_FLAVOR,
- .init = rcu_sync_torture_init,
+ .init = rcu_sync_torture_init_trivial,
.readlock = rcu_torture_read_lock_trivial,
.read_delay = rcu_read_delay, /* just reuse rcu's version. */
.readunlock = rcu_torture_read_unlock_trivial,
--
2.40.1
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH rcu 12/15] rcutorture: Fix rcutorture_one_extend_check() splat in RT kernels
2025-07-09 10:42 [PATCH rcu 00/15] RCU torture changes for v6.17 neeraj.upadhyay
` (10 preceding siblings ...)
2025-07-09 10:42 ` [PATCH rcu 11/15] rcutorture: Make Trivial RCU ignore onoff_interval and shuffle_interval neeraj.upadhyay
@ 2025-07-09 10:42 ` neeraj.upadhyay
2025-07-09 10:42 ` [PATCH rcu 13/15] rcutorture: Make BUSTED scenario check and log readers neeraj.upadhyay
` (2 subsequent siblings)
14 siblings, 0 replies; 16+ messages in thread
From: neeraj.upadhyay @ 2025-07-09 10:42 UTC (permalink / raw)
To: rcu
Cc: linux-kernel, paulmck, joelagnelf, frederic, boqun.feng, urezki,
rostedt, mathieu.desnoyers, jiangshanlai, qiang.zhang1211,
neeraj.iitr10, neeraj.upadhyay, Neeraj Upadhyay (AMD)
From: Zqiang <qiang.zhang1211@gmail.com>
For built with CONFIG_PREEMPT_RT=y kernels, running rcutorture
tests resulted in the following splat:
[ 68.797425] rcutorture_one_extend_check during change: Current 0x1 To add 0x1 To remove 0x0 preempt_count() 0x0
[ 68.797533] WARNING: CPU: 2 PID: 512 at kernel/rcu/rcutorture.c:1993 rcutorture_one_extend_check+0x419/0x560 [rcutorture]
[ 68.797601] Call Trace:
[ 68.797602] <TASK>
[ 68.797619] ? lockdep_softirqs_off+0xa5/0x160
[ 68.797631] rcutorture_one_extend+0x18e/0xcc0 [rcutorture 2466dbd2ff34dbaa36049cb323a80c3306ac997c]
[ 68.797646] ? local_clock+0x19/0x40
[ 68.797659] rcu_torture_one_read+0xf0/0x280 [rcutorture 2466dbd2ff34dbaa36049cb323a80c3306ac997c]
[ 68.797678] ? __pfx_rcu_torture_one_read+0x10/0x10 [rcutorture 2466dbd2ff34dbaa36049cb323a80c3306ac997c]
[ 68.797804] ? __pfx_rcu_torture_timer+0x10/0x10 [rcutorture 2466dbd2ff34dbaa36049cb323a80c3306ac997c]
[ 68.797815] rcu-torture: rcu_torture_reader task started
[ 68.797824] rcu-torture: Creating rcu_torture_reader task
[ 68.797824] rcu_torture_reader+0x238/0x580 [rcutorture 2466dbd2ff34dbaa36049cb323a80c3306ac997c]
[ 68.797836] ? kvm_sched_clock_read+0x15/0x30
Disable BH does not change the SOFTIRQ corresponding bits in
preempt_count() for RT kernels, this commit therefore use
softirq_count() to check the if BH is disabled.
Reviewed-by: Paul E. McKenney <paulmck@kernel.org>
Signed-off-by: Zqiang <qiang.zhang1211@gmail.com>
Signed-off-by: Joel Fernandes <joelagnelf@nvidia.com>
Signed-off-by: Neeraj Upadhyay (AMD) <neeraj.upadhyay@kernel.org>
---
kernel/rcu/rcutorture.c | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/kernel/rcu/rcutorture.c b/kernel/rcu/rcutorture.c
index 7a07b2590c27..213f23f20a64 100644
--- a/kernel/rcu/rcutorture.c
+++ b/kernel/rcu/rcutorture.c
@@ -471,7 +471,7 @@ rcu_read_delay(struct torture_random_state *rrsp, struct rt_read_seg *rtrsp)
!(torture_random(rrsp) % (nrealreaders * 2000 * longdelay_ms))) {
started = cur_ops->get_gp_seq();
ts = rcu_trace_clock_local();
- if (preempt_count() & (SOFTIRQ_MASK | HARDIRQ_MASK))
+ if ((preempt_count() & HARDIRQ_MASK) || softirq_count())
longdelay_ms = 5; /* Avoid triggering BH limits. */
mdelay(longdelay_ms);
rtrsp->rt_delay_ms = longdelay_ms;
@@ -2001,7 +2001,7 @@ static void rcutorture_one_extend_check(char *s, int curstate, int new, int old)
return;
WARN_ONCE((curstate & (RCUTORTURE_RDR_BH | RCUTORTURE_RDR_RBH)) &&
- !(preempt_count() & SOFTIRQ_MASK), ROEC_ARGS);
+ !softirq_count(), ROEC_ARGS);
WARN_ONCE((curstate & (RCUTORTURE_RDR_PREEMPT | RCUTORTURE_RDR_SCHED)) &&
!(preempt_count() & PREEMPT_MASK), ROEC_ARGS);
WARN_ONCE(cur_ops->readlock_nesting &&
@@ -2015,7 +2015,7 @@ static void rcutorture_one_extend_check(char *s, int curstate, int new, int old)
WARN_ONCE(cur_ops->extendables &&
!(curstate & (RCUTORTURE_RDR_BH | RCUTORTURE_RDR_RBH)) &&
- (preempt_count() & SOFTIRQ_MASK), ROEC_ARGS);
+ softirq_count(), ROEC_ARGS);
/*
* non-preemptible RCU in a preemptible kernel uses preempt_disable()
@@ -2036,6 +2036,9 @@ static void rcutorture_one_extend_check(char *s, int curstate, int new, int old)
if (!IS_ENABLED(CONFIG_PREEMPT_RCU))
mask |= RCUTORTURE_RDR_PREEMPT | RCUTORTURE_RDR_SCHED;
+ if (IS_ENABLED(CONFIG_PREEMPT_RT) && softirq_count())
+ mask |= RCUTORTURE_RDR_BH | RCUTORTURE_RDR_RBH;
+
WARN_ONCE(cur_ops->readlock_nesting && !(curstate & mask) &&
cur_ops->readlock_nesting() > 0, ROEC_ARGS);
}
--
2.40.1
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH rcu 13/15] rcutorture: Make BUSTED scenario check and log readers
2025-07-09 10:42 [PATCH rcu 00/15] RCU torture changes for v6.17 neeraj.upadhyay
` (11 preceding siblings ...)
2025-07-09 10:42 ` [PATCH rcu 12/15] rcutorture: Fix rcutorture_one_extend_check() splat in RT kernels neeraj.upadhyay
@ 2025-07-09 10:42 ` neeraj.upadhyay
2025-07-09 10:42 ` [PATCH rcu 14/15] rcutorture: Remove SRCU-lite scenarios neeraj.upadhyay
2025-07-09 10:42 ` [PATCH rcu 15/15] rcutorture: Remove support for SRCU-lite neeraj.upadhyay
14 siblings, 0 replies; 16+ messages in thread
From: neeraj.upadhyay @ 2025-07-09 10:42 UTC (permalink / raw)
To: rcu
Cc: linux-kernel, paulmck, joelagnelf, frederic, boqun.feng, urezki,
rostedt, mathieu.desnoyers, jiangshanlai, qiang.zhang1211,
neeraj.iitr10, neeraj.upadhyay, Neeraj Upadhyay (AMD)
From: "Paul E. McKenney" <paulmck@kernel.org>
Because the BUSTED scenario intentionally executes too-short
readers, this commit enables the RCU_TORTURE_TEST_CHK_RDR_STATE,
RCU_TORTURE_TEST_LOG_CPU, and RCU_TORTURE_TEST_LOG_GP Kconfig options
to test the resulting reader-segment dump.
Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
Signed-off-by: Neeraj Upadhyay (AMD) <neeraj.upadhyay@kernel.org>
---
tools/testing/selftests/rcutorture/configs/rcu/BUSTED | 3 +++
1 file changed, 3 insertions(+)
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/BUSTED b/tools/testing/selftests/rcutorture/configs/rcu/BUSTED
index 48d8a245c7fa..7d75f4b94943 100644
--- a/tools/testing/selftests/rcutorture/configs/rcu/BUSTED
+++ b/tools/testing/selftests/rcutorture/configs/rcu/BUSTED
@@ -5,3 +5,6 @@ CONFIG_HOTPLUG_CPU=y
CONFIG_PREEMPT_NONE=n
CONFIG_PREEMPT_VOLUNTARY=n
CONFIG_PREEMPT=y
+CONFIG_RCU_TORTURE_TEST_CHK_RDR_STATE=y
+CONFIG_RCU_TORTURE_TEST_LOG_CPU=y
+CONFIG_RCU_TORTURE_TEST_LOG_GP=y
--
2.40.1
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH rcu 14/15] rcutorture: Remove SRCU-lite scenarios
2025-07-09 10:42 [PATCH rcu 00/15] RCU torture changes for v6.17 neeraj.upadhyay
` (12 preceding siblings ...)
2025-07-09 10:42 ` [PATCH rcu 13/15] rcutorture: Make BUSTED scenario check and log readers neeraj.upadhyay
@ 2025-07-09 10:42 ` neeraj.upadhyay
2025-07-09 10:42 ` [PATCH rcu 15/15] rcutorture: Remove support for SRCU-lite neeraj.upadhyay
14 siblings, 0 replies; 16+ messages in thread
From: neeraj.upadhyay @ 2025-07-09 10:42 UTC (permalink / raw)
To: rcu
Cc: linux-kernel, paulmck, joelagnelf, frederic, boqun.feng, urezki,
rostedt, mathieu.desnoyers, jiangshanlai, qiang.zhang1211,
neeraj.iitr10, neeraj.upadhyay, Neeraj Upadhyay (AMD)
From: "Paul E. McKenney" <paulmck@kernel.org>
This commit prepares for the removal of SRCU-Lite by removing the SRCU-L
rcutorture scenario that tests it.
Signed-off-by: "Paul E. McKenney" <paulmck@kernel.org>
Signed-off-by: Neeraj Upadhyay (AMD) <neeraj.upadhyay@kernel.org>
---
tools/testing/selftests/rcutorture/configs/rcu/CFLIST | 1 -
tools/testing/selftests/rcutorture/configs/rcu/SRCU-L | 10 ----------
.../selftests/rcutorture/configs/rcu/SRCU-L.boot | 3 ---
3 files changed, 14 deletions(-)
delete mode 100644 tools/testing/selftests/rcutorture/configs/rcu/SRCU-L
delete mode 100644 tools/testing/selftests/rcutorture/configs/rcu/SRCU-L.boot
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/CFLIST b/tools/testing/selftests/rcutorture/configs/rcu/CFLIST
index 45f572570a8c..98b6175e5aa0 100644
--- a/tools/testing/selftests/rcutorture/configs/rcu/CFLIST
+++ b/tools/testing/selftests/rcutorture/configs/rcu/CFLIST
@@ -5,7 +5,6 @@ TREE04
TREE05
TREE07
TREE09
-SRCU-L
SRCU-N
SRCU-P
SRCU-T
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/SRCU-L b/tools/testing/selftests/rcutorture/configs/rcu/SRCU-L
deleted file mode 100644
index 3b4fa8dbef8a..000000000000
--- a/tools/testing/selftests/rcutorture/configs/rcu/SRCU-L
+++ /dev/null
@@ -1,10 +0,0 @@
-CONFIG_RCU_TRACE=n
-CONFIG_SMP=y
-CONFIG_NR_CPUS=6
-CONFIG_HOTPLUG_CPU=y
-CONFIG_PREEMPT_NONE=y
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=n
-#CHECK#CONFIG_RCU_EXPERT=n
-CONFIG_KPROBES=n
-CONFIG_FTRACE=n
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/SRCU-L.boot b/tools/testing/selftests/rcutorture/configs/rcu/SRCU-L.boot
deleted file mode 100644
index 0207b3138c5b..000000000000
--- a/tools/testing/selftests/rcutorture/configs/rcu/SRCU-L.boot
+++ /dev/null
@@ -1,3 +0,0 @@
-rcutorture.torture_type=srcu
-rcutorture.reader_flavor=0x4
-rcutorture.fwd_progress=3
--
2.40.1
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH rcu 15/15] rcutorture: Remove support for SRCU-lite
2025-07-09 10:42 [PATCH rcu 00/15] RCU torture changes for v6.17 neeraj.upadhyay
` (13 preceding siblings ...)
2025-07-09 10:42 ` [PATCH rcu 14/15] rcutorture: Remove SRCU-lite scenarios neeraj.upadhyay
@ 2025-07-09 10:42 ` neeraj.upadhyay
14 siblings, 0 replies; 16+ messages in thread
From: neeraj.upadhyay @ 2025-07-09 10:42 UTC (permalink / raw)
To: rcu
Cc: linux-kernel, paulmck, joelagnelf, frederic, boqun.feng, urezki,
rostedt, mathieu.desnoyers, jiangshanlai, qiang.zhang1211,
neeraj.iitr10, neeraj.upadhyay, Neeraj Upadhyay (AMD)
From: "Paul E. McKenney" <paulmck@kernel.org>
Because SRCU-lite is being replaced by SRCU-fast, this commit removes
support for SRCU-lite from rcutorture.c
Signed-off-by: "Paul E. McKenney" <paulmck@kernel.org>
Signed-off-by: Neeraj Upadhyay (AMD) <neeraj.upadhyay@kernel.org>
---
include/linux/srcu.h | 2 +-
kernel/rcu/rcutorture.c | 7 -------
2 files changed, 1 insertion(+), 8 deletions(-)
diff --git a/include/linux/srcu.h b/include/linux/srcu.h
index 900b0d5c05f5..c20dacb563e5 100644
--- a/include/linux/srcu.h
+++ b/include/linux/srcu.h
@@ -49,7 +49,7 @@ int init_srcu_struct(struct srcu_struct *ssp);
#define SRCU_READ_FLAVOR_LITE 0x4 // srcu_read_lock_lite().
#define SRCU_READ_FLAVOR_FAST 0x8 // srcu_read_lock_fast().
#define SRCU_READ_FLAVOR_ALL (SRCU_READ_FLAVOR_NORMAL | SRCU_READ_FLAVOR_NMI | \
- SRCU_READ_FLAVOR_LITE | SRCU_READ_FLAVOR_FAST) // All of the above.
+ SRCU_READ_FLAVOR_FAST) // All of the above.
#define SRCU_READ_FLAVOR_SLOWGP (SRCU_READ_FLAVOR_LITE | SRCU_READ_FLAVOR_FAST)
// Flavors requiring synchronize_rcu()
// instead of smp_mb().
diff --git a/kernel/rcu/rcutorture.c b/kernel/rcu/rcutorture.c
index 213f23f20a64..7a893d51d02b 100644
--- a/kernel/rcu/rcutorture.c
+++ b/kernel/rcu/rcutorture.c
@@ -718,11 +718,6 @@ static int srcu_torture_read_lock(void)
WARN_ON_ONCE(idx & ~0x1);
ret += idx << 1;
}
- if (reader_flavor & SRCU_READ_FLAVOR_LITE) {
- idx = srcu_read_lock_lite(srcu_ctlp);
- WARN_ON_ONCE(idx & ~0x1);
- ret += idx << 2;
- }
if (reader_flavor & SRCU_READ_FLAVOR_FAST) {
scp = srcu_read_lock_fast(srcu_ctlp);
idx = __srcu_ptr_to_ctr(srcu_ctlp, scp);
@@ -756,8 +751,6 @@ static void srcu_torture_read_unlock(int idx)
WARN_ON_ONCE((reader_flavor && (idx & ~reader_flavor)) || (!reader_flavor && (idx & ~0x1)));
if (reader_flavor & SRCU_READ_FLAVOR_FAST)
srcu_read_unlock_fast(srcu_ctlp, __srcu_ctr_to_ptr(srcu_ctlp, (idx & 0x8) >> 3));
- if (reader_flavor & SRCU_READ_FLAVOR_LITE)
- srcu_read_unlock_lite(srcu_ctlp, (idx & 0x4) >> 2);
if (reader_flavor & SRCU_READ_FLAVOR_NMI)
srcu_read_unlock_nmisafe(srcu_ctlp, (idx & 0x2) >> 1);
if ((reader_flavor & SRCU_READ_FLAVOR_NORMAL) || !(reader_flavor & SRCU_READ_FLAVOR_ALL))
--
2.40.1
^ permalink raw reply related [flat|nested] 16+ messages in thread
end of thread, other threads:[~2025-07-09 10:43 UTC | newest]
Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-07-09 10:42 [PATCH rcu 00/15] RCU torture changes for v6.17 neeraj.upadhyay
2025-07-09 10:42 ` [PATCH rcu 01/15] rcutorture: Print only one rtort_pipe_count splat neeraj.upadhyay
2025-07-09 10:42 ` [PATCH rcu 02/15] rcutorture: Start rcu_torture_writer() after rcu_torture_reader() neeraj.upadhyay
2025-07-09 10:42 ` [PATCH rcu 03/15] rcutorture: Make rcutorture_one_extend_check() account for hard IRQs neeraj.upadhyay
2025-07-09 10:42 ` [PATCH rcu 04/15] rcutorture: Add tests for SRCU up/down reader primitives neeraj.upadhyay
2025-07-09 10:42 ` [PATCH rcu 05/15] rcutorture: Pull rcu_torture_updown() loop body into new function neeraj.upadhyay
2025-07-09 10:42 ` [PATCH rcu 06/15] rcutorture: Complain if an ->up_read() is delayed more than 10 seconds neeraj.upadhyay
2025-07-09 10:42 ` [PATCH rcu 07/15] rcutorture: Check for ->up_read() without matching ->down_read() neeraj.upadhyay
2025-07-09 10:42 ` [PATCH rcu 08/15] rcutorture: Check for no up/down readers at task level neeraj.upadhyay
2025-07-09 10:42 ` [PATCH rcu 09/15] rcutorture: Print number of RCU up/down readers and migrations neeraj.upadhyay
2025-07-09 10:42 ` [PATCH rcu 10/15] rcutorture: Drop redundant "insoftirq" parameters neeraj.upadhyay
2025-07-09 10:42 ` [PATCH rcu 11/15] rcutorture: Make Trivial RCU ignore onoff_interval and shuffle_interval neeraj.upadhyay
2025-07-09 10:42 ` [PATCH rcu 12/15] rcutorture: Fix rcutorture_one_extend_check() splat in RT kernels neeraj.upadhyay
2025-07-09 10:42 ` [PATCH rcu 13/15] rcutorture: Make BUSTED scenario check and log readers neeraj.upadhyay
2025-07-09 10:42 ` [PATCH rcu 14/15] rcutorture: Remove SRCU-lite scenarios neeraj.upadhyay
2025-07-09 10:42 ` [PATCH rcu 15/15] rcutorture: Remove support for SRCU-lite neeraj.upadhyay
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).