Commit b9b52730 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] flush_scheduled_work() deadlock fix

Because keventd is a resource which is shared between unrelated parts of the
kernel it is possible for one person's workqueue handler to accidentally call
another person's flush_scheduled_work().  thockin managed it by calling
mntput() from a workqueue handler.  It deadlocks.

It's simple enough to fix: teach flush_scheduled_work() to go direct when it
discovers that the calling thread is the one which should be running the
work.

Note that this can cause recursion.  The depth of that recursion is equal to
the number of currently-queued works which themselves want to call
flush_scheduled_work().  If this ever exceeds three I'll eat my hat.
parent e6c51795
...@@ -218,6 +218,14 @@ void fastcall flush_workqueue(struct workqueue_struct *wq) ...@@ -218,6 +218,14 @@ void fastcall flush_workqueue(struct workqueue_struct *wq)
continue; continue;
cwq = wq->cpu_wq + cpu; cwq = wq->cpu_wq + cpu;
if (cwq->thread == current) {
/*
* Probably keventd trying to flush its own queue.
* So simply run it by hand rather than deadlocking.
*/
run_workqueue(cwq);
continue;
}
spin_lock_irq(&cwq->lock); spin_lock_irq(&cwq->lock);
sequence_needed = cwq->insert_sequence; sequence_needed = cwq->insert_sequence;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment