Skip to contentSkip to conversation

Torture-test updates for 4.3

PATCH New Paul E. McKenney 1 participant 7 messages Jul 17, 2015

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

cover Torture-test updates for 4.3

Hello!

This series contains torture-test updates:

1. Improve bounds checking for n_barrier_cbs: No more negatives.

2. Improve bounds checking for nfakewriters: No more negatives.

3. Improve bounds checking for shuffle_interval: No more negatives.

4. Fix rcu_torture_cbflood() for callback-free RCU to avoid
occasional segfaults when disabled.

5. Add RCU-tasks qualifier to dereference to avoid lockdep
false positives during torture testing.

6. Enable lockdep-RCU on TASKS01 to improve test coverage.

Thanx, Paul

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

 b/kernel/rcu/rcutorture.c                                |   40 ++++++++++-----
 b/tools/testing/selftests/rcutorture/configs/rcu/TASKS01 |    4 -
 2 files changed, 29 insertions(+), 15 deletions(-)
#1 lore raw

PATCH 1/6 rcutorture: Better bounds checking for n_barrier_cbs

From: "Paul E. McKenney" <[email protected]>

A negative value for rcutorture.n_barrier_cbs can pass a negative value to the memory allocator, so this commit instead causes rcu_barrier() testing to be disabled in this case.

---
 kernel/rcu/rcutorture.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/rcu/rcutorture.c +1 -1
index 59e32684c23b..7e29a3266139 100644
@@ -1507,7 +1507,7 @@ static int rcu_torture_barrier_init(void)
 	int i;
 	int ret;
 
