[3.8.y.z extended stable] Patch "workqueue: ensure @task is valid across kthread_stop()" has been added to staging queue
Kamal Mostafa
kamal at canonical.com
Thu Mar 20 15:54:41 UTC 2014
This is a note to let you know that I have just added a patch titled
workqueue: ensure @task is valid across kthread_stop()
to the linux-3.8.y-queue branch of the 3.8.y.z extended stable tree
which can be found at:
http://kernel.ubuntu.com/git?p=ubuntu/linux.git;a=shortlog;h=refs/heads/linux-3.8.y-queue
This patch is scheduled to be released in version 3.8.13.20.
If you, or anyone else, feels it should not be added to this tree, please
reply to this email.
For more information about the 3.8.y.z tree, see
https://wiki.ubuntu.com/Kernel/Dev/ExtendedStable
Thanks.
-Kamal
------
>From f8b55448454670fd26c6102f282aa814b58e1f9c Mon Sep 17 00:00:00 2001
From: Lai Jiangshan <laijs at cn.fujitsu.com>
Date: Sat, 15 Feb 2014 22:02:28 +0800
Subject: workqueue: ensure @task is valid across kthread_stop()
commit 5bdfff96c69a4d5ab9c49e60abf9e070ecd2acbb upstream.
When a kworker should die, the kworkre is notified through WORKER_DIE
flag instead of kthread_should_stop(). This, IIRC, is primarily to
keep the test synchronized inside worker_pool lock. WORKER_DIE is
first set while holding pool->lock, the lock is dropped and
kthread_stop() is called.
Unfortunately, this means that there's a slight chance that the target
kworker may see WORKER_DIE before kthread_stop() finishes and exits
and frees the target task before or during kthread_stop().
Fix it by pinning the target task before setting WORKER_DIE and
putting it after kthread_stop() is done.
tj: Improved patch description and comment. Moved pinning above
WORKER_DIE for better signify what it's protecting.
Signed-off-by: Lai Jiangshan <laijs at cn.fujitsu.com>
Signed-off-by: Tejun Heo <tj at kernel.org>
Signed-off-by: Kamal Mostafa <kamal at canonical.com>
---
kernel/workqueue.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index 338b3bd..1fd7e24 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -1902,12 +1902,19 @@ 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;
spin_unlock_irq(&gcwq->lock);
kthread_stop(worker->task);
+ put_task_struct(worker->task);
kfree(worker);
spin_lock_irq(&gcwq->lock);
--
1.8.3.2
More information about the kernel-team
mailing list