rcu: Prevent initialization race in rcutorture kthreads
authorPaul E. McKenney <paulmck@linux.vnet.ibm.com>
Sat, 25 Aug 2012 22:27:40 +0000 (15:27 -0700)
committerPaul E. McKenney <paulmck@linux.vnet.ibm.com>
Sun, 23 Sep 2012 14:42:23 +0000 (07:42 -0700)
When you do something like "t = kthread_run(...)", it is possible that
the kthread will start running before the assignment to "t" happens.
If the child kthread expects to find a pointer to its task_struct in "t",
it will then be fatally disappointed.  This commit therefore switches
such cases to kthread_create() followed by wake_up_process(), guaranteeing
that the assignment happens before the child kthread starts running.

Reported-by: Fengguang Wu <fengguang.wu@intel.com>
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
kernel/rcutorture.c

index 61be03ba598dd48926dba04248cacf330c23bed3..aaa7b9f3532a86c87580fa6202a20df8c9dcd249 100644 (file)
@@ -2029,14 +2029,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) {
@@ -2151,14 +2152,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) {