]> Pileus Git - ~andy/linux/blobdiff - kernel/workqueue.c
Merge branch 'irq-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[~andy/linux] / kernel / workqueue.c
index b010eac595d20eece261310cc4acb629ad70b92b..193e977a10eaeb6a7f9ca5927d08f558d68df434 100644 (file)
@@ -1851,6 +1851,12 @@ static void destroy_worker(struct worker *worker)
        if (worker->flags & WORKER_IDLE)
                pool->nr_idle--;
 
+       /*
+        * Once WORKER_DIE is set, the kworker may destroy itself at any
+        * point.  Pin to ensure the task stays until we're done with it.
+        */
+       get_task_struct(worker->task);
+
        list_del_init(&worker->entry);
        worker->flags |= WORKER_DIE;
 
@@ -1859,6 +1865,7 @@ static void destroy_worker(struct worker *worker)
        spin_unlock_irq(&pool->lock);
 
        kthread_stop(worker->task);
+       put_task_struct(worker->task);
        kfree(worker);
 
        spin_lock_irq(&pool->lock);
@@ -4789,6 +4796,7 @@ static int workqueue_cpu_down_callback(struct notifier_block *nfb,
 
                /* wait for per-cpu unbinding to finish */
                flush_work(&unbind_work);
+               destroy_work_on_stack(&unbind_work);
                break;
        }
        return NOTIFY_OK;
@@ -4828,6 +4836,7 @@ long work_on_cpu(int cpu, long (*fn)(void *), void *arg)
        INIT_WORK_ONSTACK(&wfc.work, work_for_cpu_fn);
        schedule_work_on(cpu, &wfc.work);
        flush_work(&wfc.work);
+       destroy_work_on_stack(&wfc.work);
        return wfc.ret;
 }
 EXPORT_SYMBOL_GPL(work_on_cpu);