2018-08-29 21:49:10

by Paul E. McKenney

[permalink] [raw]
Subject: [PATCH tip/core/rcu 0/17] 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(-)



2018-08-29 21:49:26

by Paul E. McKenney

[permalink] [raw]
Subject: [PATCH tip/core/rcu 05/17] rcutorture: Remove TREE06 and TREE08 from the default test list

Now 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.

Signed-off-by: Paul E. McKenney <[email protected]>
---
tools/testing/selftests/rcutorture/configs/rcu/CFLIST | 2 --
1 file changed, 2 deletions(-)

diff --git a/tools/testing/selftests/rcutorture/configs/rcu/CFLIST b/tools/testing/selftests/rcutorture/configs/rcu/CFLIST
index 6a0b9f69faad..c3c1fb5a9e1f 100644
--- a/tools/testing/selftests/rcutorture/configs/rcu/CFLIST
+++ b/tools/testing/selftests/rcutorture/configs/rcu/CFLIST
@@ -3,9 +3,7 @@ TREE02
TREE03
TREE04
TREE05
-TREE06
TREE07
-TREE08
TREE09
SRCU-N
SRCU-P
--
2.17.1


2018-08-29 21:49:35

by Paul E. McKenney

[permalink] [raw]
Subject: [PATCH tip/core/rcu 08/17] rcutorture: Avoid no-test complaint if too few forward-progress tries

In 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.

Signed-off-by: Paul E. McKenney <[email protected]>
---
kernel/rcu/rcutorture.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/kernel/rcu/rcutorture.c b/kernel/rcu/rcutorture.c
index dee7b45b2186..8ab23143c244 100644
--- a/kernel/rcu/rcutorture.c
+++ b/kernel/rcu/rcutorture.c
@@ -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;
}
--
2.17.1


2018-08-29 21:49:43

by Paul E. McKenney

[permalink] [raw]
Subject: [PATCH tip/core/rcu 10/17] rcutorture: Add self-propagating callback to forward-progress testing

If 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.

Signed-off-by: Paul E. McKenney <[email protected]>
---
kernel/rcu/rcutorture.c | 36 ++++++++++++++++++++++++++++++++++++
1 file changed, 36 insertions(+)

diff --git a/kernel/rcu/rcutorture.c b/kernel/rcu/rcutorture.c
index 89cc4d9c9a0c..316083687fd7 100644
--- a/kernel/rcu/rcutorture.c
+++ b/kernel/rcu/rcutorture.c
@@ -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");
--
2.17.1


2018-08-29 21:49:48

by Paul E. McKenney

[permalink] [raw]
Subject: [PATCH tip/core/rcu 17/17] rcutorture: Maintain self-propagating CB only during forward-progress test

The 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.

Signed-off-by: Paul E. McKenney <[email protected]>
---
kernel/rcu/rcutorture.c | 15 ++++++++++-----
1 file changed, 10 insertions(+), 5 deletions(-)

diff --git a/kernel/rcu/rcutorture.c b/kernel/rcu/rcutorture.c
index ae10ad531993..a02a2f21386b 100644
--- a/kernel/rcu/rcutorture.c
+++ b/kernel/rcu/rcutorture.c
@@ -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);
}
--
2.17.1


2018-08-29 21:50:00

by Paul E. McKenney

[permalink] [raw]
Subject: [PATCH tip/core/rcu 12/17] rcutorture: Limit reader duration if irq or bh disabled

There 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.

Reported-by: Thomas Gleixner <[email protected]>
Signed-off-by: Paul E. McKenney <[email protected]>
---
kernel/rcu/rcutorture.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/kernel/rcu/rcutorture.c b/kernel/rcu/rcutorture.c
index b98bb11d47a2..9622192ec5c9 100644
--- a/kernel/rcu/rcutorture.c
+++ b/kernel/rcu/rcutorture.c
@@ -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,
--
2.17.1


2018-08-29 21:50:08

by Paul E. McKenney

[permalink] [raw]
Subject: [PATCH tip/core/rcu 09/17] rcutorture: Vary forward-progress test interval

Some 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.

Signed-off-by: Paul E. McKenney <[email protected]>
---
kernel/rcu/rcutorture.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/kernel/rcu/rcutorture.c b/kernel/rcu/rcutorture.c
index 8ab23143c244..89cc4d9c9a0c 100644
--- a/kernel/rcu/rcutorture.c
+++ b/kernel/rcu/rcutorture.c
@@ -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);
--
2.17.1


2018-08-29 21:50:13

by Paul E. McKenney

[permalink] [raw]
Subject: [PATCH tip/core/rcu 13/17] rcutorture: Reduce priority of forward-progress testing

