[PATCH tip/core/rcu 32/55] rcutorture: Abstract torture_shutdown()

From: Paul E. McKenney
Date: Mon Feb 17 2014 - 17:16:16 EST


From: "Paul E. McKenney" <paulmck@xxxxxxxxxxxxxxxxxx>

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@xxxxxxxxxxxxxxxxxx>
---
include/linux/torture.h | 4 ++-
kernel/rcu/rcutorture.c | 63 +++----------------------------------
kernel/torture.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 92 insertions(+), 59 deletions(-)

diff --git a/include/linux/torture.h b/include/linux/torture.h
index 791934fa32b9..513b85f98585 100644
--- a/include/linux/torture.h
+++ b/include/linux/torture.h
@@ -72,8 +72,10 @@ unsigned long torture_random(struct torture_random_state *trsp);
void torture_shuffle_task_register(struct task_struct *tp);
int torture_shuffle_init(long shuffint);

-/* Shutdown task absorption, for when the tasks cannot safely be killed. */
+/* Test auto-shutdown handling. */
void torture_shutdown_absorb(const char *title);
+int torture_shutdown_init(int ssecs, void (*cleanup)(void));
+void torture_shutdown_cleanup(void);

/* Task stuttering, which forces load/no-load transitions. */
void stutter_wait(const char *title);
diff --git a/kernel/rcu/rcutorture.c b/kernel/rcu/rcutorture.c
index 506f1c09ed90..9f42d320531d 100644
--- a/kernel/rcu/rcutorture.c
+++ b/kernel/rcu/rcutorture.c
@@ -104,7 +104,6 @@ static struct task_struct **reader_tasks;
static struct task_struct *stats_task;
static struct task_struct *fqs_task;
static struct task_struct *boost_tasks[NR_CPUS];
-static struct task_struct *shutdown_task;
static struct task_struct *stall_task;
static struct task_struct **barrier_cbs_tasks;
static struct task_struct *barrier_task;
@@ -172,7 +171,6 @@ static u64 notrace rcu_trace_clock_local(void)
}
#endif /* #else #ifdef CONFIG_RCU_TRACE */

-static unsigned long shutdown_time; /* jiffies to system shutdown. */
static unsigned long boost_starttime; /* jiffies of next boost test start. */
DEFINE_MUTEX(boost_mutex); /* protect setting boost_starttime */
/* and boost task create/destroy. */
@@ -182,9 +180,6 @@ static atomic_t barrier_cbs_invoked; /* Barrier callbacks invoked. */
static wait_queue_head_t *barrier_cbs_wq; /* Coordinate barrier testing. */
static DECLARE_WAIT_QUEUE_HEAD(barrier_wq);

-/* Forward reference. */
-static void rcu_torture_cleanup(void);
-
/*
* Allocate an element from the rcu_tortures pool.
*/
@@ -1086,42 +1081,6 @@ static int rcutorture_booster_init(int cpu)
}

/*
- * Cause the rcutorture test to shutdown the system after the test has
- * run for the time specified by the shutdown_secs module parameter.
- */
-static int
-rcu_torture_shutdown(void *arg)
-{
- long delta;
- unsigned long jiffies_snap;
-
- VERBOSE_TOROUT_STRING("rcu_torture_shutdown task started");
- jiffies_snap = ACCESS_ONCE(jiffies);
- while (ULONG_CMP_LT(jiffies_snap, shutdown_time) &&
- !kthread_should_stop()) {
- delta = shutdown_time - jiffies_snap;
- if (verbose)
- pr_alert("%s" TORTURE_FLAG
- "rcu_torture_shutdown task: %lu jiffies remaining\n",
- torture_type, delta);
- schedule_timeout_interruptible(delta);
- jiffies_snap = ACCESS_ONCE(jiffies);
- }
- if (kthread_should_stop()) {
- VERBOSE_TOROUT_STRING("rcu_torture_shutdown task stopping");
- return 0;
- }
-
- /* OK, shut down the system. */
-
- VERBOSE_TOROUT_STRING("rcu_torture_shutdown task shutting down system");
- shutdown_task = NULL; /* Avoid self-kill deadlock. */
- rcu_torture_cleanup(); /* Get the success/failure message. */
- kernel_power_off(); /* Shut down the system. */
- return 0;
-}
-
-/*
* CPU-stall kthread. It waits as specified by stall_cpu_holdoff, then
* induces a CPU stall for the time specified by stall_cpu.
*/
@@ -1420,11 +1379,7 @@ rcu_torture_cleanup(void)
for_each_possible_cpu(i)
rcutorture_booster_cleanup(i);
}
- if (shutdown_task != NULL) {
- VERBOSE_TOROUT_STRING("Stopping rcu_torture_shutdown task");
- kthread_stop(shutdown_task);
- }
- shutdown_task = NULL;
+ torture_shutdown_cleanup();

