Torture-test changes for v4.20/v5.0
Subsystems (4)
cover Torture-test changes for v4.20/v5.0
Hello!
This series contains torture-test changes that can be reasonably separated from the RCU flavor consolidation and cleanup:
1. Stop overwriting Make.out file with obsolete version.
2. Force occasional reader waits to increase the probability
of quiescent states interacting with RCU's scheduler hooks.
3-4. Warn on bad torture type for built-in tests.
5. Remove TREE06 and TREE08 from the default test list, as they
are redundant after RCU flavor consolidation.
6. Add RCU-reader forward-progress tests for RCU grace periods.
7. Also use grace-period sequence numbers to judge forward progress.
8. Avoid forward-progress no-test complaint if too few
forward-progress tries.
9. Vary forward-progress test interval in order to exercise RCU's
varied forward-progress mechanisms.
10. Add self-propagating callback to forward-progress testing in
order to ensure that there is a reason for grace periods to exist in the first place, let alone make forward progress.
11. Increase rcu_read_delay() longdelay_ms in order to exercise
RCU's forward-progress machinery that kicks into gear at about 100 milliseconds into the grace period.
12. Limit reader duration if irq or bh disabled to avoid triggering
-rt bh-disabling complaints.
13. Reduce priority of forward-progress testing for !SMP kernels
and for PREEMPT kernels without RCU priority boosting.
14. Adjust number of reader kthreads per CPU-hotplug operations.
After all, having 32 readers is a great thing for a 32-CPU system, but not so much if 31 of the CPUs has been offlined.
15. Print forward-progress test interval on error.
16. Check grace-period completion at stutter end: If the system is
idle, grace periods should complete quickly.
17. Maintain self-propagating CB only during forward-progress test.
Thanx, Paul
------------------------------------------------------------------------
include/linux/rcutiny.h | 1 include/linux/torture.h | 2 kernel/rcu/rcuperf.c | 1 kernel/rcu/rcutorture.c | 188 +++++++++++++-- kernel/rcu/update.c | 1 kernel/torture.c | 3 tools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh | 1 tools/testing/selftests/rcutorture/configs/rcu/CFLIST | 2 8 files changed, 172 insertions(+), 27 deletions(-)
PATCH 1/17 torture: Stop overwriting Make.out file with obsolete version
The old approach placed all the build products into the b* directories, which meant that some of these build products needed to be copied to the proper directory in the res hierarchy. The new approach leaves things like .config and the .o files in the b1 directory, but directs build output and diagnostics directly to the proper directory in the res hierarchy. Unfortunately, one of the copies was still carried out, which could (and sometimes did) overwrite the build output and diagnostics with obsolete output remaining in the b1 directory.
This commit therefore removes the offending "cp" command.
--- tools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh | 1 - 1 file changed, 1 deletion(-)
tools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh +0 -1
@@ -120,7 +120,6 @@ then parse-build.sh $resdir/Make.out $title else # Build failed. - cp $builddir/Make*.out $resdir cp $builddir/.config $resdir || : echo Build failed, not running KVM, see $resdir. if test -f $builddir.wait
Signature · 1 line
2.17.1
PATCH 2/17 rcutorture: Force occasional reader waits
In reply to Paul E. McKenneyDeferred quiescent states can interact with the scheduler, but rcu_torture_reader() does not force such interaction all that frequently. This commit therefore blocks for one jiffy after ten jiffies of read-side runtime. This has the beneficial effect of being most likely to block just after long-running readers, and it is exactly these readers that are most likely to have been preempted (in CONFIG_PREEMPT=y kernels). This in turn helps increase the probability that a deferred quiescent state will be seen by RCU's context-switch hooks.
--- kernel/rcu/rcutorture.c | 5 +++++ 1 file changed, 5 insertions(+)
kernel/rcu/rcutorture.c +5 -0
@@ -1387,6 +1387,7 @@ static void rcu_torture_timer(struct timer_list *unused)static int rcu_torture_reader (void *arg) { +unsigned long lastsleep = jiffies;DEFINE_TORTURE_RANDOM (rand);struct timer_list t;
@@ -1402,6 +1403,10 @@ rcu_torture_reader(void *arg) }if (!rcu_torture_one_read (&rand))schedule_timeout_interruptible (HZ ); +if (time_after (jiffies, lastsleep)) { +schedule_timeout_interruptible (1 ); + lastsleep = jiffies +10 ; + }stutter_wait ("rcu_torture_reader" ); }while (!torture_must_stop ());if (irqreader && cur_ops->irq_capable) {
Signature · 1 line
2.17.1
PATCH 3/17 rcutorture: Warn on bad torture type for built-in tests
In reply to Paul E. McKenneyWhen running a built-in rcutorture test, specifying an invalid torture type results in what looks like a hard hang, with the error messages hidden by other boot-time output. This commit therefore executes a WARN_ON() in this case so that the splat appears just following the error messages.
--- kernel/rcu/rcutorture.c | 1 + 1 file changed, 1 insertion(+)
kernel/rcu/rcutorture.c +1 -0
@@ -1968,6 +1968,7 @@ rcu_torture_init(void)for (i =0 ; i <ARRAY_SIZE (torture_ops); i++)pr_cont (" %s" , torture_ops[i]->name);pr_cont ("\n" ); +WARN_ON (!IS_MODULE (CONFIG_RCU_TORTURE_TEST )); firsterr = -EINVAL ; goto unwind; }
Signature · 1 line
2.17.1
PATCH 4/17 rcuperf: Warn on bad perf type for built-in tests
In reply to Paul E. McKenneyWhen running a built-in rcuperf test, specifying an invalid perf type results in what looks like a hard hang, with the error messages hidden by other boot-time output. This commit therefore executes a WARN_ON() in this case so that the splat appears just following the error messages.
--- kernel/rcu/rcuperf.c | 1 + 1 file changed, 1 insertion(+)
kernel/rcu/rcuperf.c +1 -0
@@ -680,6 +680,7 @@ rcu_perf_init(void)for (i =0 ; i <ARRAY_SIZE (perf_ops); i++)pr_cont (" %s" , perf_ops[i]->name);pr_cont ("\n" ); +WARN_ON (!IS_MODULE (CONFIG_RCU_PERF_TEST )); firsterr = -EINVAL ; goto unwind; }
Signature · 1 line
2.17.1
PATCH 5/17 rcutorture: Remove TREE06 and TREE08 from the default test list
In reply to Paul E. McKenneyNow that there is only one RCU flavor to rule them all, the TREE06 and TREE08 test scenarios are redundant. This commit therefore removes them. Later changes will rebalance and renumber the tests.
--- tools/testing/selftests/rcutorture/configs/rcu/CFLIST | 2 -- 1 file changed, 2 deletions(-)
tools/testing/selftests/rcutorture/configs/rcu/CFLIST +0 -2
@@ -3,9 +3,7 @@ TREE02 TREE03 TREE04 TREE05 -TREE06 TREE07 -TREE08 TREE09 SRCU-N SRCU-P
Signature · 1 line
2.17.1
PATCH 6/17 rcutorture: Add forward-progress tests for RCU grace periods
In reply to Paul E. McKenneyThis commit adds a kthread that loops going into and out of RCU read-side critical sections, but also including a cond_resched(), optionally guarded by a check of need_resched(), in that same loop. This commit relies solely on rcu_torture_writer() progress to judge the forward progress of grace periods.
Note that Tasks RCU and SRCU are exempted from forward-progress testing due their (intentionally) less-robust forward-progress guarantees.
--- include/linux/rcutiny.h | 1 + kernel/rcu/rcutorture.c | 73 ++++++++++++++++++++++++++++++++++++++++- kernel/rcu/update.c | 1 + 3 files changed, 74 insertions(+), 1 deletion(-)
include/linux/rcutiny.h +1 -0
@@ -108,6 +108,7 @@ static inline int rcu_needs_cpu(u64 basemono, u64 *nextevt)*/ static inline void rcu_virt_note_context_switch (int cpu) { }static inline void rcu_cpu_stall_reset (void ) { } +static inline int rcu_jiffies_till_stall_check (void ) {return 21 *HZ ; }static inline void rcu_idle_enter (void ) { }static inline void rcu_idle_exit (void ) { }static inline void rcu_irq_enter (void ) { }
kernel/rcu/rcutorture.c +72 -1
121 lines not on this page · raw message
kernel/rcu/update.c +1 -0
@@ -472,6 +472,7 @@ int rcu_jiffies_till_stall_check(void) }return till_stall_check *HZ +RCU_STALL_DELAY_DELTA ; } +EXPORT_SYMBOL_GPL (rcu_jiffies_till_stall_check);void rcu_sysrq_start (void ) {
Signature · 1 line
2.17.1
PATCH 7/17 rcutorture: Also use GP sequence to judge forward progress
In reply to Paul E. McKenneyCurrently, rcutorture relies solely on the progress of rcu_torture_writer() to judge grace-period forward progress. In theory, this is the gold standard of forward progress, but in practice rcutorture separately detects and reports rcu_torture_writer() stalls. This commit therefore adds the grace-period sequence number (when provided) to the judgment of grace-period forward progress, which makes it easier to distinguish between failure of actual grace periods to progress on the one hand and downstream forward-progress failures on the other.
For example, given this change, if rcu_torture_writer() stalls, but rcu_torture_fwd_prog() does not complain, then the grace-period computation is working, which is a hint that the failure lies in callback processing, wakeup of the rcu_torture_writer() kthread, or similar.
--- kernel/rcu/rcutorture.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-)
kernel/rcu/rcutorture.c +7 -4
@@ -1673,7 +1673,8 @@ static int __init rcu_torture_stall_init(void)/* Carry out grace-period forward-progress testing. */ static int rcu_torture_fwd_prog (void *args) { -unsigned long cvar; +unsigned long cver; +unsigned long gps;int idx;unsigned long stopat;bool tested = false;
@@ -1681,7 +1682,8 @@ static int rcu_torture_fwd_prog(void *args)VERBOSE_TOROUT_STRING ("rcu_torture_fwd_progress task started" ); do { schedule_timeout_interruptible(fwd_progress_holdoff * HZ); - cvar = READ_ONCE(rcu_torture_current_version); + cver = READ_ONCE(rcu_torture_current_version); + gps = cur_ops->get_gp_seq(); stopat = jiffies + cur_ops->stall_dur() / fwd_progress_div; while (time_before(jiffies, stopat) && !torture_must_stop()) { idx = cur_ops->readlock();
@@ -1692,8 +1694,9 @@ static int rcu_torture_fwd_prog(void *args) }if (!time_before (jiffies, stopat) && !torture_must_stop ()) { tested = true; -WARN_ON_ONCE (cvar == -READ_ONCE (rcu_torture_current_version)); + cver = cver ==READ_ONCE (rcu_torture_current_version); + gps =rcutorture_seq_diff (cur_ops->get_gp_seq (), gps); +WARN_ON_ONCE (cver && gps <2 ); }/* Avoid slow periods, better to test when busy. */ stutter_wait ("rcu_torture_fwd_prog" );
Signature · 1 line
2.17.1
PATCH 8/17 rcutorture: Avoid no-test complaint if too few forward-progress tries
In reply to Paul E. McKenneyIn a too-short test, random delays can cause each attempt to do forward-progress testing to fail to complete, thus resulting in spurious splats. This commit therefore requires at least five tries before complaining about rcutorture runs that failed to produce at least one valid forward-progress testing attempt. Note that actual forward-progress failures will splat regardless of the number of tries.
--- kernel/rcu/rcutorture.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
kernel/rcu/rcutorture.c +4 -1
@@ -1678,6 +1678,7 @@ static int rcu_torture_fwd_prog(void *args)int idx;unsigned long stopat;bool tested = false; +int tested_tries =0 ;VERBOSE_TOROUT_STRING ("rcu_torture_fwd_progress task started" ); do {
@@ -1692,6 +1693,7 @@ static int rcu_torture_fwd_prog(void *args)if (!fwd_progress_need_resched ||need_resched ())cond_resched (); } + tested_tries++;if (!time_before (jiffies, stopat) && !torture_must_stop ()) { tested = true; cver = cver ==READ_ONCE (rcu_torture_current_version);
@@ -1701,7 +1703,8 @@ static int rcu_torture_fwd_prog(void *args)/* Avoid slow periods, better to test when busy. */ stutter_wait ("rcu_torture_fwd_prog" ); }while (!torture_must_stop ()); -WARN_ON (!tested); +/* Short runs might not contain a valid forward-progress attempt. */ +WARN_ON (!tested && tested_tries >=5 );torture_kthread_stopping ("rcu_torture_fwd_prog" );return 0 ; }
Signature · 1 line
2.17.1
PATCH 9/17 rcutorture: Vary forward-progress test interval
In reply to Paul E. McKenneySome of the Linux kernel's RCU implementations provide several mechanisms to promote forward progress that operate over different timeframes. This commit therefore causes rcu_torture_fwd_prog() to vary the duration of its forward-progress testing in order to test each such mechanism.
--- kernel/rcu/rcutorture.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
kernel/rcu/rcutorture.c +6 -1
@@ -1676,16 +1676,21 @@ static int rcu_torture_fwd_prog(void *args)unsigned long cver;unsigned long gps;int idx; +int sd; +int sd4;unsigned long stopat;bool tested = false;int tested_tries =0 ; +static DEFINE_TORTURE_RANDOM (trs);VERBOSE_TOROUT_STRING ("rcu_torture_fwd_progress task started" ); do { schedule_timeout_interruptible(fwd_progress_holdoff * HZ); cver = READ_ONCE(rcu_torture_current_version); gps = cur_ops->get_gp_seq(); - stopat = jiffies + cur_ops->stall_dur() / fwd_progress_div; + sd = cur_ops->stall_dur() + 1; + sd4 = (sd + fwd_progress_div - 1) / fwd_progress_div; + stopat = jiffies + sd4 + torture_random(&trs) % (sd - sd4); while (time_before(jiffies, stopat) && !torture_must_stop()) { idx = cur_ops->readlock(); udelay(10);
Signature · 1 line
2.17.1
PATCH 10/17 rcutorture: Add self-propagating callback to forward-progress testing
In reply to Paul E. McKenneyIf rcutorture is run on a quiet system with the rcutorture.stutter module parameter set high, then there can legitimately be an extended period during which no RCU forward progress takes place. This can result in false-positive no-forward-progress splats. This commit therefore makes rcu_torture_fwd_prog() create a self-propagating RCU callback to ensure that grace periods are in progress for the duration of the forward-progress test.
Note that the RCU flavor under test must define ->call(), ->sync(), and ->cb_barrier() for this self-propagating callback to be created. If one or more of those rcu_torture_ops fields are NULL, then the rcu_torture_fwd_prog() function will silently proceed without creating the self-propagating callback.
--- kernel/rcu/rcutorture.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+)
kernel/rcu/rcutorture.c +36 -0
@@ -1670,20 +1670,49 @@ static int __init rcu_torture_stall_init(void)return torture_create_kthread (rcu_torture_stall,NULL , stall_task); } +/* State structure for forward-progress self-propagating RCU callback. */ +struct fwd_cb_state { +struct rcu_head rh; +int stop; +}; + +/* +* Forward-progress self-propagating RCU callback function. Because +* callbacks run from softirq, this function is an implicit RCU read-side +* critical section. +*/ +static void rcu_torture_fwd_prog_cb (struct rcu_head *rhp) +{ + struct fwd_cb_state *fcsp = container_of(rhp, struct fwd_cb_state, rh); + +if (READ_ONCE (fcsp->stop)) { +WRITE_ONCE (fcsp->stop,2 ); +return ; + } + cur_ops->call (&fcsp->rh, rcu_torture_fwd_prog_cb); +} +/* Carry out grace-period forward-progress testing. */ static int rcu_torture_fwd_prog (void *args) {unsigned long cver; +struct fwd_cb_state fcs = { .stop =0 };unsigned long gps;int idx;int sd;int sd4; +bool selfpropcb = false;unsigned long stopat;bool tested = false;int tested_tries =0 ;static DEFINE_TORTURE_RANDOM (trs);VERBOSE_TOROUT_STRING ("rcu_torture_fwd_progress task started" ); +if (cur_ops->call && cur_ops->sync && cur_ops->cb_barrier) { +init_rcu_head_on_stack (&fcs.rh); + cur_ops->call (&fcs.rh, rcu_torture_fwd_prog_cb); + selfpropcb = true; + } do { schedule_timeout_interruptible(fwd_progress_holdoff * HZ); cver = READ_ONCE(rcu_torture_current_version);
@@ -1708,6 +1737,13 @@ static int rcu_torture_fwd_prog(void *args)/* Avoid slow periods, better to test when busy. */ stutter_wait ("rcu_torture_fwd_prog" ); }while (!torture_must_stop ()); +if (selfpropcb) { +WRITE_ONCE (fcs.stop,1 ); + cur_ops->sync ();/* Wait for running callback to complete. */ + cur_ops->cb_barrier ();/* Wait for queued callbacks. */ +WARN_ON (READ_ONCE (fcs.stop) !=2 ); +destroy_rcu_head_on_stack (&fcs.rh); + }/* Short runs might not contain a valid forward-progress attempt. */ WARN_ON (!tested && tested_tries >=5 );torture_kthread_stopping ("rcu_torture_fwd_prog" );
Signature · 1 line
2.17.1
PATCH 11/17 rcutorture: Increase rcu_read_delay() longdelay_ms
In reply to Paul E. McKenneyRCU now takes certain actions 100 and 200 milliseconds into a grace period by default, but rcutorture only runs RCU read-side critical sections with durations up to 50 milliseconds. This commit therefore increases test coverage by increasing the maximum critical-section duration to 300 milliseconds. Note that the existing code automatically dials down the probability of long delays based on the maximum duration, which means that this change should not significantly change the rate of execution of RCU read-side critical sections.
--- kernel/rcu/rcutorture.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/rcu/rcutorture.c +1 -1
@@ -323,7 +323,7 @@ static void rcu_read_delay(struct torture_random_state *rrsp)unsigned long started;unsigned long completed;const unsigned long shortdelay_us =200 ; -const unsigned long longdelay_ms =50 ; +const unsigned long longdelay_ms =300 ;unsigned long long ts;/* We want a short delay sometimes to make a reader delay the grace
Signature · 1 line
2.17.1
PATCH 12/17 rcutorture: Limit reader duration if irq or bh disabled
In reply to Paul E. McKenneyThere are debug checks in some environments that will complain if the duration of a bh-disabled region of code exceeds about 50 milliseconds. Because rcu_read_delay() can produce a 50-millisecond delay and because there could be up to eight reader segments with such delays, this commit limits the maximum delay to 10 milliseconds if either interrupts or softirqs are disabled.
--- kernel/rcu/rcutorture.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
kernel/rcu/rcutorture.c +3 -1
@@ -323,7 +323,7 @@ static void rcu_read_delay(struct torture_random_state *rrsp)unsigned long started;unsigned long completed;const unsigned long shortdelay_us =200 ; -const unsigned long longdelay_ms =300 ; +unsigned long longdelay_ms =300 ;unsigned long long ts;/* We want a short delay sometimes to make a reader delay the grace
@@ -333,6 +333,8 @@ static void rcu_read_delay(struct torture_random_state *rrsp)if (!(torture_random (rrsp) % (nrealreaders *2000 * longdelay_ms))) { started = cur_ops->get_gp_seq (); ts =rcu_trace_clock_local (); +if (preempt_count () & (SOFTIRQ_MASK |HARDIRQ_MASK )) + longdelay_ms =5 ;/* Avoid triggering BH limits. */ mdelay (longdelay_ms); completed = cur_ops->get_gp_seq (); do_trace_rcu_torture_read(cur_ops->name, NULL, ts,
Signature · 1 line
2.17.1
PATCH 13/17 rcutorture: Reduce priority of forward-progress testing
In reply to Paul E. McKenneyOn !SMP tests, the forward-progress kthread might prevent RCU's grace-period kthread from running, which would defeat RCU's forward-progress measures. On PREEMPT tests without RCU priority boosting, the forward-progress kthread might preempt a reader for an extended time period, which would also defeat RCU's forward-progress measures. This commit therefore reduced rcutorture's forward-progress kthread's priority in those cases.
--- kernel/rcu/rcutorture.c | 2 ++ 1 file changed, 2 insertions(+)
kernel/rcu/rcutorture.c +2 -0
@@ -1710,6 +1710,8 @@ static int rcu_torture_fwd_prog(void *args)static DEFINE_TORTURE_RANDOM (trs);VERBOSE_TOROUT_STRING ("rcu_torture_fwd_progress task started" ); +if (!IS_ENABLED (CONFIG_SMP ) || !IS_ENABLED (CONFIG_RCU_BOOST )) +set_user_nice (current,MAX_NICE );if (cur_ops->call && cur_ops->sync && cur_ops->cb_barrier) {init_rcu_head_on_stack (&fcs.rh); cur_ops->call (&fcs.rh, rcu_torture_fwd_prog_cb);
Signature · 1 line
2.17.1
PATCH 14/17 rcutorture: Adjust number of reader kthreads per CPU-hotplug operations
In reply to Paul E. McKenneyCurrently, rcutorture provisions rcu_torture_reader() kthreads based on the initial number of CPUs. This can be problematic when CPU hotplug is enabled, as a system with a very large number of CPUs will provision a very large number of rcu_torture_reader() kthreads. All of these kthreads will continue running even if the CPU-hotplug operations result in only one remaining online CPU. This can result in all sorts of strange artifacts due simply to massive overload.
This commit therefore causes the rcu_torture_reader() kthreads to start blocking as the number of online CPUs decreases. This is accomplished by numbering these kthreads, and having each check to make sure that the number of online CPUs is at least as large as its assigned number.
--- kernel/rcu/rcutorture.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
kernel/rcu/rcutorture.c +6 -2
@@ -1400,6 +1400,8 @@ static int rcu_torture_reader(void *arg) {unsigned long lastsleep = jiffies; +long myid = (long )arg; +int mynumonline = myid;DEFINE_TORTURE_RANDOM (rand);struct timer_list t;
@@ -1419,6 +1421,8 @@ rcu_torture_reader(void *arg)schedule_timeout_interruptible (1 ); lastsleep = jiffies +10 ; } +while (num_online_cpus () < mynumonline && !torture_must_stop ()) +schedule_timeout_interruptible (HZ /5 );stutter_wait ("rcu_torture_reader" ); }while (!torture_must_stop ());if (irqreader && cur_ops->irq_capable) {
@@ -2063,7 +2067,7 @@ static void rcu_test_debug_objects(void)static int __init rcu_torture_init (void ) { -int i; +long i;int cpu;int firsterr =0 ;static struct rcu_torture_ops *torture_ops[] = {
@@ -2169,7 +2173,7 @@ rcu_torture_init(void) goto unwind; }for (i =0 ; i < nrealreaders; i++) { - firsterr =torture_create_kthread (rcu_torture_reader,NULL , + firsterr =torture_create_kthread (rcu_torture_reader, (void *)i, reader_tasks[i]);if (firsterr) goto unwind;
Signature · 1 line
2.17.1
PATCH 15/17 rcutorture: Print forward-progress test interval on error
In reply to Paul E. McKenneyThis commit prints the duration of the forward-progress test interval in the case that no forward progress was observed as an aid to debugging. When forward progress does happen, it prints out the number of rcu_torture_writer() versions and grace periods that elapsed during the forward-progress test. At the end of the run, it also prints the number of attempted and actual forward-progress tests.
--- kernel/rcu/rcutorture.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-)
kernel/rcu/rcutorture.c +9 -5
@@ -1702,6 +1702,7 @@ static void rcu_torture_fwd_prog_cb(struct rcu_head *rhp)static int rcu_torture_fwd_prog (void *args) {unsigned long cver; +unsigned long dur;struct fwd_cb_state fcs = { .stop =0 };unsigned long gps;int idx;
@@ -1709,7 +1710,7 @@ static int rcu_torture_fwd_prog(void *args)int sd4;bool selfpropcb = false;unsigned long stopat; -bool tested = false; +int tested =0 ;int tested_tries =0 ;static DEFINE_TORTURE_RANDOM (trs);
@@ -1727,7 +1728,8 @@ static int rcu_torture_fwd_prog(void *args) gps = cur_ops->get_gp_seq (); sd = cur_ops->stall_dur () +1 ; sd4 = (sd + fwd_progress_div -1 ) / fwd_progress_div; - stopat = jiffies + sd4 +torture_random (&trs) % (sd - sd4); + dur = sd4 +torture_random (&trs) % (sd - sd4); + stopat = jiffies + dur;while (time_before (jiffies, stopat) && !torture_must_stop ()) { idx = cur_ops->readlock ();udelay (10 );
@@ -1737,10 +1739,11 @@ static int rcu_torture_fwd_prog(void *args) } tested_tries++;if (!time_before (jiffies, stopat) && !torture_must_stop ()) { - tested = true; - cver = cver ==READ_ONCE (rcu_torture_current_version); + tested++; + cver =READ_ONCE (rcu_torture_current_version) - cver; gps =rcutorture_seq_diff (cur_ops->get_gp_seq (), gps); -WARN_ON_ONCE (cver && gps <2 ); +WARN_ON (!cver && gps <2 ); +pr_alert ("%s: Duration %ld cver %ld gps %ld\n" , __func__, dur, cver, gps); }/* Avoid slow periods, better to test when busy. */ stutter_wait ("rcu_torture_fwd_prog" );
@@ -1754,6 +1757,7 @@ static int rcu_torture_fwd_prog(void *args) }/* Short runs might not contain a valid forward-progress attempt. */ WARN_ON (!tested && tested_tries >=5 ); +pr_alert ("%s: tested %d tested_tries %d\n" , __func__, tested, tested_tries);torture_kthread_stopping ("rcu_torture_fwd_prog" );return 0 ; }
Signature · 1 line
2.17.1
PATCH 16/17 rcutorture: Check GP completion at stutter end
In reply to Paul E. McKenneyThe rcu_torture_writer() function invokes stutter_wait() at the end of each writer pass, which occasionally blocks for an extended time period in order to ensure that RCU can handle intermittent loads. But part of handling a busy period is invoking all the callbacks before the end of the idle period induced by stutter_wait().
This commit therefore adds a return value to stutter_wait() indicating whether stutter_wait() actually waited. In addition, this commit causes rcu_torture_writer() to test this value and if set, checks that all the elements of the rcu_tortures[] array have been freed up.
--- include/linux/torture.h | 2 +- kernel/rcu/rcutorture.c | 5 ++++- kernel/torture.c | 3 ++- 3 files changed, 7 insertions(+), 3 deletions(-)
include/linux/torture.h +1 -1
@@ -77,7 +77,7 @@ void torture_shutdown_absorb(const char *title);int torture_shutdown_init (int ssecs,void (*cleanup)(void ));/* Task stuttering, which forces load/no-load transitions. */ -void stutter_wait (const char *title); +bool stutter_wait (const char *title);int torture_stutter_init (int s);/* Initialization and cleanup. */
kernel/rcu/rcutorture.c +4 -1
@@ -1144,7 +1144,10 @@ rcu_torture_writer(void *arg) !rcu_gp_is_normal (); } rcu_torture_writer_state =RTWS_STUTTER ; -stutter_wait ("rcu_torture_writer" ); +if (stutter_wait ("rcu_torture_writer" )) +for (i =0 ; i <ARRAY_SIZE (rcu_tortures); i++) +if (list_empty (&rcu_tortures[i].rtort_free)) +WARN_ON_ONCE (1 ); }while (!torture_must_stop ());/* Reset expediting back to unexpedited. */ if (expediting >0 )
kernel/torture.c +2 -1
@@ -573,7 +573,7 @@ static int stutter;* Block until the stutter interval ends. This must be called periodically * by all running kthreads that need to be subject to stuttering. */ -void stutter_wait (const char *title) +bool stutter_wait (const char *title) {int spt;
@@ -590,6 +590,7 @@ void stutter_wait(const char *title) }torture_shutdown_absorb (title); } +return !!spt; }EXPORT_SYMBOL_GPL (stutter_wait);
Signature · 1 line
2.17.1
PATCH 17/17 rcutorture: Maintain self-propagating CB only during forward-progress test
In reply to Paul E. McKenneyThe current forward-progress testing maintains a self-propagating callback during the full test. This could result in false negatives for stutter-end checking, where it might appear that RCU was clearing out old callbacks only because it was being continually motivated by the self-propagating callback. This commit therefore shuts down the self-propagating callback at the end of each forward-progress test interval.
--- kernel/rcu/rcutorture.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-)
kernel/rcu/rcutorture.c +10 -5
@@ -1706,7 +1706,7 @@ static int rcu_torture_fwd_prog(void *args) {unsigned long cver;unsigned long dur; -struct fwd_cb_state fcs = { .stop =0 }; +struct fwd_cb_state fcs;unsigned long gps;int idx;int sd;
@@ -1722,11 +1722,14 @@ static int rcu_torture_fwd_prog(void *args)set_user_nice (current,MAX_NICE );if (cur_ops->call && cur_ops->sync && cur_ops->cb_barrier) {init_rcu_head_on_stack (&fcs.rh); - cur_ops->call (&fcs.rh, rcu_torture_fwd_prog_cb); selfpropcb = true; } do { schedule_timeout_interruptible(fwd_progress_holdoff * HZ); + if (selfpropcb) { + WRITE_ONCE(fcs.stop, 0); + cur_ops->call(&fcs.rh, rcu_torture_fwd_prog_cb); + } cver = READ_ONCE(rcu_torture_current_version); gps = cur_ops->get_gp_seq(); sd = cur_ops->stall_dur() + 1;
@@ -1748,13 +1751,15 @@ static int rcu_torture_fwd_prog(void *args)WARN_ON (!cver && gps <2 );pr_alert ("%s: Duration %ld cver %ld gps %ld\n" , __func__, dur, cver, gps); } +if (selfpropcb) { +WRITE_ONCE (fcs.stop,1 ); + cur_ops->sync ();/* Wait for running CB to complete. */ + cur_ops->cb_barrier ();/* Wait for queued callbacks. */ + }/* Avoid slow periods, better to test when busy. */ stutter_wait ("rcu_torture_fwd_prog" ); }while (!torture_must_stop ());if (selfpropcb) { -WRITE_ONCE (fcs.stop,1 ); - cur_ops->sync ();/* Wait for running callback to complete. */ - cur_ops->cb_barrier ();/* Wait for queued callbacks. */ WARN_ON (READ_ONCE (fcs.stop) !=2 );destroy_rcu_head_on_stack (&fcs.rh); }
Signature · 1 line
2.17.1