RCU tests patches for v7.5
Subsystems (10)
cover RCU tests patches for v7.5
This series has the RCU tests patches for the v7.5 merge window.
Fu Wenxin (1):
rcutorture: Fix busted_srcud crash on module unload
Joel Fernandes (5):
kasan: Avoid an unrelated RCU warning in the callback test
rcuscale: Consolidate per-writer arrays into struct writer_state
scftorture: Reject empty workloads before starting helpers
scftorture: Protect the initial affinity check from hotplug
torture: Forgive SMT-control failures in CPU-hotplug testing
Kunwu Chan (3):
Documentation/litmus-tests: Add SRCU fastpath anchor-before-scan test Documentation/litmus-tests: Add SRCU fastpath scan-before-anchor test
rcuscale: Add srcua scale type
Paul E. McKenney (2):
rcutorture: Enable RCU_BOOST where supported
rcutorture: Disable RCU priority boost testing on non-TREE03 scenarios
Zqiang (3):
rcutorture: Fix suspicious rcu_dereference_check() usage for
trivial-preempt
rcutorture: Make tasks-tracing support duplicate call testing
rcutorture: Avoid create fwd_prog_tasks for tasks-rude and srcu-atomic
Signature · 1 line
2.54.0
PATCH 1/14 Documentation/litmus-tests: Add SRCU fastpath anchor-before-scan test
From: Kunwu Chan <[email protected]>
synchronize_srcu_atomic() may end its grace period immediately when its scan of the per-CPU lock counters finds no readers. Correctness requires the grace-period anchor written by srcu_gp_start() to precede the smp_mb() ordering the lock scan. This ordering ensures that any reader whose lock increment is missed by the scan cannot have incremented its lock counter before the grace-period anchor, and therefore cannot be a pre-existing reader of this grace period.
This litmus test models the key ordering between the grace-period anchor and the lock counter scan, where "seq" models the grace-period anchor in ->srcu_gp_seq and "ctr" models the per-CPU ->srcu_ctrs[].srcu_locks counter. P0 writes the anchor before the smp_mb() and the lock scan. P1 models the reader-side counter increment. P2 models an observer that sees the reader's increment before seeing the anchor.
The outcome is forbidden by LKMM, and herd7 reports "Never". See SRCU-fastpath-scan-before-anchor.litmus for the reversed ordering, which permits this outcome.
Tested with herd7 7.58 using linux-kernel.cfg.
--- .../SRCU-fastpath-anchor-before-scan.litmus | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 Documentation/litmus-tests/srcu/SRCU-fastpath-anchor-before-scan.litmus
Documentation/litmus-tests/srcu/SRCU-fastpath-anchor-before-scan.litmus new file +55 -0
@@ -0,0 +1,55 @@ +C SRCU-fastpath-anchor-before-scan + +(* + * Result: Never + * + * The synchronize_srcu_atomic() fastpath may end its grace period + * immediately when its scan of the per-CPU lock counters finds no + * readers. Correctness requires the grace-period anchor written by + * srcu_gp_start() to precede the smp_mb() ordering the lock scan. + * This ordering ensures that any reader whose lock increment is missed + * by the scan cannot have incremented its lock counter before the + * grace-period anchor, and therefore cannot be a pre-existing reader + * of this grace period. + * + * This litmus test models the key ordering between the grace-period + * anchor and the lock counter scan, where "seq" models the + * grace-period anchor in ->srcu_gp_seq and "ctr" models the per-CPU + * ->srcu_ctrs[].srcu_locks counter. P0 writes the anchor before the + * smp_mb() and the lock scan. P1 models the reader-side counter + * increment. P2 models an observer that sees the reader's increment + * before seeing the anchor. + * + * The outcome is forbidden by LKMM, and herd7 reports "Never". See + * SRCU-fastpath-scan-before-anchor.litmus for the reversed ordering, + * which permits this outcome. + *) + +{} + +P0(int *seq, int *ctr) +{ + int r2; + + WRITE_ONCE(*seq, 1); + smp_mb(); + r2 = READ_ONCE(*ctr); +} + +P1(int *ctr) +{ + WRITE_ONCE(*ctr, 1); +} + +P2(int *seq, int *ctr) +{ + int r3; + int r4; + + r3 = READ_ONCE(*ctr); + smp_mb(); + r4 = READ_ONCE(*seq); +} + +filter (0:r2 = 0) +exists (2:r3 = 1 /\ 2:r4 = 0)
Signature · 1 line
2.54.0
PATCH 2/14 Documentation/litmus-tests: Add SRCU fastpath scan-before-anchor test
In reply to Joel FernandesFrom: Kunwu Chan <[email protected]>
If the synchronize_srcu_atomic() fastpath instead places its lock scan before the grace-period anchor, the scan can miss a reader whose increment was already visible before the anchor. That reader already existed when the grace period started, so completing the grace period without waiting for it would violate the SRCU grace-period guarantee.
This litmus test models the reversed ordering, with the lock scan placed before the grace-period anchor. "seq" models the grace-period anchor in ->srcu_gp_seq and "ctr" models the per-CPU ->srcu_ctrs[].srcu_locks counter. P0 scans the lock counter before writing the anchor, with an smp_mb() between them. P1 models the reader-side counter increment. P2 models an observer that sees the reader's increment before seeing the anchor.
The same outcome is allowed with this ordering, and herd7 reports "Sometimes". The litmus-tests README is also updated to describe both SRCU fastpath tests.
Tested with herd7 7.58 using linux-kernel.cfg.
--- Documentation/litmus-tests/README | 19 +++++++ .../SRCU-fastpath-scan-before-anchor.litmus | 52 +++++++++++++++++++ 2 files changed, 71 insertions(+) create mode 100644 Documentation/litmus-tests/srcu/SRCU-fastpath-scan-before-anchor.litmus
Documentation/litmus-tests/README +19 -0
@@ -78,3 +78,22 @@ RCU+sync+read.litmus RCU+sync+free.litmus Both the above litmus tests demonstrate the RCU grace period guarantee that an RCU read-side critical section can never span a grace period. + +SRCU (/srcu directory) +---------------------- + +SRCU-fastpath-anchor-before-scan.litmus + This models the synchronize_srcu_atomic() fastpath with the + grace-period anchor ordered before the lock-counter scan. This + ordering prevents readers that existed before the grace period + from being missed by the scan. See + SRCU-fastpath-scan-before-anchor.litmus for the reversed + ordering. + +SRCU-fastpath-scan-before-anchor.litmus + This models the synchronize_srcu_atomic() fastpath with the + lock-counter scan ordered before the grace-period anchor. This + permits the scan to miss readers that existed before the grace + period, violating the SRCU grace-period guarantee. See + SRCU-fastpath-anchor-before-scan.litmus for the opposite + ordering.
Documentation/litmus-tests/srcu/SRCU-fastpath-scan-before-anchor.litmus new file +52 -0
52 lines not on this page · raw message
Signature · 1 line
2.54.0
PATCH 3/14 kasan: Avoid an unrelated RCU warning in the callback test
In reply to Joel Fernandesrcu_uaf() passes a false protection condition to rcu_dereference_protected(), which produces a suspicious-RCU-usage warning before the intended KASAN failure occurs.
The pointer refers to a fresh allocation that has not been published to readers. State that protection condition explicitly, leaving the intended tests intact.
Test:
Built with CONFIG_KASAN_KUNIT_TEST=m
Booted Qemu guest (8 CPUs), ran modprobe kasan_test filtered to kasan.*rcu_uaf*
--- mm/kasan/kasan_test_c.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
mm/kasan/kasan_test_c.c +2 -1
@@ -967,8 +967,9 @@ static void rcu_uaf(struct kunit *test) ptr = kmalloc_obj(struct kasan_rcu_info);KUNIT_ASSERT_NOT_ERR_OR_NULL (test, ptr); +/* The freshly allocated object has not been published to readers. */ global_rcu_ptr =rcu_dereference_protected ( - (struct kasan_rcu_info __rcu *)ptr,NULL ); + (struct kasan_rcu_info __rcu *)ptr, true);KUNIT_EXPECT_KASAN_FAIL_READ (test, call_rcu(&global_rcu_ptr->rcu, rcu_uaf_reclaim);
Signature · 1 line
2.54.0
PATCH 4/14 rcutorture: Fix busted_srcud crash on module unload
In reply to Joel FernandesFrom: Fu Wenxin <[email protected]>
Commit e4ed20c1603c ("rcutorture: Exercise DEFINE_STATIC_SRCU_FAST() and init_srcu_struct_fast()") split SRCU torture initialization into two
helpers: srcu_torture_init(), which now only points srcu_ctlp at the static srcu_ctl/srcu_ctlf/srcu_ctlfud structures, and the new srcud_torture_init(), which calls init_srcu_struct(&srcu_ctld) for the dynamically allocated srcu_ctld.
That commit updated srcud_ops to use srcud_torture_init(), but left busted_srcud_ops pairing .init = srcu_torture_init (static srcu_ctl) with .cleanup = srcu_torture_cleanup (which unconditionally calls cleanup_srcu_struct(&srcu_ctld)). As a result srcu_ctld is never initialized when running torture_type=busted_srcud, yet it is torn down at module unload.
cleanup_srcu_struct() then dereferences ssp->srcu_sup, which is still NULL for the zero-initialized srcu_ctld, and faults on the ->lock field accessed by raw_spin_lock_irq_rcu_node():
Unable to handle kernel paging request at virtual address dfff80000000001b ... el1_abort -> do_translation_fault -> do_bad_area -> die_kernel_fault
(The fault address is the KASAN shadow of NULL + offsetof(srcu_usage, lock) == 0xd8.)
This is trivially reproducible:
modprobe rcutorture torture_type=busted_srcud
sleep 45
rmmod rcutorture # panic here
Fix it by making busted_srcud_ops initialize the same srcu_ctld that its cleanup handler tears down, matching srcud_ops.
--- kernel/rcu/rcutorture.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/rcu/rcutorture.c +1 -1
@@ -1055,7 +1055,7 @@ static struct rcu_torture_ops srcud_ops = {/* As above, but broken due to inappropriate reader extension. */ static struct rcu_torture_ops busted_srcud_ops = { .ttype =SRCU_FLAVOR , - .init = srcu_torture_init, + .init = srcud_torture_init, .cleanup = srcu_torture_cleanup, .readlock = srcu_torture_read_lock, .read_delay = rcu_read_delay,
Signature · 1 line
2.54.0
PATCH 5/14 rcutorture: Fix suspicious rcu_dereference_check() usage for trivial-preempt
In reply to Joel FernandesFrom: Zqiang <[email protected]>
Running the trivial-preempt flavor triggers a lockdep "suspicious RCU usage" warning from rcu_torture_one_read_start():
WARNING: suspicious RCU usagekernel/rcu/rcutorture.c:2581 suspicious rcu_dereference_check() usage!
...lockdep_rcu_suspiciousrcu_torture_one_read_startrcu_torture_one_readrcu_torture_reader
The trivial-preempt flavor .readlock_held is set to torture_readlock_not_held(), which check RCU-bh/RCU-sched critical sections. however, it's read lock just increments current->rcu_trivial_preempt_nesting, it's not also RCU read critical sections. the rcu_dereference_check() condition is therefore false, and lockdep report warnings. this commit therefore drop .readlock_held callback to avoid this lockdep warnings.
--- kernel/rcu/rcutorture.c | 1 - 1 file changed, 1 deletion(-)
kernel/rcu/rcutorture.c +0 -1
@@ -1164,7 +1164,6 @@ static struct rcu_torture_ops trivial_preempt_ops = { .readlock = rcu_torture_read_lock_trivial_preempt, .read_delay = rcu_read_delay, // just reuse rcu's version. .readunlock = rcu_torture_read_unlock_trivial_preempt, - .readlock_held = torture_readlock_not_held, .get_gp_seq = rcu_no_completed, .sync = synchronize_rcu_trivial_preempt, .exp_sync = synchronize_rcu_trivial_preempt,
Signature · 1 line
2.54.0
PATCH 6/14 rcutorture: Make tasks-tracing support duplicate call testing
In reply to Joel FernandesFrom: Zqiang <[email protected]>
Currently, Tasks-tracing has been reimplemented by SRCU-fast, it supports the detection of duplicate calls with CONFIG_DEBUG_OBJECTS_RCU_HEAD=y. This commit therefore set tasks_tracing_ops.debug_objects to 1, enabling rcutorture's duplicate-call test for the tasks-tracing flavor.
[Joel: On this branch, object_debug=1 already invokes the duplicate-call test. This records the flavor's duplicate-detection capability rather than adding a runtime test gate.]
--- kernel/rcu/rcutorture.c | 1 + 1 file changed, 1 insertion(+)
kernel/rcu/rcutorture.c +1 -0
@@ -1313,6 +1313,7 @@ static struct rcu_torture_ops tasks_tracing_ops = { .irq_capable = 1, .slow_gps = 1, .nmi_capable = 1, + .debug_objects = 1, .name = "tasks-tracing" };
Signature · 1 line
2.54.0
PATCH 7/14 rcutorture: Avoid create fwd_prog_tasks for tasks-rude and srcu-atomic
In reply to Joel FernandesFrom: Zqiang <[email protected]>
When running the tasks-rude and srcu-atomic tests, the fwd_prog_tasks kthread is created because the default value of fwd_progress is 1. however, the two RCU flavors not support ->call():
1. tasks-rude: commit b428a9de9bba ("rcutorture: Stop testing RCU Tasks Rude asynchronous APIs") removed .call and .cb_barrier from tasks-rude, but left the .cbflood_max = 50000.
2. srcu-atomic: srcu_torture_init_forbidden_apis() sets ->call to NULL for SRCU_READ_FLAVOR_ATOMIC runs, but leaves ->cbflood_max untouched.
In both cases, the non-zero ->cbflood_max fools the check above into creating the fwd_prog_tasks kthreads, even though those kthreads cannot possibly carry out any forward-progress test:
1. The rcu_torture_fwd_prog_cr() returns immediately due to cur_ops->call is NULL:
[ 68.022674] rcu_torture_fwd_prog_cr: No ->call(), so no forward-progress test 0 [ 129.462046] rcu_torture_fwd_prog_cr: No ->call(), so no forward-progress test 0 [ 190.902123] rcu_torture_fwd_prog_cr: No ->call(), so no forward-progress test 0 [ 252.343809] rcu_torture_fwd_prog_cr: No ->call(), so no forward-progress test 0
2. The rcu_torture_fwd_prog_nr() is never even invoked, because its caller requires cur_ops->stall_dur, and neither tasks-rude nor srcu-atomic provide ->stall_dur (only rcu_ops does).
Therefore, creating fwd_prog_tasks kthreads is pointless, this commit adds ->call and ->cb_barrier to the forward-progress check, rejecting flavors that lack the cbflood_max set and a positive ->stall_dur.
simple verification output:
[ 3.062959][ T1] srcu-torture: rcu_torture_fwd_prog_init: Disabled, unsupported by RCU flavor under test [ 2.922323][ T1] tasks-rude-torture: rcu_torture_fwd_prog_init: Disabled, unsupported by RCU flavor under test
--- kernel/rcu/rcutorture.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)
kernel/rcu/rcutorture.c +2 -3
@@ -4007,9 +4007,8 @@ static int __init rcu_torture_fwd_prog_init(void) }else if (fwd_progress <0 ) { fwd_progress = nr_cpu_ids; } -if ((!cur_ops->sync && !cur_ops->call) || - (!cur_ops->cbflood_max && (!cur_ops->stall_dur || cur_ops->stall_dur () <=0 )) || - cur_ops == &rcu_busted_ops) { +if (!cur_ops->sync || ((!cur_ops->call || !cur_ops->cb_barrier || !cur_ops->cbflood_max) && + (!cur_ops->stall_dur || cur_ops->stall_dur () <=0 ))) {VERBOSE_TOROUT_STRING ("rcu_torture_fwd_prog_init: Disabled, unsupported by RCU flavor under test" ); fwd_progress =0 ;return 0 ;
Signature · 1 line
2.54.0
PATCH 8/14 rcuscale: Consolidate per-writer arrays into struct writer_state
In reply to Joel FernandesThe writer kthreads keep their state in five parallel arrays indexed by writer number: writer_tasks, writer_durations, writer_n_durations, writer_done and writer_freelists. Each must be allocated, NULL-checked, freed and cleared separately, and the cleanup path needs several guards to cope with any one of them being missing.
Collapse them into a single array of struct writer_state, holding the task pointer, the duration buffer, the measurement count, the done flag and the existing struct writer_freelist.
This reduces initialization to one allocation and one out-of-memory check, and cleanup to a single kfree(). As a side effect, this also fixes a leak: cleanup only ran its frees under "if (writer_tasks)", so if the writer_tasks allocation failed while a later allocation (for example writer_durations or writer_n_durations) still succeeded, those already-allocated arrays were never freed. With a single allocation, that partial-allocation state can no longer occur.
--- kernel/rcu/rcuscale.c | 125 ++++++++++++++++++------------------------ 1 file changed, 54 insertions(+), 71 deletions(-)
kernel/rcu/rcuscale.c +54 -71
@@ -115,17 +115,21 @@ struct writer_freelist {struct writer_mblock *ws_mblocks; }; +struct writer_state { +struct writer_freelist wst_fl; +struct task_struct *wst_task; +u64 *wst_durations; +int wst_n_durations; +bool wst_done; +}; +static int nrealreaders;static int nrealwriters;static int nrealexp; -static struct task_struct **writer_tasks;static struct task_struct **reader_tasks;static struct task_struct **exp_tasks; -static u64 **writer_durations; -static bool *writer_done; -static struct writer_freelist *writer_freelists; -static int *writer_n_durations; +static struct writer_state *writer_states;static atomic_t n_rcu_scale_reader_started;static atomic_t n_rcu_scale_writer_started;static atomic_t n_rcu_scale_writer_finished;
@@ -504,9 +508,9 @@ static struct writer_mblock *rcu_scale_alloc(long me)struct writer_freelist *wflp;struct writer_mblock *wmbp; -if (WARN_ON_ONCE (!writer_freelists)) +if (WARN_ON_ONCE (!writer_states))return NULL ; - wflp = &writer_freelists[me]; + wflp = &writer_states[me].wst_fl;if (llist_empty (&wflp->ws_lhp)) {// ->ws_lhp is private to its rcu_scale_writer task. wmbp = container_of(llist_del_all(&wflp->ws_lhg), struct writer_mblock, wmb_node);
@@ -560,8 +564,9 @@ rcu_scale_writer(void *arg)u64 t;DEFINE_TORTURE_RANDOM (tr);u64 *wdp; -u64 *wdpp = writer_durations[me]; -struct writer_freelist *wflp = &writer_freelists[me]; +struct writer_state *wsp = &writer_states[me]; +u64 *wdpp = wsp->wst_durations; +struct writer_freelist *wflp = &wsp->wst_fl;struct writer_mblock *wmbp =NULL ;VERBOSE_SCALEOUT_STRING ("rcu_scale_writer task started" );
@@ -631,7 +636,7 @@ rcu_scale_writer(void *arg) started = true;if (!done && i >=MIN_MEAS &&time_after (jiffies, jdone)) { done = true; -WRITE_ONCE (writer_done[me], true); +WRITE_ONCE (wsp->wst_done, true);sched_set_normal (current,0 );pr_alert ("%s%s rcu_scale_writer %ld has %d measurements\n" , scale_type,SCALE_FLAG , me,MIN_MEAS );
@@ -649,7 +654,7 @@ rcu_scale_writer(void *arg) cur_ops->get_gp_seq (); }if (shutdown_secs) { - writer_tasks[me] =NULL ; + wsp->wst_task =NULL ;smp_mb ();/* Assign before wake. */ rcu_scale_cleanup ();kernel_power_off ();
@@ -665,10 +670,10 @@ rcu_scale_writer(void *arg)if (!atomic_xchg (&dumped,1 )) {for (i =0 ; i < nrealwriters; i++) { -if (writer_done[i]) +if (writer_states[i].wst_done)continue ;pr_info ("%s: Task %ld flags writer %d:\n" , __func__, me, i); -sched_show_task (writer_tasks[i]); +sched_show_task (writer_states[i].wst_task); }if (cur_ops->stats) cur_ops->stats ();
@@ -676,7 +681,7 @@ rcu_scale_writer(void *arg) }if (!selfreport &&time_after (jiffies, jdone +HZ * (70 + me))) {pr_info ("%s: Writer %ld self-report: started %d done %d/%d->%d i %d jdone %lu.\n" , - __func__, me, started, done, writer_done[me],atomic_read (&n_rcu_scale_writer_finished), i, jiffies - jdone); + __func__, me, started, done, wsp->wst_done,atomic_read (&n_rcu_scale_writer_finished), i, jiffies - jdone); selfreport = true; }if (gp_succeeded && started && !alldone && i <MAX_MEAS -1 )
@@ -687,7 +692,7 @@ rcu_scale_writer(void *arg)rcu_scale_free (wmbp); cur_ops->gp_barrier (); } - writer_n_durations[me] = i_max +1 ; + wsp->wst_n_durations = i_max +1 ;torture_kthread_stopping ("rcu_scale_writer" );return 0 ; }
@@ -1031,13 +1036,11 @@ rcu_scale_cleanup(void) reader_tasks =NULL ; } -if (writer_tasks) { +if (writer_states) {for (i =0 ; i < nrealwriters; i++) {torture_stop_kthread (rcu_scale_writer, - writer_tasks[i]); -if (!writer_n_durations) -continue ; - j = writer_n_durations[i]; + writer_states[i].wst_task); + j = writer_states[i].wst_n_durations;pr_alert ("%s%s writer %d gps: %d\n" , scale_type,SCALE_FLAG , i, j); ngps += j;
@@ -1051,14 +1054,12 @@ rcu_scale_cleanup(void)rcuscale_seq_diff (b_rcu_gp_test_finished, b_rcu_gp_test_started));for (i =0 ; i < nrealwriters; i++) { -if (!writer_durations) -break ; -if (!writer_n_durations) -continue ; - wdpp = writer_durations[i]; +struct writer_state *wsp = &writer_states[i]; + + wdpp = wsp->wst_durations;if (!wdpp)continue ; -for (j =0 ; j < writer_n_durations[i]; j++) { +for (j =0 ; j < wsp->wst_n_durations; j++) { wdp = &wdpp[j]; pr_alert("%s%s %4d writer-duration: %5d %llu\n", scale_type, SCALE_FLAG,
@@ -1066,34 +1067,23 @@ rcu_scale_cleanup(void)if (j %100 ==0 )schedule_timeout_uninterruptible (1 ); } -kfree (writer_durations[i]); -if (writer_freelists) { +kfree (wdpp); +if (wsp->wst_fl.ws_mblocks) {int ctr =0 ;struct llist_node *llnp; -struct writer_freelist *wflp = &writer_freelists[i]; -if (wflp->ws_mblocks) { -llist_for_each (llnp, wflp->ws_lhg.first) - ctr++; -llist_for_each (llnp, wflp->ws_lhp.first) - ctr++; -WARN_ONCE (ctr != gp_async_max, -"%s: ctr = %d gp_async_max = %d\n" , - __func__, ctr, gp_async_max); -kfree (wflp->ws_mblocks); - } +llist_for_each (llnp, wsp->wst_fl.ws_lhg.first) + ctr++; +llist_for_each (llnp, wsp->wst_fl.ws_lhp.first) + ctr++; +WARN_ONCE (ctr != gp_async_max, +"%s: ctr = %d gp_async_max = %d\n" , + __func__, ctr, gp_async_max); +kfree (wsp->wst_fl.ws_mblocks); } } -kfree (writer_tasks); - writer_tasks =NULL ; -kfree (writer_durations); - writer_durations =NULL ; -kfree (writer_n_durations); - writer_n_durations =NULL ; -kfree (writer_done); - writer_done =NULL ; -kfree (writer_freelists); - writer_freelists =NULL ; +kfree (writer_states); + writer_states =NULL ; }/* Do torture-type-specific cleanup operations. */
@@ -1187,36 +1177,29 @@ rcu_scale_init(void) goto unwind; } } - writer_tasks =kzalloc_objs (writer_tasks[0 ], nrealwriters); - writer_durations =kzalloc_objs (*writer_durations, nrealwriters); - writer_n_durations =kzalloc_objs (*writer_n_durations, nrealwriters); - writer_done =kzalloc_objs (writer_done[0 ], nrealwriters); -if (gp_async) { -if (gp_async_max <=0 ) { -pr_warn ("%s: gp_async_max = %d must be greater than zero.\n" , - __func__, gp_async_max); -WARN_ON_ONCE (IS_BUILTIN (CONFIG_RCU_TORTURE_TEST )); - firsterr = -EINVAL ; - goto unwind; - } - writer_freelists =kzalloc_objs (writer_freelists[0 ], - nrealwriters); + writer_states =kzalloc_objs (writer_states[0 ], nrealwriters); +if (gp_async && gp_async_max <=0 ) { +pr_warn ("%s: gp_async_max = %d must be greater than zero.\n" , + __func__, gp_async_max); +WARN_ON_ONCE (IS_BUILTIN (CONFIG_RCU_TORTURE_TEST )); + firsterr = -EINVAL ; + goto unwind; } -if (!writer_tasks || !writer_durations || !writer_n_durations || !writer_done || - (gp_async && !writer_freelists)) { +if (!writer_states) {SCALEOUT_ERRSTRING ("out of memory" ); firsterr = -ENOMEM ; goto unwind; }for (i =0 ; i < nrealwriters; i++) { - writer_durations[i] = -kzalloc_objs (*writer_durations[i],MAX_MEAS ); -if (!writer_durations[i]) { +struct writer_state *wsp = &writer_states[i]; + + wsp->wst_durations =kzalloc_objs (*wsp->wst_durations,MAX_MEAS ); +if (!wsp->wst_durations) { firsterr = -ENOMEM ; goto unwind; } -if (writer_freelists) { -struct writer_freelist *wflp = &writer_freelists[i]; +if (gp_async) { +struct writer_freelist *wflp = &wsp->wst_fl;init_llist_head (&wflp->ws_lhg);init_llist_head (&wflp->ws_lhp);
@@ -1234,7 +1217,7 @@ rcu_scale_init(void) } } firsterr =torture_create_kthread (rcu_scale_writer, (void *)i, - writer_tasks[i]); + wsp->wst_task);if (torture_init_error (firsterr)) goto unwind; }
Signature · 1 line
2.54.0
PATCH 9/14 rcuscale: Add srcua scale type
In reply to Joel FernandesFrom: Kunwu Chan <[email protected]>
Add support for scaling atomic SRCU grace periods using srcu_read_lock_atomic()/srcu_read_unlock_atomic() and synchronize_srcu_atomic().
--- kernel/rcu/rcuscale.c | 41 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-)
kernel/rcu/rcuscale.c +40 -1
@@ -297,6 +297,44 @@ static struct rcu_scale_ops srcud_ops = { .name = "srcud" }; +static struct srcu_struct srcua; + +static int srcu_scale_atomic_read_lock (void ) +{ +return srcu_read_lock_atomic (srcu_ctlp); +} + +static void srcu_scale_atomic_read_unlock (int idx) +{ +srcu_read_unlock_atomic (srcu_ctlp, idx); +} + +static void srcu_scale_atomic_synchronize (void ) +{ +synchronize_srcu_atomic (srcu_ctlp); +} + +static void srcu_atomic_scale_init (void ) +{ + srcu_ctlp = &srcua; +init_srcu_struct_atomic (srcu_ctlp); +} + +static struct rcu_scale_ops srcua_ops = { + .ptype =SRCU_FLAVOR , + .init = srcu_atomic_scale_init, + .cleanup = srcu_sync_scale_cleanup, + .readlock = srcu_scale_atomic_read_lock, + .readunlock = srcu_scale_atomic_read_unlock, + .get_gp_seq = srcu_scale_completed, + .gp_diff = rcu_seq_diff, + .exp_completed = srcu_scale_completed, + .sync = srcu_scale_atomic_synchronize, + .exp_sync = srcu_scale_atomic_synchronize, + .stats = srcu_scale_stats, + .name ="srcua" +}; +#ifdef CONFIG_TASKS_RCU /*
@@ -1100,7 +1138,8 @@ rcu_scale_init(void)long i;long j;static struct rcu_scale_ops *scale_ops[] = { - &rcu_ops, &srcu_ops, &srcud_ops, TASKS_OPS TASKS_RUDE_OPS TASKS_TRACING_OPS + &rcu_ops, &srcu_ops, &srcua_ops, &srcud_ops, + TASKS_OPS TASKS_RUDE_OPS TASKS_TRACING_OPS };if (!torture_init_begin (scale_type, verbose))
Signature · 1 line
2.54.0
PATCH 10/14 scftorture: Reject empty workloads before starting helpers
In reply to Joel FernandesA module loaded with nthreads=0 starts its statistics task, but cleanup skips stopping that task. Unloading the module then leaves it executing freed module text. Reject a zero thread count before starting helpers; negative counts still select the online CPU count.
Also, when built as a module with reschedule-only, this leaves the selector empty because resched_cpu() is unavailable to modules. It warns while selecting an operation, invokes no callbacks, and can nevertheless report SUCCESS. Reject an empty effective selector after filtering unsupported operations.
Both failures were reproduced in a guest without the patches.
--- kernel/scftorture.c | 11 +++++++++++ 1 file changed, 11 insertions(+)
kernel/scftorture.c +11 -0
@@ -588,6 +588,12 @@ static int __init scf_torture_init(void)scftorture_print_module_parms ("Start of test" ); +if (!nthreads) { +SCFTORTOUT_ERRSTRING ("nthreads must be nonzero" ); + firsterr = -EINVAL ; + goto unwind; + } + if (weight_resched <= 0 && weight_single <= 0 && weight_single_rpc <= 0 && weight_single_wait <= 0 && weight_many <= 0 && weight_many_wait <= 0 &&
@@ -636,6 +642,11 @@ static int __init scf_torture_init(void)scf_sel_add (weight_many_wait1,SCF_PRIM_MANY , true);scf_sel_add (weight_all1,SCF_PRIM_ALL , false);scf_sel_add (weight_all_wait1,SCF_PRIM_ALL , true); +if (!scf_sel_array_len) { +SCFTORTOUT_ERRSTRING ("no supported operations selected" ); + firsterr = -EINVAL ; + goto unwind; + }scf_sel_dump ();if (onoff_interval >0 ) {
Signature · 1 line
2.54.0
PATCH 11/14 scftorture: Protect the initial affinity check from hotplug
In reply to Joel FernandesAn invoker binds to its target CPU, sleeps for the holdoff interval, and then warns if it is running elsewhere. CPU hotplug can offline the target during that sleep and legitimately move the invoker. A built-in test with matching worker and hotplug holdoffs reproduces this warning.
Check the initial binding while holding cpus_read_lock(), before sleeping. If the target is already offline, let the existing offline/rebind path handle it instead of warning about an impossible initial binding. Release the read lock before the holdoff and test loop so hotplug remains tested.
--- kernel/scftorture.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-)
kernel/scftorture.c +12 -7
@@ -479,19 +479,24 @@ static int scftorture_invoker(void *arg)VERBOSE_SCFTORTOUT ("scftorture_invoker %d: task started" , scfp->cpu); cpu = scfp->cpu % nr_cpu_ids; -WARN_ON_ONCE (set_cpus_allowed_ptr (current,cpumask_of (cpu))); +cpus_read_lock (); +if (cpu_online (cpu)) { +WARN_ON_ONCE (set_cpus_allowed_ptr (current,cpumask_of (cpu))); +/* Check affinity before hotplug can move this task away. */ + curcpu =raw_smp_processor_id (); +WARN_ONCE (curcpu != cpu, +"%s: Wanted CPU %d, running on %d, nr_cpu_ids = %d\n" , + __func__, scfp->cpu, curcpu, nr_cpu_ids); + }else { + was_offline = true; + } +cpus_read_unlock ();set_user_nice (current,MAX_NICE );if (holdoff)schedule_timeout_interruptible (holdoff *HZ );VERBOSE_SCFTORTOUT ("scftorture_invoker %d: Waiting for all SCF torturers from cpu %d" , scfp->cpu,raw_smp_processor_id ()); -// Make sure that the CPU is affinitized appropriately during testing. - curcpu =raw_smp_processor_id (); -WARN_ONCE (curcpu != cpu, -"%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))while (atomic_read_acquire (&n_started)) {if (torture_must_stop ()) {
Signature · 1 line
2.54.0
PATCH 12/14 rcutorture: Enable RCU_BOOST where supported
In reply to Joel FernandesFrom: "Paul E. McKenney" <[email protected]>
Currently, RCU_BOOST depends on RCU_EXPERT, and is therefore often disabled in stress-test such as those run by syzbot. This means that if syzbot runs a test that overloads CPUs on kernels built with PREEMPT_RCU, RCU CPU stall warnings are not unexpected. What happens is that a low-priority task in an RCU read-side critical section is preempted, cannot be priority boosted, and stays that way for more than 21 seconds.
This commit therefore drops RCU_EXPERT from the RCU_BOOST "depends on" line and removes the prompt, thus directly driving RCU_BOOST from the kernel configuration so as to enable it anywhere it is supported and might help.
This commit is also marked experimental because neither Ubuntu, Fedora, nor CentOS enable RCU_BOOST. This suggests less testing of RCU priority boosting than one might wish.
--- kernel/rcu/Kconfig | 10 ++++------ tools/testing/selftests/rcutorture/configs/rcu/NOCB01 | 1 - tools/testing/selftests/rcutorture/configs/rcu/NOCB02 | 1 - tools/testing/selftests/rcutorture/configs/rcu/TREE01 | 1 - tools/testing/selftests/rcutorture/configs/rcu/TREE02 | 1 - tools/testing/selftests/rcutorture/configs/rcu/TREE08 | 1 - .../testing/selftests/rcutorture/configs/rcuscale/TINY | 1 - .../selftests/rcutorture/configs/rcuscale/TRACE01 | 1 - .../testing/selftests/rcutorture/configs/rcuscale/TREE | 1 - .../selftests/rcutorture/configs/rcuscale/TREE54 | 1 - .../selftests/rcutorture/configs/refscale/NOPREEMPT | 1 - .../selftests/rcutorture/configs/refscale/PREEMPT | 1 - .../testing/selftests/rcutorture/configs/refscale/TINY | 1 - 13 files changed, 4 insertions(+), 18 deletions(-)
kernel/rcu/Kconfig +4 -6
@@ -238,17 +238,15 @@ config RCU_FANOUT_LEAF Take the default if unsure. config RCU_BOOST - bool "Enable RCU priority boosting" - depends on (RT_MUTEXES && PREEMPT_RCU && RCU_EXPERT) || PREEMPT_RT - default y if PREEMPT_RT + bool + default y if (RT_MUTEXES && PREEMPT_RCU) || PREEMPT_RT help This option boosts the priority of preempted RCU readers that block the current preemptible RCU grace period for too long. This option also prevents heavy loads from blocking RCU - callback invocation. + callback invocation. It is now automatically enabled in + any kernel that can benefit from it and that can support it. - Say Y here if you are working with real-time apps or heavy loads - Say N here if you are unsure. config RCU_BOOST_DELAY int "Milliseconds to delay boosting after RCU grace-period start"
tools/testing/selftests/rcutorture/configs/rcu/NOCB01 +0 -1
@@ -14,7 +14,6 @@ CONFIG_RCU_FANOUT_LEAF=2 CONFIG_RCU_NOCB_CPU=y CONFIG_DEBUG_LOCK_ALLOC=n CONFIG_PROVE_LOCKING=n -CONFIG_RCU_BOOST=n CONFIG_DEBUG_OBJECTS_RCU_HEAD=n CONFIG_RCU_EXPERT=y CONFIG_RCU_EQS_DEBUG=y
tools/testing/selftests/rcutorture/configs/rcu/NOCB02 +0 -1
@@ -14,7 +14,6 @@ CONFIG_RCU_FANOUT_LEAF=2 CONFIG_RCU_NOCB_CPU=y CONFIG_DEBUG_LOCK_ALLOC=n CONFIG_PROVE_LOCKING=n -CONFIG_RCU_BOOST=n CONFIG_DEBUG_OBJECTS_RCU_HEAD=n CONFIG_RCU_EXPERT=y CONFIG_RCU_EQS_DEBUG=y
tools/testing/selftests/rcutorture/configs/rcu/TREE01 +0 -1
@@ -10,6 +10,5 @@ CONFIG_RCU_TRACE=y CONFIG_HOTPLUG_CPU=y CONFIG_RCU_NOCB_CPU=y CONFIG_DEBUG_LOCK_ALLOC=n -CONFIG_RCU_BOOST=n CONFIG_DEBUG_OBJECTS_RCU_HEAD=n CONFIG_RCU_EXPERT=y
tools/testing/selftests/rcutorture/configs/rcu/TREE02 +0 -1
@@ -13,7 +13,6 @@ CONFIG_RCU_FANOUT_LEAF=3 CONFIG_RCU_NOCB_CPU=n CONFIG_DEBUG_LOCK_ALLOC=y CONFIG_PROVE_LOCKING=n -CONFIG_RCU_BOOST=n CONFIG_RCU_EXPERT=y CONFIG_DEBUG_OBJECTS=y CONFIG_DEBUG_OBJECTS_RCU_HEAD=y
tools/testing/selftests/rcutorture/configs/rcu/TREE08 +0 -1
@@ -13,7 +13,6 @@ CONFIG_RCU_FANOUT_LEAF=2 CONFIG_RCU_NOCB_CPU=y CONFIG_DEBUG_LOCK_ALLOC=n CONFIG_PROVE_LOCKING=n -CONFIG_RCU_BOOST=n CONFIG_DEBUG_OBJECTS_RCU_HEAD=n CONFIG_RCU_EXPERT=y CONFIG_RCU_EQS_DEBUG=y
tools/testing/selftests/rcutorture/configs/rcuscale/TINY +0 -1
@@ -11,7 +11,6 @@ CONFIG_NO_HZ_FULL=n CONFIG_RCU_NOCB_CPU=n CONFIG_DEBUG_LOCK_ALLOC=n CONFIG_PROVE_LOCKING=n -CONFIG_RCU_BOOST=n CONFIG_DEBUG_OBJECTS_RCU_HEAD=n CONFIG_RCU_EXPERT=y CONFIG_RCU_TRACE=y
tools/testing/selftests/rcutorture/configs/rcuscale/TRACE01 +0 -1
@@ -11,7 +11,6 @@ CONFIG_NO_HZ_FULL=n CONFIG_RCU_NOCB_CPU=n CONFIG_DEBUG_LOCK_ALLOC=n CONFIG_PROVE_LOCKING=n -CONFIG_RCU_BOOST=n CONFIG_DEBUG_OBJECTS_RCU_HEAD=n CONFIG_RCU_EXPERT=y CONFIG_RCU_TRACE=y
tools/testing/selftests/rcutorture/configs/rcuscale/TREE +0 -1
@@ -12,7 +12,6 @@ CONFIG_HIBERNATION=n CONFIG_RCU_NOCB_CPU=n CONFIG_DEBUG_LOCK_ALLOC=n CONFIG_PROVE_LOCKING=n -CONFIG_RCU_BOOST=n CONFIG_DEBUG_OBJECTS_RCU_HEAD=n CONFIG_RCU_EXPERT=y CONFIG_RCU_TRACE=y
tools/testing/selftests/rcutorture/configs/rcuscale/TREE54 +0 -1
@@ -15,7 +15,6 @@ CONFIG_RCU_FANOUT_LEAF=2 CONFIG_RCU_NOCB_CPU=n CONFIG_DEBUG_LOCK_ALLOC=n CONFIG_PROVE_LOCKING=n -CONFIG_RCU_BOOST=n CONFIG_DEBUG_OBJECTS_RCU_HEAD=n CONFIG_RCU_EXPERT=y CONFIG_RCU_TRACE=y
tools/testing/selftests/rcutorture/configs/refscale/NOPREEMPT +0 -1
@@ -14,7 +14,6 @@ CONFIG_HIBERNATION=n CONFIG_RCU_NOCB_CPU=n CONFIG_DEBUG_LOCK_ALLOC=n CONFIG_PROVE_LOCKING=n -CONFIG_RCU_BOOST=n CONFIG_DEBUG_OBJECTS_RCU_HEAD=n CONFIG_RCU_EXPERT=y CONFIG_KPROBES=n
tools/testing/selftests/rcutorture/configs/refscale/PREEMPT +0 -1
@@ -12,6 +12,5 @@ CONFIG_HIBERNATION=n CONFIG_RCU_NOCB_CPU=n CONFIG_DEBUG_LOCK_ALLOC=n CONFIG_PROVE_LOCKING=n -CONFIG_RCU_BOOST=n CONFIG_DEBUG_OBJECTS_RCU_HEAD=n CONFIG_RCU_EXPERT=y
tools/testing/selftests/rcutorture/configs/refscale/TINY +0 -1
@@ -14,7 +14,6 @@ CONFIG_HIBERNATION=n CONFIG_RCU_NOCB_CPU=n CONFIG_DEBUG_LOCK_ALLOC=n CONFIG_PROVE_LOCKING=n -CONFIG_RCU_BOOST=n CONFIG_DEBUG_OBJECTS_RCU_HEAD=n CONFIG_RCU_EXPERT=y CONFIG_KPROBES=n
Signature · 1 line
2.54.0
[email protected]
AI reviewRe: [PATCH for-v7.5 12/14] rcutorture: Enable RCU_BOOST where supported
Thank you for your contribution! Sashiko AI review found 3 potential issues to consider: - [Medium] rcutorture: promptless RCU_BOOST default y breaks BUSTED-BOOST negative test - [Medium]…
Thank you for your contribution! Sashiko AI review found 3 potential issues to consider:
- [Medium] rcutorture: promptless RCU_BOOST default y breaks BUSTED-BOOST negative test
- [Medium] rcutorture: unintended rcu_torture_boost() activation in NOCB01 and NOCB02
- [Low] rcu: Kconfig exposes RCU_BOOST_DELAY prompt when RCU_EXPERT=n --
commit d21fbe9cdf60a4b081f0f993ea961ee602b93a2c
Author: Paul E. McKenney <[email protected]>
rcutorture: Enable RCU_BOOST where supported
This commit drops the RCU_EXPERT dependency and prompt from RCU_BOOST so that it is automatically enabled whenever RT_MUTEXES and PREEMPT_RCU (or PREEMPT_RT) are enabled, and removes CONFIG_RCU_BOOST=n from rcutorture config fragments.
kernel/rcu/Kconfig config RCU_FANOUT_LEAF · line 241
Quoted 13 lines
kernel/rcu/Kconfig +2
-3@@ -237,17 +237,15 @@ config RCU_FANOUT_LEAF Take the default if unsure. config RCU_BOOST - bool "Enable RCU priority boosting" - depends on (RT_MUTEXES && PREEMPT_RCU && RCU_EXPERT) || PREEMPT_RT - default y if PREEMPT_RT + bool + default y if (RT_MUTEXES && PREEMPT_RCU) || PREEMPT_RT
[Severity: Medium]
Does making RCU_BOOST a promptless symbol that defaults to y break the BUSTED-BOOST rcutorture negative test added in d4240d628f98 ("rcutorture:
Add BUSTED-BOOST to test RCU priority boosting tests")?
BUSTED-BOOST sets CONFIG_PREEMPT=y (selecting CONFIG_PREEMPT_RCU=y) and passes rcutorture.test_boost=2 so rcu_torture_can_boost() runs the boost test on a kernel with CONFIG_RCU_BOOST=n to verify boost-failure detection. With this change, BUSTED-BOOST builds with CONFIG_RCU_BOOST=y and cannot override it in its config fragment, so priority boosting is active and the negative test passes instead of failing.
kernel/rcu/Kconfig config RCU_FANOUT_LEAF · line 252
Quoted 13 lines
kernel/rcu/Kconfig +2
-3help This option boosts the priority of preempted RCU readers that block the current preemptible RCU grace period for too long. This option also prevents heavy loads from blocking RCU - callback invocation. + callback invocation. It is now automatically enabled in + any kernel that can benefit from it and that can support it. - Say Y here if you are working with real-time apps or heavy loads - Say N here if you are unsure. config RCU_BOOST_DELAY int "Milliseconds to delay boosting after RCU grace-period start"
[Severity: Low]
Will enabling RCU_BOOST when CONFIG_RCU_EXPERT=n expose the RCU_BOOST_DELAY (and RCU_NOCB_CPU_CB_BOOST when NO_HZ_FULL selects RCU_NOCB_CPU) prompts during make oldconfig on non-expert configurations?
Both options depend on RCU_BOOST and have unconditional prompts that were previously hidden when RCU_EXPERT=n kept RCU_BOOST disabled. Since kernel/rcu/tree_plugin.h uses CONFIG_RCU_BOOST_DELAY unconditionally under #ifdef CONFIG_RCU_BOOST, gating their prompts with "if RCU_EXPERT" would keep the default value defined without prompting non-expert users.
Quoted 17 lines
tools/testing/selftests/rcutorture/configs/rcu/NOCB01 +0
-1@@ -14,7 +14,6 @@ CONFIG_RCU_FANOUT_LEAF=2 CONFIG_RCU_NOCB_CPU=y CONFIG_DEBUG_LOCK_ALLOC=n CONFIG_PROVE_LOCKING=n -CONFIG_RCU_BOOST=n CONFIG_DEBUG_OBJECTS_RCU_HEAD=n CONFIG_RCU_EXPERT=y CONFIG_RCU_EQS_DEBUG=ytools/testing/selftests/rcutorture/configs/rcu/NOCB02 +0
-0
tools/testing/selftests/rcutorture/configs/rcu/NOCB02 CONFIG_RCU_FANOUT_LEAF=2 · line 19
Quoted 7 lines
tools/testing/selftests/rcutorture/configs/rcu/NOCB02 +0
-1@@ -14,7 +14,6 @@ CONFIG_RCU_FANOUT_LEAF=2 CONFIG_RCU_NOCB_CPU=y CONFIG_DEBUG_LOCK_ALLOC=n CONFIG_PROVE_LOCKING=n -CONFIG_RCU_BOOST=n CONFIG_DEBUG_OBJECTS_RCU_HEAD=n CONFIG_RCU_EXPERT=y CONFIG_RCU_EQS_DEBUG=y
[Severity: Medium]
Does enabling CONFIG_RCU_BOOST=y in NOCB01 and NOCB02 unintentionally start rcu_torture_boost() stress threads on these scenarios?
With CONFIG_RCU_TORTURE_TEST=y and CONFIG_RCU_BOOST=y, sanitize_kthread_prio() raises kthread_prio to 2 and rcu_torture_can_boost() returns true by default, spawning per-CPU SCHED_FIFO rcu_torture_boost() threads on scenarios that leave rcuop kthreads at SCHED_NORMAL without CONFIG_RCU_NOCB_CPU_CB_BOOST=y. The follow-up commit "rcutorture: Disable RCU priority boost testing on non-TREE03 scenarios" adds rcutorture.test_boost=0 to TREE01, TREE02, TREE08, and TREE09, but omits NOCB01.boot and NOCB02.boot.
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=12
PATCH 13/14 rcutorture: Disable RCU priority boost testing on non-TREE03 scenarios
In reply to Joel FernandesFrom: "Paul E. McKenney" <[email protected]>
The TREE03 scenario has been configured to permit testing of RCU priority boosting, including setting RCU kthead priorities to 2. But now that RCU priority boosting is default for preemptible kernels, it is now automatically tested for TREE01, TREE02, TREE08, and TREE09, none of which have RCU kthread priorities set up for such testing. One approach would be to set up these scenarios' kthread priorities, but this would fail to test common-case kernels having default priorities.
This commit therefore disables the testing of RCU priority boosting except on scenario TREE03, which is set up properly for this purpose, though rather unrealistically.
--- tools/testing/selftests/rcutorture/configs/rcu/TREE01.boot | 1 + tools/testing/selftests/rcutorture/configs/rcu/TREE02.boot | 1 + tools/testing/selftests/rcutorture/configs/rcu/TREE08.boot | 1 + tools/testing/selftests/rcutorture/configs/rcu/TREE09.boot | 1 + 4 files changed, 4 insertions(+) create mode 100644 tools/testing/selftests/rcutorture/configs/rcu/TREE09.boot
tools/testing/selftests/rcutorture/configs/rcu/TREE01.boot +1 -0
@@ -6,3 +6,4 @@ rcu_nocbs=0-1,3-7 rcutorture.nocbs_nthreads=8 rcutorture.nocbs_toggle=1000 rcutorture.fwd_progress=0 +rcutorture.test_boost=0
tools/testing/selftests/rcutorture/configs/rcu/TREE02.boot +1 -0
@@ -1 +1,2 @@ rcutorture.fwd_progress=2 +rcutorture.test_boost=0
tools/testing/selftests/rcutorture/configs/rcu/TREE08.boot +1 -0
@@ -1,3 +1,4 @@ rcupdate.rcu_self_test=1 rcutree.rcu_fanout_exact=1 rcu_nocbs=all +rcutorture.test_boost=0
tools/testing/selftests/rcutorture/configs/rcu/TREE09.boot new file +1 -0
@@ -0,0 +1 @@ +rcutorture.test_boost=0
Signature · 1 line
2.54.0
PATCH 14/14 torture: Forgive SMT-control failures in CPU-hotplug testing
In reply to Joel FernandesThe onoff task ends rcutorture with "End of test: RCU_HOTPLUG" if any CPU-hotplug attempt fails, other than -EBUSY during boot. Toggling /sys/devices/system/cpu/smt/control while onoff runs causes two failures that are not the test's fault. cpu_up() returns -EPERM for an SMT thread that SMT control keeps offline, and device_online() and device_offline() return 1 when the toggle already did the operation.
Repro: in a 16-vCPU guest (8 cores, 2 threads), run "modprobe rcutorture onoff_interval=1 gp_exp=0" while looping "echo off/on > smt/control" for 120 seconds. This ended in RCU_HOTPLUG, with no reader errors. With this change it ends in SUCCESS.
Forgive these like boot-time -EBUSY, by not counting the attempt.
--- kernel/torture.c | 40 ++++++++++++++++++++++++++++------------ 1 file changed, 28 insertions(+), 12 deletions(-)
kernel/torture.c +28 -12
@@ -194,6 +194,24 @@ int torture_num_online_cpus(void) }EXPORT_SYMBOL_GPL (torture_num_online_cpus); +/* +* If the CPU-hotplug failure is not the torture test's fault, return a +* string saying why it is forgiven. Otherwise, return NULL. +*/ +static const char *torture_onoff_forgive (int ret) +{ +// PCI probe frequently disables hotplug during boot. +if (!rcu_inkernel_boot_has_ended () && ret == -EBUSY ) +return " (-EBUSY forgiven during boot)" ; +// Hotplug is forbidden, for example by SMT control. +if (ret == -EPERM ) +return " (-EPERM forgiven, hotplug forbidden)" ; +// Something else, such as SMT control, already did the operation. +if (ret ==1 ) +return " (already in requested state, forgiven)" ; +return NULL ; +} +/* * Attempt to take a CPU offline. Return false if the CPU is already * offline or if it is not subject to CPU-hotplug operations. The
@@ -204,7 +222,7 @@ bool torture_offline(int cpu, long *n_offl_attempts, long *n_offl_successes, {unsigned long delta;int ret; -char *s; +const char *s;unsigned long starttime;if (!cpu_online (cpu) || !cpu_is_hotpluggable (cpu))
@@ -220,12 +238,11 @@ bool torture_offline(int cpu, long *n_offl_attempts, long *n_offl_successes, (*n_offl_attempts)++; ret =remove_cpu (cpu);if (ret) { - s ="" ; -if (!rcu_inkernel_boot_has_ended () && ret == -EBUSY ) { -// PCI probe frequently disables hotplug during boot. + s =torture_onoff_forgive (ret); +if (s) (*n_offl_attempts)--; - s =" (-EBUSY forgiven during boot)" ; - } +else + s ="" ;if (verbose) pr_alert("%s" TORTURE_FLAG "torture_onoff task: offline %d failed%s: errno %d\n",
@@ -266,7 +283,7 @@ bool torture_online(int cpu, long *n_onl_attempts, long *n_onl_successes, {unsigned long delta;int ret; -char *s; +const char *s;unsigned long starttime;if (cpu_online (cpu) || !cpu_is_hotpluggable (cpu))
@@ -280,12 +297,11 @@ bool torture_online(int cpu, long *n_onl_attempts, long *n_onl_successes, (*n_onl_attempts)++; ret =add_cpu (cpu);if (ret) { - s ="" ; -if (!rcu_inkernel_boot_has_ended () && ret == -EBUSY ) { -// PCI probe frequently disables hotplug during boot. + s =torture_onoff_forgive (ret); +if (s) (*n_onl_attempts)--; - s =" (-EBUSY forgiven during boot)" ; - } +else + s ="" ;if (verbose) pr_alert("%s" TORTURE_FLAG "torture_onoff task: online %d failed%s: errno %d\n",
Signature · 1 line
2.54.0
Quoted 1 line · Joel Fernandes
This series has the RCU tests patches for the v7.5 merge window.
Thanx for keeping my tags, mind changing my tags to my new email? If it doesn't pain you too much? New email change is a pain...
Quoted 20 lines
Fu Wenxin (1):
rcutorture: Fixbusted_srcudcrash on module unloadJoel Fernandes (5):
kasan: Avoid an unrelated RCU warning in the callback test
rcuscale: Consolidate per-writer arrays into structwriter_state
scftorture: Reject empty workloads before starting helpers
scftorture: Protect the initial affinity check from hotplug
torture: Forgive SMT-control failures in CPU-hotplug testingKunwu Chan (3):
Documentation/litmus-tests: Add SRCU fastpath anchor-before-scan testDocumentation/litmus-tests: Add SRCU fastpath scan-before-anchor test
rcuscale: Add srcua scale typePaul E. McKenney (2):
rcutorture: EnableRCU_BOOSTwhere supported
rcutorture: Disable RCU priority boost testing on non-TREE03 scenarios
Quoted 7 lines
Zqiang (3):
rcutorture: Fix suspiciousrcu_dereference_check()usage for
trivial-preempt
rcutorture: Make tasks-tracing support duplicate call testing
rcutorture: Avoid createfwd_prog_tasksfor tasks-rude and srcu-atomic
--- Thanks!
Quoted 10 lines · Bradley Morgan
Quoted 1 line · Joel Fernandes
This series has the RCU tests patches for the v7.5 merge window.
Thanx for keeping my tags, mind changing my tags to my new email? If it doesn't pain you too much? New email change is a pain...
Yes will do.
Quoted 29 lines
Quoted 20 lines
Fu Wenxin (1):
rcutorture: Fixbusted_srcudcrash on module unloadJoel Fernandes (5):
kasan: Avoid an unrelated RCU warning in the callback test
rcuscale: Consolidate per-writer arrays into structwriter_state
scftorture: Reject empty workloads before starting helpers
scftorture: Protect the initial affinity check from hotplug
torture: Forgive SMT-control failures in CPU-hotplug testingKunwu Chan (3):
Documentation/litmus-tests: Add SRCU fastpath anchor-before-scan testDocumentation/litmus-tests: Add SRCU fastpath scan-before-anchor test
rcuscale: Add srcua scale typePaul E. McKenney (2):
rcutorture: EnableRCU_BOOSTwhere supported
rcutorture: Disable RCU priority boost testing on non-TREE03 scenariosQuoted 7 lines
Zqiang (3):
rcutorture: Fix suspiciousrcu_dereference_check()usage for
trivial-preempt
rcutorture: Make tasks-tracing support duplicate call testing
rcutorture: Avoid createfwd_prog_tasksfor tasks-rude and srcu-atomic--- Thanks!