On !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.

Signed-off-by: Paul E. McKenney <[email protected]>
---
kernel/rcu/rcutorture.c | 2 ++
1 file changed, 2 insertions(+)

diff --git a/kernel/rcu/rcutorture.c b/kernel/rcu/rcutorture.c
index 9622192ec5c9..ac487ea8d245 100644
--- a/kernel/rcu/rcutorture.c
+++ b/kernel/rcu/rcutorture.c
@@ -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);
--
2.17.1


2018-08-29 21:50:24

by Paul E. McKenney

[permalink] [raw]
Subject: [PATCH tip/core/rcu 15/17] rcutorture: Print forward-progress test interval on error

This 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.

Signed-off-by: Paul E. McKenney <[email protected]>
---
kernel/rcu/rcutorture.c | 14 +++++++++-----
1 file changed, 9 insertions(+), 5 deletions(-)

diff --git a/kernel/rcu/rcutorture.c b/kernel/rcu/rcutorture.c
index 50015b78a43f..7df8142a6a22 100644
--- a/kernel/rcu/rcutorture.c
+++ b/kernel/rcu/rcutorture.c
@@ -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;
}
--
2.17.1


2018-08-29 21:50:30

by Paul E. McKenney

[permalink] [raw]
Subject: [PATCH tip/core/rcu 16/17] rcutorture: Check GP completion at stutter end

The 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.

Signed-off-by: Paul E. McKenney <[email protected]>
---
include/linux/torture.h | 2 +-
kernel/rcu/rcutorture.c | 5 ++++-
kernel/torture.c | 3 ++-
3 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/include/linux/torture.h b/include/linux/torture.h
index 61dfd93b6ee4..48fad21109fc 100644
--- a/include/linux/torture.h
+++ b/include/linux/torture.h
@@ -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. */
diff --git a/kernel/rcu/rcutorture.c b/kernel/rcu/rcutorture.c
index 7df8142a6a22..ae10ad531993 100644
--- a/kernel/rcu/rcutorture.c
+++ b/kernel/rcu/rcutorture.c
@@ -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)
diff --git a/kernel/torture.c b/kernel/torture.c
index 1ac24a826589..17d91f5fba2a 100644
--- a/kernel/torture.c
+++ b/kernel/torture.c
@@ -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);

--
2.17.1


2018-08-29 21:50:43

by Paul E. McKenney

[permalink] [raw]
Subject: [PATCH tip/core/rcu 11/17] rcutorture: Increase rcu_read_delay() longdelay_ms

RCU 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.

Signed-off-by: Paul E. McKenney <[email protected]>
---
kernel/rcu/rcutorture.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/kernel/rcu/rcutorture.c b/kernel/rcu/rcutorture.c
index 316083687fd7..b98bb11d47a2 100644
--- a/kernel/rcu/rcutorture.c
+++ b/kernel/rcu/rcutorture.c
@@ -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
--
2.17.1


2018-08-29 21:51:04

by Paul E. McKenney

