diff options
Diffstat (limited to 'kernel/workqueue.c')
-rw-r--r-- | kernel/workqueue.c | 9 |
1 files changed, 9 insertions, 0 deletions
diff --git a/kernel/workqueue.c b/kernel/workqueue.c index b010eac595d2..193e977a10ea 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c | |||
@@ -1851,6 +1851,12 @@ static void destroy_worker(struct worker *worker) | |||
1851 | if (worker->flags & WORKER_IDLE) | 1851 | if (worker->flags & WORKER_IDLE) |
1852 | pool->nr_idle--; | 1852 | pool->nr_idle--; |
1853 | 1853 | ||
1854 | /* | ||
1855 | * Once WORKER_DIE is set, the kworker may destroy itself at any | ||
1856 | * point. Pin to ensure the task stays until we're done with it. | ||
1857 | */ | ||
1858 | get_task_struct(worker->task); | ||
1859 | |||
1854 | list_del_init(&worker->entry); | 1860 | list_del_init(&worker->entry); |
1855 | worker->flags |= WORKER_DIE; | 1861 | worker->flags |= WORKER_DIE; |
1856 | 1862 | ||
@@ -1859,6 +1865,7 @@ static void destroy_worker(struct worker *worker) | |||
1859 | spin_unlock_irq(&pool->lock); | 1865 | spin_unlock_irq(&pool->lock); |
1860 | 1866 | ||
1861 | kthread_stop(worker->task); | 1867 | kthread_stop(worker->task); |
1868 | put_task_struct(worker->task); | ||
1862 | kfree(worker); | 1869 | kfree(worker); |
1863 | 1870 | ||
1864 | spin_lock_irq(&pool->lock); | 1871 | spin_lock_irq(&pool->lock); |
@@ -4789,6 +4796,7 @@ static int workqueue_cpu_down_callback(struct notifier_block *nfb, | |||
4789 | 4796 | ||
4790 | /* wait for per-cpu unbinding to finish */ | 4797 | /* wait for per-cpu unbinding to finish */ |
4791 | flush_work(&unbind_work); | 4798 | flush_work(&unbind_work); |
4799 | destroy_work_on_stack(&unbind_work); | ||
4792 | break; | 4800 | break; |
4793 | } | 4801 | } |
4794 | return NOTIFY_OK; | 4802 | return NOTIFY_OK; |
@@ -4828,6 +4836,7 @@ long work_on_cpu(int cpu, long (*fn)(void *), void *arg) | |||
4828 | INIT_WORK_ONSTACK(&wfc.work, work_for_cpu_fn); | 4836 | INIT_WORK_ONSTACK(&wfc.work, work_for_cpu_fn); |
4829 | schedule_work_on(cpu, &wfc.work); | 4837 | schedule_work_on(cpu, &wfc.work); |
4830 | flush_work(&wfc.work); | 4838 | flush_work(&wfc.work); |
4839 | destroy_work_on_stack(&wfc.work); | ||
4831 | return wfc.ret; | 4840 | return wfc.ret; |
4832 | } | 4841 | } |
4833 | EXPORT_SYMBOL_GPL(work_on_cpu); | 4842 | EXPORT_SYMBOL_GPL(work_on_cpu); |