History

workqueue: Wrap flush_workqueue() using a macro

Since flush operation synchronously waits for completion, flushing system-wide WQs (e.g. system_wq) might introduce possibility of deadlock due to unexpected locking dependency. Tejun Heo commented at [1] that it makes no sense at all to call flush_workqueue() on the shared WQs as the caller has no idea what it's gonna end up waiting for. Although there is flush_scheduled_work() which flushes system_wq WQ with "Think twice before calling this function! It's very easy to get into trouble if you don't take great care." warning message, syzbot found a circular locking dependency caused by flushing system_wq WQ [2]. Therefore, let's change the direction to that developers had better use their local WQs if flush_scheduled_work()/flush_workqueue(system_*_wq) is inevitable. Steps for converting system-wide WQs into local WQs are explained at [3], and a conversion to stop flushing system-wide WQs is in progress. Now we want some mechanism for preventing developers who are not aware of this conversion from again start flushing system-wide WQs. Since I found that WARN_ON() is complete but awkward approach for teaching developers about this problem, let's use __compiletime_warning() for incomplete but handy approach. For completeness, we will also insert WARN_ON() into __flush_workqueue() after all in-tree users stopped calling flush_scheduled_work().

Tetsuo Handa committed 4 years ago

Commit c4f135d1 parent e71e60c2 files · +68 −12Browse files

Showing the changes to kernel/workqueue.c (1 of 2 files). Show all

Unified · Split

kernel/workqueue.c+12−4
@@ -2788,13 +2788,13 @@ static bool flush_workqueue_prep_pwqs(struct workqueue_struct *wq, · 2787 unmodified lines
27882788 }
27892789
27902790 /**
2791− * flush_workqueue - ensure that any scheduled work has run to completion.
2791+ * __flush_workqueue - ensure that any scheduled work has run to completion.
27922792 * @wq: workqueue to flush
27932793 *
27942794 * This function sleeps until all work items which were queued on entry
27952795 * have finished execution, but it is not livelocked by new incoming ones.
27962796 */
2797−void flush_workqueue(struct workqueue_struct *wq)
2797+void __flush_workqueue(struct workqueue_struct *wq)
27982798 {
27992799 struct wq_flusher this_flusher = {
28002800 .list = LIST_HEAD_INIT(this_flusher.list),
@@ -2943,7 +2943,7 @@ void flush_workqueue(struct workqueue_struct *wq) · 142 unmodified lines
29432943 out_unlock:
29442944 mutex_unlock(&wq->mutex);
29452945 }
2946−EXPORT_SYMBOL(flush_workqueue);
2946+EXPORT_SYMBOL(__flush_workqueue);
29472947
29482948 /**
29492949 * drain_workqueue - drain a workqueue
@@ -2971,7 +2971,7 @@ void drain_workqueue(struct workqueue_struct *wq) · 21 unmodified lines
29712971 wq->flags |= __WQ_DRAINING;
29722972 mutex_unlock(&wq->mutex);
29732973 reflush:
2974− flush_workqueue(wq);
2974+ __flush_workqueue(wq);
29752975
29762976 mutex_lock(&wq->mutex);
29772977
@@ -6111,3 +6111,11 @@ void __init workqueue_init(void) · 3133 unmodified lines
61116111 wq_online = true;
61126112 wq_watchdog_init();
61136113 }
6114+
6115+/*
6116+ * Despite the naming, this is a no-op function which is here only for avoiding
6117+ * link error. Since compile-time warning may fail to catch, we will need to
6118+ * emit run-time warning from __flush_workqueue().
6119+ */
6120+void __warn_flushing_systemwide_wq(void) { }
6121+EXPORT_SYMBOL(__warn_flushing_systemwide_wq);