rcutorture: Abstract torture_shutdown()
authorPaul E. McKenney <paulmck@linux.vnet.ibm.com>
Fri, 31 Jan 2014 22:52:13 +0000 (14:52 -0800)
committerPaul E. McKenney <paulmck@linux.vnet.ibm.com>
Sun, 23 Feb 2014 17:03:18 +0000 (09:03 -0800)
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>
include/linux/torture.h
kernel/rcu/rcutorture.c
kernel/torture.c

index 203f127d9ddfb83cd7e5e210e28b161501d7e94b..c79c41d543efed4a7a839f6c00e949a649fd8ff8 100644 (file)
@@ -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);
index 4329ad14f8dc3db1369e276b1f18422368b04e91..897b0f91f8991d55a442e0603e35b75a45ae48bf 100644 (file)
@@ -105,7 +105,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;
@@ -173,7 +172,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. */
@@ -183,9 +181,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)
        return 0;
 }
 
-/*
- * 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.
@@ -1421,11 +1380,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.  */
 
@@ -1681,18 +1636,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) {
index 1bafd02d1eedd9cf268aabb54fbae86355894bb9..df2c700e96e424149fb3de8e9d60afe6b119e495 100644 (file)
@@ -418,6 +418,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.
@@ -432,6 +441,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.
  */