Skip to contentSkip to conversation

Torture-test changes for 4.7

PATCH New Paul E. McKenney 1 participant 25 messages Apr 12, 2016

Subsystems (6)
lore
Share & tools
lore
#0 lore raw

cover Torture-test changes for 4.7

Hello!

This series contains torture-test changes for RCU, most notably a new test for performance of RCU grace periods named "rcuperf":

1. Update scripting to accommodate rcuperf.

2. Allow for rcupdate.rcu_normal in rcu_torture_writer() decisions.

3. Expedited-GP batch progress access to torturing for progress
statistics.

4. Add RCU grace-period performance tests, AKA "rcuperf".

5. Documentation for rcuperf kernel parameters.

6. Bind rcuperf reader/writer kthreads to CPUs.

7. Set rcuperf writer kthreads to real-time priority.

8. Print measure of batching efficiency.

9. Make rcuperf collect expedited event-trace data.

10. Make scripts analyze rcuperf trace data, if present.

11. Add rcuperf holdoff boot parameter to reduce interference.

12. Avoid RCU CPU stall warning and RT throttling.

13. Add largish-system rcuperf scenario.

14. Do not wake up shutdown wait queue if "shutdown" is false, courtesy
of Artem Savkov.

15. Remove redundant initialization to zero.

16. Consider FROZEN hotplug notifier transitions, courtesy of
Anna-Maria Gleixner.

17. Clarify refusal to run more than one torture test.

18. Kill qemu, not parent process.

19. Convert test duration to seconds early.

20. Add OS-jitter capability.

21. Don't rebuild identical kernel.

22. Dump trace buffer upon shutdown.

23. Add irqs-disabled test for call_rcu().

24. Add boot-time adjustment of leaf fanout.

Thanx, Paul

------------------------------------------------------------------------

 Documentation/kernel-parameters.txt                                  |   38 
 include/linux/rcutiny.h                                              |   16 
 include/linux/rcutree.h                                              |    2 
 kernel/rcu/Makefile                                                  |    1 
 kernel/rcu/rcuperf.c                                                 |  661 +++++++++-
 kernel/rcu/rcutorture.c                                              |   12 
 kernel/rcu/tree.c                                                    |   22 
 kernel/torture.c                                                     |    4 
 lib/Kconfig.debug                                                    |   33 
 tools/testing/selftests/rcutorture/bin/jitter.sh                     |   83 +
 tools/testing/selftests/rcutorture/bin/kvm-recheck-rcuperf-ftrace.sh |  121 +
 tools/testing/selftests/rcutorture/bin/kvm-recheck-rcuperf.sh        |  116 +
 tools/testing/selftests/rcutorture/bin/kvm-recheck.sh                |    5 
 tools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh             |   61 
 tools/testing/selftests/rcutorture/bin/kvm.sh                        |   24 
 tools/testing/selftests/rcutorture/configs/rcu/TREE04                |    2 
 tools/testing/selftests/rcutorture/configs/rcu/TREE04.boot           |    2 
 tools/testing/selftests/rcutorture/configs/rcuperf/CFLIST            |    1 
 tools/testing/selftests/rcutorture/configs/rcuperf/CFcommon          |    2 
 tools/testing/selftests/rcutorture/configs/rcuperf/TREE              |   20 
 tools/testing/selftests/rcutorture/configs/rcuperf/TREE54            |   23 
 tools/testing/selftests/rcutorture/configs/rcuperf/ver_functions.sh  |   52 
 22 files changed, 1260 insertions(+), 41 deletions(-)
#1 lore raw

PATCH 1/24 rcutorture: Update scripting to accommodate rcuperf

This commit adds the scripting changes to add support for the shiny new rcuperf kernel module.

---
 .../rcutorture/bin/kvm-recheck-rcuperf.sh          | 82 ++++++++++++++++++++++
 .../selftests/rcutorture/bin/kvm-recheck.sh        |  5 +-
 tools/testing/selftests/rcutorture/bin/kvm.sh      |  2 +-
 .../selftests/rcutorture/configs/rcuperf/CFLIST    |  1 +
 .../selftests/rcutorture/configs/rcuperf/CFcommon  |  2 +
 .../selftests/rcutorture/configs/rcuperf/TREE      | 19 +++++
 .../rcutorture/configs/rcuperf/ver_functions.sh    | 52 ++++++++++++++
 7 files changed, 161 insertions(+), 2 deletions(-)
 create mode 100755 tools/testing/selftests/rcutorture/bin/kvm-recheck-rcuperf.sh
 create mode 100644 tools/testing/selftests/rcutorture/configs/rcuperf/CFLIST
 create mode 100644 tools/testing/selftests/rcutorture/configs/rcuperf/CFcommon
 create mode 100644 tools/testing/selftests/rcutorture/configs/rcuperf/TREE
 create mode 100644 tools/testing/selftests/rcutorture/configs/rcuperf/ver_functions.sh
tools/testing/selftests/rcutorture/bin/kvm-recheck-rcuperf.sh new file +82 -0
new file mode 100755
index 000000000000..e5b28174fda0
@@ -0,0 +1,82 @@
+#!/bin/bash
+#
+# Analyze a given results directory for rcuperf performance measurements.
+#
+# Usage: kvm-recheck-rcuperf.sh resdir
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, you can access it online at
+# http://www.gnu.org/licenses/gpl-2.0.html.
+#
+# Copyright (C) IBM Corporation, 2016
+#
+# Authors: Paul E. McKenney <[email protected]>
+
+i="$1"
+if test -d $i
+then
+	:
+else
+	echo Unreadable results directory: $i
+	exit 1
+fi
+. tools/testing/selftests/rcutorture/bin/functions.sh
+
+configfile=`echo $i | sed -e 's/^.*\///'`
+
+grep -e '-perf:.*writer-duration' $i/console.log | sed -e 's/^\[[^]]*]//' |
+awk '
+{
+	gptimes[++n] = $5 / 1000.;
+	sum += $5 / 1000.;
+}
+
+END {
+	if (NR <= 0) {
+		print "No rcuperf records found???"
+		exit;
+	}
+	asort(gptimes);
+	pct50 = int(NR * 50 / 100);
+	if (pct50 < 1)
+		pct50 = 1;
+	pct90 = int(NR * 90 / 100);
+	if (pct90 < 1)
+		pct90 = 1;
+	pct99 = int(NR * 99 / 100);
+	if (pct99 < 1)
+		pct99 = 1;
+	div = 10 ** int(log(gptimes[pct90]) / log(10) + .5) / 100;
+	print "Histogram bucket size: " div;
+	last = gptimes[1] - 10;
+	count = 0;
+	for (i = 1; i <= NR; i++) {
+		current = div * int(gptimes[i] / div);
+		if (last == current) {
+			count++;
+		} else {
+			if (count > 0)
+				print last, count;
+			count = 1;
+			last = current;
+		}
+	}
+	if (count > 0)
+		print last, count;
+	print "Average grace-period duration: " sum / NR " microseconds";
+	print "Minimum grace-period duration: " gptimes[1];
+	print "50th percentile grace-period duration: " gptimes[pct50];
+	print "90th percentile grace-period duration: " gptimes[pct90];
+	print "99th percentile grace-period duration: " gptimes[pct99];
+	print "Maximum grace-period duration: " gptimes[NR];
+}'
tools/testing/selftests/rcutorture/bin/kvm-recheck.sh +4 -1
index d86bdd6b6cc2..f659346d3358 100755
@@ -48,7 +48,10 @@ do
 				cat $i/Make.oldconfig.err
 			fi
 			parse-build.sh $i/Make.out $configfile
-			parse-torture.sh $i/console.log $configfile
+			if test "$TORTURE_SUITE" != rcuperf
+			then
+				parse-torture.sh $i/console.log $configfile
+			fi
 			parse-console.sh $i/console.log $configfile
 			if test -r $i/Warnings
 			then
