diff mbox

[3.8.y.z,extended,stable] Patch "workqueue: ensure @task is valid across kthread_stop()" has been added to staging queue

Message ID 1395330881-6112-1-git-send-email-kamal@canonical.com
State New
Headers show

Commit Message

Kamal Mostafa March 20, 2014, 3:54 p.m. UTC
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@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@cn.fujitsu.com>
Signed-off-by: Tejun Heo <tj@kernel.org>
Signed-off-by: Kamal Mostafa <kamal@canonical.com>
---
 kernel/workqueue.c | 7 +++++++
 1 file changed, 7 insertions(+)

--
1.8.3.2
diff mbox

Patch

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);