workqueue: don't clear cwq->thread until it exits
Pointed out by Srivatsa Vaddagiri. cleanup_workqueue_thread() sets cwq->thread = NULL and does kthread_stop(). This breaks the "if (cwq->thread == current)" logic in flush_cpu_workqueue() and leads to deadlock. Kill the thead first, then clear cwq->thread. workqueue_mutex protects us from create_workqueue_thread() so we don't need cwq->lock. Signed-off-by: Oleg Nesterov <oleg@tv-sign.ru> Cc: Srivatsa Vaddagiri <vatsa@in.ibm.com> Cc: "Pallipadi, Venkatesh" <venkatesh.pallipadi@intel.com> Cc: Gautham shenoy <ego@in.ibm.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
Родитель
d721304dce
Коммит
36aa9dfc39
|
@ -625,17 +625,12 @@ EXPORT_SYMBOL_GPL(__create_workqueue);
|
|||
|
||||
static void cleanup_workqueue_thread(struct workqueue_struct *wq, int cpu)
|
||||
{
|
||||
struct cpu_workqueue_struct *cwq;
|
||||
unsigned long flags;
|
||||
struct task_struct *p;
|
||||
struct cpu_workqueue_struct *cwq = per_cpu_ptr(wq->cpu_wq, cpu);
|
||||
|
||||
cwq = per_cpu_ptr(wq->cpu_wq, cpu);
|
||||
spin_lock_irqsave(&cwq->lock, flags);
|
||||
p = cwq->thread;
|
||||
cwq->thread = NULL;
|
||||
spin_unlock_irqrestore(&cwq->lock, flags);
|
||||
if (p)
|
||||
kthread_stop(p);
|
||||
if (cwq->thread) {
|
||||
kthread_stop(cwq->thread);
|
||||
cwq->thread = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Загрузка…
Ссылка в новой задаче