summaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorAndrew Morton <akpm@osdl.org>2004-03-15 15:19:29 -0800
committerLinus Torvalds <torvalds@ppc970.osdl.org>2004-03-15 15:19:29 -0800
commitb9b52730c0c103b677e29e723ce0db878003d496 (patch)
tree53647adcd27f2958db6a8c4ab3544051835c189c /kernel
parente6c51795efa014a7c0ce4a2e82d7598b57e1542b (diff)
[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.
Diffstat (limited to 'kernel')
-rw-r--r--kernel/workqueue.c8
1 files changed, 8 insertions, 0 deletions
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index 2e94fd93abe6..6ca72d53d9ca 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -218,6 +218,14 @@ void fastcall flush_workqueue(struct workqueue_struct *wq)
continue;
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);
sequence_needed = cwq->insert_sequence;