* [PATCH v2 1/8] rcutorture: Fix divide-by-zero with fwd_progress_div=1
2026-10-07 21:04 [PATCH 0/8] Torture-test updates for v7.4 Paul E. McKenney
@ 2026-10-07 21:04 ` Paul E. McKenney
2026-10-07 21:04 ` [PATCH v2 2/8] rcutorture: Synchronously wait for all rcu_torture_irq() callbacks to complete Paul E. McKenney
` (6 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Paul E. McKenney @ 2026-10-07 21:04 UTC (permalink / raw)
To: rcu; +Cc: linux-kernel, kernel-team, rostedt, Kunwu Chan, Paul E . McKenney
From: Kunwu Chan <kunwu.chan@gmail.com>
When fwd_progress_div=1, the forward-progress test computes:
sd4 = (sd + div - 1) / div = sd
dur = sd4 + torture_random(&trs) % (sd - sd4) = sd4 + % 0
The modulo operation with a zero divisor triggers an integer
division by zero (undefined behavior at the C level, #DE trap on x86),
causing a kernel Oops and panic. On x86_64, this manifests as:
rcu_torture_fwd_prog_nr: Starting forward-progress test 0
Oops: divide error: 0000 [#1] SMP PTI
RIP: 0010:rcu_torture_fwd_prog+0x90b/0x1160
R12: 0000000000000000
The existing guard only handles non-positive values. However,
fwd_progress_div=1 also makes the random range empty because
sd4 == sd.
Change the guard to reject values below 2. The forward-progress test
only reaches this calculation when stall_dur() is positive, so
sd = stall_dur() + 1 >= 2. For fwd_progress_div >= 2, sd4 < sd,
ensuring that sd - sd4 is at least 1.
Keep the existing fallback to the default value of 4 for invalid
values.
Verified with QEMU/KVM: a 138-second run with fwd_progress_div=1
completed 81 forward-progress test cycles without a crash.
Fixes: 1b27291b1ea4f ("rcutorture: Add forward-progress tests for RCU grace periods")
Signed-off-by: Kunwu Chan <kunwu.chan@gmail.com>
Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
---
kernel/rcu/rcutorture.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/kernel/rcu/rcutorture.c b/kernel/rcu/rcutorture.c
index 182d47975efd1..79807475b6724 100644
--- a/kernel/rcu/rcutorture.c
+++ b/kernel/rcu/rcutorture.c
@@ -4024,7 +4024,7 @@ static int __init rcu_torture_fwd_prog_init(void)
}
if (fwd_progress_holdoff <= 0)
fwd_progress_holdoff = 1;
- if (fwd_progress_div <= 0)
+ if (fwd_progress_div < 2)
fwd_progress_div = 4;
rfp = kzalloc_objs(*rfp, fwd_progress);
fwd_prog_tasks = kzalloc_objs(*fwd_prog_tasks, fwd_progress);
--
2.40.1
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 0/8] Torture-test updates for v7.4
@ 2026-10-07 21:04 Paul E. McKenney
2026-10-07 21:04 ` [PATCH v2 1/8] rcutorture: Fix divide-by-zero with fwd_progress_div=1 Paul E. McKenney
` (7 more replies)
0 siblings, 8 replies; 9+ messages in thread
From: Paul E. McKenney @ 2026-10-07 21:04 UTC (permalink / raw)
To: rcu; +Cc: linux-kernel, kernel-team, rostedt
Hello!
This series adds some torture-test updates:
1. Fix divide-by-zero with fwd_progress_div=1, courtesy of Kunwu
Chan.
2. Synchronously wait for all rcu_torture_irq() callbacks to
complete, courtesy of Zqiang.
3. Allow specifying alternative ssh command to kvm-remote.sh.
4. Fix kvm-again.sh re-run failure on ppc64, courtesy of Zhouyi Zhou.
5. Add atomic SRCU lockdep support, courtesy of Kunwu Chan.
6. Wire atomic SRCU into srcu_lockdep.sh, courtesy of Kunwu Chan.
7. Fix double nerrs count in srcu_lockdep.sh, courtesy of Kunwu Chan.
8. Add atomic SRCU cross-CPU IRQ context mismatch test, courtesy
of Kunwu Chan.
Changes since v1:
https://lore.kernel.org/all/860880d0-fb46-4039-a47c-33dd42a215d1@paulmck-laptop/
o Add patches 4-8.
Thanx, Paul
------------------------------------------------------------------------
b/kernel/rcu/rcutorture.c | 2
b/tools/testing/selftests/rcutorture/bin/kvm-again.sh | 11 +
b/tools/testing/selftests/rcutorture/bin/kvm-remote.sh | 22 ++
b/tools/testing/selftests/rcutorture/bin/srcu_lockdep.sh | 39 +++++
kernel/rcu/rcutorture.c | 113 ++++++++++++++-
tools/testing/selftests/rcutorture/bin/srcu_lockdep.sh | 38 ++++-
6 files changed, 211 insertions(+), 14 deletions(-)
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v2 2/8] rcutorture: Synchronously wait for all rcu_torture_irq() callbacks to complete
2026-10-07 21:04 [PATCH 0/8] Torture-test updates for v7.4 Paul E. McKenney
2026-10-07 21:04 ` [PATCH v2 1/8] rcutorture: Fix divide-by-zero with fwd_progress_div=1 Paul E. McKenney
@ 2026-10-07 21:04 ` Paul E. McKenney
2026-10-07 21:04 ` [PATCH v2 3/8] torture: Allow specifying alternative ssh command to kvm-remote.sh Paul E. McKenney
` (5 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Paul E. McKenney @ 2026-10-07 21:04 UTC (permalink / raw)
To: rcu; +Cc: linux-kernel, kernel-team, rostedt, Zqiang, Paul E . McKenney
From: Zqiang <qiang.zhang@linux.dev>
The rcu_torture_reader() drives RCU readers from interrupt context via
smp_call_function_single(cpu, rcu_torture_irq, NULL, 0) with wait=0, to
runs rcu_torture_irq() on a remote CPU. this is async, nothing waits for
the remote handler to run.
On shutdown, torture_stop_kthread() only waits for each reader kthread to
return, and the reader's timer_delete_sync() only drains its timer. Neither
waits for a rcu_torture_irq() which still pending or executing on a remote
CPU, so it can run after all readers have exited and rcu_torture_cleanup()
has already advanced.
1. rcu_torture_irq() may issue cur_ops->call(rhp, rcu_torture_timer_cb)
after cur_ops->cb_barrier() has been waiting for all outstanding
callbacks complete. once the module is unloaded, fires into freed
module text, a use-after-free happen.
2. rcu_torture_irq() may still be inside rcu_torture_one_read(), holding
a read-side critical section, when cur_ops->cleanup() tears the flavor
down (e.g. cleanup_srcu_struct()), triggering an active-reader warning
or use-after-free of the torn-down structure.
This commit therefore issue a kick_all_cpus_sync() after all readers
kthread have returned and before cur_ops->cb_barrier(), synchronous IPI
round trip to every CPU guarantees that every rcu_torture_irq() which
previously issued by any reader has completed.
Signed-off-by: Zqiang <qiang.zhang@linux.dev>
Signed-off-by: Paul E. McKenney <paulmck@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 79807475b6724..51ed35f5aab17 100644
--- a/kernel/rcu/rcutorture.c
+++ b/kernel/rcu/rcutorture.c
@@ -4491,6 +4491,8 @@ rcu_torture_cleanup(void)
for (i = 0; i < nrealreaders; i++)
torture_stop_kthread(rcu_torture_reader,
reader_tasks[i]);
+ if (irqreader && cur_ops->irq_capable)
+ kick_all_cpus_sync();
kfree(reader_tasks);
reader_tasks = NULL;
}
--
2.40.1
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v2 3/8] torture: Allow specifying alternative ssh command to kvm-remote.sh
2026-10-07 21:04 [PATCH 0/8] Torture-test updates for v7.4 Paul E. McKenney
2026-10-07 21:04 ` [PATCH v2 1/8] rcutorture: Fix divide-by-zero with fwd_progress_div=1 Paul E. McKenney
2026-10-07 21:04 ` [PATCH v2 2/8] rcutorture: Synchronously wait for all rcu_torture_irq() callbacks to complete Paul E. McKenney
@ 2026-10-07 21:04 ` Paul E. McKenney
2026-10-07 21:04 ` [PATCH v2 4/8] rcutorture: Fix kvm-again.sh re-run failure on ppc64 Paul E. McKenney
` (4 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Paul E. McKenney @ 2026-10-07 21:04 UTC (permalink / raw)
To: rcu; +Cc: linux-kernel, kernel-team, rostedt, Paul E. McKenney
Some environments require use of alternative commands to access the
test hosts. This commit therefore adds a KVM_REMOTE_SSH environment
variable for this purpose. If this variable is unset, ssh is used.
Any alternative ssh command must support the usual ssh arguments,
including the command to be executed remotely. In some cases, you may
need a wrapper script to make the alternative ssh-like command look
enough like ssh to satisfy kvm-remote.sh.
Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
---
.../selftests/rcutorture/bin/kvm-remote.sh | 22 ++++++++++++++-----
1 file changed, 16 insertions(+), 6 deletions(-)
diff --git a/tools/testing/selftests/rcutorture/bin/kvm-remote.sh b/tools/testing/selftests/rcutorture/bin/kvm-remote.sh
index 48a8052d5dae3..a8397f86e49dc 100755
--- a/tools/testing/selftests/rcutorture/bin/kvm-remote.sh
+++ b/tools/testing/selftests/rcutorture/bin/kvm-remote.sh
@@ -6,6 +6,11 @@
# Usage: kvm-remote.sh "systems" [ <kvm.sh args> ]
# kvm-remote.sh "systems" /path/to/old/run [ <kvm-again.sh args> ]
#
+# The caller may set the KVM_REMOTE_SSH environment in order to specify
+# an alternative ssh command, which is necessary in some environments
+# for authentication purposes. This alternative ssn command must support
+# ssh's usual arguments.
+#
# Copyright (C) 2021 Facebook, Inc.
#
# Authors: Paul E. McKenney <paulmck@kernel.org>
@@ -13,6 +18,11 @@
scriptname=$0
args="$*"
+if test -z "${KVM_REMOTE_SSH}"
+then
+ KVM_REMOTE_SSH=ssh; export KVM_REMOTE_SSH
+fi
+
if ! test -d tools/testing/selftests/rcutorture/bin
then
echo $scriptname must be run from top-level directory of kernel source tree.
@@ -137,7 +147,7 @@ chmod +x $T/bin/kvm-remote-*.sh
# Check first to avoid the need for cleanup for system-name typos
for i in $systems
do
- ssh -o BatchMode=yes $i getconf _NPROCESSORS_ONLN > $T/ssh.stdout 2> $T/ssh.stderr
+ ${KVM_REMOTE_SSH} -o BatchMode=yes $i getconf _NPROCESSORS_ONLN > $T/ssh.stdout 2> $T/ssh.stderr
ret=$?
if test "$ret" -ne 0
then
@@ -158,14 +168,14 @@ echo Build-products tarball: `du -h $T/binres.tgz` | tee -a "$oldrun/remote-log"
for i in $systems
do
echo Downloading tarball to $i `date` | tee -a "$oldrun/remote-log"
- cat $T/binres.tgz | ssh -o BatchMode=yes $i "cd /tmp; tar -xzf -"
+ cat $T/binres.tgz | ${KVM_REMOTE_SSH} -o BatchMode=yes $i "cd /tmp; tar -xzf -"
ret=$?
tries=0
while test "$ret" -ne 0
do
echo Unable to download $T/binres.tgz to system $i, waiting and then retrying. $tries prior retries. | tee -a "$oldrun/remote-log"
sleep 60
- cat $T/binres.tgz | ssh -o BatchMode=yes $i "cd /tmp; tar -xzf -"
+ cat $T/binres.tgz | ${KVM_REMOTE_SSH} -o BatchMode=yes $i "cd /tmp; tar -xzf -"
ret=$?
if test "$ret" -ne 0
then
@@ -191,7 +201,7 @@ checkremotefile () {
while :
do
- ssh -o BatchMode=yes $1 "test -f \"$2\""
+ ${KVM_REMOTE_SSH} -o BatchMode=yes $1 "test -f \"$2\""
ret=$?
if test "$ret" -eq 255
then
@@ -239,7 +249,7 @@ startbatches () {
then
continue # System still running last test, skip.
fi
- ssh -o BatchMode=yes "$i" "cd \"$resdir/$ds\"; touch remote.run; PATH=\"$T/bin:$PATH\" nohup kvm-remote-$curbatch.sh > kvm-remote-$curbatch.sh.out 2>&1 &" 1>&2
+ ${KVM_REMOTE_SSH} -o BatchMode=yes "$i" "cd \"$resdir/$ds\"; touch remote.run; PATH=\"$T/bin:$PATH\" nohup kvm-remote-$curbatch.sh > kvm-remote-$curbatch.sh.out 2>&1 &" 1>&2
ret=$?
if test "$ret" -ne 0
then
@@ -281,7 +291,7 @@ do
if test "$ret" -eq 1
then
echo " ---" Collecting results from $i `date` | tee -a "$oldrun/remote-log"
- ( cd "$oldrun"; ssh -o BatchMode=yes $i "cd $rundir; tar -czf - kvm-remote-*.sh.out */console.log */kvm-test-1-run*.sh.out */qemu[_-]pid */qemu-retval */qemu-affinity; rm -rf $T > /dev/null 2>&1" | tar -xzf - )
+ ( cd "$oldrun"; ${KVM_REMOTE_SSH} -o BatchMode=yes $i "cd $rundir; tar -czf - kvm-remote-*.sh.out */console.log */kvm-test-1-run*.sh.out */qemu[_-]pid */qemu-retval */qemu-affinity; rm -rf $T > /dev/null 2>&1" | tar -xzf - )
break;
fi
if test "$ret" -eq 255
--
2.40.1
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v2 4/8] rcutorture: Fix kvm-again.sh re-run failure on ppc64
2026-10-07 21:04 [PATCH 0/8] Torture-test updates for v7.4 Paul E. McKenney
` (2 preceding siblings ...)
2026-10-07 21:04 ` [PATCH v2 3/8] torture: Allow specifying alternative ssh command to kvm-remote.sh Paul E. McKenney
@ 2026-10-07 21:04 ` Paul E. McKenney
2026-10-07 21:04 ` [PATCH v2 5/8] rcutorture: Add atomic SRCU lockdep support Paul E. McKenney
` (3 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Paul E. McKenney @ 2026-10-07 21:04 UTC (permalink / raw)
To: rcu
Cc: linux-kernel, kernel-team, rostedt, Zhouyi Zhou, Joel Fernandes,
Paul E . McKenney
From: Zhouyi Zhou <zhouzhouyi@gmail.com>
Discovered in the Open Source Lab of Oregon State University when running
torture.sh on a ppc64le VM. Two bugs were exposed:
1. The kvm-transform.sh call hard-coded "bzImage" as the kernel image
name. On ppc64, the boot image is vmlinux, not bzImage, so the
re-run failed to find the image. Fix this by extracting the QEMU
binary from the qemu-cmd file and passing it to identify_boot_image()
to obtain the correct architecture-specific image name, the same way
kvm.sh already does.
2. The rm -f invocation on re-run listed vmlinux among the files to
delete. On ppc64 vmlinux is the boot image, so deleting it broke
the re-run on that architecture. Drop vmlinux from the unconditional
list, and instead conditionally delete it only when the boot image
basename is not vmlinux.
In addition, identify qemu_binary before the copy step so that on
non-PowerPC systems (where vmlinux is not the boot image) the vmlinux
file can be removed immediately after the run directory is copied,
saving storage before any tests run. This also eliminates the
per-iteration re-computation of qemu_binary and boot_image inside
the qemu-cmd transform loop.
Tested on a local x86_64 machine and on a PPC VM of the Open Source Lab
of Oregon State University.
Signed-off-by: Zhouyi Zhou <zhouzhouyi@gmail.com>
Reviewed-by: Joel Fernandes <joelagnelf@nvidia.com>
Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
---
tools/testing/selftests/rcutorture/bin/kvm-again.sh | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/tools/testing/selftests/rcutorture/bin/kvm-again.sh b/tools/testing/selftests/rcutorture/bin/kvm-again.sh
index b5239b52cb5da..9060b3dc89262 100755
--- a/tools/testing/selftests/rcutorture/bin/kvm-again.sh
+++ b/tools/testing/selftests/rcutorture/bin/kvm-again.sh
@@ -180,6 +180,9 @@ fi
echo ---- Re-run results directory: $rundir
+qemu_binary="$(find "$oldrun" -maxdepth 2 -name 'qemu-cmd' -type f 2>/dev/null | head -1 | xargs -r grep -v '^#' 2>/dev/null | awk 'NF { print $1; exit }')"
+boot_image="`identify_boot_image "$qemu_binary"`"
+
if test "$oldrun" != "$rundir"
then
# Copy old run directory tree over and adjust.
@@ -189,7 +192,7 @@ then
echo "Cannot copy from $oldrun to $rundir."
usage
fi
- rm -f "$rundir"/*/{console.log,console.log.diags,qemu_pid,qemu-pid,qemu-retval,Warnings,kvm-test-1-run.sh.out,kvm-test-1-run-qemu.sh.out,vmlinux} "$rundir"/log
+ rm -f "$rundir"/*/{console.log,console.log.diags,qemu_pid,qemu-pid,qemu-retval,Warnings,kvm-test-1-run.sh.out,kvm-test-1-run-qemu.sh.out} "$rundir"/log
touch "$rundir/log"
echo $scriptname $args | tee -a "$rundir/log"
echo $oldrun > "$rundir/re-run"
@@ -197,6 +200,10 @@ then
then
$arg_link "$oldrun/../../bin" "$rundir/../.."
fi
+ if test "`basename "$boot_image"`" != vmlinux
+ then
+ rm -f "$rundir"/*/vmlinux
+ fi
else
# Check for a run having already happened.
find "$rundir" -name console.log -print > $T/oldrun-console.log
@@ -217,7 +224,7 @@ do
qemu_cmd_dir="`dirname "$i"`"
kernel_dir="`echo $qemu_cmd_dir | sed -e 's/\.[0-9]\+$//'`"
jitter_dir="`dirname "$kernel_dir"`"
- kvm-transform.sh "$kernel_dir/bzImage" "$qemu_cmd_dir/console.log" "$jitter_dir" "$dur" "$bootargs" < $T/qemu-cmd > $i
+ kvm-transform.sh "$kernel_dir/`basename $boot_image`" "$qemu_cmd_dir/console.log" "$jitter_dir" "$dur" "$bootargs" < $T/qemu-cmd > $i
if test -n "$arg_remote"
then
echo "# TORTURE_KCONFIG_GDB_ARG=''" >> $i
--
2.40.1
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v2 5/8] rcutorture: Add atomic SRCU lockdep support
2026-10-07 21:04 [PATCH 0/8] Torture-test updates for v7.4 Paul E. McKenney
` (3 preceding siblings ...)
2026-10-07 21:04 ` [PATCH v2 4/8] rcutorture: Fix kvm-again.sh re-run failure on ppc64 Paul E. McKenney
@ 2026-10-07 21:04 ` Paul E. McKenney
2026-10-07 21:04 ` [PATCH v2 6/8] selftests/rcutorture: Wire atomic SRCU into srcu_lockdep.sh Paul E. McKenney
` (2 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Paul E. McKenney @ 2026-10-07 21:04 UTC (permalink / raw)
To: rcu
Cc: linux-kernel, kernel-team, rostedt, Kunwu Chan, Zqiang,
Boqun Feng, Joel Fernandes, Paul E . McKenney
From: Kunwu Chan <kunwu.chan@gmail.com>
Add three testtypes covering atomic SRCU lockdep behavior:
testtype 4: atomic SRCU same-type deadlock
testtype 5: atomic SRCU + raw spinlock dependency cycle
testtype 6: synchronize_srcu_atomic() inside rcu_read_lock()
Co-developed-by: Zqiang <qiang.zhang@linux.dev>
Signed-off-by: Zqiang <qiang.zhang@linux.dev>
Signed-off-by: Kunwu Chan <kunwu.chan@gmail.com>
Acked-by: Boqun Feng <boqun@kernel.org>
Reviewed-by: Joel Fernandes <joelagnelf@nvidia.com>
Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
---
kernel/rcu/rcutorture.c | 84 ++++++++++++++++++++++++++++++++++++++++-
1 file changed, 83 insertions(+), 1 deletion(-)
diff --git a/kernel/rcu/rcutorture.c b/kernel/rcu/rcutorture.c
index 51ed35f5aab17..35dc61d871b98 100644
--- a/kernel/rcu/rcutorture.c
+++ b/kernel/rcu/rcutorture.c
@@ -4662,6 +4662,17 @@ static DECLARE_RWSEM(rwsem7);
static DECLARE_RWSEM(rwsem8);
static DECLARE_RWSEM(rwsem9);
+static DEFINE_RAW_SPINLOCK(spin0);
+static DEFINE_RAW_SPINLOCK(spin1);
+static DEFINE_RAW_SPINLOCK(spin2);
+static DEFINE_RAW_SPINLOCK(spin3);
+static DEFINE_RAW_SPINLOCK(spin4);
+static DEFINE_RAW_SPINLOCK(spin5);
+static DEFINE_RAW_SPINLOCK(spin6);
+static DEFINE_RAW_SPINLOCK(spin7);
+static DEFINE_RAW_SPINLOCK(spin8);
+static DEFINE_RAW_SPINLOCK(spin9);
+
DEFINE_STATIC_SRCU(srcu0);
DEFINE_STATIC_SRCU(srcu1);
DEFINE_STATIC_SRCU(srcu2);
@@ -4673,6 +4684,17 @@ DEFINE_STATIC_SRCU(srcu7);
DEFINE_STATIC_SRCU(srcu8);
DEFINE_STATIC_SRCU(srcu9);
+DEFINE_STATIC_SRCU_ATOMIC(srcu0_atomic);
+DEFINE_STATIC_SRCU_ATOMIC(srcu1_atomic);
+DEFINE_STATIC_SRCU_ATOMIC(srcu2_atomic);
+DEFINE_STATIC_SRCU_ATOMIC(srcu3_atomic);
+DEFINE_STATIC_SRCU_ATOMIC(srcu4_atomic);
+DEFINE_STATIC_SRCU_ATOMIC(srcu5_atomic);
+DEFINE_STATIC_SRCU_ATOMIC(srcu6_atomic);
+DEFINE_STATIC_SRCU_ATOMIC(srcu7_atomic);
+DEFINE_STATIC_SRCU_ATOMIC(srcu8_atomic);
+DEFINE_STATIC_SRCU_ATOMIC(srcu9_atomic);
+
static int srcu_lockdep_next(const char *f, const char *fl, const char *fs, const char *fu, int i,
int cyclelen, int deadlock)
{
@@ -4702,6 +4724,12 @@ static void rcu_torture_init_srcu_lockdep(void)
&rwsem5, &rwsem6, &rwsem7, &rwsem8, &rwsem9 };
struct srcu_struct *srcus[] = { &srcu0, &srcu1, &srcu2, &srcu3, &srcu4,
&srcu5, &srcu6, &srcu7, &srcu8, &srcu9 };
+ raw_spinlock_t *spins[] = { &spin0, &spin1, &spin2, &spin3, &spin4,
+ &spin5, &spin6, &spin7, &spin8, &spin9 };
+ struct srcu_struct *srcus_atomic[] = { &srcu0_atomic, &srcu1_atomic, &srcu2_atomic,
+ &srcu3_atomic, &srcu4_atomic, &srcu5_atomic,
+ &srcu6_atomic, &srcu7_atomic, &srcu8_atomic,
+ &srcu9_atomic };
int testtype;
if (!test_srcu_lockdep)
@@ -4812,11 +4840,65 @@ static void rcu_torture_init_srcu_lockdep(void)
}
#endif // #ifdef CONFIG_TASKS_TRACE_RCU
+ if (testtype == 4) {
+ pr_info("%s: test_srcu_lockdep = %05d: SRCU_ATOMIC %d-way %sdeadlock.\n",
+ __func__, test_srcu_lockdep, cyclelen, deadlock ? "" : "non-");
+ if (deadlock && cyclelen == 1)
+ pr_info("%s: Expect hang.\n", __func__);
+ for (i = 0; i < cyclelen; i++) {
+ j = srcu_lockdep_next(__func__, "srcu_read_lock_atomic",
+ "synchronize_srcu_atomic",
+ "srcu_read_unlock_atomic", i,
+ cyclelen, deadlock);
+ idx = srcu_read_lock_atomic(srcus_atomic[i]);
+ if (j >= 0)
+ synchronize_srcu_atomic(srcus_atomic[j]);
+ srcu_read_unlock_atomic(srcus_atomic[i], idx);
+ }
+ return;
+ }
+
+ if (testtype == 5) {
+ pr_info("%s: test_srcu_lockdep = %05d: SRCU_ATOMIC/raw_spinlock %d-way %sdeadlock.\n",
+ __func__, test_srcu_lockdep, cyclelen, deadlock ? "" : "non-");
+ for (i = 0; i < cyclelen; i++) {
+ pr_info("%s: srcu_read_lock_atomic(%d), raw_spin_lock(%d), raw_spin_unlock(%d), srcu_read_unlock_atomic(%d)\n",
+ __func__, i, i, i, i);
+ idx = srcu_read_lock_atomic(srcus_atomic[i]);
+ raw_spin_lock(spins[i]);
+ raw_spin_unlock(spins[i]);
+ srcu_read_unlock_atomic(srcus_atomic[i], idx);
+
+ j = srcu_lockdep_next(__func__, "raw_spin_lock",
+ "synchronize_srcu_atomic",
+ "raw_spin_unlock", i, cyclelen,
+ deadlock);
+ raw_spin_lock(spins[i]);
+ if (j >= 0)
+ synchronize_srcu_atomic(srcus_atomic[j]);
+ raw_spin_unlock(spins[i]);
+ }
+ return;
+ }
+
+ if (testtype == 6) {
+ pr_info("%s: test_srcu_lockdep = %05d: synchronize_srcu_atomic() inside rcu_read_lock() %d-way.\n",
+ __func__, test_srcu_lockdep, cyclelen);
+ for (i = 0; i < cyclelen; i++) {
+ rcu_read_lock();
+ synchronize_srcu_atomic(srcus_atomic[i]);
+ rcu_read_unlock();
+ }
+ return;
+ }
+
err_out:
pr_info("%s: test_srcu_lockdep = %05d does nothing.\n", __func__, test_srcu_lockdep);
pr_info("%s: test_srcu_lockdep = DNNL.\n", __func__);
pr_info("%s: D: Deadlock if nonzero.\n", __func__);
- pr_info("%s: NN: Test number, 0=SRCU, 1=SRCU/mutex, 2=SRCU/rwsem, 3=SRCU/Tasks Trace RCU.\n", __func__);
+ pr_info("%s: NN: Test number, 0=SRCU, 1=SRCU/mutex, 2=SRCU/rwsem, 3=SRCU/Tasks Trace RCU, 4=SRCU_ATOMIC, ",
+ __func__);
+ pr_cont("5=SRCU_ATOMIC/raw_spinlock, 6=synchronize_srcu_atomic inside rcu_read_lock.\n");
pr_info("%s: L: Cycle length.\n", __func__);
if (!IS_ENABLED(CONFIG_TASKS_TRACE_RCU))
pr_info("%s: NN=3 disallowed because kernel is built with CONFIG_TASKS_TRACE_RCU=n\n", __func__);
--
2.40.1
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v2 6/8] selftests/rcutorture: Wire atomic SRCU into srcu_lockdep.sh
2026-10-07 21:04 [PATCH 0/8] Torture-test updates for v7.4 Paul E. McKenney
` (4 preceding siblings ...)
2026-10-07 21:04 ` [PATCH v2 5/8] rcutorture: Add atomic SRCU lockdep support Paul E. McKenney
@ 2026-10-07 21:04 ` Paul E. McKenney
2026-10-07 21:04 ` [PATCH v2 7/8] selftests/rcutorture: Fix double nerrs count in srcu_lockdep.sh Paul E. McKenney
2026-10-07 21:04 ` [PATCH v2 8/8] rcutorture: Add atomic SRCU cross-CPU IRQ context mismatch test Paul E. McKenney
7 siblings, 0 replies; 9+ messages in thread
From: Paul E. McKenney @ 2026-10-07 21:04 UTC (permalink / raw)
To: rcu
Cc: linux-kernel, kernel-team, rostedt, Kunwu Chan, Zqiang,
Boqun Feng, Paul E . McKenney
From: Kunwu Chan <kunwu.chan@gmail.com>
Add testtypes 4 (atomic SRCU same-type deadlock) and 5 (atomic SRCU
+ raw_spinlock dependency cycle) to the deadlock-detection loop.
Add a separate loop for testtype 6 (rcu_read_lock() →
synchronize_srcu_atomic()), which also verifies via console.log that
no lockdep warning is triggered.
Co-developed-by: Zqiang <qiang.zhang@linux.dev>
Signed-off-by: Zqiang <qiang.zhang@linux.dev>
Signed-off-by: Kunwu Chan <kunwu.chan@gmail.com>
Acked-by: Boqun Feng <boqun@kernel.org>
Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
---
.../selftests/rcutorture/bin/srcu_lockdep.sh | 39 ++++++++++++++++++-
1 file changed, 38 insertions(+), 1 deletion(-)
diff --git a/tools/testing/selftests/rcutorture/bin/srcu_lockdep.sh b/tools/testing/selftests/rcutorture/bin/srcu_lockdep.sh
index 4e98c697def48..72791499dd96b 100755
--- a/tools/testing/selftests/rcutorture/bin/srcu_lockdep.sh
+++ b/tools/testing/selftests/rcutorture/bin/srcu_lockdep.sh
@@ -44,7 +44,7 @@ nerrs=0
# Test lockdep's handling of deadlocks.
for d in 0 1
do
- for t in 0 1 2
+ for t in 0 1 2 4 5
do
for c in 1 2 3
do
@@ -79,6 +79,43 @@ do
done
done
+# Verify that synchronize_srcu_atomic() does not trigger lockdep
+# warnings when called inside rcu_read_lock().
+for c in 1 2 3
+do
+ err=
+ val=$((6*10+c))
+ tools/testing/selftests/rcutorture/bin/kvm.sh --allcpus --duration 5s \
+ --configs "SRCU-P" \
+ --kconfig "CONFIG_FORCE_NEED_SRCU_NMI_SAFE=y" \
+ --bootargs "rcutorture.test_srcu_lockdep=$val" \
+ --trust-make --datestamp "$ds/$val" > "$T/kvm.sh.out" 2>&1
+ ret=$?
+ mv "$T/kvm.sh.out" "$RCUTORTURE/res/$ds/$val"
+ if ! grep -q '^CONFIG_PROVE_LOCKING=y' .config
+ then
+ echo "rcu_torture_init_srcu_lockdep:Error: CONFIG_PROVE_LOCKING" \
+ "disabled in rcutorture SRCU-P scenario"
+ err=1
+ fi
+ if test "$ret" -ne 0
+ then
+ err=1
+ echo -n Unexpected failure for > "$RCUTORTURE/res/$ds/$val/kvm.sh.err"
+ elif grep -qE "WARNING: possible (recursive locking|circular locking dependency)" \
+ "$RCUTORTURE/res/$ds/$val/SRCU-P/console.log"
+ then
+ err=1
+ echo -n Unexpected lockdep warning for > "$RCUTORTURE/res/$ds/$val/kvm.sh.err"
+ fi
+ if test -n "$err"
+ then
+ grep "rcu_torture_init_srcu_lockdep: test_srcu_lockdep = " "$RCUTORTURE/res/$ds/$val/SRCU-P/console.log" | sed -e 's/^.*rcu_torture_init_srcu_lockdep://' >> "$RCUTORTURE/res/$ds/$val/kvm.sh.err"
+ cat "$RCUTORTURE/res/$ds/$val/kvm.sh.err"
+ nerrs=$((nerrs+1))
+ fi
+done
+
# Test lockdep-enabled testing of mixed SRCU readers.
for val in 0x1 0xf
do
--
2.40.1
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v2 7/8] selftests/rcutorture: Fix double nerrs count in srcu_lockdep.sh
2026-10-07 21:04 [PATCH 0/8] Torture-test updates for v7.4 Paul E. McKenney
` (5 preceding siblings ...)
2026-10-07 21:04 ` [PATCH v2 6/8] selftests/rcutorture: Wire atomic SRCU into srcu_lockdep.sh Paul E. McKenney
@ 2026-10-07 21:04 ` Paul E. McKenney
2026-10-07 21:04 ` [PATCH v2 8/8] rcutorture: Add atomic SRCU cross-CPU IRQ context mismatch test Paul E. McKenney
7 siblings, 0 replies; 9+ messages in thread
From: Paul E. McKenney @ 2026-10-07 21:04 UTC (permalink / raw)
To: rcu
Cc: linux-kernel, kernel-team, rostedt, Kunwu Chan, Boqun Feng,
Paul E . McKenney
From: Kunwu Chan <kunwu.chan@gmail.com>
When CONFIG_PROVE_LOCKING is missing, the deadlock-detection loop
and the mixed-SRCU-readers section each increment nerrs once in
the configuration check and again in the common error path,
counting the same error twice.
Remove the stray increments so that each error advances nerrs
by one.
Signed-off-by: Kunwu Chan <kunwu.chan@gmail.com>
Acked-by: Boqun Feng <boqun@kernel.org>
Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
---
tools/testing/selftests/rcutorture/bin/srcu_lockdep.sh | 2 --
1 file changed, 2 deletions(-)
diff --git a/tools/testing/selftests/rcutorture/bin/srcu_lockdep.sh b/tools/testing/selftests/rcutorture/bin/srcu_lockdep.sh
index 72791499dd96b..3acaffe52c784 100755
--- a/tools/testing/selftests/rcutorture/bin/srcu_lockdep.sh
+++ b/tools/testing/selftests/rcutorture/bin/srcu_lockdep.sh
@@ -56,7 +56,6 @@ do
if ! grep -q '^CONFIG_PROVE_LOCKING=y' .config
then
echo "rcu_torture_init_srcu_lockdep:Error: CONFIG_PROVE_LOCKING disabled in rcutorture SRCU-P scenario"
- nerrs=$((nerrs+1))
err=1
fi
if test "$d" -ne 0 && test "$ret" -eq 0
@@ -126,7 +125,6 @@ do
if ! grep -q '^CONFIG_PROVE_LOCKING=y' .config
then
echo "rcu_torture_init_srcu_lockdep:Error: CONFIG_PROVE_LOCKING disabled in rcutorture SRCU-P scenario"
- nerrs=$((nerrs+1))
err=1
fi
if test "$val" = 0xf && test "$ret" -eq 0
--
2.40.1
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v2 8/8] rcutorture: Add atomic SRCU cross-CPU IRQ context mismatch test
2026-10-07 21:04 [PATCH 0/8] Torture-test updates for v7.4 Paul E. McKenney
` (6 preceding siblings ...)
2026-10-07 21:04 ` [PATCH v2 7/8] selftests/rcutorture: Fix double nerrs count in srcu_lockdep.sh Paul E. McKenney
@ 2026-10-07 21:04 ` Paul E. McKenney
7 siblings, 0 replies; 9+ messages in thread
From: Paul E. McKenney @ 2026-10-07 21:04 UTC (permalink / raw)
To: rcu
Cc: linux-kernel, kernel-team, rostedt, Kunwu Chan, Zqiang,
Boqun Feng, Paul E . McKenney
From: Kunwu Chan <kunwu.chan@gmail.com>
Add testtype 7 to verify that lockdep detects an IRQ-context
mismatch when an atomic SRCU read-side critical section is held
with IRQs enabled on one CPU and synchronize_srcu_atomic() is
called from an IPI handler on another CPU.
This covers the cross-CPU case that cannot be detected by
checking the current task's held locks.
Co-developed-by: Zqiang <qiang.zhang@linux.dev>
Signed-off-by: Zqiang <qiang.zhang@linux.dev>
Signed-off-by: Kunwu Chan <kunwu.chan@gmail.com>
Acked-by: Boqun Feng <boqun@kernel.org>
Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
---
kernel/rcu/rcutorture.c | 27 +++++++++++++-
.../selftests/rcutorture/bin/srcu_lockdep.sh | 36 +++++++++++++++++++
2 files changed, 62 insertions(+), 1 deletion(-)
diff --git a/kernel/rcu/rcutorture.c b/kernel/rcu/rcutorture.c
index 35dc61d871b98..968343be4e0d1 100644
--- a/kernel/rcu/rcutorture.c
+++ b/kernel/rcu/rcutorture.c
@@ -4695,6 +4695,8 @@ DEFINE_STATIC_SRCU_ATOMIC(srcu7_atomic);
DEFINE_STATIC_SRCU_ATOMIC(srcu8_atomic);
DEFINE_STATIC_SRCU_ATOMIC(srcu9_atomic);
+DEFINE_STATIC_SRCU_ATOMIC(srcu_irq);
+
static int srcu_lockdep_next(const char *f, const char *fl, const char *fs, const char *fu, int i,
int cyclelen, int deadlock)
{
@@ -4709,6 +4711,11 @@ static int srcu_lockdep_next(const char *f, const char *fl, const char *fs, cons
return j;
}
+static void srcu_sync_irq(void *unused)
+{
+ synchronize_srcu_atomic(&srcu_irq);
+}
+
// Test lockdep on SRCU-based deadlock scenarios.
static void rcu_torture_init_srcu_lockdep(void)
{
@@ -4892,13 +4899,31 @@ static void rcu_torture_init_srcu_lockdep(void)
return;
}
+ if (testtype == 7) {
+ int cpu;
+
+ for (i = 0; i < cyclelen; i++) {
+ idx = srcu_read_lock_atomic(&srcu_irq);
+ cpu = cpumask_any_but(cpu_online_mask,
+ smp_processor_id());
+ if (cpu < nr_cpu_ids) {
+ pr_info("%s: CPU%d sending IPI to CPU%d\n",
+ __func__, smp_processor_id(), cpu);
+ smp_call_function_single(cpu, srcu_sync_irq,
+ NULL, 1);
+ }
+ srcu_read_unlock_atomic(&srcu_irq, idx);
+ }
+ return;
+ }
+
err_out:
pr_info("%s: test_srcu_lockdep = %05d does nothing.\n", __func__, test_srcu_lockdep);
pr_info("%s: test_srcu_lockdep = DNNL.\n", __func__);
pr_info("%s: D: Deadlock if nonzero.\n", __func__);
pr_info("%s: NN: Test number, 0=SRCU, 1=SRCU/mutex, 2=SRCU/rwsem, 3=SRCU/Tasks Trace RCU, 4=SRCU_ATOMIC, ",
__func__);
- pr_cont("5=SRCU_ATOMIC/raw_spinlock, 6=synchronize_srcu_atomic inside rcu_read_lock.\n");
+ pr_cont("5=SRCU_ATOMIC/raw_spinlock, 6=synchronize_srcu_atomic inside rcu_read_lock, 7=atomic SRCU cross-CPU IRQ context mismatch.\n");
pr_info("%s: L: Cycle length.\n", __func__);
if (!IS_ENABLED(CONFIG_TASKS_TRACE_RCU))
pr_info("%s: NN=3 disallowed because kernel is built with CONFIG_TASKS_TRACE_RCU=n\n", __func__);
diff --git a/tools/testing/selftests/rcutorture/bin/srcu_lockdep.sh b/tools/testing/selftests/rcutorture/bin/srcu_lockdep.sh
index 3acaffe52c784..c29a39f7d8914 100755
--- a/tools/testing/selftests/rcutorture/bin/srcu_lockdep.sh
+++ b/tools/testing/selftests/rcutorture/bin/srcu_lockdep.sh
@@ -115,6 +115,42 @@ do
fi
done
+# Verify that synchronize_srcu_atomic() detects IRQ context mismatch
+# when SRCU reader previously ran with IRQs enabled.
+for c in 1 2 3
+do
+ err=
+ val=$((1000+7*10+c))
+ tools/testing/selftests/rcutorture/bin/kvm.sh --allcpus --duration 5s \
+ --configs "SRCU-P" \
+ --kconfig "CONFIG_FORCE_NEED_SRCU_NMI_SAFE=y" \
+ --bootargs "rcutorture.test_srcu_lockdep=$val" \
+ --trust-make --datestamp "$ds/$val" > "$T/kvm.sh.out" 2>&1
+ ret=$?
+ mv "$T/kvm.sh.out" "$RCUTORTURE/res/$ds/$val"
+ if ! grep -q '^CONFIG_PROVE_LOCKING=y' .config
+ then
+ echo "rcu_torture_init_srcu_lockdep:Error: CONFIG_PROVE_LOCKING" \
+ "disabled in rcutorture SRCU-P scenario"
+ err=1
+ fi
+ if test "$ret" -eq 0
+ then
+ err=1
+ echo -n Missing lockdep warning for > "$RCUTORTURE/res/$ds/$val/kvm.sh.err"
+ elif ! grep -q "inconsistent {HARDIRQ-ON-R}" "$RCUTORTURE/res/$ds/$val/SRCU-P/console.log"
+ then
+ err=1
+ echo -n Missing lockdep warning for > "$RCUTORTURE/res/$ds/$val/kvm.sh.err"
+ fi
+ if test -n "$err"
+ then
+ grep "rcu_torture_init_srcu_lockdep: test_srcu_lockdep = " "$RCUTORTURE/res/$ds/$val/SRCU-P/console.log" | sed -e 's/^.*rcu_torture_init_srcu_lockdep://' >> "$RCUTORTURE/res/$ds/$val/kvm.sh.err"
+ cat "$RCUTORTURE/res/$ds/$val/kvm.sh.err"
+ nerrs=$((nerrs+1))
+ fi
+done
+
# Test lockdep-enabled testing of mixed SRCU readers.
for val in 0x1 0xf
do
--
2.40.1
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2026-10-07 21:04 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-07 21:04 [PATCH 0/8] Torture-test updates for v7.4 Paul E. McKenney
2026-10-07 21:04 ` [PATCH v2 1/8] rcutorture: Fix divide-by-zero with fwd_progress_div=1 Paul E. McKenney
2026-10-07 21:04 ` [PATCH v2 2/8] rcutorture: Synchronously wait for all rcu_torture_irq() callbacks to complete Paul E. McKenney
2026-10-07 21:04 ` [PATCH v2 3/8] torture: Allow specifying alternative ssh command to kvm-remote.sh Paul E. McKenney
2026-10-07 21:04 ` [PATCH v2 4/8] rcutorture: Fix kvm-again.sh re-run failure on ppc64 Paul E. McKenney
2026-10-07 21:04 ` [PATCH v2 5/8] rcutorture: Add atomic SRCU lockdep support Paul E. McKenney
2026-10-07 21:04 ` [PATCH v2 6/8] selftests/rcutorture: Wire atomic SRCU into srcu_lockdep.sh Paul E. McKenney
2026-10-07 21:04 ` [PATCH v2 7/8] selftests/rcutorture: Fix double nerrs count in srcu_lockdep.sh Paul E. McKenney
2026-10-07 21:04 ` [PATCH v2 8/8] rcutorture: Add atomic SRCU cross-CPU IRQ context mismatch test Paul E. McKenney
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®