Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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()

+30 -15
+30 -15
kernel/workqueue.c
··· 2652 2652 if (WARN_ON(!wq_online)) 2653 2653 return; 2654 2654 2655 + lock_map_acquire(&wq->lockdep_map); 2656 + lock_map_release(&wq->lockdep_map); 2657 + 2655 2658 mutex_lock(&wq->mutex); 2656 2659 2657 2660 /* ··· 2846 2843 } 2847 2844 EXPORT_SYMBOL_GPL(drain_workqueue); 2848 2845 2849 - static bool start_flush_work(struct work_struct *work, struct wq_barrier *barr) 2846 + static bool start_flush_work(struct work_struct *work, struct wq_barrier *barr, 2847 + bool from_cancel) 2850 2848 { 2851 2849 struct worker *worker = NULL; 2852 2850 struct worker_pool *pool; ··· 2889 2885 * workqueues the deadlock happens when the rescuer stalls, blocking 2890 2886 * forward progress. 2891 2887 */ 2892 - if (pwq->wq->saved_max_active == 1 || pwq->wq->rescuer) { 2888 + if (!from_cancel && 2889 + (pwq->wq->saved_max_active == 1 || pwq->wq->rescuer)) { 2893 2890 lock_map_acquire(&pwq->wq->lockdep_map); 2894 2891 lock_map_release(&pwq->wq->lockdep_map); 2895 2892 } ··· 2899 2894 already_gone: 2900 2895 spin_unlock_irq(&pool->lock); 2901 2896 return false; 2897 + } 2898 + 2899 + static bool __flush_work(struct work_struct *work, bool from_cancel) 2900 + { 2901 + struct wq_barrier barr; 2902 + 2903 + if (WARN_ON(!wq_online)) 2904 + return false; 2905 + 2906 + if (!from_cancel) { 2907 + lock_map_acquire(&work->lockdep_map); 2908 + lock_map_release(&work->lockdep_map); 2909 + } 2910 + 2911 + if (start_flush_work(work, &barr, from_cancel)) { 2912 + wait_for_completion(&barr.done); 2913 + destroy_work_on_stack(&barr.work); 2914 + return true; 2915 + } else { 2916 + return false; 2917 + } 2902 2918 } 2903 2919 2904 2920 /** ··· 2935 2909 */ 2936 2910 bool flush_work(struct work_struct *work) 2937 2911 { 2938 - struct wq_barrier barr; 2939 - 2940 - if (WARN_ON(!wq_online)) 2941 - return false; 2942 - 2943 - if (start_flush_work(work, &barr)) { 2944 - wait_for_completion(&barr.done); 2945 - destroy_work_on_stack(&barr.work); 2946 - return true; 2947 - } else { 2948 - return false; 2949 - } 2912 + return __flush_work(work, false); 2950 2913 } 2951 2914 EXPORT_SYMBOL_GPL(flush_work); 2952 2915 ··· 3001 2986 * isn't executing. 3002 2987 */ 3003 2988 if (wq_online) 3004 - flush_work(work); 2989 + __flush_work(work, true); 3005 2990 3006 2991 clear_work_data(work); 3007 2992