tools/testing/selftests/rcutorture/bin/kvm.sh +1 -1
index 4a431767f77a..c33cb582b3dc 100755
@@ -156,7 +156,7 @@ do
 		shift
 		;;
 	--torture)
-		checkarg --torture "(suite name)" "$#" "$2" '^\(lock\|rcu\)$' '^--'
+		checkarg --torture "(suite name)" "$#" "$2" '^\(lock\|rcu\|rcuperf\)$' '^--'
 		TORTURE_SUITE=$2
 		shift
 		;;
tools/testing/selftests/rcutorture/configs/rcuperf/CFLIST new file +1 -0
new file mode 100644
index 000000000000..c9f56cf20775
@@ -0,0 +1 @@
+TREE
tools/testing/selftests/rcutorture/configs/rcuperf/CFcommon new file +2 -0
new file mode 100644
index 000000000000..a09816b8c0f3
@@ -0,0 +1,2 @@
+CONFIG_RCU_PERF_TEST=y
+CONFIG_PRINTK_TIME=y
tools/testing/selftests/rcutorture/configs/rcuperf/TREE new file +19 -0
new file mode 100644
index 000000000000..614e107f6db5
@@ -0,0 +1,19 @@
+CONFIG_SMP=y
+CONFIG_PREEMPT_NONE=n
+CONFIG_PREEMPT_VOLUNTARY=n
+CONFIG_PREEMPT=y
+#CHECK#CONFIG_PREEMPT_RCU=y
+CONFIG_HZ_PERIODIC=n
+CONFIG_NO_HZ_IDLE=y
+CONFIG_NO_HZ_FULL=n
+CONFIG_RCU_FAST_NO_HZ=n
+CONFIG_RCU_TRACE=n
+CONFIG_HOTPLUG_CPU=n
+CONFIG_SUSPEND=n
+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/rcuperf/ver_functions.sh new file +52 -0

52 lines not on this page · raw message

Signature · 1 line
2.5.2
#2 lore raw

PATCH 2/24 rcutorture: Allow for rcupdate.rcu_normal

In reply to Paul E. McKenney

Currently, rcu_torture_writer() checks only for rcu_gp_is_expedited() when deciding whether or not to do dynamic control of RCU expediting. This means that if rcupdate.rcu_normal is specified, rcu_torture_writer() will attempt to dynamically control RCU expediting, but will nonetheless only test normal RCU grace periods. This commit therefore adds a check for !rcu_gp_is_normal(), and prints a message and desists from testing dynamic control of RCU expediting when doing so is futile.

---
 kernel/rcu/rcutorture.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
