Skip to content

Commit

Permalink
workqueue: Warn attempt to flush system-wide workqueues.
Browse files Browse the repository at this point in the history
Based on commit c4f135d ("workqueue: Wrap flush_workqueue() using
a macro"), all in-tree users stopped flushing system-wide workqueues.
Therefore, start emitting runtime message so that all out-of-tree users
will understand that they need to update their code.

Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Signed-off-by: Tejun Heo <tj@kernel.org>
  • Loading branch information
Tetsuo Handa authored and Tejun Heo committed Jul 10, 2023
1 parent 3f01e9f commit 20bdeda
Show file tree
Hide file tree
Showing 2 changed files with 8 additions and 47 deletions.
44 changes: 3 additions & 41 deletions include/linux/workqueue.h
Original file line number Diff line number Diff line change
Expand Up @@ -569,59 +569,21 @@ static inline bool schedule_work(struct work_struct *work)

/*
* Detect attempt to flush system-wide workqueues at compile time when possible.
* Warn attempt to flush system-wide workqueues at runtime.
*
* See https://lkml.kernel.org/r/49925af7-78a8-a3dd-bce6-cfc02e1a9236@I-love.SAKURA.ne.jp
* for reasons and steps for converting system-wide workqueues into local workqueues.
*/
extern void __warn_flushing_systemwide_wq(void)
__compiletime_warning("Please avoid flushing system-wide workqueues.");

/**
* flush_scheduled_work - ensure that any scheduled work has run to completion.
*
* Forces execution of the kernel-global workqueue and blocks until its
* completion.
*
* It's very easy to get into trouble if you don't take great care.
* Either of the following situations will lead to deadlock:
*
* One of the work items currently on the workqueue needs to acquire
* a lock held by your code or its caller.
*
* Your code is running in the context of a work routine.
*
* They will be detected by lockdep when they occur, but the first might not
* occur very often. It depends on what work items are on the workqueue and
* what locks they need, which you have no control over.
*
* In most situations flushing the entire workqueue is overkill; you merely
* need to know that a particular work item isn't queued and isn't running.
* In such cases you should use cancel_delayed_work_sync() or
* cancel_work_sync() instead.
*
* Please stop calling this function! A conversion to stop flushing system-wide
* workqueues is in progress. This function will be removed after all in-tree
* users stopped calling this function.
*/
/*
* The background of commit 771c035372a036f8 ("deprecate the
* '__deprecated' attribute warnings entirely and for good") is that,
* since Linus builds all modules between every single pull he does,
* the standard kernel build needs to be _clean_ in order to be able to
* notice when new problems happen. Therefore, don't emit warning while
* there are in-tree users.
*/
/* Please stop using this function, for this function will be removed in near future. */
#define flush_scheduled_work() \
({ \
if (0) \
__warn_flushing_systemwide_wq(); \
__warn_flushing_systemwide_wq(); \
__flush_workqueue(system_wq); \
})

/*
* Although there is no longer in-tree caller, for now just emit warning
* in order to give out-of-tree callers time to update.
*/
#define flush_workqueue(wq) \
({ \
struct workqueue_struct *_wq = (wq); \
Expand Down
11 changes: 5 additions & 6 deletions kernel/workqueue.c
Original file line number Diff line number Diff line change
Expand Up @@ -6571,10 +6571,9 @@ void __init workqueue_init(void)
wq_watchdog_init();
}

/*
* Despite the naming, this is a no-op function which is here only for avoiding
* link error. Since compile-time warning may fail to catch, we will need to
* emit run-time warning from __flush_workqueue().
*/
void __warn_flushing_systemwide_wq(void) { }
void __warn_flushing_systemwide_wq(void)
{
pr_warn("WARNING: Flushing system-wide workqueues will be prohibited in near future.\n");
dump_stack();
}
EXPORT_SYMBOL(__warn_flushing_systemwide_wq);

0 comments on commit 20bdeda

Please sign in to comment.