summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul E. McKenney <paulmck@linux.ibm.com>2018-12-10 12:44:52 -0500
committerPaul E. McKenney <paulmck@linux.ibm.com>2019-01-25 18:37:10 -0500
commit3a6cb58f159e64241b2af9374acad41a70939349 (patch)
treeada940f453392a61ee945b23974647841ee65700
parent0d8a9ea9764a0e34e17e3b80a2be3855de239d6e (diff)
rcutorture: Add grace period after CPU offline
Beyond a certain point in the CPU-hotplug offline process, timers get stranded on the outgoing CPU, and won't fire until that CPU comes back online, which might well be never. This commit therefore adds a hook in torture_onoff_init() that is invoked from torture_offline(), which rcutorture uses to occasionally wait for a grace period. This should result in failures for RCU implementations that rely on stranded timers eventually firing in the absence of the CPU coming back online. Reported-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> Signed-off-by: Paul E. McKenney <paulmck@linux.ibm.com>
-rw-r--r--include/linux/torture.h3
-rw-r--r--kernel/locking/locktorture.c2
-rw-r--r--kernel/rcu/rcutorture.c11
-rw-r--r--kernel/torture.c6
4 files changed, 18 insertions, 4 deletions
diff --git a/include/linux/torture.h b/include/linux/torture.h
index 48fad21109fc..f2d3bcbf4337 100644
--- a/include/linux/torture.h
+++ b/include/linux/torture.h
@@ -50,11 +50,12 @@
50 do { if (verbose) pr_alert("%s" TORTURE_FLAG "!!! %s\n", torture_type, s); } while (0) 50 do { if (verbose) pr_alert("%s" TORTURE_FLAG "!!! %s\n", torture_type, s); } while (0)
51 51
52/* Definitions for online/offline exerciser. */ 52/* Definitions for online/offline exerciser. */
53typedef void torture_ofl_func(void);
53bool torture_offline(int cpu, long *n_onl_attempts, long *n_onl_successes, 54bool torture_offline(int cpu, long *n_onl_attempts, long *n_onl_successes,
54 unsigned long *sum_offl, int *min_onl, int *max_onl); 55 unsigned long *sum_offl, int *min_onl, int *max_onl);
55bool torture_online(int cpu, long *n_onl_attempts, long *n_onl_successes, 56bool torture_online(int cpu, long *n_onl_attempts, long *n_onl_successes,
56 unsigned long *sum_onl, int *min_onl, int *max_onl); 57 unsigned long *sum_onl, int *min_onl, int *max_onl);
57int torture_onoff_init(long ooholdoff, long oointerval); 58int torture_onoff_init(long ooholdoff, long oointerval, torture_ofl_func *f);
58void torture_onoff_stats(void); 59void torture_onoff_stats(void);
59bool torture_onoff_failures(void); 60bool torture_onoff_failures(void);
60 61
diff --git a/kernel/locking/locktorture.c b/kernel/locking/locktorture.c
index 7d0b0ed74404..c8b348097bb5 100644
--- a/kernel/locking/locktorture.c
+++ b/kernel/locking/locktorture.c
@@ -970,7 +970,7 @@ static int __init lock_torture_init(void)
970 /* Prepare torture context. */ 970 /* Prepare torture context. */
971 if (onoff_interval > 0) { 971 if (onoff_interval > 0) {
972 firsterr = torture_onoff_init(onoff_holdoff * HZ, 972 firsterr = torture_onoff_init(onoff_holdoff * HZ,
973 onoff_interval * HZ); 973 onoff_interval * HZ, NULL);
974 if (firsterr) 974 if (firsterr)
975 goto unwind; 975 goto unwind;
976 } 976 }
diff --git a/kernel/rcu/rcutorture.c b/kernel/rcu/rcutorture.c
index 0955f3a20952..9eb9235c1ec9 100644
--- a/kernel/rcu/rcutorture.c
+++ b/kernel/rcu/rcutorture.c
@@ -2243,6 +2243,14 @@ static void rcu_test_debug_objects(void)
2243#endif /* #else #ifdef CONFIG_DEBUG_OBJECTS_RCU_HEAD */ 2243#endif /* #else #ifdef CONFIG_DEBUG_OBJECTS_RCU_HEAD */
2244} 2244}
2245 2245
2246static void rcutorture_sync(void)
2247{
2248 static unsigned long n;
2249
2250 if (cur_ops->sync && !(++n & 0xfff))
2251 cur_ops->sync();
2252}
2253
2246static int __init 2254static int __init
2247rcu_torture_init(void) 2255rcu_torture_init(void)
2248{ 2256{
@@ -2404,7 +2412,8 @@ rcu_torture_init(void)
2404 firsterr = torture_shutdown_init(shutdown_secs, rcu_torture_cleanup); 2412 firsterr = torture_shutdown_init(shutdown_secs, rcu_torture_cleanup);
2405 if (firsterr) 2413 if (firsterr)
2406 goto unwind; 2414 goto unwind;
2407 firsterr = torture_onoff_init(onoff_holdoff * HZ, onoff_interval); 2415 firsterr = torture_onoff_init(onoff_holdoff * HZ, onoff_interval,
2416 rcutorture_sync);
2408 if (firsterr) 2417 if (firsterr)
2409 goto unwind; 2418 goto unwind;
2410 firsterr = rcu_torture_stall_init(); 2419 firsterr = rcu_torture_stall_init();
diff --git a/kernel/torture.c b/kernel/torture.c
index bbf6d473e50c..a03ff722352b 100644
--- a/kernel/torture.c
+++ b/kernel/torture.c
@@ -75,6 +75,7 @@ static DEFINE_MUTEX(fullstop_mutex);
75static struct task_struct *onoff_task; 75static struct task_struct *onoff_task;
76static long onoff_holdoff; 76static long onoff_holdoff;
77static long onoff_interval; 77static long onoff_interval;
78static torture_ofl_func *onoff_f;
78static long n_offline_attempts; 79static long n_offline_attempts;
79static long n_offline_successes; 80static long n_offline_successes;
80static unsigned long sum_offline; 81static unsigned long sum_offline;
@@ -118,6 +119,8 @@ bool torture_offline(int cpu, long *n_offl_attempts, long *n_offl_successes,
118 pr_alert("%s" TORTURE_FLAG 119 pr_alert("%s" TORTURE_FLAG
119 "torture_onoff task: offlined %d\n", 120 "torture_onoff task: offlined %d\n",
120 torture_type, cpu); 121 torture_type, cpu);
122 if (onoff_f)
123 onoff_f();
121 (*n_offl_successes)++; 124 (*n_offl_successes)++;
122 delta = jiffies - starttime; 125 delta = jiffies - starttime;
123 *sum_offl += delta; 126 *sum_offl += delta;
@@ -243,11 +246,12 @@ stop:
243/* 246/*
244 * Initiate online-offline handling. 247 * Initiate online-offline handling.
245 */ 248 */
246int torture_onoff_init(long ooholdoff, long oointerval) 249int torture_onoff_init(long ooholdoff, long oointerval, torture_ofl_func *f)
247{ 250{
248#ifdef CONFIG_HOTPLUG_CPU 251#ifdef CONFIG_HOTPLUG_CPU
249 onoff_holdoff = ooholdoff; 252 onoff_holdoff = ooholdoff;
250 onoff_interval = oointerval; 253 onoff_interval = oointerval;
254 onoff_f = f;
251 if (onoff_interval <= 0) 255 if (onoff_interval <= 0)
252 return 0; 256 return 0;
253 return torture_create_kthread(torture_onoff, NULL, onoff_task); 257 return torture_create_kthread(torture_onoff, NULL, onoff_task);