]> nv-tegra.nvidia Code Review - linux-3.10.git/blobdiff - kernel/rcutorture.c
Make suspend abort reason logging depend on CONFIG_PM_SLEEP
[linux-3.10.git] / kernel / rcutorture.c
index f7fe73e59c9f2ddf938622e03df5eb287642061a..e1f3a8c96724374be64e1cf252a40f2e9eac5a70 100644 (file)
 #include <linux/stat.h>
 #include <linux/srcu.h>
 #include <linux/slab.h>
+#include <linux/trace_clock.h>
 #include <asm/byteorder.h>
 
 MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Paul E. McKenney <paulmck@us.ibm.com> and "
-             "Josh Triplett <josh@freedesktop.org>");
+MODULE_AUTHOR("Paul E. McKenney <paulmck@us.ibm.com> and Josh Triplett <josh@freedesktop.org>");
 
 static int nreaders = -1;      /* # reader threads, defaults to 2*ncpus */
 static int nfakewriters = 4;   /* # fake writer threads */
-static int stat_interval;      /* Interval between stats, in seconds. */
-                               /*  Defaults to "only at end of test". */
+static int stat_interval = 60; /* Interval between stats, in seconds. */
+                               /*  Zero means "only at end of test". */
 static bool verbose;           /* Print more debug info. */
-static bool test_no_idle_hz;   /* Test RCU's support for tickless idle CPUs. */
+static bool test_no_idle_hz = true;
+                               /* Test RCU support for tickless idle CPUs. */
 static int shuffle_interval = 3; /* Interval between shuffles (in sec)*/
 static int stutter = 5;                /* Start/stop testing interval (in sec) */
 static int irqreader = 1;      /* RCU readers from irq (timers). */
@@ -120,11 +121,11 @@ MODULE_PARM_DESC(torture_type, "Type of RCU to torture (rcu, rcu_bh, srcu)");
 
 #define TORTURE_FLAG "-torture:"
 #define PRINTK_STRING(s) \
-       do { printk(KERN_ALERT "%s" TORTURE_FLAG s "\n", torture_type); } while (0)
+       do { pr_alert("%s" TORTURE_FLAG s "\n", torture_type); } while (0)
 #define VERBOSE_PRINTK_STRING(s) \
-       do { if (verbose) printk(KERN_ALERT "%s" TORTURE_FLAG s "\n", torture_type); } while (0)
+       do { if (verbose) pr_alert("%s" TORTURE_FLAG s "\n", torture_type); } while (0)
 #define VERBOSE_PRINTK_ERRSTRING(s) \
-       do { if (verbose) printk(KERN_ALERT "%s" TORTURE_FLAG "!!! " s "\n", torture_type); } while (0)
+       do { if (verbose) pr_alert("%s" TORTURE_FLAG "!!! " s "\n", torture_type); } while (0)
 
 static char printk_buf[4096];
 
@@ -177,8 +178,14 @@ static long n_rcu_torture_boosts;
 static long n_rcu_torture_timers;
 static long n_offline_attempts;
 static long n_offline_successes;
+static unsigned long sum_offline;
+static int min_offline = -1;
+static int max_offline;
 static long n_online_attempts;
 static long n_online_successes;
+static unsigned long sum_online;
+static int min_online = -1;
+static int max_online;
 static long n_barrier_attempts;
 static long n_barrier_successes;
 static struct list_head rcu_torture_removed;
@@ -201,6 +208,20 @@ MODULE_PARM_DESC(rcutorture_runnable, "Start rcutorture at boot");
 #define rcu_can_boost() 0
 #endif /* #else #if defined(CONFIG_RCU_BOOST) && !defined(CONFIG_HOTPLUG_CPU) */
 
