* [PATCH v1 1/6] rcu: Remove unused expedited_need_qs field from rcu_state
2026-07-18 17:15 [PATCH v1 0/6] RCU and torture fixes and cleanups Joel Fernandes
@ 2026-07-18 17:15 ` Joel Fernandes
2026-07-18 17:15 ` [PATCH v1 2/6] rcu: Remove unused rdp parameter from trace_rcu_this_gp() Joel Fernandes
` (5 subsequent siblings)
6 siblings, 0 replies; 10+ messages in thread
From: Joel Fernandes @ 2026-07-18 17:15 UTC (permalink / raw)
To: linux-kernel, Paul E. McKenney, Frederic Weisbecker,
Neeraj Upadhyay, Joel Fernandes, Josh Triplett, Boqun Feng,
Uladzislau Rezki, Steven Rostedt, Mathieu Desnoyers,
Lai Jiangshan, Zqiang
Cc: rcu
The ->expedited_need_qs counter was part of the old expedited
grace-period machinery that spun waiting for each CPU to check in.
The current implementation instead tracks holdout CPUs via the
rcu_node structures' ->expmask fields and waits on the ->exp_wq[]
wait queues, so nothing reads or writes ->expedited_need_qs any
longer.
Remove the field to avoid wasting space in rcu_state and to keep
readers of the expedited code from searching for nonexistent users.
Signed-off-by: Joel Fernandes <joelagnelf@nvidia.com>
---
kernel/rcu/tree.h | 1 -
1 file changed, 1 deletion(-)
diff --git a/kernel/rcu/tree.h b/kernel/rcu/tree.h
index 7dfc57e9adb1..beb86e39909a 100644
--- a/kernel/rcu/tree.h
+++ b/kernel/rcu/tree.h
@@ -386,7 +386,6 @@ struct rcu_state {
struct mutex exp_mutex; /* Serialize expedited GP. */
struct mutex exp_wake_mutex; /* Serialize wakeup. */
unsigned long expedited_sequence; /* Take a ticket. */
- atomic_t expedited_need_qs; /* # CPUs left to check in. */
struct swait_queue_head expedited_wq; /* Wait for check-ins. */
int ncpus_snap; /* # CPUs seen last time. */
u8 cbovld; /* Callback overload now? */
--
2.34.1
^ permalink raw reply [flat|nested] 10+ messages in thread* [PATCH v1 2/6] rcu: Remove unused rdp parameter from trace_rcu_this_gp()
2026-07-18 17:15 [PATCH v1 0/6] RCU and torture fixes and cleanups Joel Fernandes
2026-07-18 17:15 ` [PATCH v1 1/6] rcu: Remove unused expedited_need_qs field from rcu_state Joel Fernandes
@ 2026-07-18 17:15 ` Joel Fernandes
2026-07-18 17:15 ` [PATCH v1 3/6] rcu: Remove unused func parameter from callback-enqueue functions Joel Fernandes
` (4 subsequent siblings)
6 siblings, 0 replies; 10+ messages in thread
From: Joel Fernandes @ 2026-07-18 17:15 UTC (permalink / raw)
To: linux-kernel, Paul E. McKenney, Frederic Weisbecker,
Neeraj Upadhyay, Joel Fernandes, Josh Triplett, Boqun Feng,
Uladzislau Rezki, Steven Rostedt, Mathieu Desnoyers,
Lai Jiangshan, Zqiang
Cc: rcu
The trace_rcu_this_gp() wrapper forwards only the rcu_node structure's
fields and the requested grace-period sequence number to the
rcu_future_grace_period tracepoint. Its rcu_data pointer parameter
has no users, but every one of the ten call sites must nevertheless
come up with an rcu_data pointer to pass in.
Remove the parameter and update all callers. This also allows
rcu_future_gp_cleanup() to drop the local rcu_data pointer that
existed solely to feed this trace call.
No functional change.
Signed-off-by: Joel Fernandes <joelagnelf@nvidia.com>
---
kernel/rcu/tree.c | 23 ++++++++++-------------
kernel/rcu/tree_nocb.h | 4 ++--
2 files changed, 12 insertions(+), 15 deletions(-)
diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c
index 03a43d3d2616..ef553189ee24 100644
--- a/kernel/rcu/tree.c
+++ b/kernel/rcu/tree.c
@@ -986,8 +986,8 @@ static int rcu_watching_snap_recheck(struct rcu_data *rdp)
}
/* Trace-event wrapper function for trace_rcu_future_grace_period. */
-static void trace_rcu_this_gp(struct rcu_node *rnp, struct rcu_data *rdp,
- unsigned long gp_seq_req, const char *s)
+static void trace_rcu_this_gp(struct rcu_node *rnp, unsigned long gp_seq_req,
+ const char *s)
{
trace_rcu_future_grace_period(rcu_state.name, READ_ONCE(rnp->gp_seq),
gp_seq_req, rnp->level,
@@ -1026,7 +1026,7 @@ static bool rcu_start_this_gp(struct rcu_node *rnp_start, struct rcu_data *rdp,
* Note that rnp_start->lock must not be released.
*/
raw_lockdep_assert_held_rcu_node(rnp_start);
- trace_rcu_this_gp(rnp_start, rdp, gp_seq_req, TPS("Startleaf"));
+ trace_rcu_this_gp(rnp_start, gp_seq_req, TPS("Startleaf"));
for (rnp = rnp_start; 1; rnp = rnp->parent) {
if (rnp != rnp_start)
raw_spin_lock_rcu_node(rnp);
@@ -1034,8 +1034,7 @@ static bool rcu_start_this_gp(struct rcu_node *rnp_start, struct rcu_data *rdp,
rcu_seq_started(&rnp->gp_seq, gp_seq_req) ||
(rnp != rnp_start &&
rcu_seq_state(rcu_seq_current(&rnp->gp_seq)))) {
- trace_rcu_this_gp(rnp, rdp, gp_seq_req,
- TPS("Prestarted"));
+ trace_rcu_this_gp(rnp, gp_seq_req, TPS("Prestarted"));
goto unlock_out;
}
WRITE_ONCE(rnp->gp_seq_needed, gp_seq_req);
@@ -1046,7 +1045,7 @@ static bool rcu_start_this_gp(struct rcu_node *rnp_start, struct rcu_data *rdp,
* rcu_gp_cleanup() will see the marking. Bail to
* reduce contention.
*/
- trace_rcu_this_gp(rnp_start, rdp, gp_seq_req,
+ trace_rcu_this_gp(rnp_start, gp_seq_req,
TPS("Startedleaf"));
goto unlock_out;
}
@@ -1058,14 +1057,14 @@ static bool rcu_start_this_gp(struct rcu_node *rnp_start, struct rcu_data *rdp,
/* If GP already in progress, just leave, otherwise start one. */
if (rcu_gp_in_progress()) {
- trace_rcu_this_gp(rnp, rdp, gp_seq_req, TPS("Startedleafroot"));
+ trace_rcu_this_gp(rnp, gp_seq_req, TPS("Startedleafroot"));
goto unlock_out;
}
- trace_rcu_this_gp(rnp, rdp, gp_seq_req, TPS("Startedroot"));
+ trace_rcu_this_gp(rnp, gp_seq_req, TPS("Startedroot"));
WRITE_ONCE(rcu_state.gp_flags, rcu_state.gp_flags | RCU_GP_FLAG_INIT);
WRITE_ONCE(rcu_state.gp_req_activity, jiffies);
if (!READ_ONCE(rcu_state.gp_kthread)) {
- trace_rcu_this_gp(rnp, rdp, gp_seq_req, TPS("NoGPkthread"));
+ trace_rcu_this_gp(rnp, gp_seq_req, TPS("NoGPkthread"));
goto unlock_out;
}
trace_rcu_grace_period(rcu_state.name, data_race(rcu_state.gp_seq), TPS("newreq"));
@@ -1088,12 +1087,11 @@ static bool rcu_start_this_gp(struct rcu_node *rnp_start, struct rcu_data *rdp,
static bool rcu_future_gp_cleanup(struct rcu_node *rnp)
{
bool needmore;
- struct rcu_data *rdp = this_cpu_ptr(&rcu_data);
needmore = ULONG_CMP_LT(rnp->gp_seq, rnp->gp_seq_needed);
if (!needmore)
rnp->gp_seq_needed = rnp->gp_seq; /* Avoid counter wrap. */
- trace_rcu_this_gp(rnp, rdp, rnp->gp_seq,
+ trace_rcu_this_gp(rnp, rnp->gp_seq,
needmore ? TPS("CleanupMore") : TPS("Cleanup"));
return needmore;
}
@@ -2252,8 +2250,7 @@ static noinline void rcu_gp_cleanup(void)
/* Check for GP requests since above loop. */
rdp = this_cpu_ptr(&rcu_data);
if (!needgp && ULONG_CMP_LT(rnp->gp_seq, rnp->gp_seq_needed)) {
- trace_rcu_this_gp(rnp, rdp, rnp->gp_seq_needed,
- TPS("CleanupMore"));
+ trace_rcu_this_gp(rnp, rnp->gp_seq_needed, TPS("CleanupMore"));
needgp = true;
}
/* Advance CBs to reduce false positives below. */
diff --git a/kernel/rcu/tree_nocb.h b/kernel/rcu/tree_nocb.h
index 373b877cf171..c4a5b4662b3a 100644
--- a/kernel/rcu/tree_nocb.h
+++ b/kernel/rcu/tree_nocb.h
@@ -802,12 +802,12 @@ static noinline_for_stack void nocb_gp_wait(struct rcu_data *my_rdp)
nocb_gp_sleep(my_rdp, cpu);
} else {
rnp = my_rdp->mynode;
- trace_rcu_this_gp(rnp, my_rdp, wait_gp_seq, TPS("StartWait"));
+ trace_rcu_this_gp(rnp, wait_gp_seq, TPS("StartWait"));
swait_event_interruptible_exclusive(
rnp->nocb_gp_wq[rcu_seq_ctr(wait_gp_seq) & 0x1],
rcu_seq_done(&rnp->gp_seq, wait_gp_seq) ||
!READ_ONCE(my_rdp->nocb_gp_sleep));
- trace_rcu_this_gp(rnp, my_rdp, wait_gp_seq, TPS("EndWait"));
+ trace_rcu_this_gp(rnp, wait_gp_seq, TPS("EndWait"));
}
if (!rcu_nocb_poll) {
--
2.34.1
^ permalink raw reply [flat|nested] 10+ messages in thread* [PATCH v1 3/6] rcu: Remove unused func parameter from callback-enqueue functions
2026-07-18 17:15 [PATCH v1 0/6] RCU and torture fixes and cleanups Joel Fernandes
2026-07-18 17:15 ` [PATCH v1 1/6] rcu: Remove unused expedited_need_qs field from rcu_state Joel Fernandes
2026-07-18 17:15 ` [PATCH v1 2/6] rcu: Remove unused rdp parameter from trace_rcu_this_gp() Joel Fernandes
@ 2026-07-18 17:15 ` Joel Fernandes
2026-07-18 17:15 ` [PATCH v1 4/6] torture: Don't leak shuffle_tmp_mask when shuffler kthread fails to start Joel Fernandes
` (3 subsequent siblings)
6 siblings, 0 replies; 10+ messages in thread
From: Joel Fernandes @ 2026-07-18 17:15 UTC (permalink / raw)
To: linux-kernel, Paul E. McKenney, Frederic Weisbecker,
Neeraj Upadhyay, Joel Fernandes, Josh Triplett, Boqun Feng,
Uladzislau Rezki, Steven Rostedt, Mathieu Desnoyers,
Lai Jiangshan, Zqiang
Cc: rcu
Ever since the kvfree_rcu() tracing moved out of the callback-enqueue
path, rcutree_enqueue() no longer looks at the callback function
pointer: By the time it is invoked, __call_rcu_common() has already
stored the function into rhp->func, and the enqueue path only adds
the rcu_head to the segmented callback list and emits tracepoints
that do not take the function pointer.
Nevertheless, the function pointer is still threaded through
call_rcu_core(), call_rcu_nocb(), and rcutree_enqueue(), forcing
each level to carry a dead argument.
Remove the parameter from all three functions, from the no-CBs stub,
and from the corresponding declarations. Anything needing the
callback function can still get it from rhp->func.
No functional change.
Signed-off-by: Joel Fernandes <joelagnelf@nvidia.com>
---
kernel/rcu/tree.c | 10 +++++-----
kernel/rcu/tree.h | 2 +-
kernel/rcu/tree_nocb.h | 6 +++---
3 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c
index ef553189ee24..f741654e80e1 100644
--- a/kernel/rcu/tree.c
+++ b/kernel/rcu/tree.c
@@ -3020,7 +3020,7 @@ static int __init rcu_spawn_core_kthreads(void)
return 0;
}
-static void rcutree_enqueue(struct rcu_data *rdp, struct rcu_head *head, rcu_callback_t func)
+static void rcutree_enqueue(struct rcu_data *rdp, struct rcu_head *head)
{
rcu_segcblist_enqueue(&rdp->cblist, head);
trace_rcu_callback(rcu_state.name, head,
@@ -3032,9 +3032,9 @@ static void rcutree_enqueue(struct rcu_data *rdp, struct rcu_head *head, rcu_cal
* Handle any core-RCU processing required by a call_rcu() invocation.
*/
static void call_rcu_core(struct rcu_data *rdp, struct rcu_head *head,
- rcu_callback_t func, unsigned long flags)
+ unsigned long flags)
{
- rcutree_enqueue(rdp, head, func);
+ rcutree_enqueue(rdp, head);
/*
* If called from an extended quiescent state, invoke the RCU
* core in order to force a re-evaluation of RCU's idleness.
@@ -3175,9 +3175,9 @@ __call_rcu_common(struct rcu_head *head, rcu_callback_t func, bool lazy_in)
check_cb_ovld(rdp);
if (unlikely(rcu_rdp_is_offloaded(rdp)))
- call_rcu_nocb(rdp, head, func, flags, lazy);
+ call_rcu_nocb(rdp, head, flags, lazy);
else
- call_rcu_core(rdp, head, func, flags);
+ call_rcu_core(rdp, head, flags);
local_irq_restore(flags);
}
diff --git a/kernel/rcu/tree.h b/kernel/rcu/tree.h
index beb86e39909a..aaccc57e75b1 100644
--- a/kernel/rcu/tree.h
+++ b/kernel/rcu/tree.h
@@ -502,7 +502,7 @@ static bool wake_nocb_gp(struct rcu_data *rdp);
static bool rcu_nocb_flush_bypass(struct rcu_data *rdp, struct rcu_head *rhp,
unsigned long j, bool lazy);
static void call_rcu_nocb(struct rcu_data *rdp, struct rcu_head *head,
- rcu_callback_t func, unsigned long flags, bool lazy);
+ unsigned long flags, bool lazy);
static void __maybe_unused __call_rcu_nocb_wake(struct rcu_data *rdp, bool was_empty,
unsigned long flags);
static int rcu_nocb_need_deferred_wakeup(struct rcu_data *rdp, int level);
diff --git a/kernel/rcu/tree_nocb.h b/kernel/rcu/tree_nocb.h
index c4a5b4662b3a..9e5757e6f875 100644
--- a/kernel/rcu/tree_nocb.h
+++ b/kernel/rcu/tree_nocb.h
@@ -603,13 +603,13 @@ static void __call_rcu_nocb_wake(struct rcu_data *rdp, bool was_alldone,
}
static void call_rcu_nocb(struct rcu_data *rdp, struct rcu_head *head,
- rcu_callback_t func, unsigned long flags, bool lazy)
+ unsigned long flags, bool lazy)
{
bool was_alldone;
if (!rcu_nocb_try_bypass(rdp, head, &was_alldone, flags, lazy)) {
/* Not enqueued on bypass but locked, do regular enqueue */
- rcutree_enqueue(rdp, head, func);
+ rcutree_enqueue(rdp, head);
__call_rcu_nocb_wake(rdp, was_alldone, flags); /* unlocks */
}
}
@@ -1666,7 +1666,7 @@ static bool rcu_nocb_flush_bypass(struct rcu_data *rdp, struct rcu_head *rhp,
}
static void call_rcu_nocb(struct rcu_data *rdp, struct rcu_head *head,
- rcu_callback_t func, unsigned long flags, bool lazy)
+ unsigned long flags, bool lazy)
{
WARN_ON_ONCE(1); /* Should be dead code! */
}
--
2.34.1
^ permalink raw reply [flat|nested] 10+ messages in thread* [PATCH v1 4/6] torture: Don't leak shuffle_tmp_mask when shuffler kthread fails to start
2026-07-18 17:15 [PATCH v1 0/6] RCU and torture fixes and cleanups Joel Fernandes
` (2 preceding siblings ...)
2026-07-18 17:15 ` [PATCH v1 3/6] rcu: Remove unused func parameter from callback-enqueue functions Joel Fernandes
@ 2026-07-18 17:15 ` Joel Fernandes
2026-07-18 17:15 ` [PATCH v1 5/6] scftorture: Count single_rpc offline failures in statistics output Joel Fernandes
` (2 subsequent siblings)
6 siblings, 0 replies; 10+ messages in thread
From: Joel Fernandes @ 2026-07-18 17:15 UTC (permalink / raw)
To: linux-kernel, Davidlohr Bueso, Paul E. McKenney, Josh Triplett
Cc: Joel Fernandes
If torture_shuffle_init() successfully allocates shuffle_tmp_mask but
then fails to create the torture_shuffle kthread, the cpumask is never
freed.
Free the cpumask directly on the kthread-creation error path.
Signed-off-by: Joel Fernandes <joelagnelf@nvidia.com>
---
kernel/torture.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/kernel/torture.c b/kernel/torture.c
index 77cb3589b19f..8c4e6b2fe8ba 100644
--- a/kernel/torture.c
+++ b/kernel/torture.c
@@ -577,6 +577,8 @@ static int torture_shuffle(void *arg)
*/
int torture_shuffle_init(long shuffint)
{
+ int ret;
+
shuffle_interval = shuffint;
shuffle_idle_cpu = -1;
@@ -587,7 +589,10 @@ int torture_shuffle_init(long shuffint)
}
/* Create the shuffler thread */
- return torture_create_kthread(torture_shuffle, NULL, shuffler_task);
+ ret = torture_create_kthread(torture_shuffle, NULL, shuffler_task);
+ if (ret)
+ free_cpumask_var(shuffle_tmp_mask);
+ return ret;
}
EXPORT_SYMBOL_GPL(torture_shuffle_init);
--
2.34.1
^ permalink raw reply [flat|nested] 10+ messages in thread* [PATCH v1 5/6] scftorture: Count single_rpc offline failures in statistics output
2026-07-18 17:15 [PATCH v1 0/6] RCU and torture fixes and cleanups Joel Fernandes
` (3 preceding siblings ...)
2026-07-18 17:15 ` [PATCH v1 4/6] torture: Don't leak shuffle_tmp_mask when shuffler kthread fails to start Joel Fernandes
@ 2026-07-18 17:15 ` Joel Fernandes
2026-07-18 17:17 ` Joel Fernandes
2026-07-18 17:15 ` [PATCH v1 6/6] scftorture: Make invoker threads actually wait for all threads to start Joel Fernandes
2026-07-20 15:52 ` [PATCH v1 0/6] RCU and torture fixes and cleanups Paul E. McKenney
6 siblings, 1 reply; 10+ messages in thread
From: Joel Fernandes @ 2026-07-18 17:15 UTC (permalink / raw)
To: linux-kernel; +Cc: Joel Fernandes
scf_torture_stats_print() aggregates each invoker thread's counters
into a local scf_statistics structure before printing, but the
n_single_rpc_ofl field is missing from the aggregation loop. As a
result, the "single_rpc_ofl" value printed in the statistics line is
always zero, even when smp_call_function_single() invocations for the
RPC test have failed due to offline CPUs and been counted by the
invoker threads.
Add the missing accumulation so that the printed value reflects the
actual counts.
Signed-off-by: Joel Fernandes <joelagnelf@nvidia.com>
---
kernel/scftorture.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/kernel/scftorture.c b/kernel/scftorture.c
index 327c315f411c..ffd6c83732ee 100644
--- a/kernel/scftorture.c
+++ b/kernel/scftorture.c
@@ -193,6 +193,7 @@ static void scf_torture_stats_print(void)
scfs.n_single += scf_stats_p[i].n_single;
scfs.n_single_ofl += scf_stats_p[i].n_single_ofl;
scfs.n_single_rpc += scf_stats_p[i].n_single_rpc;
+ scfs.n_single_rpc_ofl += scf_stats_p[i].n_single_rpc_ofl;
scfs.n_single_wait += scf_stats_p[i].n_single_wait;
scfs.n_single_wait_ofl += scf_stats_p[i].n_single_wait_ofl;
scfs.n_many += scf_stats_p[i].n_many;
--
2.34.1
^ permalink raw reply [flat|nested] 10+ messages in thread* Re: [PATCH v1 5/6] scftorture: Count single_rpc offline failures in statistics output
2026-07-18 17:15 ` [PATCH v1 5/6] scftorture: Count single_rpc offline failures in statistics output Joel Fernandes
@ 2026-07-18 17:17 ` Joel Fernandes
0 siblings, 0 replies; 10+ messages in thread
From: Joel Fernandes @ 2026-07-18 17:17 UTC (permalink / raw)
To: linux-kernel, Paul E . McKenney, RCU
Some reason my scripting missed rcu list for these last 2 patches. But they
are on the lkml list :) sorry.
Adding back rcu@.
On 7/18/2026 1:15 PM, Joel Fernandes wrote:
> scf_torture_stats_print() aggregates each invoker thread's counters
> into a local scf_statistics structure before printing, but the
> n_single_rpc_ofl field is missing from the aggregation loop. As a
> result, the "single_rpc_ofl" value printed in the statistics line is
> always zero, even when smp_call_function_single() invocations for the
> RPC test have failed due to offline CPUs and been counted by the
> invoker threads.
>
> Add the missing accumulation so that the printed value reflects the
> actual counts.
>
> Signed-off-by: Joel Fernandes <joelagnelf@nvidia.com>
> ---
> kernel/scftorture.c | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/kernel/scftorture.c b/kernel/scftorture.c
> index 327c315f411c..ffd6c83732ee 100644
> --- a/kernel/scftorture.c
> +++ b/kernel/scftorture.c
> @@ -193,6 +193,7 @@ static void scf_torture_stats_print(void)
> scfs.n_single += scf_stats_p[i].n_single;
> scfs.n_single_ofl += scf_stats_p[i].n_single_ofl;
> scfs.n_single_rpc += scf_stats_p[i].n_single_rpc;
> + scfs.n_single_rpc_ofl += scf_stats_p[i].n_single_rpc_ofl;
> scfs.n_single_wait += scf_stats_p[i].n_single_wait;
> scfs.n_single_wait_ofl += scf_stats_p[i].n_single_wait_ofl;
> scfs.n_many += scf_stats_p[i].n_many;
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v1 6/6] scftorture: Make invoker threads actually wait for all threads to start
2026-07-18 17:15 [PATCH v1 0/6] RCU and torture fixes and cleanups Joel Fernandes
` (4 preceding siblings ...)
2026-07-18 17:15 ` [PATCH v1 5/6] scftorture: Count single_rpc offline failures in statistics output Joel Fernandes
@ 2026-07-18 17:15 ` Joel Fernandes
2026-07-18 17:17 ` Joel Fernandes
2026-07-20 15:52 ` [PATCH v1 0/6] RCU and torture fixes and cleanups Paul E. McKenney
6 siblings, 1 reply; 10+ messages in thread
From: Joel Fernandes @ 2026-07-18 17:15 UTC (permalink / raw)
To: linux-kernel; +Cc: Joel Fernandes
Each scftorture_invoker() thread decrements n_started, which is
initialized to the number of threads, and is then supposed to wait
until all of its siblings have also checked in before starting the
test proper. However, the wait loop is guarded by
!atomic_dec_return(&n_started), which is true only for the final
thread to arrive, and by then n_started is already zero, so the
final thread does not wait either. The side-effect (possibly positive)
is that no thread ever waits and the start-synchronization barrier is
dead code, with early threads beginning to hammer smp_call_function*()
while later threads are still being spawned.
Invert the test so that every thread other than the last spins until
n_started reaches zero, making the threads start testing together as
intended. The existing torture_must_stop() check in the wait loop
continues to bound the wait during shutdown.
We can also drop the spinning entirely if the intent is to leave it as
dead code, however for the current intent, this patches fixes the code.
Signed-off-by: Joel Fernandes <joelagnelf@nvidia.com>
---
kernel/scftorture.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/kernel/scftorture.c b/kernel/scftorture.c
index ffd6c83732ee..392df1b4d4ed 100644
--- a/kernel/scftorture.c
+++ b/kernel/scftorture.c
@@ -497,7 +497,7 @@ static int scftorture_invoker(void *arg)
"%s: Wanted CPU %d, running on %d, nr_cpu_ids = %d\n",
__func__, scfp->cpu, curcpu, nr_cpu_ids);
- if (!atomic_dec_return(&n_started))
+ if (atomic_dec_return(&n_started))
while (atomic_read_acquire(&n_started)) {
if (torture_must_stop()) {
VERBOSE_SCFTORTOUT("scftorture_invoker %d ended before starting", scfp->cpu);
--
2.34.1
^ permalink raw reply [flat|nested] 10+ messages in thread* Re: [PATCH v1 6/6] scftorture: Make invoker threads actually wait for all threads to start
2026-07-18 17:15 ` [PATCH v1 6/6] scftorture: Make invoker threads actually wait for all threads to start Joel Fernandes
@ 2026-07-18 17:17 ` Joel Fernandes
0 siblings, 0 replies; 10+ messages in thread
From: Joel Fernandes @ 2026-07-18 17:17 UTC (permalink / raw)
To: linux-kernel, RCU, Paul E . McKenney
Some reason my scripting missed rcu list for these last 2 patches. But they
are on the lkml list :) sorry.
Adding back rcu@.
On 7/18/2026 1:15 PM, Joel Fernandes wrote:
> Each scftorture_invoker() thread decrements n_started, which is
> initialized to the number of threads, and is then supposed to wait
> until all of its siblings have also checked in before starting the
> test proper. However, the wait loop is guarded by
> !atomic_dec_return(&n_started), which is true only for the final
> thread to arrive, and by then n_started is already zero, so the
> final thread does not wait either. The side-effect (possibly positive)
> is that no thread ever waits and the start-synchronization barrier is
> dead code, with early threads beginning to hammer smp_call_function*()
> while later threads are still being spawned.
>
> Invert the test so that every thread other than the last spins until
> n_started reaches zero, making the threads start testing together as
> intended. The existing torture_must_stop() check in the wait loop
> continues to bound the wait during shutdown.
>
> We can also drop the spinning entirely if the intent is to leave it as
> dead code, however for the current intent, this patches fixes the code.
>
> Signed-off-by: Joel Fernandes <joelagnelf@nvidia.com>
> ---
> kernel/scftorture.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/kernel/scftorture.c b/kernel/scftorture.c
> index ffd6c83732ee..392df1b4d4ed 100644
> --- a/kernel/scftorture.c
> +++ b/kernel/scftorture.c
> @@ -497,7 +497,7 @@ static int scftorture_invoker(void *arg)
> "%s: Wanted CPU %d, running on %d, nr_cpu_ids = %d\n",
> __func__, scfp->cpu, curcpu, nr_cpu_ids);
>
> - if (!atomic_dec_return(&n_started))
> + if (atomic_dec_return(&n_started))
> while (atomic_read_acquire(&n_started)) {
> if (torture_must_stop()) {
> VERBOSE_SCFTORTOUT("scftorture_invoker %d ended before starting", scfp->cpu);
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v1 0/6] RCU and torture fixes and cleanups
2026-07-18 17:15 [PATCH v1 0/6] RCU and torture fixes and cleanups Joel Fernandes
` (5 preceding siblings ...)
2026-07-18 17:15 ` [PATCH v1 6/6] scftorture: Make invoker threads actually wait for all threads to start Joel Fernandes
@ 2026-07-20 15:52 ` Paul E. McKenney
6 siblings, 0 replies; 10+ messages in thread
From: Paul E. McKenney @ 2026-07-20 15:52 UTC (permalink / raw)
To: Joel Fernandes
Cc: linux-kernel, Frederic Weisbecker, Neeraj Upadhyay,
Josh Triplett, Boqun Feng, Uladzislau Rezki, Steven Rostedt,
Mathieu Desnoyers, Lai Jiangshan, Zqiang, Davidlohr Bueso, rcu
On Sat, Jul 18, 2026 at 01:15:31PM -0400, Joel Fernandes wrote:
> This series contains miscellaneous RCU cleanups and torture-test fixes for the
> next merge window. Tested various rcutorture and scftorture scenarios.
>
> The git tree with all patches can be found at:
> git://git.kernel.org/pub/scm/linux/kernel/git/jfern/linux.git (tag: rcu-torture-simple-fixes-v1-20260718)
Good catches! Applied for further review and testing, thank you!
Thanx, Paul
> Joel Fernandes (6):
> rcu: Remove unused expedited_need_qs field from rcu_state
> rcu: Remove unused rdp parameter from trace_rcu_this_gp()
> rcu: Remove unused func parameter from callback-enqueue functions
> torture: Don't leak shuffle_tmp_mask when shuffler kthread fails to
> start
> scftorture: Count single_rpc offline failures in statistics output
> scftorture: Make invoker threads actually wait for all threads to
> start
>
> kernel/rcu/tree.c | 33 +++++++++++++++------------------
> kernel/rcu/tree.h | 3 +--
> kernel/rcu/tree_nocb.h | 10 +++++-----
> kernel/scftorture.c | 3 ++-
> kernel/torture.c | 7 ++++++-
> 5 files changed, 29 insertions(+), 27 deletions(-)
>
>
> base-commit: a13c140cc289c0b7b3770bce5b3ad42ab35074aa
> --
> 2.34.1
^ permalink raw reply [flat|nested] 10+ messages in thread