-	if (n_barrier_cbs == 0)
+	if (n_barrier_cbs <= 0)
 		return 0;
 	if (cur_ops->call == NULL || cur_ops->cb_barrier == NULL) {
 		pr_alert("%s" TORTURE_FLAG
Signature · 1 line
1.8.1.5
#2 lore raw

PATCH 2/6 rcutorture: Check nfakewriters parameter

From: "Paul E. McKenney" <[email protected]>

Currently, a negative value for rcutorture.nfakewriters= can cause rcutorture to pass a negative size to the memory allocator, which is not really a particularly good thing to do. This commit therefore adds bounds checking to this parameter, so that values that are less than or equal to zero disable fake writing.

---
 kernel/rcu/rcutorture.c | 15 +++++++++------
 1 file changed, 9 insertions(+), 6 deletions(-)
kernel/rcu/rcutorture.c +9 -6
index 7e29a3266139..2cbe569ac5dd 100644
@@ -1786,12 +1786,15 @@ rcu_torture_init(void)
 					  writer_task);
 	if (firsterr)
 		goto unwind;
-	fakewriter_tasks = kzalloc(nfakewriters * sizeof(fakewriter_tasks[0]),
-				   GFP_KERNEL);
-	if (fakewriter_tasks == NULL) {
-		VERBOSE_TOROUT_ERRSTRING("out of memory");
-		firsterr = -ENOMEM;
-		goto unwind;
+	if (nfakewriters > 0) {
+		fakewriter_tasks = kzalloc(nfakewriters *
+					   sizeof(fakewriter_tasks[0]),
+					   GFP_KERNEL);
+		if (fakewriter_tasks == NULL) {
+			VERBOSE_TOROUT_ERRSTRING("out of memory");
+			firsterr = -ENOMEM;
+			goto unwind;
+		}
 	}
 	for (i = 0; i < nfakewriters; i++) {
 		firsterr = torture_create_kthread(rcu_torture_fakewriter,
Signature · 1 line
1.8.1.5
#3 lore raw

PATCH 3/6 rcutorture: Bounds-check rcutorture.shuffle_interval

In reply to Paul E. McKenney

From: "Paul E. McKenney" <[email protected]>

Specifying a negative rcutorture.shuffle_interval value will cause a negative value to be used as a sleep time. This commit therefore refuses to start shuffling unless the rcutorture.shuffle_interval value is greater than zero.

---
 kernel/rcu/rcutorture.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/rcu/rcutorture.c +1 -1
index 2cbe569ac5dd..1cead7806ca6 100644
@@ -1821,7 +1821,7 @@ rcu_torture_init(void)
 		if (firsterr)
 			goto unwind;
 	}
-	if (test_no_idle_hz) {
+	if (test_no_idle_hz && shuffle_interval > 0) {
 		firsterr = torture_shuffle_init(shuffle_interval * HZ);
 		if (firsterr)
 			goto unwind;
Signature · 1 line
1.8.1.5
#4 lore raw

PATCH 4/6 rcutorture: Fix rcu_torture_cbflood() for callback-free RCU

In reply to Paul E. McKenney

From: "Paul E. McKenney" <[email protected]>

The rcu_torture_cbflood() function correctly checks for flavors of RCU that lack analogs to call_rcu() and rcu_barrier(), but in that case it fails to terminate correctly. In fact, it terminates so incorrectly that segfaults can result. This commit therefore causes rcu_torture_cbflood() to do the proper wait-for-stop procedure.

---
 kernel/rcu/rcutorture.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)
kernel/rcu/rcutorture.c +2 -3
index 1cead7806ca6..e0eda3c1b621 100644
@@ -823,9 +823,7 @@ rcu_torture_cbflood(void *arg)
 	}
 	if (err) {
 		VERBOSE_TOROUT_STRING("rcu_torture_cbflood disabled: Bad args or OOM");
-		while (!torture_must_stop())
-			schedule_timeout_interruptible(HZ);
-		return 0;
+		goto wait_for_stop;
 	}
 	VERBOSE_TOROUT_STRING("rcu_torture_cbflood task started");
 	do {
@@ -844,6 +842,7 @@ rcu_torture_cbflood(void *arg)
 		stutter_wait("rcu_torture_cbflood");
 	} while (!torture_must_stop());
 	vfree(rhp);
+wait_for_stop:
 	torture_kthread_stopping("rcu_torture_cbflood");
 	return 0;
 }
Signature · 1 line
1.8.1.5
#5 lore raw

PATCH 5/6 rcutorture: Add RCU-tasks qualifier to dereference

In reply to Paul E. McKenney

From: "Paul E. McKenney" <[email protected]>

Although RCU-tasks isn't really designed to support rcu_dereference() and list manipulation, that is how rcutorture tests it. Which means that lockdep-RCU complains about the rcu_dereference_check() invocations because RCU-tasks doesn't have read-side markers. This commit therefore creates a torturing_tasks() to silence the lockdep-RCU complaints from rcu_dereference_check() when RCU-tasks is being tortured.

---
 kernel/rcu/rcutorture.c | 16 ++++++++++++++--
 1 file changed, 14 insertions(+), 2 deletions(-)
kernel/rcu/rcutorture.c +14 -2
index e0eda3c1b621..67b3f260720e 100644
@@ -684,10 +684,20 @@ static struct rcu_torture_ops tasks_ops = {
 
 #define RCUTORTURE_TASKS_OPS &tasks_ops,
 
+static bool __maybe_unused torturing_tasks(void)
+{
+	return cur_ops == &tasks_ops;
+}
+
 #else /* #ifdef CONFIG_TASKS_RCU */
 
 #define RCUTORTURE_TASKS_OPS
 
+static bool torturing_tasks(void)
+{
+	return false;
+}
+
 #endif /* #else #ifdef CONFIG_TASKS_RCU */
 
 /*
@@ -1087,7 +1097,8 @@ static void rcu_torture_timer(unsigned long unused)
 	p = rcu_dereference_check(rcu_torture_current,
 				  rcu_read_lock_bh_held() ||
 				  rcu_read_lock_sched_held() ||
-				  srcu_read_lock_held(srcu_ctlp));
+				  srcu_read_lock_held(srcu_ctlp) ||
+				  torturing_tasks());
 	if (p == NULL) {
 		/* Leave because rcu_torture_writer is not yet underway */
 		cur_ops->readunlock(idx);
@@ -1161,7 +1172,8 @@ rcu_torture_reader(void *arg)
 		p = rcu_dereference_check(rcu_torture_current,
 					  rcu_read_lock_bh_held() ||
 					  rcu_read_lock_sched_held() ||
-					  srcu_read_lock_held(srcu_ctlp));
+					  srcu_read_lock_held(srcu_ctlp) ||
+					  torturing_tasks());
 		if (p == NULL) {
 			/* Wait for rcu_torture_writer to get underway */
 			cur_ops->readunlock(idx);
Signature · 1 line
1.8.1.5
#6 lore raw

PATCH 6/6 rcutorture: Enable lockdep-RCU on TASKS01

In reply to Paul E. McKenney

From: "Paul E. McKenney" <[email protected]>

Currently none of the RCU-tasks scenarios enables lockdep-RCU, which causes bugs to be missed. This commit therefore enables lockdep-RCU on TASKS01.

---
 tools/testing/selftests/rcutorture/configs/rcu/TASKS01 | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
tools/testing/selftests/rcutorture/configs/rcu/TASKS01 +2 -2
index 2cc0e60eba6e..bafe94cbd739 100644
@@ -5,6 +5,6 @@ CONFIG_PREEMPT_NONE=n
 CONFIG_PREEMPT_VOLUNTARY=n
 CONFIG_PREEMPT=y
 CONFIG_DEBUG_LOCK_ALLOC=y
-CONFIG_PROVE_LOCKING=n
-#CHECK#CONFIG_PROVE_RCU=n
+CONFIG_PROVE_LOCKING=y
+#CHECK#CONFIG_PROVE_RCU=y
 CONFIG_RCU_EXPERT=y
Signature · 1 line
1.8.1.5