diff options
author | Paul E. McKenney <paulmck@linux.vnet.ibm.com> | 2012-08-25 18:27:40 -0400 |
---|---|---|
committer | Paul E. McKenney <paulmck@linux.vnet.ibm.com> | 2012-09-23 10:42:23 -0400 |
commit | 60f53782c51f27c695840ce90c6c432284319eef (patch) | |
tree | daf20b20a35f09ecfa214127cf3c676f12c4edd1 /kernel/rcutorture.c | |
parent | 2caa1e4432be7260dca60c3de6949b77eb007515 (diff) |
rcu: Prevent initialization race in rcutorture kthreads
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>
Diffstat (limited to 'kernel/rcutorture.c')
-rw-r--r-- | kernel/rcutorture.c | 10 |
1 files changed, 6 insertions, 4 deletions
diff --git a/kernel/rcutorture.c b/kernel/rcutorture.c index 61be03ba598d..aaa7b9f3532a 100644 --- a/kernel/rcutorture.c +++ b/kernel/rcutorture.c | |||
@@ -2029,14 +2029,15 @@ rcu_torture_init(void) | |||
2029 | /* Start up the kthreads. */ | 2029 | /* Start up the kthreads. */ |
2030 | 2030 | ||
2031 | VERBOSE_PRINTK_STRING("Creating rcu_torture_writer task"); | 2031 | VERBOSE_PRINTK_STRING("Creating rcu_torture_writer task"); |
2032 | writer_task = kthread_run(rcu_torture_writer, NULL, | 2032 | writer_task = kthread_create(rcu_torture_writer, NULL, |
2033 | "rcu_torture_writer"); | 2033 | "rcu_torture_writer"); |
2034 | if (IS_ERR(writer_task)) { | 2034 | if (IS_ERR(writer_task)) { |
2035 | firsterr = PTR_ERR(writer_task); | 2035 | firsterr = PTR_ERR(writer_task); |
2036 | VERBOSE_PRINTK_ERRSTRING("Failed to create writer"); | 2036 | VERBOSE_PRINTK_ERRSTRING("Failed to create writer"); |
2037 | writer_task = NULL; | 2037 | writer_task = NULL; |
2038 | goto unwind; | 2038 | goto unwind; |
2039 | } | 2039 | } |
2040 | wake_up_process(writer_task); | ||
2040 | fakewriter_tasks = kzalloc(nfakewriters * sizeof(fakewriter_tasks[0]), | 2041 | fakewriter_tasks = kzalloc(nfakewriters * sizeof(fakewriter_tasks[0]), |
2041 | GFP_KERNEL); | 2042 | GFP_KERNEL); |
2042 | if (fakewriter_tasks == NULL) { | 2043 | if (fakewriter_tasks == NULL) { |
@@ -2151,14 +2152,15 @@ rcu_torture_init(void) | |||
2151 | } | 2152 | } |
2152 | if (shutdown_secs > 0) { | 2153 | if (shutdown_secs > 0) { |
2153 | shutdown_time = jiffies + shutdown_secs * HZ; | 2154 | shutdown_time = jiffies + shutdown_secs * HZ; |
2154 | shutdown_task = kthread_run(rcu_torture_shutdown, NULL, | 2155 | shutdown_task = kthread_create(rcu_torture_shutdown, NULL, |
2155 | "rcu_torture_shutdown"); | 2156 | "rcu_torture_shutdown"); |
2156 | if (IS_ERR(shutdown_task)) { | 2157 | if (IS_ERR(shutdown_task)) { |
2157 | firsterr = PTR_ERR(shutdown_task); | 2158 | firsterr = PTR_ERR(shutdown_task); |
2158 | VERBOSE_PRINTK_ERRSTRING("Failed to create shutdown"); | 2159 | VERBOSE_PRINTK_ERRSTRING("Failed to create shutdown"); |
2159 | shutdown_task = NULL; | 2160 | shutdown_task = NULL; |
2160 | goto unwind; | 2161 | goto unwind; |
2161 | } | 2162 | } |
2163 | wake_up_process(shutdown_task); | ||
2162 | } | 2164 | } |
2163 | i = rcu_torture_onoff_init(); | 2165 | i = rcu_torture_onoff_init(); |
2164 | if (i != 0) { | 2166 | if (i != 0) { |