/* Wait for all RCU callbacks to fire. */

@@ -1680,18 +1635,10 @@ rcu_torture_init(void)
}
}
}
- if (shutdown_secs > 0) {
- shutdown_time = jiffies + shutdown_secs * HZ;
- shutdown_task = kthread_create(rcu_torture_shutdown, NULL,
- "rcu_torture_shutdown");
- if (IS_ERR(shutdown_task)) {
- firsterr = PTR_ERR(shutdown_task);
- VERBOSE_TOROUT_ERRSTRING("Failed to create shutdown");
- shutdown_task = NULL;
- goto unwind;
- }
- torture_shuffle_task_register(shutdown_task);
- wake_up_process(shutdown_task);
+ i = torture_shutdown_init(shutdown_secs, rcu_torture_cleanup);
+ if (i != 0) {
+ firsterr = i;
+ goto unwind;
}
i = torture_onoff_init(onoff_holdoff * HZ, onoff_interval * HZ);
if (i != 0) {
diff --git a/kernel/torture.c b/kernel/torture.c
index 82a8735472f0..217baffcaa66 100644
--- a/kernel/torture.c
+++ b/kernel/torture.c
@@ -419,6 +419,15 @@ static void torture_shuffle_cleanup(void)
EXPORT_SYMBOL_GPL(torture_shuffle_cleanup);

/*
+ * Variables for auto-shutdown. This allows "lights out" torture runs
+ * to be fully scripted.
+ */
+static int shutdown_secs; /* desired test duration in seconds. */
+static struct task_struct *shutdown_task;
+static unsigned long shutdown_time; /* jiffies to system shutdown. */
+static void (*torture_shutdown_hook)(void);
+
+/*
* Absorb kthreads into a kernel function that won't return, so that
* they won't ever access module text or data again.
*/
@@ -433,6 +442,81 @@ void torture_shutdown_absorb(const char *title)
EXPORT_SYMBOL_GPL(torture_shutdown_absorb);

/*
+ * Cause the torture test to shutdown the system after the test has
+ * run for the time specified by the shutdown_secs parameter.
+ */
+static int torture_shutdown(void *arg)
+{
+ long delta;
+ unsigned long jiffies_snap;
+
+ VERBOSE_TOROUT_STRING("torture_shutdown task started");
+ jiffies_snap = jiffies;
+ while (ULONG_CMP_LT(jiffies_snap, shutdown_time) &&
+ !torture_must_stop()) {
+ delta = shutdown_time - jiffies_snap;
+ if (verbose)
+ pr_alert("%s" TORTURE_FLAG
+ "torture_shutdown task: %lu jiffies remaining\n",
+ torture_type, delta);
+ schedule_timeout_interruptible(delta);
+ jiffies_snap = jiffies;
+ }
+ if (torture_must_stop()) {
+ VERBOSE_TOROUT_STRING("torture_shutdown task stopping");
+ return 0;
+ }
+
+ /* OK, shut down the system. */
+
+ VERBOSE_TOROUT_STRING("torture_shutdown task shutting down system");
+ shutdown_task = NULL; /* Avoid self-kill deadlock. */
+ torture_shutdown_hook();/* Shut down the enclosing torture test. */
+ kernel_power_off(); /* Shut down the system. */
+ return 0;
+}
+
+/*
+ * Start up the shutdown task.
+ */
+int torture_shutdown_init(int ssecs, void (*cleanup)(void))
+{
+ int ret;
+
+ shutdown_secs = ssecs;
+ torture_shutdown_hook = cleanup;
+ if (shutdown_secs > 0) {
+ shutdown_time = jiffies + shutdown_secs * HZ;
+ shutdown_task = kthread_create(torture_shutdown, NULL,
+ "torture_shutdown");
+ if (IS_ERR(shutdown_task)) {
+ ret = PTR_ERR(shutdown_task);
+ VERBOSE_TOROUT_ERRSTRING("Failed to create shutdown");
+ shutdown_task = NULL;
+ return ret;
+ }
+ torture_shuffle_task_register(shutdown_task);
+ wake_up_process(shutdown_task);
+ }
+ return 0;
+}
+EXPORT_SYMBOL_GPL(torture_shutdown_init);
+
+/*
+ * Shut down the shutdown task. Say what??? Heh! This can happen if
+ * the torture module gets an rmmod before the shutdown time arrives. ;-)
+ */
+void torture_shutdown_cleanup(void)
+{
+ if (shutdown_task != NULL) {
+ VERBOSE_TOROUT_STRING("Stopping torture_shutdown task");
+ kthread_stop(shutdown_task);
+ }
+ shutdown_task = NULL;
+}
+EXPORT_SYMBOL_GPL(torture_shutdown_cleanup);
+
+/*
* Detect and respond to a system shutdown.
*/
static int torture_shutdown_notify(struct notifier_block *unused1,
--
1.8.1.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/