From 24cdab5787a0ae90260df1f8ac8284877a70b7b3 Mon Sep 17 00:00:00 2001 From: Philipp Stanner Date: Fri, 4 Apr 2025 12:15:44 +0200 Subject: workqueue: Better document teardown for delayed_work destroy_workqueue() does not ensure that non-pending work submitted with queue_delayed_work() gets cancelled. The caller has to ensure that manually. Add this information about delayed_work in destroy_workqueue()'s docstring. Add a TODO for destroy_workqueue() to wait for all delayed_work. Signed-off-by: Philipp Stanner Signed-off-by: Tejun Heo --- kernel/workqueue.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/kernel/workqueue.c b/kernel/workqueue.c index cf6203282737..2cb8276a27a9 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -5837,6 +5837,17 @@ static bool pwq_busy(struct pool_workqueue *pwq) * @wq: target workqueue * * Safely destroy a workqueue. All work currently pending will be done first. + * + * This function does NOT guarantee that non-pending work that has been + * submitted with queue_delayed_work() and similar functions will be done + * before destroying the workqueue. The fundamental problem is that, currently, + * the workqueue has no way of accessing non-pending delayed_work. delayed_work + * is only linked on the timer-side. All delayed_work must, therefore, be + * canceled before calling this function. + * + * TODO: It would be better if the problem described above wouldn't exist and + * destroy_workqueue() would cleanly cancel all pending and non-pending + * delayed_work. */ void destroy_workqueue(struct workqueue_struct *wq) { -- cgit v1.2.3 From 70e1683ca3a6474360af1d3a020a9a98c8492cc0 Mon Sep 17 00:00:00 2001 From: Jiayuan Chen Date: Thu, 24 Apr 2025 00:17:42 +0800 Subject: workqueue: Fix race condition in wq->stats incrementation Fixed a race condition in incrementing wq->stats[PWQ_STAT_COMPLETED] by moving the operation under pool->lock. Reported-by: syzbot+01affb1491750534256d@syzkaller.appspotmail.com Signed-off-by: Jiayuan Chen Signed-off-by: Tejun Heo --- kernel/workqueue.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/kernel/workqueue.c b/kernel/workqueue.c index 2cb8276a27a9..f9ef467020cf 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -3241,7 +3241,7 @@ __acquires(&pool->lock) * point will only record its address. */ trace_workqueue_execute_end(work, worker->current_func); - pwq->stats[PWQ_STAT_COMPLETED]++; + lock_map_release(&lockdep_map); if (!bh_draining) lock_map_release(pwq->wq->lockdep_map); @@ -3272,6 +3272,8 @@ __acquires(&pool->lock) raw_spin_lock_irq(&pool->lock); + pwq->stats[PWQ_STAT_COMPLETED]++; + /* * In addition to %WQ_CPU_INTENSIVE, @worker may also have been marked * CPU intensive by wq_worker_tick() if @work hogged CPU longer than -- cgit v1.2.3 From 23227e71b69af95e421e263302d13f426c548155 Mon Sep 17 00:00:00 2001 From: Guan-Chun Wu <409411716@gms.tku.edu.tw> Date: Sat, 3 May 2025 16:12:03 +0800 Subject: workqueue: fix typo in comment Fix a duplicated word "that that" in the comment describing the @max_active behavior for unbound workqueues. Signed-off-by: Guan-Chun Wu <409411716@gms.tku.edu.tw> Signed-off-by: Tejun Heo --- include/linux/workqueue.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/workqueue.h b/include/linux/workqueue.h index b0dc957c3e56..a6dacc0eb688 100644 --- a/include/linux/workqueue.h +++ b/include/linux/workqueue.h @@ -480,7 +480,7 @@ void workqueue_softirq_dead(unsigned int cpu); * executing at most one work item for the workqueue. * * For unbound workqueues, @max_active limits the number of in-flight work items - * for the whole system. e.g. @max_active of 16 indicates that that there can be + * for the whole system. e.g. @max_active of 16 indicates that there can be * at most 16 work items executing for the workqueue in the whole system. * * As sharing the same active counter for an unbound workqueue across multiple -- cgit v1.2.3