workqueue: Warn attempt to flush system-wide workqueues.

Based on commit c4f135d643 ("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>
This commit is contained in:
Tetsuo Handa 2023-06-30 21:28:53 +09:00 committed by Tejun Heo
parent 3f01e9fed8
commit 20bdedafd2
2 changed files with 8 additions and 47 deletions

View File

@ -569,6 +569,7 @@ 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.
@ -576,52 +577,13 @@ static inline bool schedule_work(struct work_struct *work)
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); \

View File

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