diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-08-24 16:16:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-08-24 16:16:36 -0400 |
commit | 9022ada8ab6f1f1a932a3c93815061042e6548a5 (patch) | |
tree | 1d87519ea97b2939ec61d8d0f94c22b59d8c9c7b | |
parent | 18b8bfdfbae5821a7df691bc1e542bbab6c31e9c (diff) | |
parent | 87915adc3f0acdf03c776df42e308e5a155c19af (diff) |
Merge branch 'for-4.19' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/wq
Pull workqueue updates from Tejun Heo:
"Over the lockdep cross-release churn, workqueue lost some of the
existing annotations. Johannes Berg restored it and also improved
them"
* 'for-4.19' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/wq:
workqueue: re-add lockdep dependencies for flushing
workqueue: skip lockdep wq dependency in cancel_work_sync()
-rw-r--r-- | kernel/workqueue.c | 45 |
1 files changed, 30 insertions, 15 deletions
diff --git a/kernel/workqueue.c b/kernel/workqueue.c index 78b192071ef7..60e80198c3df 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c | |||
@@ -2652,6 +2652,9 @@ void flush_workqueue(struct workqueue_struct *wq) | |||
2652 | if (WARN_ON(!wq_online)) | 2652 | if (WARN_ON(!wq_online)) |
2653 | return; | 2653 | return; |
2654 | 2654 | ||
2655 | lock_map_acquire(&wq->lockdep_map); | ||
2656 | lock_map_release(&wq->lockdep_map); | ||
2657 | |||
2655 | mutex_lock(&wq->mutex); | 2658 | mutex_lock(&wq->mutex); |
2656 | 2659 | ||
2657 | /* | 2660 | /* |
@@ -2843,7 +2846,8 @@ reflush: | |||
2843 | } | 2846 | } |
2844 | EXPORT_SYMBOL_GPL(drain_workqueue); | 2847 | EXPORT_SYMBOL_GPL(drain_workqueue); |
2845 | 2848 | ||
2846 | static bool start_flush_work(struct work_struct *work, struct wq_barrier *barr) | 2849 | static bool start_flush_work(struct work_struct *work, struct wq_barrier *barr, |
2850 | bool from_cancel) | ||
2847 | { | 2851 | { |
2848 | struct worker *worker = NULL; | 2852 | struct worker *worker = NULL; |
2849 | struct worker_pool *pool; | 2853 | struct worker_pool *pool; |
@@ -2885,7 +2889,8 @@ static bool start_flush_work(struct work_struct *work, struct wq_barrier *barr) | |||
2885 | * workqueues the deadlock happens when the rescuer stalls, blocking | 2889 | * workqueues the deadlock happens when the rescuer stalls, blocking |
2886 | * forward progress. | 2890 | * forward progress. |
2887 | */ | 2891 | */ |
2888 | if (pwq->wq->saved_max_active == 1 || pwq->wq->rescuer) { | 2892 | if (!from_cancel && |
2893 | (pwq->wq->saved_max_active == 1 || pwq->wq->rescuer)) { | ||
2889 | lock_map_acquire(&pwq->wq->lockdep_map); | 2894 | lock_map_acquire(&pwq->wq->lockdep_map); |
2890 | lock_map_release(&pwq->wq->lockdep_map); | 2895 | lock_map_release(&pwq->wq->lockdep_map); |
2891 | } | 2896 | } |
@@ -2896,6 +2901,27 @@ already_gone: | |||
2896 | return false; | 2901 | return false; |
2897 | } | 2902 | } |
2898 | 2903 | ||
2904 | static bool __flush_work(struct work_struct *work, bool from_cancel) | ||
2905 | { | ||
2906 | struct wq_barrier barr; | ||
2907 | |||
2908 | if (WARN_ON(!wq_online)) | ||
2909 | return false; | ||
2910 | |||
2911 | if (!from_cancel) { | ||
2912 | lock_map_acquire(&work->lockdep_map); | ||
2913 | lock_map_release(&work->lockdep_map); | ||
2914 | } | ||
2915 | |||
2916 | if (start_flush_work(work, &barr, from_cancel)) { | ||
2917 | wait_for_completion(&barr.done); | ||
2918 | destroy_work_on_stack(&barr.work); | ||
2919 | return true; | ||
2920 | } else { | ||
2921 | return false; | ||
2922 | } | ||
2923 | } | ||
2924 | |||
2899 | /** | 2925 | /** |
2900 | * flush_work - wait for a work to finish executing the last queueing instance | 2926 | * flush_work - wait for a work to finish executing the last queueing instance |
2901 | * @work: the work to flush | 2927 | * @work: the work to flush |
@@ -2909,18 +2935,7 @@ already_gone: | |||
2909 | */ | 2935 | */ |
2910 | bool flush_work(struct work_struct *work) | 2936 | bool flush_work(struct work_struct *work) |
2911 | { | 2937 | { |
2912 | struct wq_barrier barr; | 2938 | return __flush_work(work, false); |
2913 | |||
2914 | if (WARN_ON(!wq_online)) | ||
2915 | return false; | ||
2916 | |||
2917 | if (start_flush_work(work, &barr)) { | ||
2918 | wait_for_completion(&barr.done); | ||
2919 | destroy_work_on_stack(&barr.work); | ||
2920 | return true; | ||
2921 | } else { | ||
2922 | return false; | ||
2923 | } | ||
2924 | } | 2939 | } |
2925 | EXPORT_SYMBOL_GPL(flush_work); | 2940 | EXPORT_SYMBOL_GPL(flush_work); |
2926 | 2941 | ||
@@ -2986,7 +3001,7 @@ static bool __cancel_work_timer(struct work_struct *work, bool is_dwork) | |||
2986 | * isn't executing. | 3001 | * isn't executing. |
2987 | */ | 3002 | */ |
2988 | if (wq_online) | 3003 | if (wq_online) |
2989 | flush_work(work); | 3004 | __flush_work(work, true); |
2990 | 3005 | ||
2991 | clear_work_data(work); | 3006 | clear_work_data(work); |
2992 | 3007 | ||