aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul E. McKenney <paulmck@linux.vnet.ibm.com>2014-01-31 17:52:13 -0500
committerPaul E. McKenney <paulmck@linux.vnet.ibm.com>2014-02-23 12:03:18 -0500
commite991dbc0770b01b7dc7d6d7660442e83ebd11828 (patch)
treee95081adbe3c4e85daeae774a9736af2fcfc1f46
parent57a2fe90fcdaa812ac1aa6c91ba0e591c30f461a (diff)
rcutorture: Abstract torture_shutdown()
Because auto-shutdown of torture testing is not specific to RCU, this commit moves the auto-shutdown function to kernel/torture.c. Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Reviewed-by: Josh Triplett <josh@joshtriplett.org>
-rw-r--r--include/linux/torture.h4
-rw-r--r--kernel/rcu/rcutorture.c63
-rw-r--r--kernel/torture.c84
3 files changed, 92 insertions, 59 deletions
diff --git a/include/linux/torture.h b/include/linux/torture.h
index 203f127d9ddf..c79c41d543ef 100644
--- a/include/linux/torture.h
+++ b/include/linux/torture.h
@@ -72,8 +72,10 @@ unsigned long torture_random(struct torture_random_state *trsp);
72void torture_shuffle_task_register(struct task_struct *tp); 72void torture_shuffle_task_register(struct task_struct *tp);
73int torture_shuffle_init(long shuffint); 73int torture_shuffle_init(long shuffint);
74 74
75/* Shutdown task absorption, for when the tasks cannot safely be killed. */ 75/* Test auto-shutdown handling. */
76void torture_shutdown_absorb(const char *title); 76void torture_shutdown_absorb(const char *title);
77int torture_shutdown_init(int ssecs, void (*cleanup)(void));
78void torture_shutdown_cleanup(void);
77 79
78/* Task stuttering, which forces load/no-load transitions. */ 80/* Task stuttering, which forces load/no-load transitions. */
79void stutter_wait(const char *title); 81void stutter_wait(const char *title);
diff --git a/kernel/rcu/rcutorture.c b/kernel/rcu/rcutorture.c
index 4329ad14f8dc..897b0f91f899 100644
--- a/kernel/rcu/rcutorture.c
+++ b/kernel/rcu/rcutorture.c
@@ -105,7 +105,6 @@ static struct task_struct **reader_tasks;
105static struct task_struct *stats_task; 105static struct task_struct *stats_task;
106static struct task_struct *fqs_task; 106static struct task_struct *fqs_task;
107static struct task_struct *boost_tasks[NR_CPUS]; 107static struct task_struct *boost_tasks[NR_CPUS];
108static struct task_struct *shutdown_task;
109static struct task_struct *stall_task; 108static struct task_struct *stall_task;
110static struct task_struct **barrier_cbs_tasks; 109static struct task_struct **barrier_cbs_tasks;
111static struct task_struct *barrier_task; 110static struct task_struct *barrier_task;
@@ -173,7 +172,6 @@ static u64 notrace rcu_trace_clock_local(void)
173} 172}
174#endif /* #else #ifdef CONFIG_RCU_TRACE */ 173#endif /* #else #ifdef CONFIG_RCU_TRACE */
175 174
176static unsigned long shutdown_time; /* jiffies to system shutdown. */
177static unsigned long boost_starttime; /* jiffies of next boost test start. */ 175static unsigned long boost_starttime; /* jiffies of next boost test start. */
178DEFINE_MUTEX(boost_mutex); /* protect setting boost_starttime */ 176DEFINE_MUTEX(boost_mutex); /* protect setting boost_starttime */
179 /* and boost task create/destroy. */ 177 /* and boost task create/destroy. */
@@ -183,9 +181,6 @@ static atomic_t barrier_cbs_invoked; /* Barrier callbacks invoked. */
183static wait_queue_head_t *barrier_cbs_wq; /* Coordinate barrier testing. */ 181static wait_queue_head_t *barrier_cbs_wq; /* Coordinate barrier testing. */
184static DECLARE_WAIT_QUEUE_HEAD(barrier_wq); 182static DECLARE_WAIT_QUEUE_HEAD(barrier_wq);
185 183
186/* Forward reference. */
187static void rcu_torture_cleanup(void);
188
189/* 184/*
190 * Allocate an element from the rcu_tortures pool. 185 * Allocate an element from the rcu_tortures pool.
191 */ 186 */
@@ -1087,42 +1082,6 @@ static int rcutorture_booster_init(int cpu)
1087} 1082}
1088 1083
1089/* 1084/*
1090 * Cause the rcutorture test to shutdown the system after the test has
1091 * run for the time specified by the shutdown_secs module parameter.
1092 */
1093static int
1094rcu_torture_shutdown(void *arg)
1095{
1096 long delta;
1097 unsigned long jiffies_snap;
1098
1099 VERBOSE_TOROUT_STRING("rcu_torture_shutdown task started");
1100 jiffies_snap = ACCESS_ONCE(jiffies);
1101 while (ULONG_CMP_LT(jiffies_snap, shutdown_time) &&
1102 !kthread_should_stop()) {
1103 delta = shutdown_time - jiffies_snap;
1104 if (verbose)
1105 pr_alert("%s" TORTURE_FLAG
1106 "rcu_torture_shutdown task: %lu jiffies remaining\n",
1107 torture_type, delta);
1108 schedule_timeout_interruptible(delta);
1109 jiffies_snap = ACCESS_ONCE(jiffies);
1110 }
1111 if (kthread_should_stop()) {
1112 VERBOSE_TOROUT_STRING("rcu_torture_shutdown task stopping");
1113 return 0;
1114 }
1115
1116 /* OK, shut down the system. */
1117
1118 VERBOSE_TOROUT_STRING("rcu_torture_shutdown task shutting down system");
1119 shutdown_task = NULL; /* Avoid self-kill deadlock. */
1120 rcu_torture_cleanup(); /* Get the success/failure message. */
1121 kernel_power_off(); /* Shut down the system. */
1122 return 0;
1123}
1124
1125/*
1126 * CPU-stall kthread. It waits as specified by stall_cpu_holdoff, then 1085 * CPU-stall kthread. It waits as specified by stall_cpu_holdoff, then
1127 * induces a CPU stall for the time specified by stall_cpu. 1086 * induces a CPU stall for the time specified by stall_cpu.
1128 */ 1087 */
@@ -1421,11 +1380,7 @@ rcu_torture_cleanup(void)
1421 for_each_possible_cpu(i) 1380 for_each_possible_cpu(i)
1422 rcutorture_booster_cleanup(i); 1381 rcutorture_booster_cleanup(i);
1423 } 1382 }
1424 if (shutdown_task != NULL) { 1383 torture_shutdown_cleanup();
1425 VERBOSE_TOROUT_STRING("Stopping rcu_torture_shutdown task");
1426 kthread_stop(shutdown_task);
1427 }
1428 shutdown_task = NULL;
1429 1384
1430 /* Wait for all RCU callbacks to fire. */ 1385 /* Wait for all RCU callbacks to fire. */
1431 1386
@@ -1681,18 +1636,10 @@ rcu_torture_init(void)
1681 } 1636 }
1682 } 1637 }
1683 } 1638 }
1684 if (shutdown_secs > 0) { 1639 i = torture_shutdown_init(shutdown_secs, rcu_torture_cleanup);
1685 shutdown_time = jiffies + shutdown_secs * HZ; 1640 if (i != 0) {
1686 shutdown_task = kthread_create(rcu_torture_shutdown, NULL, 1641 firsterr = i;
1687 "rcu_torture_shutdown"); 1642 goto unwind;
1688 if (IS_ERR(shutdown_task)) {
1689 firsterr = PTR_ERR(shutdown_task);
1690 VERBOSE_TOROUT_ERRSTRING("Failed to create shutdown");
1691 shutdown_task = NULL;
1692 goto unwind;
1693 }
1694 torture_shuffle_task_register(shutdown_task);
1695 wake_up_process(shutdown_task);
1696 } 1643 }
1697 i = torture_onoff_init(onoff_holdoff * HZ, onoff_interval * HZ); 1644 i = torture_onoff_init(onoff_holdoff * HZ, onoff_interval * HZ);
1698 if (i != 0) { 1645 if (i != 0) {
diff --git a/kernel/torture.c b/kernel/torture.c
index 1bafd02d1eed..df2c700e96e4 100644
--- a/kernel/torture.c
+++ b/kernel/torture.c
@@ -419,6 +419,15 @@ static void torture_shuffle_cleanup(void)
419EXPORT_SYMBOL_GPL(torture_shuffle_cleanup); 419EXPORT_SYMBOL_GPL(torture_shuffle_cleanup);
420 420
421/* 421/*
422 * Variables for auto-shutdown. This allows "lights out" torture runs
423 * to be fully scripted.
424 */
425static int shutdown_secs; /* desired test duration in seconds. */
426static struct task_struct *shutdown_task;
427static unsigned long shutdown_time; /* jiffies to system shutdown. */
428static void (*torture_shutdown_hook)(void);
429
430/*
422 * Absorb kthreads into a kernel function that won't return, so that 431 * Absorb kthreads into a kernel function that won't return, so that
423 * they won't ever access module text or data again. 432 * they won't ever access module text or data again.
424 */ 433 */
@@ -433,6 +442,81 @@ void torture_shutdown_absorb(const char *title)
433EXPORT_SYMBOL_GPL(torture_shutdown_absorb); 442EXPORT_SYMBOL_GPL(torture_shutdown_absorb);
434 443
435/* 444/*
445 * Cause the torture test to shutdown the system after the test has
446 * run for the time specified by the shutdown_secs parameter.
447 */
448static int torture_shutdown(void *arg)
449{
450 long delta;
451 unsigned long jiffies_snap;
452
453 VERBOSE_TOROUT_STRING("torture_shutdown task started");
454 jiffies_snap = jiffies;
455 while (ULONG_CMP_LT(jiffies_snap, shutdown_time) &&
456 !torture_must_stop()) {
457 delta = shutdown_time - jiffies_snap;
458 if (verbose)
459 pr_alert("%s" TORTURE_FLAG
460 "torture_shutdown task: %lu jiffies remaining\n",
461 torture_type, delta);
462 schedule_timeout_interruptible(delta);
463 jiffies_snap = jiffies;
464 }
465 if (torture_must_stop()) {
466 VERBOSE_TOROUT_STRING("torture_shutdown task stopping");
467 return 0;
468 }
469
470 /* OK, shut down the system. */
471
472 VERBOSE_TOROUT_STRING("torture_shutdown task shutting down system");
473 shutdown_task = NULL; /* Avoid self-kill deadlock. */
474 torture_shutdown_hook();/* Shut down the enclosing torture test. */
475 kernel_power_off(); /* Shut down the system. */
476 return 0;
477}
478
479/*
480 * Start up the shutdown task.
481 */
482int torture_shutdown_init(int ssecs, void (*cleanup)(void))
483{
484 int ret;
485
486 shutdown_secs = ssecs;
487 torture_shutdown_hook = cleanup;
488 if (shutdown_secs > 0) {
489 shutdown_time = jiffies + shutdown_secs * HZ;
490 shutdown_task = kthread_create(torture_shutdown, NULL,
491 "torture_shutdown");
492 if (IS_ERR(shutdown_task)) {
493 ret = PTR_ERR(shutdown_task);
494 VERBOSE_TOROUT_ERRSTRING("Failed to create shutdown");
495 shutdown_task = NULL;
496 return ret;
497 }
498 torture_shuffle_task_register(shutdown_task);
499 wake_up_process(shutdown_task);
500 }
501 return 0;
502}
503EXPORT_SYMBOL_GPL(torture_shutdown_init);
504
505/*
506 * Shut down the shutdown task. Say what??? Heh! This can happen if
507 * the torture module gets an rmmod before the shutdown time arrives. ;-)
508 */
509void torture_shutdown_cleanup(void)
510{
511 if (shutdown_task != NULL) {
512 VERBOSE_TOROUT_STRING("Stopping torture_shutdown task");
513 kthread_stop(shutdown_task);
514 }
515 shutdown_task = NULL;
516}
517EXPORT_SYMBOL_GPL(torture_shutdown_cleanup);
518
519/*
436 * Detect and respond to a system shutdown. 520 * Detect and respond to a system shutdown.
437 */ 521 */
438static int torture_shutdown_notify(struct notifier_block *unused1, 522static int torture_shutdown_notify(struct notifier_block *unused1,