+#ifdef CONFIG_RCU_TRACE
+static u64 notrace rcu_trace_clock_local(void)
+{
+       u64 ts = trace_clock_local();
+       unsigned long __maybe_unused ts_rem = do_div(ts, NSEC_PER_USEC);
+       return ts;
+}
+#else /* #ifdef CONFIG_RCU_TRACE */
+static u64 notrace rcu_trace_clock_local(void)
+{
+       return 0ULL;
+}
+#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 */
@@ -236,7 +257,7 @@ rcutorture_shutdown_notify(struct notifier_block *unused1,
        if (fullstop == FULLSTOP_DONTSTOP)
                fullstop = FULLSTOP_SHUTDOWN;
        else
-               printk(KERN_WARNING /* but going down anyway, so... */
+               pr_warn(/* but going down anyway, so... */
                       "Concurrent 'rmmod rcutorture' and shutdown illegal!\n");
        mutex_unlock(&fullstop_mutex);
        return NOTIFY_DONE;
@@ -249,7 +270,7 @@ rcutorture_shutdown_notify(struct notifier_block *unused1,
 static void rcutorture_shutdown_absorb(char *title)
 {
        if (ACCESS_ONCE(fullstop) == FULLSTOP_SHUTDOWN) {
-               printk(KERN_NOTICE
+               pr_notice(
                       "rcutorture thread %s parking due to system shutdown\n",
                       title);
                schedule_timeout_uninterruptible(MAX_SCHEDULE_TIMEOUT);
@@ -333,7 +354,6 @@ rcu_stutter_wait(char *title)
 
 struct rcu_torture_ops {
        void (*init)(void);
-       void (*cleanup)(void);
        int (*readlock)(void);
        void (*read_delay)(struct rcu_random_state *rrsp);
        void (*readunlock)(int idx);
@@ -408,8 +428,9 @@ rcu_torture_cb(struct rcu_head *p)
        if (++rp->rtort_pipe_count >= RCU_TORTURE_PIPE_LEN) {
                rp->rtort_mbtest = 0;
                rcu_torture_free(rp);
-       } else
+       } else {
                cur_ops->deferred_free(rp);
+       }
 }
 
 static int rcu_no_completed(void)
@@ -424,7 +445,6 @@ static void rcu_torture_deferred_free(struct rcu_torture *p)
 
 static struct rcu_torture_ops rcu_ops = {
        .init           = NULL,
-       .cleanup        = NULL,
        .readlock       = rcu_torture_read_lock,
        .read_delay     = rcu_read_delay,
        .readunlock     = rcu_torture_read_unlock,
@@ -468,7 +488,6 @@ static void rcu_sync_torture_init(void)
 
 static struct rcu_torture_ops rcu_sync_ops = {
        .init           = rcu_sync_torture_init,
-       .cleanup        = NULL,
        .readlock       = rcu_torture_read_lock,
        .read_delay     = rcu_read_delay,
        .readunlock     = rcu_torture_read_unlock,
@@ -486,7 +505,6 @@ static struct rcu_torture_ops rcu_sync_ops = {
 
 static struct rcu_torture_ops rcu_expedited_ops = {
        .init           = rcu_sync_torture_init,
-       .cleanup        = NULL,
        .readlock       = rcu_torture_read_lock,
        .read_delay     = rcu_read_delay,  /* just reuse rcu's version. */
        .readunlock     = rcu_torture_read_unlock,
@@ -529,7 +547,6 @@ static void rcu_bh_torture_deferred_free(struct rcu_torture *p)
 
 static struct rcu_torture_ops rcu_bh_ops = {
        .init           = NULL,
-       .cleanup        = NULL,
        .readlock       = rcu_bh_torture_read_lock,
        .read_delay     = rcu_read_delay,  /* just reuse rcu's version. */
        .readunlock     = rcu_bh_torture_read_unlock,
@@ -546,7 +563,6 @@ static struct rcu_torture_ops rcu_bh_ops = {
 
 static struct rcu_torture_ops rcu_bh_sync_ops = {
        .init           = rcu_sync_torture_init,
-       .cleanup        = NULL,
        .readlock       = rcu_bh_torture_read_lock,
        .read_delay     = rcu_read_delay,  /* just reuse rcu's version. */
        .readunlock     = rcu_bh_torture_read_unlock,
@@ -563,7 +579,6 @@ static struct rcu_torture_ops rcu_bh_sync_ops = {
 
 static struct rcu_torture_ops rcu_bh_expedited_ops = {
        .init           = rcu_sync_torture_init,
-       .cleanup        = NULL,
        .readlock       = rcu_bh_torture_read_lock,
        .read_delay     = rcu_read_delay,  /* just reuse rcu's version. */
        .readunlock     = rcu_bh_torture_read_unlock,
@@ -582,19 +597,7 @@ static struct rcu_torture_ops rcu_bh_expedited_ops = {
  * Definitions for srcu torture testing.
  */
 
-static struct srcu_struct srcu_ctl;
-
-static void srcu_torture_init(void)
-{
-       init_srcu_struct(&srcu_ctl);
-       rcu_sync_torture_init();
-}
-
-static void srcu_torture_cleanup(void)
-{
-       synchronize_srcu(&srcu_ctl);
-       cleanup_srcu_struct(&srcu_ctl);
-}
+DEFINE_STATIC_SRCU(srcu_ctl);
 
 static int srcu_torture_read_lock(void) __acquires(&srcu_ctl)
 {
@@ -665,8 +668,7 @@ static int srcu_torture_stats(char *page)
 }
 
 static struct rcu_torture_ops srcu_ops = {
-       .init           = srcu_torture_init,
-       .cleanup        = srcu_torture_cleanup,
+       .init           = rcu_sync_torture_init,
        .readlock       = srcu_torture_read_lock,
        .read_delay     = srcu_read_delay,
        .readunlock     = srcu_torture_read_unlock,
@@ -680,8 +682,7 @@ static struct rcu_torture_ops srcu_ops = {
 };
 
 static struct rcu_torture_ops srcu_sync_ops = {
-       .init           = srcu_torture_init,
-       .cleanup        = srcu_torture_cleanup,
+       .init           = rcu_sync_torture_init,
        .readlock       = srcu_torture_read_lock,
        .read_delay     = srcu_read_delay,
        .readunlock     = srcu_torture_read_unlock,
@@ -705,8 +706,7 @@ static void srcu_torture_read_unlock_raw(int idx) __releases(&srcu_ctl)
 }
 
 static struct rcu_torture_ops srcu_raw_ops = {
-       .init           = srcu_torture_init,
-       .cleanup        = srcu_torture_cleanup,
+       .init           = rcu_sync_torture_init,
        .readlock       = srcu_torture_read_lock_raw,
        .read_delay     = srcu_read_delay,
        .readunlock     = srcu_torture_read_unlock_raw,
@@ -720,8 +720,7 @@ static struct rcu_torture_ops srcu_raw_ops = {
 };
 
 static struct rcu_torture_ops srcu_raw_sync_ops = {
-       .init           = srcu_torture_init,
-       .cleanup        = srcu_torture_cleanup,
+       .init           = rcu_sync_torture_init,
        .readlock       = srcu_torture_read_lock_raw,
        .read_delay     = srcu_read_delay,
        .readunlock     = srcu_torture_read_unlock_raw,
@@ -740,8 +739,7 @@ static void srcu_torture_synchronize_expedited(void)
 }
 
 static struct rcu_torture_ops srcu_expedited_ops = {
-       .init           = srcu_torture_init,
-       .cleanup        = srcu_torture_cleanup,
+       .init           = rcu_sync_torture_init,
        .readlock       = srcu_torture_read_lock,
        .read_delay     = srcu_read_delay,
        .readunlock     = srcu_torture_read_unlock,
@@ -776,7 +774,6 @@ static void rcu_sched_torture_deferred_free(struct rcu_torture *p)
 
 static struct rcu_torture_ops sched_ops = {
        .init           = rcu_sync_torture_init,
-       .cleanup        = NULL,
        .readlock       = sched_torture_read_lock,
        .read_delay     = rcu_read_delay,  /* just reuse rcu's version. */
        .readunlock     = sched_torture_read_unlock,
@@ -792,7 +789,6 @@ static struct rcu_torture_ops sched_ops = {
 
 static struct rcu_torture_ops sched_sync_ops = {
        .init           = rcu_sync_torture_init,
-       .cleanup        = NULL,
        .readlock       = sched_torture_read_lock,
        .read_delay     = rcu_read_delay,  /* just reuse rcu's version. */
        .readunlock     = sched_torture_read_unlock,
@@ -807,7 +803,6 @@ static struct rcu_torture_ops sched_sync_ops = {
 
 static struct rcu_torture_ops sched_expedited_ops = {
        .init           = rcu_sync_torture_init,
-       .cleanup        = NULL,
        .readlock       = sched_torture_read_lock,
        .read_delay     = rcu_read_delay,  /* just reuse rcu's version. */
        .readunlock     = sched_torture_read_unlock,
@@ -865,7 +860,7 @@ static int rcu_torture_boost(void *arg)
                /* Wait for the next test interval. */
                oldstarttime = boost_starttime;
                while (ULONG_CMP_LT(jiffies, oldstarttime)) {
-                       schedule_timeout_uninterruptible(1);
+                       schedule_timeout_interruptible(oldstarttime - jiffies);
                        rcu_stutter_wait("rcu_torture_boost");
                        if (kthread_should_stop() ||
                            fullstop != FULLSTOP_DONTSTOP)
@@ -1025,7 +1020,11 @@ rcu_torture_fakewriter(void *arg)
        do {
                schedule_timeout_uninterruptible(1 + rcu_random(&rand)%10);
                udelay(rcu_random(&rand) & 0x3ff);
-               cur_ops->sync();
+               if (cur_ops->cb_barrier != NULL &&
+                   rcu_random(&rand) % (nfakewriters * 8) == 0)
+                       cur_ops->cb_barrier();
+               else
+                       cur_ops->sync();
                rcu_stutter_wait("rcu_torture_fakewriter");
        } while (!kthread_should_stop() && fullstop == FULLSTOP_DONTSTOP);
 
@@ -1044,7 +1043,6 @@ void rcutorture_trace_dump(void)
                return;
        if (atomic_xchg(&beenhere, 1) != 0)
                return;
-       do_trace_rcu_torture_read(cur_ops->name, (struct rcu_head *)~0UL);
        ftrace_dump(DUMP_ALL);
 }
 
@@ -1058,13 +1056,16 @@ static void rcu_torture_timer(unsigned long unused)
 {
        int idx;
        int completed;
+       int completed_end;
        static DEFINE_RCU_RANDOM(rand);
        static DEFINE_SPINLOCK(rand_lock);
        struct rcu_torture *p;
        int pipe_count;
+       unsigned long long ts;
 
        idx = cur_ops->readlock();
        completed = cur_ops->completed();
+       ts = rcu_trace_clock_local();
        p = rcu_dereference_check(rcu_torture_current,
                                  rcu_read_lock_bh_held() ||
                                  rcu_read_lock_sched_held() ||
@@ -1074,7 +1075,6 @@ static void rcu_torture_timer(unsigned long unused)
                cur_ops->readunlock(idx);
                return;
        }
-       do_trace_rcu_torture_read(cur_ops->name, &p->rtort_rcu);
        if (p->rtort_mbtest == 0)
                atomic_inc(&n_rcu_torture_mberror);
        spin_lock(&rand_lock);
@@ -1087,10 +1087,14 @@ static void rcu_torture_timer(unsigned long unused)
                /* Should not happen, but... */
                pipe_count = RCU_TORTURE_PIPE_LEN;
        }
-       if (pipe_count > 1)
+       completed_end = cur_ops->completed();
+       if (pipe_count > 1) {
+               do_trace_rcu_torture_read(cur_ops->name, &p->rtort_rcu, ts,
+                                         completed, completed_end);
                rcutorture_trace_dump();
+       }
        __this_cpu_inc(rcu_torture_count[pipe_count]);
-       completed = cur_ops->completed() - completed;
+       completed = completed_end - completed;
        if (completed > RCU_TORTURE_PIPE_LEN) {
                /* Should not happen, but... */
                completed = RCU_TORTURE_PIPE_LEN;
@@ -1110,11 +1114,13 @@ static int
 rcu_torture_reader(void *arg)
 {
        int completed;
+       int completed_end;
        int idx;
        DEFINE_RCU_RANDOM(rand);
        struct rcu_torture *p;
        int pipe_count;
        struct timer_list t;
+       unsigned long long ts;
 
        VERBOSE_PRINTK_STRING("rcu_torture_reader task started");
        set_user_nice(current, 19);
@@ -1128,6 +1134,7 @@ rcu_torture_reader(void *arg)
                }
                idx = cur_ops->readlock();
                completed = cur_ops->completed();
+               ts = rcu_trace_clock_local();
                p = rcu_dereference_check(rcu_torture_current,
                                          rcu_read_lock_bh_held() ||
                                          rcu_read_lock_sched_held() ||
@@ -1138,7 +1145,6 @@ rcu_torture_reader(void *arg)
                        schedule_timeout_interruptible(HZ);
                        continue;
                }
-               do_trace_rcu_torture_read(cur_ops->name, &p->rtort_rcu);
                if (p->rtort_mbtest == 0)
                        atomic_inc(&n_rcu_torture_mberror);
                cur_ops->read_delay(&rand);
@@ -1148,10 +1154,14 @@ rcu_torture_reader(void *arg)
                        /* Should not happen, but... */
                        pipe_count = RCU_TORTURE_PIPE_LEN;
                }
-               if (pipe_count > 1)
+               completed_end = cur_ops->completed();
+               if (pipe_count > 1) {
+                       do_trace_rcu_torture_read(cur_ops->name, &p->rtort_rcu,
+                                                 ts, completed, completed_end);
                        rcutorture_trace_dump();
+               }
                __this_cpu_inc(rcu_torture_count[pipe_count]);
-               completed = cur_ops->completed() - completed;
+               completed = completed_end - completed;
                if (completed > RCU_TORTURE_PIPE_LEN) {
                        /* Should not happen, but... */
                        completed = RCU_TORTURE_PIPE_LEN;
@@ -1195,27 +1205,29 @@ rcu_torture_printk(char *page)
        }
        cnt += sprintf(&page[cnt], "%s%s ", torture_type, TORTURE_FLAG);
        cnt += sprintf(&page[cnt],
-                      "rtc: %p ver: %lu tfle: %d rta: %d rtaf: %d rtf: %d "
-                      "rtmbe: %d rtbke: %ld rtbre: %ld "
-                      "rtbf: %ld rtb: %ld nt: %ld "
-                      "onoff: %ld/%ld:%ld/%ld "
-                      "barrier: %ld/%ld:%ld",
+                      "rtc: %p ver: %lu tfle: %d rta: %d rtaf: %d rtf: %d ",
                       rcu_torture_current,
                       rcu_torture_current_version,
                       list_empty(&rcu_torture_freelist),
                       atomic_read(&n_rcu_torture_alloc),
                       atomic_read(&n_rcu_torture_alloc_fail),
-                      atomic_read(&n_rcu_torture_free),
+                      atomic_read(&n_rcu_torture_free));
+       cnt += sprintf(&page[cnt], "rtmbe: %d rtbke: %ld rtbre: %ld ",
                       atomic_read(&n_rcu_torture_mberror),
                       n_rcu_torture_boost_ktrerror,
-                      n_rcu_torture_boost_rterror,
+                      n_rcu_torture_boost_rterror);
+       cnt += sprintf(&page[cnt], "rtbf: %ld rtb: %ld nt: %ld ",
                       n_rcu_torture_boost_failure,
                       n_rcu_torture_boosts,
-                      n_rcu_torture_timers,
-                      n_online_successes,
-                      n_online_attempts,
-                      n_offline_successes,
-                      n_offline_attempts,
+                      n_rcu_torture_timers);
+       cnt += sprintf(&page[cnt],
+                      "onoff: %ld/%ld:%ld/%ld %d,%d:%d,%d %lu:%lu (HZ=%d) ",
+                      n_online_successes, n_online_attempts,
+                      n_offline_successes, n_offline_attempts,
+                      min_online, max_online,
+                      min_offline, max_offline,
+                      sum_online, sum_offline, HZ);
+       cnt += sprintf(&page[cnt], "barrier: %ld/%ld:%ld",
                       n_barrier_successes,
                       n_barrier_attempts,
                       n_rcu_torture_barrier_error);
@@ -1263,7 +1275,7 @@ rcu_torture_stats_print(void)
        int cnt;
 
        cnt = rcu_torture_printk(printk_buf);
-       printk(KERN_ALERT "%s", printk_buf);
+       pr_alert("%s", printk_buf);
 }
 
 /*
@@ -1315,19 +1327,35 @@ static void rcu_torture_shuffle_tasks(void)
                                set_cpus_allowed_ptr(reader_tasks[i],
                                                     shuffle_tmp_mask);
        }
-
        if (fakewriter_tasks) {
                for (i = 0; i < nfakewriters; i++)
                        if (fakewriter_tasks[i])
                                set_cpus_allowed_ptr(fakewriter_tasks[i],
                                                     shuffle_tmp_mask);
        }
-
        if (writer_task)
                set_cpus_allowed_ptr(writer_task, shuffle_tmp_mask);
-
        if (stats_task)
                set_cpus_allowed_ptr(stats_task, shuffle_tmp_mask);
+       if (stutter_task)
+               set_cpus_allowed_ptr(stutter_task, shuffle_tmp_mask);
+       if (fqs_task)
+               set_cpus_allowed_ptr(fqs_task, shuffle_tmp_mask);
+       if (shutdown_task)
+               set_cpus_allowed_ptr(shutdown_task, shuffle_tmp_mask);
+#ifdef CONFIG_HOTPLUG_CPU
+       if (onoff_task)
+               set_cpus_allowed_ptr(onoff_task, shuffle_tmp_mask);
+#endif /* #ifdef CONFIG_HOTPLUG_CPU */
+       if (stall_task)
+               set_cpus_allowed_ptr(stall_task, shuffle_tmp_mask);
+       if (barrier_cbs_tasks)
+               for (i = 0; i < n_barrier_cbs; i++)
+                       if (barrier_cbs_tasks[i])
+                               set_cpus_allowed_ptr(barrier_cbs_tasks[i],
+                                                    shuffle_tmp_mask);
+       if (barrier_task)
+               set_cpus_allowed_ptr(barrier_task, shuffle_tmp_mask);
 
        if (rcu_idle_cpu == -1)
                rcu_idle_cpu = num_online_cpus() - 1;
@@ -1376,20 +1404,24 @@ rcu_torture_stutter(void *arg)
 static inline void
 rcu_torture_print_module_parms(struct rcu_torture_ops *cur_ops, char *tag)
 {
-       printk(KERN_ALERT "%s" TORTURE_FLAG
-               "--- %s: nreaders=%d nfakewriters=%d "
-               "stat_interval=%d verbose=%d test_no_idle_hz=%d "
-               "shuffle_interval=%d stutter=%d irqreader=%d "
-               "fqs_duration=%d fqs_holdoff=%d fqs_stutter=%d "
-               "test_boost=%d/%d test_boost_interval=%d "
-               "test_boost_duration=%d shutdown_secs=%d "
-               "onoff_interval=%d onoff_holdoff=%d\n",
-               torture_type, tag, nrealreaders, nfakewriters,
-               stat_interval, verbose, test_no_idle_hz, shuffle_interval,
-               stutter, irqreader, fqs_duration, fqs_holdoff, fqs_stutter,
-               test_boost, cur_ops->can_boost,
-               test_boost_interval, test_boost_duration, shutdown_secs,
-               onoff_interval, onoff_holdoff);
+       pr_alert("%s" TORTURE_FLAG
+                "--- %s: nreaders=%d nfakewriters=%d "
+                "stat_interval=%d verbose=%d test_no_idle_hz=%d "
+                "shuffle_interval=%d stutter=%d irqreader=%d "
+                "fqs_duration=%d fqs_holdoff=%d fqs_stutter=%d "
+                "test_boost=%d/%d test_boost_interval=%d "
+                "test_boost_duration=%d shutdown_secs=%d "
+                "stall_cpu=%d stall_cpu_holdoff=%d "
+                "n_barrier_cbs=%d "
+                "onoff_interval=%d onoff_holdoff=%d\n",
+                torture_type, tag, nrealreaders, nfakewriters,
+                stat_interval, verbose, test_no_idle_hz, shuffle_interval,
+                stutter, irqreader, fqs_duration, fqs_holdoff, fqs_stutter,
+                test_boost, cur_ops->can_boost,
+                test_boost_interval, test_boost_duration, shutdown_secs,
+                stall_cpu, stall_cpu_holdoff,
+                n_barrier_cbs,
+                onoff_interval, onoff_holdoff);
 }
 
 static struct notifier_block rcutorture_shutdown_nb = {
@@ -1456,10 +1488,9 @@ rcu_torture_shutdown(void *arg)
               !kthread_should_stop()) {
                delta = shutdown_time - jiffies_snap;
                if (verbose)
-                       printk(KERN_ALERT "%s" TORTURE_FLAG
-                              "rcu_torture_shutdown task: %lu "
-                              "jiffies remaining\n",
-                              torture_type, delta);
+                       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);
        }
@@ -1487,8 +1518,11 @@ static int __cpuinit
 rcu_torture_onoff(void *arg)
 {
        int cpu;
+       unsigned long delta;
        int maxcpu = -1;
        DEFINE_RCU_RANDOM(rand);
+       int ret;
+       unsigned long starttime;
 
        VERBOSE_PRINTK_STRING("rcu_torture_onoff task started");
        for_each_online_cpu(cpu)
@@ -1503,31 +1537,57 @@ rcu_torture_onoff(void *arg)
                cpu = (rcu_random(&rand) >> 4) % (maxcpu + 1);
                if (cpu_online(cpu) && cpu_is_hotpluggable(cpu)) {
                        if (verbose)
-                               printk(KERN_ALERT "%s" TORTURE_FLAG
-                                      "rcu_torture_onoff task: offlining %d\n",
-                                      torture_type, cpu);
+                               pr_alert("%s" TORTURE_FLAG
+                                        "rcu_torture_onoff task: offlining %d\n",
+                                        torture_type, cpu);
+                       starttime = jiffies;
                        n_offline_attempts++;
-                       if (cpu_down(cpu) == 0) {
+                       ret = cpu_down(cpu);
+                       if (ret) {
                                if (verbose)
-                                       printk(KERN_ALERT "%s" TORTURE_FLAG
-                                              "rcu_torture_onoff task: "
-                                              "offlined %d\n",
-                                              torture_type, cpu);
+                                       pr_alert("%s" TORTURE_FLAG
+                                                "rcu_torture_onoff task: offline %d failed: errno %d\n",
+                                                torture_type, cpu, ret);
+                       } else {
+                               if (verbose)
+                                       pr_alert("%s" TORTURE_FLAG
+                                                "rcu_torture_onoff task: offlined %d\n",
+                                                torture_type, cpu);
                                n_offline_successes++;
+                               delta = jiffies - starttime;
+                               sum_offline += delta;
+                               if (min_offline < 0) {
+                                       min_offline = delta;
+                                       max_offline = delta;
+                               }
+                               if (min_offline > delta)
+                                       min_offline = delta;
+                               if (max_offline < delta)
+                                       max_offline = delta;
                        }
                } else if (cpu_is_hotpluggable(cpu)) {
                        if (verbose)
-                               printk(KERN_ALERT "%s" TORTURE_FLAG
-                                      "rcu_torture_onoff task: onlining %d\n",
-                                      torture_type, cpu);
+                               pr_alert("%s" TORTURE_FLAG
+                                        "rcu_torture_onoff task: onlining %d\n",
+                                        torture_type, cpu);
+                       starttime = jiffies;
                        n_online_attempts++;
                        if (cpu_up(cpu) == 0) {
                                if (verbose)
-                                       printk(KERN_ALERT "%s" TORTURE_FLAG
-                                              "rcu_torture_onoff task: "
-                                              "onlined %d\n",
-                                              torture_type, cpu);
+                                       pr_alert("%s" TORTURE_FLAG
+                                                "rcu_torture_onoff task: onlined %d\n",
+                                                torture_type, cpu);
                                n_online_successes++;
+                               delta = jiffies - starttime;
+                               sum_online += delta;
+                               if (min_online < 0) {
+                                       min_online = delta;
+                                       max_online = delta;
+                               }
+                               if (min_online > delta)
+                                       min_online = delta;
+                               if (max_online < delta)
+                                       max_online = delta;
                        }
                }
                schedule_timeout_interruptible(onoff_interval * HZ);
@@ -1592,14 +1652,14 @@ static int __cpuinit rcu_torture_stall(void *args)
        if (!kthread_should_stop()) {
                stop_at = get_seconds() + stall_cpu;
                /* RCU CPU stall is expected behavior in following code. */
-               printk(KERN_ALERT "rcu_torture_stall start.\n");
+               pr_alert("rcu_torture_stall start.\n");
                rcu_read_lock();
                preempt_disable();
                while (ULONG_CMP_LT(get_seconds(), stop_at))
                        continue;  /* Induce RCU CPU stall warning. */
                preempt_enable();
                rcu_read_unlock();
-               printk(KERN_ALERT "rcu_torture_stall end.\n");
+               pr_alert("rcu_torture_stall end.\n");
        }
        rcutorture_shutdown_absorb("rcu_torture_stall");
        while (!kthread_should_stop())
@@ -1700,7 +1760,7 @@ static int rcu_torture_barrier(void *arg)
                schedule_timeout_interruptible(HZ / 10);
        } while (!kthread_should_stop() && fullstop == FULLSTOP_DONTSTOP);
        VERBOSE_PRINTK_STRING("rcu_torture_barrier task stopping");
-       rcutorture_shutdown_absorb("rcu_torture_barrier_cbs");
+       rcutorture_shutdown_absorb("rcu_torture_barrier");
        while (!kthread_should_stop())
                schedule_timeout_interruptible(1);
        return 0;
@@ -1715,12 +1775,12 @@ static int rcu_torture_barrier_init(void)
        if (n_barrier_cbs == 0)
                return 0;
        if (cur_ops->call == NULL || cur_ops->cb_barrier == NULL) {
-               printk(KERN_ALERT "%s" TORTURE_FLAG
-                      " Call or barrier ops missing for %s,\n",
-                      torture_type, cur_ops->name);
-               printk(KERN_ALERT "%s" TORTURE_FLAG
-                      " RCU barrier testing omitted from run.\n",
-                      torture_type);
+               pr_alert("%s" TORTURE_FLAG
+                        " Call or barrier ops missing for %s,\n",
+                        torture_type, cur_ops->name);
+               pr_alert("%s" TORTURE_FLAG
+                        " RCU barrier testing omitted from run.\n",
+                        torture_type);
                return 0;
        }
        atomic_set(&barrier_cbs_count, 0);
@@ -1731,7 +1791,7 @@ static int rcu_torture_barrier_init(void)
        barrier_cbs_wq =
                kzalloc(n_barrier_cbs * sizeof(barrier_cbs_wq[0]),
                        GFP_KERNEL);
-       if (barrier_cbs_tasks == NULL || barrier_cbs_wq == 0)
+       if (barrier_cbs_tasks == NULL || !barrier_cbs_wq)
                return -ENOMEM;
        for (i = 0; i < n_barrier_cbs; i++) {
                init_waitqueue_head(&barrier_cbs_wq[i]);
@@ -1813,7 +1873,7 @@ rcu_torture_cleanup(void)
        mutex_lock(&fullstop_mutex);
        rcutorture_record_test_transition();
        if (fullstop == FULLSTOP_SHUTDOWN) {
-               printk(KERN_WARNING /* but going down anyway, so... */
+               pr_warn(/* but going down anyway, so... */
                       "Concurrent 'rmmod rcutorture' and shutdown illegal!\n");
                mutex_unlock(&fullstop_mutex);
                schedule_timeout_uninterruptible(10);
@@ -1902,8 +1962,6 @@ rcu_torture_cleanup(void)
 
        rcu_torture_stats_print();  /* -After- the stats thread is stopped! */
 
-       if (cur_ops->cleanup)
-               cur_ops->cleanup();
        if (atomic_read(&n_rcu_torture_error) || n_rcu_torture_barrier_error)
                rcu_torture_print_module_parms(cur_ops, "End of test: FAILURE");
        else if (n_online_successes != n_online_attempts ||
@@ -1937,18 +1995,17 @@ rcu_torture_init(void)
                        break;
        }
        if (i == ARRAY_SIZE(torture_ops)) {
-               printk(KERN_ALERT "rcu-torture: invalid torture type: \"%s\"\n",
-                      torture_type);
-               printk(KERN_ALERT "rcu-torture types:");
+               pr_alert("rcu-torture: invalid torture type: \"%s\"\n",
+                        torture_type);
+               pr_alert("rcu-torture types:");
                for (i = 0; i < ARRAY_SIZE(torture_ops); i++)
-                       printk(KERN_ALERT " %s", torture_ops[i]->name);
-               printk(KERN_ALERT "\n");
+                       pr_alert(" %s", torture_ops[i]->name);
+               pr_alert("\n");
                mutex_unlock(&fullstop_mutex);
                return -EINVAL;
        }
        if (cur_ops->fqs == NULL && fqs_duration != 0) {
-               printk(KERN_ALERT "rcu-torture: ->fqs NULL and non-zero "
-                                 "fqs_duration, fqs disabled.\n");
+               pr_alert("rcu-torture: ->fqs NULL and non-zero fqs_duration, fqs disabled.\n");
                fqs_duration = 0;
        }
        if (cur_ops->init)
@@ -1996,14 +2053,15 @@ rcu_torture_init(void)
        /* Start up the kthreads. */
 
        VERBOSE_PRINTK_STRING("Creating rcu_torture_writer task");
-       writer_task = kthread_run(rcu_torture_writer, NULL,
-                                 "rcu_torture_writer");
+       writer_task = kthread_create(rcu_torture_writer, NULL,
+                                    "rcu_torture_writer");
        if (IS_ERR(writer_task)) {
                firsterr = PTR_ERR(writer_task);
                VERBOSE_PRINTK_ERRSTRING("Failed to create writer");
                writer_task = NULL;
                goto unwind;
        }
+       wake_up_process(writer_task);
        fakewriter_tasks = kzalloc(nfakewriters * sizeof(fakewriter_tasks[0]),
                                   GFP_KERNEL);
        if (fakewriter_tasks == NULL) {
@@ -2118,14 +2176,15 @@ rcu_torture_init(void)
        }
        if (shutdown_secs > 0) {
                shutdown_time = jiffies + shutdown_secs * HZ;
-               shutdown_task = kthread_run(rcu_torture_shutdown, NULL,
-                                           "rcu_torture_shutdown");
+               shutdown_task = kthread_create(rcu_torture_shutdown, NULL,
+                                              "rcu_torture_shutdown");
                if (IS_ERR(shutdown_task)) {
                        firsterr = PTR_ERR(shutdown_task);
                        VERBOSE_PRINTK_ERRSTRING("Failed to create shutdown");
                        shutdown_task = NULL;
                        goto unwind;
                }
+               wake_up_process(shutdown_task);
        }
        i = rcu_torture_onoff_init();
        if (i != 0) {