Commit 20bdedaf authored by Tetsuo Handa's avatar Tetsuo Handa Committed by Tejun Heo
Browse files

workqueue: Warn attempt to flush system-wide workqueues.



Based on commit c4f135d6 ("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: default avatarTetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Signed-off-by: default avatarTejun Heo <tj@kernel.org>
parent 3f01e9fe
Loading
Loading
Loading
Loading
+3 −41
Original line number Diff line number Diff line
@@ -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();				\
	__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);				\
+5 −6
Original line number Diff line number Diff line
@@ -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);