Now rescuer checks pwq->nr_active before requeues the pwq,
it is a more robust check and the rescuer must be still valid.

Signed-off-by: Lai Jiangshan <[email protected]>
---
 kernel/workqueue.c | 23 +++++++++--------------
 1 file changed, 9 insertions(+), 14 deletions(-)

diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index b2b15f1f0c8d..8d017727bfbc 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -248,7 +248,7 @@ struct workqueue_struct {
        struct list_head        flusher_overflow; /* WQ: flush overflow list */
 
        struct list_head        maydays;        /* MD: pwqs requesting rescue */
-       struct worker           *rescuer;       /* MD: rescue worker */
+       struct worker           *rescuer;       /* I: rescue worker */
 
        int                     nr_drainers;    /* WQ: drain in progress */
        int                     saved_max_active; /* WQ: saved pwq max_active */
@@ -2532,12 +2532,13 @@ static int rescuer_thread(void *__rescuer)
                        if (pwq->nr_active && need_to_create_worker(pool)) {
                                spin_lock(&wq_mayday_lock);
                                /*
-                                * Queue iff we aren't racing destruction
-                                * and somebody else hasn't queued it already.
+                                * Queue iff somebody else hasn't queued it
+                                * already.
                                 */
-                               if (wq->rescuer && 
list_empty(&pwq->mayday_node)) {
+                               if (list_empty(&pwq->mayday_node)) {
                                        get_pwq(pwq);
-                                       list_add_tail(&pwq->mayday_node, 
&wq->maydays);
+                                       list_add_tail(&pwq->mayday_node,
+                                                     &wq->maydays);
                                }
                                spin_unlock(&wq_mayday_lock);
                        }
@@ -4356,16 +4357,10 @@ void destroy_workqueue(struct workqueue_struct *wq)
 
        /* kill rescuer, if sanity checks fail, leave it w/o rescuer */
        if (wq->rescuer) {
-               struct worker *rescuer = wq->rescuer;
-
-               /* this prevents new queueing */
-               spin_lock_irq(&wq_mayday_lock);
-               wq->rescuer = NULL;
-               spin_unlock_irq(&wq_mayday_lock);
-
                /* rescuer will empty maydays list before exiting */
-               kthread_stop(rescuer->task);
-               kfree(rescuer);
+               kthread_stop(wq->rescuer->task);
+               kfree(wq->rescuer);
+               wq->rescuer = NULL;
        }
 
        /*
-- 
2.20.1

Reply via email to