]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
workqueue: Move kthread_flush_worker() out of alloc_and_link_pwqs()
authorLai Jiangshan <jiangshan.ljs@antgroup.com>
Thu, 4 Jul 2024 03:49:12 +0000 (11:49 +0800)
committerTejun Heo <tj@kernel.org>
Fri, 5 Jul 2024 19:14:40 +0000 (09:14 -1000)
kthread_flush_worker() can't be called with wq_pool_mutex held.

Prepare for moving wq_pool_mutex and cpu hotplug lock out of
alloc_and_link_pwqs().

Cc: Zqiang <qiang.zhang1211@gmail.com>
Link: https://lore.kernel.org/lkml/20230920060704.24981-1-qiang.zhang1211@gmail.com/
Signed-off-by: Lai Jiangshan <jiangshan.ljs@antgroup.com>
Signed-off-by: Tejun Heo <tj@kernel.org>
kernel/workqueue.c

index af00e63182d0a9b9b84ab424d430360f356debae..ab0aca0ccc8f261c317b486d058427a0caad89ae 100644 (file)
@@ -5467,12 +5467,6 @@ static int alloc_and_link_pwqs(struct workqueue_struct *wq)
        }
        cpus_read_unlock();
 
-       /* for unbound pwq, flush the pwq_release_worker ensures that the
-        * pwq_release_workfn() completes before calling kfree(wq).
-        */
-       if (ret)
-               kthread_flush_worker(pwq_release_worker);
-
        return ret;
 
 enomem:
@@ -5705,8 +5699,15 @@ struct workqueue_struct *alloc_workqueue(const char *fmt,
        return wq;
 
 err_free_node_nr_active:
-       if (wq->flags & WQ_UNBOUND)
+       /*
+        * Failed alloc_and_link_pwqs() may leave pending pwq->release_work,
+        * flushing the pwq_release_worker ensures that the pwq_release_workfn()
+        * completes before calling kfree(wq).
+        */
+       if (wq->flags & WQ_UNBOUND) {
+               kthread_flush_worker(pwq_release_worker);
                free_node_nr_active(wq->node_nr_active);
+       }
 err_unreg_lockdep:
        wq_unregister_lockdep(wq);
        wq_free_lockdep(wq);