[permalink] [raw]
Subject: [PATCH tip/core/rcu 01/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.

Signed-off-by: Paul E. McKenney <[email protected]>
---
tools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh | 1 -
1 file changed, 1 deletion(-)

diff --git a/tools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh b/tools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh
index f7247ee00514..58ca758a5786 100755
--- a/tools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh
+++ b/tools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh
@@ -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
--
2.17.1


2018-08-29 21:51:10

by Paul E. McKenney

[permalink] [raw]
Subject: [PATCH tip/core/rcu 06/17] rcutorture: Add forward-progress tests for RCU grace periods

This 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.

Signed-off-by: Paul E. McKenney <[email protected]>
---
include/linux/rcutiny.h | 1 +
kernel/rcu/rcutorture.c | 73 ++++++++++++++++++++++++++++++++++++++++-
kernel/rcu/update.c | 1 +
3 files changed, 74 insertions(+), 1 deletion(-)

diff --git a/include/linux/rcutiny.h b/include/linux/rcutiny.h
index 8d9a0ea8f0b5..a6353f3d6094 100644
--- a/include/linux/rcutiny.h
+++ b/include/linux/rcutiny.h
@@ -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) { }
diff --git a/kernel/rcu/rcutorture.c b/kernel/rcu/rcutorture.c
index 5df2411f7aee..fd3ce6cc8eea 100644
--- a/kernel/rcu/rcutorture.c
+++ b/kernel/rcu/rcutorture.c
@@ -89,6 +89,12 @@ torture_param(int, fqs_duration, 0,
"Duration of fqs bursts (us), 0 to disable");
torture_param(int, fqs_holdoff, 0, "Holdoff time within fqs bursts (us)");
torture_param(int, fqs_stutter, 3, "Wait time between fqs bursts (s)");
+torture_param(bool, fwd_progress, 1, "Test grace-period forward progress");
+torture_param(int, fwd_progress_div, 4, "Fraction of CPU stall to wait");
+torture_param(int, fwd_progress_holdoff, 60,
+ "Time between forward-progress tests (s)");
+torture_param(bool, fwd_progress_need_resched, 1,
+ "Hide cond_resched() behind need_resched()");
torture_param(bool, gp_cond, false, "Use conditional/async GP wait primitives");
torture_param(bool, gp_exp, false, "Use expedited GP wait primitives");
torture_param(bool, gp_normal, false,
@@ -137,6 +143,7 @@ static struct task_struct **cbflood_task;
static struct task_struct *fqs_task;
static struct task_struct *boost_tasks[NR_CPUS];
static struct task_struct *stall_task;
+static struct task_struct *fwd_prog_task;
static struct task_struct **barrier_cbs_tasks;
static struct task_struct *barrier_task;

@@ -291,6 +298,7 @@ struct rcu_torture_ops {
void (*cb_barrier)(void);
void (*fqs)(void);
void (*stats)(void);
+ int (*stall_dur)(void);
int irq_capable;
int can_boost;
int extendables;
@@ -429,6 +437,7 @@ static struct rcu_torture_ops rcu_ops = {
.cb_barrier = rcu_barrier,
.fqs = rcu_force_quiescent_state,
.stats = NULL,
+ .stall_dur = rcu_jiffies_till_stall_check,
.irq_capable = 1,
.can_boost = rcu_can_boost(),
.name = "rcu"
@@ -1116,7 +1125,8 @@ rcu_torture_writer(void *arg)
break;
}
}
- rcu_torture_current_version++;
+ WRITE_ONCE(rcu_torture_current_version,
+ rcu_torture_current_version + 1);
/* Cycle through nesting levels of rcu_expedite_gp() calls. */
if (can_expedite &&
!(torture_random(&rand) & 0xff & (!!expediting - 1))) {
@@ -1660,6 +1670,63 @@ static int __init rcu_torture_stall_init(void)
return torture_create_kthread(rcu_torture_stall, NULL, stall_task);
}

+/* Carry out grace-period forward-progress testing. */
+static int rcu_torture_fwd_prog(void *args)
+{
+ unsigned long cvar;
+ int idx;
+ unsigned long stopat;
+ bool tested = false;
+
+ VERBOSE_TOROUT_STRING("rcu_torture_fwd_progress task started");
+ do {
+ schedule_timeout_interruptible(fwd_progress_holdoff * HZ);
+ cvar = READ_ONCE(rcu_torture_current_version);
+ stopat = jiffies + cur_ops->stall_dur() / fwd_progress_div;
+ while (time_before(jiffies, stopat) && !torture_must_stop()) {
+ idx = cur_ops->readlock();
+ udelay(10);
+ cur_ops->readunlock(idx);
+ if (!fwd_progress_need_resched || need_resched())
+ cond_resched();
+ }
+ if (!time_before(jiffies, stopat) && !torture_must_stop()) {
+ tested = true;
+ WARN_ON_ONCE(cvar ==
+ READ_ONCE(rcu_torture_current_version));
+ }
+ /* Avoid slow periods, better to test when busy. */
+ stutter_wait("rcu_torture_fwd_prog");
+ } while (!torture_must_stop());
+ WARN_ON(!tested);
+ torture_kthread_stopping("rcu_torture_fwd_prog");
+ return 0;
+}
+
+/* If forward-progress checking is requested and feasible, spawn the thread. */
+static int __init rcu_torture_fwd_prog_init(void)
+{
+ if (!fwd_progress)
+ return 0; /* Not requested, so don't do it. */
+ if (!cur_ops->stall_dur || cur_ops->stall_dur() <= 0) {
+ VERBOSE_TOROUT_STRING("rcu_torture_fwd_prog_init: Disabled, unsupported by RCU flavor under test");
+ return 0;
+ }
+ if (stall_cpu > 0) {
+ VERBOSE_TOROUT_STRING("rcu_torture_fwd_prog_init: Disabled, conflicts with CPU-stall testing");
+ if (IS_MODULE(CONFIG_RCU_TORTURE_TESTS))
+ return -EINVAL; /* In module, can fail back to user. */
+ WARN_ON(1); /* Make sure rcutorture notices conflict. */
+ return 0;
+ }
+ if (fwd_progress_holdoff <= 0)
+ fwd_progress_holdoff = 1;
+ if (fwd_progress_div <= 0)
+ fwd_progress_div = 4;
+ return torture_create_kthread(rcu_torture_fwd_prog,
+ NULL, fwd_prog_task);
+}
+
/* Callback function for RCU barrier testing. */
static void rcu_torture_barrier_cbf(struct rcu_head *rcu)
{
@@ -1833,6 +1900,7 @@ rcu_torture_cleanup(void)
}

rcu_torture_barrier_cleanup();
+ torture_stop_kthread(rcu_torture_fwd_prog, fwd_prog_task);
torture_stop_kthread(rcu_torture_stall, stall_task);
torture_stop_kthread(rcu_torture_writer, writer_task);

@@ -2104,6 +2172,9 @@ rcu_torture_init(void)
if (firsterr)
goto unwind;
firsterr = rcu_torture_stall_init();
+ if (firsterr)
+ goto unwind;
+ firsterr = rcu_torture_fwd_prog_init();
if (firsterr)
goto unwind;
firsterr = rcu_torture_barrier_init();
diff --git a/kernel/rcu/update.c b/kernel/rcu/update.c
index 39cb23d22109..a6b860422d18 100644
--- a/kernel/rcu/update.c
+++ b/kernel/rcu/update.c
@@ -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)
{
--
2.17.1


2018-08-29 21:51:11

by Paul E. McKenney

[permalink] [raw]
Subject: [PATCH tip/core/rcu 07/17] rcutorture: Also use GP sequence to judge forward progress

Currently, 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.

Signed-off-by: Paul E. McKenney <[email protected]>
---
kernel/rcu/rcutorture.c | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/kernel/rcu/rcutorture.c b/kernel/rcu/rcutorture.c
index fd3ce6cc8eea..dee7b45b2186 100644
--- a/kernel/rcu/rcutorture.c
+++ b/kernel/rcu/rcutorture.c
@@ -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");
--
2.17.1


2018-08-29 21:51:20

by Paul E. McKenney

[permalink] [raw]
Subject: [PATCH tip/core/rcu 02/17] rcutorture: Force occasional reader waits

Deferred 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.

Signed-off-by: Paul E. McKenney <[email protected]>
---
kernel/rcu/rcutorture.c | 5 +++++
1 file changed, 5 insertions(+)

diff --git a/kernel/rcu/rcutorture.c b/kernel/rcu/rcutorture.c
index c596c6f1e457..50a4f0ed4ebf 100644
--- a/kernel/rcu/rcutorture.c
+++ b/kernel/rcu/rcutorture.c
@@ -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) {
--
2.17.1


2018-08-29 21:51:24

by Paul E. McKenney

[permalink] [raw]
Subject: [PATCH tip/core/rcu 14/17] rcutorture: Adjust number of reader kthreads per CPU-hotplug operations

Currently, 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.

Signed-off-by: Paul E. McKenney <[email protected]>
---
kernel/rcu/rcutorture.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/kernel/rcu/rcutorture.c b/kernel/rcu/rcutorture.c
index ac487ea8d245..50015b78a43f 100644
--- a/kernel/rcu/rcutorture.c
+++ b/kernel/rcu/rcutorture.c
@@ -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;
--
2.17.1


2018-08-29 21:51:34

by Paul E. McKenney

[permalink] [raw]
Subject: [PATCH tip/core/rcu 04/17] rcuperf: Warn on bad perf type for built-in tests

When 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.

Signed-off-by: Paul E. McKenney <[email protected]>
---
kernel/rcu/rcuperf.c | 1 +
1 file changed, 1 insertion(+)

diff --git a/kernel/rcu/rcuperf.c b/kernel/rcu/rcuperf.c
index 34244523550e..832ce68fd45f 100644
--- a/kernel/rcu/rcuperf.c
+++ b/kernel/rcu/rcuperf.c
@@ -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;
}
--
2.17.1


2018-08-29 21:51:38

by Paul E. McKenney

[permalink] [raw]
Subject: [PATCH tip/core/rcu 03/17] rcutorture: Warn on bad torture type for built-in tests

When 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.

Signed-off-by: Paul E. McKenney <[email protected]>
---
kernel/rcu/rcutorture.c | 1 +
1 file changed, 1 insertion(+)

diff --git a/kernel/rcu/rcutorture.c b/kernel/rcu/rcutorture.c
index 50a4f0ed4ebf..5df2411f7aee 100644
--- a/kernel/rcu/rcutorture.c
+++ b/kernel/rcu/rcutorture.c
@@ -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;
}
--
2.17.1