kernel/rcu/rcutorture.c +2 -2
index 463867c43221..9234e75b106a 100644
@@ -916,7 +916,7 @@ rcu_torture_fqs(void *arg)
 static int
 rcu_torture_writer(void *arg)
 {
-	bool can_expedite = !rcu_gp_is_expedited();
+	bool can_expedite = !rcu_gp_is_expedited() && !rcu_gp_is_normal();
 	int expediting = 0;
 	unsigned long gp_snap;
 	bool gp_cond1 = gp_cond, gp_exp1 = gp_exp, gp_normal1 = gp_normal;
@@ -932,7 +932,7 @@ rcu_torture_writer(void *arg)
 	VERBOSE_TOROUT_STRING("rcu_torture_writer task started");
 	if (!can_expedite) {
 		pr_alert("%s" TORTURE_FLAG
-			 " Grace periods expedited from boot/sysfs for %s,\n",
+			 " GP expediting controlled from boot/sysfs for %s,\n",
 			 torture_type, cur_ops->name);
 		pr_alert("%s" TORTURE_FLAG
 			 " Disabled dynamic grace-period expediting.\n",
Signature · 1 line
2.5.2
#3 lore raw

PATCH 3/24 rcutorture: Expedited-GP batch progress access to torturing

In reply to Paul E. McKenney

This commit provides rcu_exp_batches_completed() and rcu_exp_batches_completed_sched() functions to allow torture-test modules to check how many expedited grace period batches have completed. These are analogous to the existing rcu_batches_completed(), rcu_batches_completed_bh(), and rcu_batches_completed_sched() functions.

---
 include/linux/rcutiny.h | 16 ++++++++++++++++
 include/linux/rcutree.h |  2 ++
 kernel/rcu/tree.c       | 22 ++++++++++++++++++++++
 3 files changed, 40 insertions(+)
include/linux/rcutiny.h +16 -0
index 64809aea661c..93aea75029fb 100644
@@ -149,6 +149,22 @@ static inline unsigned long rcu_batches_completed_sched(void)
 	return 0;
 }
 
+/*
+ * Return the number of expedited grace periods completed.
+ */
+static inline unsigned long rcu_exp_batches_completed(void)
+{
+	return 0;
+}
+
+/*
+ * Return the number of expedited sched grace periods completed.
+ */
+static inline unsigned long rcu_exp_batches_completed_sched(void)
+{
+	return 0;
+}
+
 static inline void rcu_force_quiescent_state(void)
 {
 }
include/linux/rcutree.h +2 -0
index ad1eda9fa4da..5043cb823fb2 100644
@@ -87,6 +87,8 @@ unsigned long rcu_batches_started_sched(void);
 unsigned long rcu_batches_completed(void);
 unsigned long rcu_batches_completed_bh(void);
 unsigned long rcu_batches_completed_sched(void);
+unsigned long rcu_exp_batches_completed(void);
+unsigned long rcu_exp_batches_completed_sched(void);
 void show_rcu_gp_kthreads(void);
 
 void rcu_force_quiescent_state(void);
kernel/rcu/tree.c +22 -0
index 531a328076bd..88df64087dfe 100644
@@ -460,6 +460,28 @@ unsigned long rcu_batches_completed_bh(void)
 EXPORT_SYMBOL_GPL(rcu_batches_completed_bh);
 
 /*
+ * Return the number of RCU expedited batches completed thus far for
+ * debug & stats.  Odd numbers mean that a batch is in progress, even
+ * numbers mean idle.  The value returned will thus be roughly double
+ * the cumulative batches since boot.
+ */
+unsigned long rcu_exp_batches_completed(void)
+{
+	return rcu_state_p->expedited_sequence;
+}
+EXPORT_SYMBOL_GPL(rcu_exp_batches_completed);
+
+/*
+ * Return the number of RCU-sched expedited batches completed thus far
+ * for debug & stats.  Similar to rcu_exp_batches_completed().
+ */
+unsigned long rcu_exp_batches_completed_sched(void)
+{
+	return rcu_sched_state.expedited_sequence;
+}
+EXPORT_SYMBOL_GPL(rcu_exp_batches_completed_sched);
+
+/*
  * Force a quiescent state.
  */
 void rcu_force_quiescent_state(void)
Signature · 1 line
2.5.2
#4 lore raw

PATCH 4/24 rcutorture: Add RCU grace-period performance tests

In reply to Paul E. McKenney

This commit adds a new rcuperf module that carries out simple performance tests of RCU grace periods.

---
 kernel/rcu/Makefile  |   1 +
 kernel/rcu/rcuperf.c | 637 +++++++++++++++++++++++++++++++++++++++++++++++++++
 lib/Kconfig.debug    |  33 +++
 3 files changed, 671 insertions(+)
 create mode 100644 kernel/rcu/rcuperf.c
kernel/rcu/Makefile +1 -0
index 032b2c015beb..18dfc485225c 100644
@@ -5,6 +5,7 @@ KCOV_INSTRUMENT := n
 obj-y += update.o sync.o
 obj-$(CONFIG_SRCU) += srcu.o
 obj-$(CONFIG_RCU_TORTURE_TEST) += rcutorture.o
+obj-$(CONFIG_RCU_PERF_TEST) += rcuperf.o
 obj-$(CONFIG_TREE_RCU) += tree.o
 obj-$(CONFIG_PREEMPT_RCU) += tree.o
 obj-$(CONFIG_TREE_RCU_TRACE) += tree_trace.o
kernel/rcu/rcuperf.c new file +637 -0

637 lines not on this page · raw message

lib/Kconfig.debug +33 -0
index 1e9a607534ca..f4b797a690ba 100644
@@ -1289,6 +1289,39 @@ config TORTURE_TEST
 	tristate
 	default n
 
+config RCU_PERF_TEST
+	tristate "performance tests for RCU"
+	depends on DEBUG_KERNEL
+	select TORTURE_TEST
+	select SRCU
+	select TASKS_RCU
+	default n
+	help
+	  This option provides a kernel module that runs performance
+	  tests on the RCU infrastructure.  The kernel module may be built
+	  after the fact on the running kernel to be tested, if desired.
+
+	  Say Y here if you want RCU performance tests to be built into
+	  the kernel.
+	  Say M if you want the RCU performance tests to build as a module.
+	  Say N if you are unsure.
+
+config RCU_PERF_TEST_RUNNABLE
+	bool "performance tests for RCU runnable by default"
+	depends on RCU_PERF_TEST = y
+	default n
+	help
+	  This option provides a way to build the RCU performance tests
+	  directly into the kernel without them starting up at boot time.
+	  You can use /sys/module to manually override this setting.
+	  This /proc file is available only when the RCU performance
+	  tests have been built into the kernel.
+
+	  Say Y here if you want the RCU performance tests to start during
+	  boot (you probably don't).
+	  Say N here if you want the RCU performance tests to start only
+	  after being manually enabled via /sys/module.
+
 config RCU_TORTURE_TEST
 	tristate "torture tests for RCU"
 	depends on DEBUG_KERNEL
Signature · 1 line
2.5.2
#5 lore raw

PATCH 5/24 rcutorture: Documentation for rcuperf kernel parameters

In reply to Paul E. McKenney

This commit adds documentation for the new rcuperf module's kernel boot parameters.

---
 Documentation/kernel-parameters.txt | 32 ++++++++++++++++++++++++++++++++
 1 file changed, 32 insertions(+)
Documentation/kernel-parameters.txt +32 -0
index ecc74fa4bfde..951af481da5a 100644
@@ -3284,6 +3284,38 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 			Lazy RCU callbacks are those which RCU can
 			prove do nothing more than free memory.
 
+	rcuperf.gp_exp= [KNL]
+			Measure performance of expedited synchronous
+			grace-period primitives.
+
+	rcuperf.nreaders= [KNL]
+			Set number of RCU readers.  The value -1 selects
+			N, where N is the number of CPUs.  A value
+			"n" less than -1 selects N-n+1, where N is again
+			the number of CPUs.  For example, -2 selects N
+			(the number of CPUs), -3 selects N+1, and so on.
+			A value of "n" less than or equal to -N selects
+			a single reader.
+
+	rcuperf.nwriters= [KNL]
+			Set number of RCU writers.  The values operate
+			the same as for rcuperf.nreaders.
+			N, where N is the number of CPUs
+
+	rcuperf.perf_runnable= [BOOT]
+			Start rcuperf running at boot time.
+
+	rcuperf.shutdown= [KNL]
+			Shut the system down after performance tests
+			complete.  This is useful for hands-off automated
+			testing.
+
+	rcuperf.perf_type= [KNL]
+			Specify the RCU implementation to test.
+
+	rcuperf.verbose= [KNL]
+			Enable additional printk() statements.
+
 	rcutorture.cbflood_inter_holdoff= [KNL]
 			Set holdoff time (jiffies) between successive
 			callback-flood tests.
Signature · 1 line
2.5.2
#6 lore raw

PATCH 6/24 rcutorture: Bind rcuperf reader/writer kthreads to CPUs

In reply to Paul E. McKenney

This commit forces more deterministic behavior by binding rcuperf's rcu_perf_reader() and rcu_perf_writer() kthreads to their respective CPUs.

---
 kernel/rcu/rcuperf.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)
kernel/rcu/rcuperf.c +4 -1
index 9d54a57bee7d..7a1edf417d18 100644
@@ -328,8 +328,10 @@ rcu_perf_reader(void *arg)
 {
 	unsigned long flags;
 	int idx;
+	long me = (long)arg;
 
 	VERBOSE_PERFOUT_STRING("rcu_perf_reader task started");
+	set_cpus_allowed_ptr(current, cpumask_of(me % nr_cpu_ids));
 	set_user_nice(current, MAX_NICE);
 	atomic_inc(&n_rcu_perf_reader_started);
 
@@ -362,6 +364,7 @@ rcu_perf_writer(void *arg)
 	WARN_ON(rcu_gp_is_expedited() && !rcu_gp_is_normal() && !gp_exp);
 	WARN_ON(rcu_gp_is_normal() && gp_exp);
 	WARN_ON(!wdpp);
+	set_cpus_allowed_ptr(current, cpumask_of(me % nr_cpu_ids));
 	t = ktime_get_mono_fast_ns();
 	if (atomic_inc_return(&n_rcu_perf_writer_started) >= nrealwriters) {
 		t_rcu_perf_writer_started = t;
@@ -594,7 +597,7 @@ rcu_perf_init(void)
 		goto unwind;
 	}
 	for (i = 0; i < nrealreaders; i++) {
-		firsterr = torture_create_kthread(rcu_perf_reader, NULL,
+		firsterr = torture_create_kthread(rcu_perf_reader, (void *)i,
 						  reader_tasks[i]);
 		if (firsterr)
 			goto unwind;
Signature · 1 line
2.5.2
#7 lore raw

PATCH 7/24 rcutorture: Set rcuperf writer kthreads to real-time priority

In reply to Paul E. McKenney

This commit forces more deterministic update-side behavior by setting rcuperf's rcu_perf_writer() kthreads to real-time priority.

---
 kernel/rcu/rcuperf.c | 3 +++
 1 file changed, 3 insertions(+)
kernel/rcu/rcuperf.c +3 -0
index 7a1edf417d18..e18d016a9888 100644
@@ -355,6 +355,7 @@ rcu_perf_writer(void *arg)
 	int i = 0;
 	int i_max;
 	long me = (long)arg;
+	struct sched_param sp;
 	bool started = false, done = false, alldone = false;
 	u64 t;
 	u64 *wdp;
@@ -365,6 +366,8 @@ rcu_perf_writer(void *arg)
 	WARN_ON(rcu_gp_is_normal() && gp_exp);
 	WARN_ON(!wdpp);
 	set_cpus_allowed_ptr(current, cpumask_of(me % nr_cpu_ids));
+	sp.sched_priority = 1;
+	sched_setscheduler_nocheck(current, SCHED_FIFO, &sp);
 	t = ktime_get_mono_fast_ns();
 	if (atomic_inc_return(&n_rcu_perf_writer_started) >= nrealwriters) {
 		t_rcu_perf_writer_started = t;
Signature · 1 line
2.5.2
#8 lore raw

PATCH 8/24 rcutorture: Print measure of batching efficiency

In reply to Paul E. McKenney

This commit adds a line giving the number of grace periods, the number of batches, and the ratio. The larger the ratio, the greater the batching efficiency.

---
 .../rcutorture/bin/kvm-recheck-rcuperf.sh          | 26 +++++++++++++---------
 1 file changed, 16 insertions(+), 10 deletions(-)
tools/testing/selftests/rcutorture/bin/kvm-recheck-rcuperf.sh +16 -10
index e5b28174fda0..1f72df8eedc7 100755
@@ -34,33 +34,38 @@ fi
 
 configfile=`echo $i | sed -e 's/^.*\///'`
 
-grep -e '-perf:.*writer-duration' $i/console.log | sed -e 's/^\[[^]]*]//' |
+sed -e 's/^\[[^]]*]//' < $i/console.log |
 awk '
-{
+/-perf: .* gps: .* batches:/ {
+	ngps = $9;
+	nbatches = $11;
+}
+
+/-perf: .*writer-duration/ {
 	gptimes[++n] = $5 / 1000.;
 	sum += $5 / 1000.;
 }
 
 END {
-	if (NR <= 0) {
+	newNR = asort(gptimes);
+	if (newNR <= 0) {
 		print "No rcuperf records found???"
 		exit;
 	}
-	asort(gptimes);
-	pct50 = int(NR * 50 / 100);
+	pct50 = int(newNR * 50 / 100);
 	if (pct50 < 1)
 		pct50 = 1;
-	pct90 = int(NR * 90 / 100);
+	pct90 = int(newNR * 90 / 100);
 	if (pct90 < 1)
 		pct90 = 1;
-	pct99 = int(NR * 99 / 100);
+	pct99 = int(newNR * 99 / 100);
 	if (pct99 < 1)
 		pct99 = 1;
 	div = 10 ** int(log(gptimes[pct90]) / log(10) + .5) / 100;
 	print "Histogram bucket size: " div;
 	last = gptimes[1] - 10;
 	count = 0;
-	for (i = 1; i <= NR; i++) {
+	for (i = 1; i <= newNR; i++) {
 		current = div * int(gptimes[i] / div);
 		if (last == current) {
 			count++;
@@ -73,10 +78,11 @@ END {
 	}
 	if (count > 0)
 		print last, count;
-	print "Average grace-period duration: " sum / NR " microseconds";
+	print "Average grace-period duration: " sum / newNR " microseconds";
 	print "Minimum grace-period duration: " gptimes[1];
 	print "50th percentile grace-period duration: " gptimes[pct50];
 	print "90th percentile grace-period duration: " gptimes[pct90];
 	print "99th percentile grace-period duration: " gptimes[pct99];
-	print "Maximum grace-period duration: " gptimes[NR];
+	print "Maximum grace-period duration: " gptimes[newNR];
+	print "Grace periods: " ngps + 0 " Batches: " nbatches + 0 " Ratio: " ngps / nbatches;
 }'
Signature · 1 line
2.5.2
#9 lore raw

PATCH 9/24 rcutorture: Make rcuperf collect expedited event-trace data

In reply to Paul E. McKenney

This commit enables ftrace in the rcuperf TREE kernel build and adds an ftrace_dump() at the end of rcuperf processing. This data will be used to measure the actual durations of the expedited grace periods without the added delays inherent in the kernel-module measurements.

---
 kernel/rcu/rcuperf.c                                    | 1 +
 tools/testing/selftests/rcutorture/configs/rcuperf/TREE | 1 +
 2 files changed, 2 insertions(+)
kernel/rcu/rcuperf.c +1 -0
index e18d016a9888..12561f96f0a2 100644
@@ -404,6 +404,7 @@ rcu_perf_writer(void *arg)
 				 perf_type, me, MIN_MEAS);
 			if (atomic_inc_return(&n_rcu_perf_writer_finished) >=
 			    nrealwriters) {
+				rcu_ftrace_dump(DUMP_ALL);
 				PERFOUT_STRING("Test complete");
 				t_rcu_perf_writer_finished = t;
 				if (gp_exp) {
tools/testing/selftests/rcutorture/configs/rcuperf/TREE +1 -0
index 614e107f6db5..a312f671a29a 100644
@@ -17,3 +17,4 @@ CONFIG_PROVE_LOCKING=n
 CONFIG_RCU_BOOST=n
 CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
 CONFIG_RCU_EXPERT=y
+CONFIG_RCU_TRACE=y
Signature · 1 line
2.5.2
#10 lore raw

PATCH 10/24 rcutorture: Make scripts analyze rcuperf trace data, if present

In reply to Paul E. McKenney

The rcuperf event-trace data is more accurate than are the rcuperf printk()s because locking keeps things ordered. This commit therefore parses and analyzes this event-trace data if present, and falls back on the printk()s otherwise.

---
 .../rcutorture/bin/kvm-recheck-rcuperf-ftrace.sh   | 121 +++++++++++++++++++++
 .../rcutorture/bin/kvm-recheck-rcuperf.sh          |   8 ++
 2 files changed, 129 insertions(+)
 create mode 100755 tools/testing/selftests/rcutorture/bin/kvm-recheck-rcuperf-ftrace.sh
tools/testing/selftests/rcutorture/bin/kvm-recheck-rcuperf-ftrace.sh new file +121 -0
new file mode 100755
index 000000000000..f79b0e9e84fc
@@ -0,0 +1,121 @@
+#!/bin/bash
+#
+# Analyze a given results directory for rcuperf performance measurements,
+# looking for ftrace data.  Exits with 0 if data was found, analyzed, and
+# printed.  Intended to be invoked from kvm-recheck-rcuperf.sh after
+# argument checking.
+#
+# Usage: kvm-recheck-rcuperf-ftrace.sh resdir
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, you can access it online at
+# http://www.gnu.org/licenses/gpl-2.0.html.
+#
+# Copyright (C) IBM Corporation, 2016
+#
+# Authors: Paul E. McKenney <[email protected]>
+
+i="$1"
+. tools/testing/selftests/rcutorture/bin/functions.sh
+
+if test "`grep -c 'rcu_exp_grace_period.*start' < $i/console.log`" -lt 100
+then
+	exit 10
+fi
+
+sed -e 's/^\[[^]]*]//' < $i/console.log |
+grep 'us : rcu_exp_grace_period' |
+sed -e 's/us : / : /' |
+tr -d '\015' |
+awk '
+$8 == "start" {
+	if (starttask != "")
+		nlost++;
+	starttask = $1;
+	starttime = $3;
+	startseq = $7;
+}
+
+$8 == "end" {
+	if (starttask == $1 && startseq == $7) {
+		curgpdur = $3 - starttime;
+		gptimes[++n] = curgpdur;
+		gptaskcnt[starttask]++;
+		sum += curgpdur;
+		if (curgpdur > 1000)
+			print "Long GP " starttime "us to " $3 "us (" curgpdur "us)";
+		starttask = "";
+	} else {
+		# Lost a message or some such, reset.
+		starttask = "";
+		nlost++;
+	}
+}
+
+$8 == "done" {
+	piggybackcnt[$1]++;
+}
+
+END {
+	newNR = asort(gptimes);
+	if (newNR <= 0) {
+		print "No ftrace records found???"
+		exit 10;
+	}
+	pct50 = int(newNR * 50 / 100);
+	if (pct50 < 1)
+		pct50 = 1;
+	pct90 = int(newNR * 90 / 100);
+	if (pct90 < 1)
+		pct90 = 1;
+	pct99 = int(newNR * 99 / 100);
+	if (pct99 < 1)
+		pct99 = 1;
+	div = 10 ** int(log(gptimes[pct90]) / log(10) + .5) / 100;
+	print "Histogram bucket size: " div;
+	last = gptimes[1] - 10;
+	count = 0;
+	for (i = 1; i <= newNR; i++) {
+		current = div * int(gptimes[i] / div);
+		if (last == current) {
+			count++;
+		} else {
+			if (count > 0)
+				print last, count;
+			count = 1;
+			last = current;
+		}
+	}
+	if (count > 0)
+		print last, count;
+	print "Distribution of grace periods across tasks:";
+	for (i in gptaskcnt) {
+		print "\t" i, gptaskcnt[i];
+		nbatches += gptaskcnt[i];
+	}
+	ngps = nbatches;
+	print "Distribution of piggybacking across tasks:";
+	for (i in piggybackcnt) {
+		print "\t" i, piggybackcnt[i];
+		ngps += piggybackcnt[i];
+	}
+	print "Average grace-period duration: " sum / newNR " microseconds";
+	print "Minimum grace-period duration: " gptimes[1];
+	print "50th percentile grace-period duration: " gptimes[pct50];
+	print "90th percentile grace-period duration: " gptimes[pct90];
+	print "99th percentile grace-period duration: " gptimes[pct99];
+	print "Maximum grace-period duration: " gptimes[newNR];
+	print "Grace periods: " ngps + 0 " Batches: " nbatches + 0 " Ratio: " ngps / nbatches " Lost: " nlost + 0;
+	print "Computed from ftrace data.";
+}'
+exit 0
tools/testing/selftests/rcutorture/bin/kvm-recheck-rcuperf.sh +8 -0
index 1f72df8eedc7..8f3121afc716 100755
@@ -30,8 +30,15 @@ else
 	echo Unreadable results directory: $i
 	exit 1
 fi
+PATH=`pwd`/tools/testing/selftests/rcutorture/bin:$PATH; export PATH
 . tools/testing/selftests/rcutorture/bin/functions.sh
 
+if kvm-recheck-rcuperf-ftrace.sh $i
+then
+	# ftrace data was successfully analyzed, call it good!
+	exit 0
+fi
+
 configfile=`echo $i | sed -e 's/^.*\///'`
 
 sed -e 's/^\[[^]]*]//' < $i/console.log |
@@ -85,4 +92,5 @@ END {
 	print "99th percentile grace-period duration: " gptimes[pct99];
 	print "Maximum grace-period duration: " gptimes[newNR];
 	print "Grace periods: " ngps + 0 " Batches: " nbatches + 0 " Ratio: " ngps / nbatches;
+	print "Computed from rcuperf printk output.";
 }'
Signature · 1 line
2.5.2
#11 lore raw

PATCH 11/24 rcutorture: Add rcuperf holdoff boot parameter to reduce interference

In reply to Paul E. McKenney

Boot-time activity can legitimately grab CPUs for extended time periods, so the commit adds a boot parameter to delay the start of the performance test until boot has completed. Defaults to 10 seconds.

---
 Documentation/kernel-parameters.txt | 6 ++++++
 kernel/rcu/rcuperf.c                | 5 +++++
 2 files changed, 11 insertions(+)
Documentation/kernel-parameters.txt +6 -0
index 951af481da5a..da9ee466789b 100644
@@ -3288,6 +3288,12 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 			Measure performance of expedited synchronous
 			grace-period primitives.
 
+	rcuperf.holdoff= [KNL]
+			Set test-start holdoff period.  The purpose of
+			this parameter is to delay the start of the
+			test until boot completes in order to avoid
+			interference.
+
 	rcuperf.nreaders= [KNL]
 			Set number of RCU readers.  The value -1 selects
 			N, where N is the number of CPUs.  A value
kernel/rcu/rcuperf.c +5 -0
index 12561f96f0a2..278600143bb6 100644
@@ -59,6 +59,7 @@ MODULE_AUTHOR("Paul E. McKenney <[email protected]>");
 	do { if (verbose) pr_alert("%s" PERF_FLAG "!!! %s\n", perf_type, s); } while (0)
 
 torture_param(bool, gp_exp, true, "Use expedited GP wait primitives");
+torture_param(int, holdoff, 10, "Holdoff time before test start (s)");
 torture_param(int, nreaders, -1, "Number of RCU reader threads");
 torture_param(int, nwriters, -1, "Number of RCU updater threads");
 torture_param(bool, shutdown, false, "Shutdown at end of performance tests.");
@@ -368,6 +369,10 @@ rcu_perf_writer(void *arg)
 	set_cpus_allowed_ptr(current, cpumask_of(me % nr_cpu_ids));
 	sp.sched_priority = 1;
 	sched_setscheduler_nocheck(current, SCHED_FIFO, &sp);
+
+	if (holdoff)
+		schedule_timeout_uninterruptible(holdoff * HZ);
+
 	t = ktime_get_mono_fast_ns();
 	if (atomic_inc_return(&n_rcu_perf_writer_started) >= nrealwriters) {
 		t_rcu_perf_writer_started = t;
Signature · 1 line
2.5.2
#12 lore raw

PATCH 12/24 rcutorture: Avoid RCU CPU stall warning and RT throttling

In reply to Paul E. McKenney

Running rcuperf can result in RCU CPU stall warnings and RT throttling. These occur because on of the real-time writer processes does ftrace_dump() while still running at real-time priority. This commit therefore prevents these problems by setting the writer thread back to SCHED_NORMAL (AKA SCHED_OTHER) before doing ftrace_dump().

In addition, this commit adds a small fixed delay before dumping ftrace buffer in order to decrease the probability that this dumping will interfere with other writers' grace periods.

---
 kernel/rcu/rcuperf.c | 4 ++++
 1 file changed, 4 insertions(+)
kernel/rcu/rcuperf.c +4 -0
index 278600143bb6..4c0572859ff0 100644
@@ -404,11 +404,15 @@ rcu_perf_writer(void *arg)
 			started = true;
 		if (!done && i >= MIN_MEAS) {
 			done = true;
+			sp.sched_priority = 0;
+			sched_setscheduler_nocheck(current,
+						   SCHED_NORMAL, &sp);
 			pr_alert("%s" PERF_FLAG
 				 "rcu_perf_writer %ld has %d measurements\n",
 				 perf_type, me, MIN_MEAS);
 			if (atomic_inc_return(&n_rcu_perf_writer_finished) >=
 			    nrealwriters) {
+				schedule_timeout_interruptible(10);
 				rcu_ftrace_dump(DUMP_ALL);
 				PERFOUT_STRING("Test complete");
 				t_rcu_perf_writer_finished = t;
Signature · 1 line
2.5.2
#13 lore raw

PATCH 13/24 rcutorture: Add largish-system rcuperf scenario

In reply to Paul E. McKenney

This commit adds an rcuperf scenario named TREE54 that uses 54 CPUs and provides a four-level rcu_node combining tree.

---
 .../selftests/rcutorture/configs/rcuperf/TREE54    | 23 ++++++++++++++++++++++
 1 file changed, 23 insertions(+)
 create mode 100644 tools/testing/selftests/rcutorture/configs/rcuperf/TREE54
tools/testing/selftests/rcutorture/configs/rcuperf/TREE54 new file +23 -0
new file mode 100644
index 000000000000..985fb170d13c
@@ -0,0 +1,23 @@
+CONFIG_SMP=y
+CONFIG_NR_CPUS=54
+CONFIG_PREEMPT_NONE=n
+CONFIG_PREEMPT_VOLUNTARY=n
+CONFIG_PREEMPT=y
+#CHECK#CONFIG_PREEMPT_RCU=y
+CONFIG_HZ_PERIODIC=n
+CONFIG_NO_HZ_IDLE=y
+CONFIG_NO_HZ_FULL=n
+CONFIG_RCU_FAST_NO_HZ=n
+CONFIG_RCU_TRACE=n
+CONFIG_HOTPLUG_CPU=n
+CONFIG_SUSPEND=n
+CONFIG_HIBERNATION=n
+CONFIG_RCU_FANOUT=3
+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
Signature · 1 line
2.5.2
#14 lore raw

PATCH 14/24 rcuperf: Do not wake up shutdown wait queue if "shutdown" is false.

In reply to Paul E. McKenney

From: Artem Savkov <[email protected]>

After finishing its tests rcuperf tries to wake up shutdown_wq even if "shutdown" param is set to false, resulting in a wake_up() call on an unitialized wait_queue_head_t which leads to "BUG: spinlock bad magic" and "BUG: unable to handle kernel NULL pointer dereference".

Fix by checking "shutdown" param before waking up the queue.

---
 kernel/rcu/rcuperf.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)
kernel/rcu/rcuperf.c +4 -2
index 4c0572859ff0..3cee0d8393ed 100644
@@ -423,8 +423,10 @@ rcu_perf_writer(void *arg)
 					b_rcu_perf_writer_finished =
 						cur_ops->completed();
 				}
-				smp_mb(); /* Assign before wake. */
-				wake_up(&shutdown_wq);
+				if (shutdown) {
+					smp_mb(); /* Assign before wake. */
+					wake_up(&shutdown_wq);
+				}
 			}
 		}
 		if (done && !alldone &&
Signature · 1 line
2.5.2
#15 lore raw

PATCH 15/24 rcutorture: Remove redundant initialization to zero

In reply to Paul E. McKenney

The current code initializes the global per-CPU variables rcu_torture_count and rcu_torture_batch to zero. However, C does this initialization by default, and explicit initialization of per-CPU variables now needs a different syntax if "make tags" is to work. This commit therefore removes the initialization.

---
 kernel/rcu/rcutorture.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
kernel/rcu/rcutorture.c +2 -2
index 9234e75b106a..52b49fe90919 100644
@@ -130,8 +130,8 @@ static struct rcu_torture __rcu *rcu_torture_current;
 static unsigned long rcu_torture_current_version;
 static struct rcu_torture rcu_tortures[10 * RCU_TORTURE_PIPE_LEN];
 static DEFINE_SPINLOCK(rcu_torture_lock);
-static DEFINE_PER_CPU(long [RCU_TORTURE_PIPE_LEN + 1], rcu_torture_count) = { 0 };
-static DEFINE_PER_CPU(long [RCU_TORTURE_PIPE_LEN + 1], rcu_torture_batch) = { 0 };
+static DEFINE_PER_CPU(long [RCU_TORTURE_PIPE_LEN + 1], rcu_torture_count);
+static DEFINE_PER_CPU(long [RCU_TORTURE_PIPE_LEN + 1], rcu_torture_batch);
 static atomic_t rcu_torture_wcount[RCU_TORTURE_PIPE_LEN + 1];
 static atomic_t n_rcu_torture_alloc;
 static atomic_t n_rcu_torture_alloc_fail;
Signature · 1 line
2.5.2
#16 lore raw

PATCH 16/24 rcutorture: Consider FROZEN hotplug notifier transitions

In reply to Paul E. McKenney

From: Anna-Maria Gleixner <[email protected]>

The hotplug notifier rcutorture_cpu_notify() doesn't consider the corresponding CPU_XXX_FROZEN transitions. They occur on suspend/resume and are usually handled the same way as the corresponding non frozen transitions.

Mask the switch case action argument with '~CPU_TASKS_FROZEN' to map CPU_XXX_FROZEN hotplug transitions on corresponding non-frozen transitions.

---
 kernel/rcu/rcutorture.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/rcu/rcutorture.c +1 -1
index 52b49fe90919..633a68a09440 100644
@@ -1585,7 +1585,7 @@ static int rcutorture_cpu_notify(struct notifier_block *self,
 {
 	long cpu = (long)hcpu;
 
-	switch (action) {
+	switch (action & ~CPU_TASKS_FROZEN) {
 	case CPU_ONLINE:
 	case CPU_DOWN_FAILED:
 		(void)rcutorture_booster_init(cpu);
Signature · 1 line
2.5.2
#17 lore raw

PATCH 17/24 torture: Clarify refusal to run more than one torture test

In reply to Paul E. McKenney

This commit clarifies error messages -- you only get to run one torture test at a time!

---
 kernel/torture.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
kernel/torture.c +2 -1
index 44aa462d033f..e912ccd960f0 100644
@@ -602,8 +602,9 @@ bool torture_init_begin(char *ttype, bool v, int *runnable)
 {
 	mutex_lock(&fullstop_mutex);
 	if (torture_type != NULL) {
-		pr_alert("torture_init_begin: refusing %s init: %s running",
+		pr_alert("torture_init_begin: Refusing %s init: %s running.\n",
 			 ttype, torture_type);
+		pr_alert("torture_init_begin: One torture test at a time!\n");
 		mutex_unlock(&fullstop_mutex);
 		return false;
 	}
Signature · 1 line
2.5.2
#18 lore raw

PATCH 18/24 torture: Kill qemu, not parent process

In reply to Paul E. McKenney

The current hang-check machinery in the rcutorture scripts uses "$!" of a parenthesized bash statement to capture the pid. Unfortunately, this captures not qemu's pid, but rather that of its parent that implements the parenthesized statement. This commit therefore adjusts things so as to capture qemu's actual pid, which then allows the script to actually kill qemu in event of a kernel hang.

---
 .../selftests/rcutorture/bin/kvm-test-1-run.sh     | 30 +++++++++++++++++-----
 1 file changed, 24 insertions(+), 6 deletions(-)
tools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh +24 -6
index 0f80eefb0bfd..2eb8fefbe7d9 100755
@@ -168,14 +168,25 @@ then
 fi
 echo "NOTE: $QEMU either did not run or was interactive" > $resdir/console.log
 echo $QEMU $qemu_args -m 512 -kernel $resdir/bzImage -append \"$qemu_append $boot_args\" > $resdir/qemu-cmd
-( $QEMU $qemu_args -m 512 -kernel $resdir/bzImage -append "$qemu_append $boot_args"; echo $? > $resdir/qemu-retval ) &
-qemu_pid=$!
+( $QEMU $qemu_args -m 512 -kernel $resdir/bzImage -append "$qemu_append $boot_args"& echo $! > $resdir/qemu_pid; wait `cat  $resdir/qemu_pid`; echo $? > $resdir/qemu-retval ) &
 commandcompleted=0
-echo Monitoring qemu job at pid $qemu_pid
+sleep 10 # Give qemu's pid a chance to reach the file
+if test -s "$resdir/qemu_pid"
+then
+	qemu_pid=`cat "$resdir/qemu_pid"`
+	echo Monitoring qemu job at pid $qemu_pid
+else
+	qemu_pid=""
+	echo Monitoring qemu job at yet-as-unknown pid
+fi
 while :
 do
+	if test -z "$qemu_pid" -a -s "$resdir/qemu_pid"
+	then
+		qemu_pid=`cat "$resdir/qemu_pid"`
+	fi
 	kruntime=`awk 'BEGIN { print systime() - '"$kstarttime"' }' < /dev/null`
-	if kill -0 $qemu_pid > /dev/null 2>&1
+	if test -z "$qemu_pid" || kill -0 "$qemu_pid" > /dev/null 2>&1
 	then
 		if test $kruntime -ge $seconds
 		then
@@ -195,12 +206,16 @@ do
 				ps -fp $killpid >> $resdir/Warnings 2>&1
 			fi
 		else
-			echo ' ---' `date`: Kernel done
+			echo ' ---' `date`: "Kernel done"
 		fi
 		break
 	fi
 done
-if test $commandcompleted -eq 0
+if test -z "$qemu_pid" -a -s "$resdir/qemu_pid"
+then
+	qemu_pid=`cat "$resdir/qemu_pid"`
+fi
+if test $commandcompleted -eq 0 -a -n "$qemu_pid"
 then
 	echo Grace period for qemu job at pid $qemu_pid
 	while :
@@ -220,6 +235,9 @@ then
 		fi
 		sleep 1
 	done
+elif test -z "$qemu_pid"
+then
+	echo Unknown PID, cannot kill qemu command
 fi
 
 parse-torture.sh $resdir/console.log $title
Signature · 1 line
2.5.2
#19 lore raw

PATCH 19/24 rcutorture: Convert test duration to seconds early

In reply to Paul E. McKenney

This commit converts test duration from minutes to seconds early on in order to prepare for upcoming OS-jitter-injection changes.

---
 tools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh | 5 ++---
 tools/testing/selftests/rcutorture/bin/kvm.sh            | 4 ++--
 2 files changed, 4 insertions(+), 5 deletions(-)
tools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh +2 -3
index 2eb8fefbe7d9..73a265668421 100755
@@ -6,7 +6,7 @@
 # Execute this in the source tree.  Do not run it as a background task
 # because qemu does not seem to like that much.
 #
-# Usage: kvm-test-1-run.sh config builddir resdir minutes qemu-args boot_args
+# Usage: kvm-test-1-run.sh config builddir resdir seconds qemu-args boot_args
 #
 # qemu-args defaults to "-enable-kvm -soundhw pcspk -nographic", along with
 #			arguments specifying the number of CPUs and other
@@ -123,8 +123,7 @@ while test -f $builddir.ready
 do
 	sleep 1
 done
-minutes=$4
-seconds=$(($minutes * 60))
+seconds=$4
 qemu_args=$5
 boot_args=$6
 
tools/testing/selftests/rcutorture/bin/kvm.sh +2 -2
index c33cb582b3dc..704e219f67a7 100755
@@ -34,7 +34,7 @@ T=/tmp/kvm.sh.$$
 trap 'rm -rf $T' 0
 mkdir $T
 
-dur=30
+dur=$((30*60))
 dryrun=""
 KVM="`pwd`/tools/testing/selftests/rcutorture"; export KVM
 PATH=${KVM}/bin:$PATH; export PATH
@@ -116,7 +116,7 @@ do
 		;;
 	--duration)
 		checkarg --duration "(minutes)" $# "$2" '^[0-9]*$' '^error'
-		dur=$2
+		dur=$(($2*60))
 		shift
 		;;
 	--interactive)
Signature · 1 line
2.5.2
#20 lore raw

PATCH 20/24 rcutorture: Add OS-jitter capability

In reply to Paul E. McKenney

This commit adds a --jitter OS-jitter capability to expose bugs based on no-delay assumptions.

---
 tools/testing/selftests/rcutorture/bin/jitter.sh | 83 ++++++++++++++++++++++++
 tools/testing/selftests/rcutorture/bin/kvm.sh    | 18 +++++
 2 files changed, 101 insertions(+)
 create mode 100755 tools/testing/selftests/rcutorture/bin/jitter.sh
tools/testing/selftests/rcutorture/bin/jitter.sh new file +83 -0
new file mode 100755
index 000000000000..276d6b93f9ec
@@ -0,0 +1,83 @@
+#!/bin/bash
+#
+# Alternate sleeping and spinning on randomly selected CPUs.  The purpose
+# of this script is to inflict random OS jitter on a concurrently running
+# test.
+#
+# Usage: jitter.sh me duration [ sleepmax [ spinmax ] ]
+#
+# me: Random-number-generator seed salt.
+# duration: Time to run in seconds.
+# sleepmax: Maximum microseconds to sleep, defaults to one second.
+# spinmax: Maximum microseconds to spin, defaults to one millisecond.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, you can access it online at
+# http://www.gnu.org/licenses/gpl-2.0.html.
+#
+# Copyright (C) IBM Corporation, 2016
+#
+# Authors: Paul E. McKenney <[email protected]>
+
+me=$(($1 * 1000))
+duration=$2
+sleepmax=${3-1000000}
+spinmax=${4-1000}
+
+n=1
+
+starttime=`awk 'BEGIN { print systime(); }' < /dev/null`
+
+while :
+do
+	# Check for done.
+	t=`awk -v s=$starttime 'BEGIN { print systime() - s; }' < /dev/null`
+	if test "$t" -gt "$duration"
+	then
+		exit 0;
+	fi
+
+	# Set affinity to randomly selected CPU
+	cpus=`ls /sys/devices/system/cpu/*/online |
+		sed -e 's,/[^/]*$,,' -e 's/^[^0-9]*//' |
+		grep -v '^0*$'`
+	cpumask=`awk -v cpus="$cpus" -v me=$me -v n=$n 'BEGIN {
+		srand(n + me + systime());
+		ncpus = split(cpus, ca);
+		curcpu = ca[int(rand() * ncpus + 1)];
+		printf("%#x\n", lshift(1, curcpu));
+	}' < /dev/null`
+	n=$(($n+1))
+	taskset -p $cpumask $$ > /dev/null
+
+	# Sleep a random duration
+	sleeptime=`awk -v me=$me -v n=$n -v sleepmax=$sleepmax 'BEGIN {
+		srand(n + me + systime());
+		printf("%06d", int(rand() * sleepmax));
+	}' < /dev/null`
+	n=$(($n+1))
+	sleep .$sleeptime
+
+	# Spin a random duration
+	limit=`awk -v me=$me -v n=$n -v spinmax=$spinmax 'BEGIN {
+		srand(n + me + systime());
+		printf("%06d", int(rand() * spinmax));
+	}' < /dev/null`
+	n=$(($n+1))
+	for i in {1..$limit}
+	do
+		echo > /dev/null
+	done
+done
+
+exit 1
tools/testing/selftests/rcutorture/bin/kvm.sh +18 -0
index 704e219f67a7..0d598145873e 100755
@@ -48,6 +48,7 @@ resdir=""
 configs=""
 cpus=0
 ds=`date +%Y.%m.%d-%H:%M:%S`
+jitter=0
 
 . functions.sh
 
@@ -63,6 +64,7 @@ usage () {
 	echo "       --dryrun sched|script"
 	echo "       --duration minutes"
 	echo "       --interactive"
+	echo "       --jitter N [ maxsleep (us) [ maxspin (us) ] ]"
 	echo "       --kmake-arg kernel-make-arguments"
 	echo "       --mac nn:nn:nn:nn:nn:nn"
 	echo "       --no-initrd"
@@ -122,6 +124,11 @@ do
 	--interactive)
 		TORTURE_QEMU_INTERACTIVE=1; export TORTURE_QEMU_INTERACTIVE
 		;;
+	--jitter)
+		checkarg --jitter "(# threads [ sleep [ spin ] ])" $# "$2" '^-\{,1\}[0-9]\+\( \+[0-9]\+\)\{,2\} *$' '^error$'
+		jitter="$2"
+		shift
+		;;
 	--kmake-arg)
 		checkarg --kmake-arg "(kernel make arguments)" $# "$2" '.*' '^error$'
 		TORTURE_KMAKE_ARG="$2"
@@ -299,6 +306,7 @@ awk < $T/cfgcpu.pack \
 	-v CONFIGDIR="$CONFIGFRAG/" \
 	-v KVM="$KVM" \
 	-v ncpus=$cpus \
+	-v jitter="$jitter" \
 	-v rd=$resdir/$ds/ \
 	-v dur=$dur \
 	-v TORTURE_QEMU_ARG="$TORTURE_QEMU_ARG" \
@@ -359,6 +367,16 @@ function dump(first, pastlast, batchnum)
 		print "\techo ----", cfr[j], cpusr[j] ovf ": Starting kernel. `date` >> " rd "/log";
 		print "fi"
 	}
+	njitter = 0;
+	split(jitter, ja);
+	if (ja[1] == -1 && ncpus == 0)
+		njitter = 1;
+	else if (ja[1] == -1)
+		njitter = ncpus;
+	else
+		njitter = ja[1];
+	for (j = 0; j < njitter; j++)
+		print "jitter.sh " j " " dur " " ja[2] " " ja[3] "&"
 	print "wait"
 	print "if test -z \"$TORTURE_BUILDONLY\""
 	print "then"
Signature · 1 line
2.5.2
#21 lore raw

PATCH 21/24 rcutorture: Don't rebuild identical kernel

In reply to Paul E. McKenney

Currently, if the user specifies multiple runs of a given test configuration, the scripting does multiple kernel builds. This wastes both time and disk space, so this commit makes the scripting use the first build for all runs of a given test configuration.

---
 .../selftests/rcutorture/bin/kvm-test-1-run.sh     | 26 ++++++++++++++++------
 1 file changed, 19 insertions(+), 7 deletions(-)
tools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh +19 -7
index 73a265668421..4109f306d855 100755
@@ -91,25 +91,33 @@ fi
 # CONFIG_PCMCIA=n
 # CONFIG_CARDBUS=n
 # CONFIG_YENTA=n
-if kvm-build.sh $config_template $builddir $T
+base_resdir=`echo $resdir | sed -e 's/\.[0-9]\+$//'`
+if test "$base_resdir" != "$resdir" -a -f $base_resdir/bzImage -a -f $base_resdir/vmlinux
 then
+	# Rerunning previous test, so use that test's kernel.
+	QEMU="`identify_qemu $base_resdir/vmlinux`"
+	KERNEL=$base_resdir/bzImage
+	ln -s $base_resdir/Make*.out $resdir  # for kvm-recheck.sh
+	ln -s $base_resdir/.config $resdir  # for kvm-recheck.sh
+elif kvm-build.sh $config_template $builddir $T
+then
+	# Had to build a kernel for this test.
 	QEMU="`identify_qemu $builddir/vmlinux`"
 	BOOT_IMAGE="`identify_boot_image $QEMU`"
 	cp $builddir/Make*.out $resdir
+	cp $builddir/vmlinux $resdir
 	cp $builddir/.config $resdir
 	if test -n "$BOOT_IMAGE"
 	then
 		cp $builddir/$BOOT_IMAGE $resdir
+		KERNEL=$resdir/bzImage
 	else
 		echo No identifiable boot image, not running KVM, see $resdir.
 		echo Do the torture scripts know about your architecture?
 	fi
 	parse-build.sh $resdir/Make.out $title
-	if test -f $builddir.wait
-	then
-		mv $builddir.wait $builddir.ready
-	fi
 else
+	# Build failed.
 	cp $builddir/Make*.out $resdir
 	cp $builddir/.config $resdir || :
 	echo Build failed, not running KVM, see $resdir.
@@ -119,6 +127,10 @@ else
 	fi
 	exit 1
 fi
+if test -f $builddir.wait
+then
+	mv $builddir.wait $builddir.ready
+fi
 while test -f $builddir.ready
 do
 	sleep 1
@@ -166,8 +178,8 @@ then
 	exit 0
 fi
 echo "NOTE: $QEMU either did not run or was interactive" > $resdir/console.log
-echo $QEMU $qemu_args -m 512 -kernel $resdir/bzImage -append \"$qemu_append $boot_args\" > $resdir/qemu-cmd
-( $QEMU $qemu_args -m 512 -kernel $resdir/bzImage -append "$qemu_append $boot_args"& echo $! > $resdir/qemu_pid; wait `cat  $resdir/qemu_pid`; echo $? > $resdir/qemu-retval ) &
+echo $QEMU $qemu_args -m 512 -kernel $KERNEL -append \"$qemu_append $boot_args\" > $resdir/qemu-cmd
+( $QEMU $qemu_args -m 512 -kernel $KERNEL -append "$qemu_append $boot_args"& echo $! > $resdir/qemu_pid; wait `cat  $resdir/qemu_pid`; echo $? > $resdir/qemu-retval ) &
 commandcompleted=0
 sleep 10 # Give qemu's pid a chance to reach the file
 if test -s "$resdir/qemu_pid"
Signature · 1 line
2.5.2
#22 lore raw

PATCH 22/24 rcutorture: Dump trace buffer upon shutdown

In reply to Paul E. McKenney

When running from the scripts, rcutorture is completely headless, so there is no way to to manually dump the trace buffer. This commit therefore unconditionally dumps the trace buffer upon timed shutdown. However, if you are using rmmod to end the test, it is still up to you to manually dump the trace buffer.

---
 kernel/torture.c | 1 +
 1 file changed, 1 insertion(+)
kernel/torture.c +1 -0
index e912ccd960f0..fa0bdeee17ac 100644
@@ -451,6 +451,7 @@ static int torture_shutdown(void *arg)
 		torture_shutdown_hook();
 	else
 		VERBOSE_TOROUT_STRING("No torture_shutdown_hook(), skipping.");
+	ftrace_dump(DUMP_ALL);
 	kernel_power_off();	/* Shut down the system. */
 	return 0;
 }
Signature · 1 line
2.5.2
#23 lore raw

PATCH 23/24 rcutorture: Add irqs-disabled test for call_rcu()

In reply to Paul E. McKenney

Mutation testing carried out by Iftekhar Ahmed of Oregon State University showed that rcutorture is failing to test invocations of call_rcu() having interrupts disabled. This commit therefore adds interrupt disabling around one of the existing invocations of call_rcu() (and friends).

---
 kernel/rcu/rcutorture.c | 2 ++
 1 file changed, 2 insertions(+)
kernel/rcu/rcutorture.c +2 -0
index 633a68a09440..084a28a732eb 100644
@@ -1478,7 +1478,9 @@ static int rcu_torture_barrier_cbs(void *arg)
 		 * The above smp_load_acquire() ensures barrier_phase load
 		 * is ordered before the folloiwng ->call().
 		 */
+		local_irq_disable(); /* Just to test no-irq call_rcu(). */
 		cur_ops->call(&rcu, rcu_torture_barrier_cbf);
+		local_irq_enable();
 		if (atomic_dec_and_test(&barrier_cbs_count))
 			wake_up(&barrier_wq);
 	} while (!torture_must_stop());
Signature · 1 line
2.5.2
#24 lore raw

PATCH 24/24 rcutorture: Add boot-time adjustment of leaf fanout

In reply to Paul E. McKenney

Currently, the rcutorture scripts do not test boot-time adjustment of leaf fanout (via the rcutree.rcu_fanout_leaf boot parameter), as was noted during testing carried out by Iftekhar Ahmed of Oregon State University. This commit therefore adjusts TREE04's CONFIG_RCU_FANOUT_LEAF from 4 to 3, and also adds rcutree.rcu_fanout_leaf=4 to its boot parameters. This change forces RCU's boot-time geometry-change code to be exercised.

---
 tools/testing/selftests/rcutorture/configs/rcu/TREE04      | 2 +-
 tools/testing/selftests/rcutorture/configs/rcu/TREE04.boot | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)
tools/testing/selftests/rcutorture/configs/rcu/TREE04 +1 -1
index 39a2c6d7d7ec..17cbe098b115 100644
@@ -14,7 +14,7 @@ CONFIG_HOTPLUG_CPU=n
 CONFIG_SUSPEND=n
 CONFIG_HIBERNATION=n
 CONFIG_RCU_FANOUT=4
-CONFIG_RCU_FANOUT_LEAF=4
+CONFIG_RCU_FANOUT_LEAF=3
 CONFIG_RCU_NOCB_CPU=n
 CONFIG_DEBUG_LOCK_ALLOC=n
 CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
tools/testing/selftests/rcutorture/configs/rcu/TREE04.boot +1 -1
index 0fc8a3428938..e34c33430447 100644
@@ -1 +1 @@
-rcutorture.torture_type=rcu_bh
+rcutorture.torture_type=rcu_bh rcutree.rcu_fanout_leaf=4
Signature · 1 line
2.5.2