summaryrefslogtreecommitdiffstats
path: root/kernel/workqueue.c
diff options
context:
space:
mode:
authorBart Van Assche <bvanassche@acm.org>2019-02-14 18:00:54 -0500
committerIngo Molnar <mingo@kernel.org>2019-02-28 01:55:47 -0500
commit669de8bda87b92ab9a2fc663b3f5743c2ad1ae9f (patch)
treeae91c3f4142c13b98dd7547f0b9f6c1c4ec43142 /kernel/workqueue.c
parent108c14858b9ea224686e476c8f5ec345a0df9e27 (diff)
kernel/workqueue: Use dynamic lockdep keys for workqueues
The following commit: 87915adc3f0a ("workqueue: re-add lockdep dependencies for flushing") improved deadlock checking in the workqueue implementation. Unfortunately that patch also introduced a few false positive lockdep complaints. This patch suppresses these false positives by allocating the workqueue mutex lockdep key dynamically. An example of a false positive lockdep complaint suppressed by this patch can be found below. The root cause of the lockdep complaint shown below is that the direct I/O code can call alloc_workqueue() from inside a work item created by another alloc_workqueue() call and that both workqueues share the same lockdep key. This patch avoids that that lockdep complaint is triggered by allocating the work queue lockdep keys dynamically. In other words, this patch guarantees that a unique lockdep key is associated with each work queue mutex. ====================================================== WARNING: possible circular locking dependency detected 4.19.0-dbg+ #1 Not tainted fio/4129 is trying to acquire lock: 00000000a01cfe1a ((wq_completion)"dio/%s"sb->s_id){+.+.}, at: flush_workqueue+0xd0/0x970 but task is already holding lock: 00000000a0acecf9 (&sb->s_type->i_mutex_key#14){+.+.}, at: ext4_file_write_iter+0x154/0x710 which lock already depends on the new lock. the existing dependency chain (in reverse order) is: -> #2 (&sb->s_type->i_mutex_key#14){+.+.}: down_write+0x3d/0x80 __generic_file_fsync+0x77/0xf0 ext4_sync_file+0x3c9/0x780 vfs_fsync_range+0x66/0x100 dio_complete+0x2f5/0x360 dio_aio_complete_work+0x1c/0x20 process_one_work+0x481/0x9f0 worker_thread+0x63/0x5a0 kthread+0x1cf/0x1f0 ret_from_fork+0x24/0x30 -> #1 ((work_completion)(&dio->complete_work)){+.+.}: process_one_work+0x447/0x9f0 worker_thread+0x63/0x5a0 kthread+0x1cf/0x1f0 ret_from_fork+0x24/0x30 -> #0 ((wq_completion)"dio/%s"sb->s_id){+.+.}: lock_acquire+0xc5/0x200 flush_workqueue+0xf3/0x970 drain_workqueue+0xec/0x220 destroy_workqueue+0x23/0x350 sb_init_dio_done_wq+0x6a/0x80 do_blockdev_direct_IO+0x1f33/0x4be0 __blockdev_direct_IO+0x79/0x86 ext4_direct_IO+0x5df/0xbb0 generic_file_direct_write+0x119/0x220 __generic_file_write_iter+0x131/0x2d0 ext4_file_write_iter+0x3fa/0x710 aio_write+0x235/0x330 io_submit_one+0x510/0xeb0 __x64_sys_io_submit+0x122/0x340 do_syscall_64+0x71/0x220 entry_SYSCALL_64_after_hwframe+0x49/0xbe other info that might help us debug this: Chain exists of: (wq_completion)"dio/%s"sb->s_id --> (work_completion)(&dio->complete_work) --> &sb->s_type->i_mutex_key#14 Possible unsafe locking scenario: CPU0 CPU1 ---- ---- lock(&sb->s_type->i_mutex_key#14); lock((work_completion)(&dio->complete_work)); lock(&sb->s_type->i_mutex_key#14); lock((wq_completion)"dio/%s"sb->s_id); *** DEADLOCK *** 1 lock held by fio/4129: #0: 00000000a0acecf9 (&sb->s_type->i_mutex_key#14){+.+.}, at: ext4_file_write_iter+0x154/0x710 stack backtrace: CPU: 3 PID: 4129 Comm: fio Not tainted 4.19.0-dbg+ #1 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.10.2-1 04/01/2014 Call Trace: dump_stack+0x86/0xc5 print_circular_bug.isra.32+0x20a/0x218 __lock_acquire+0x1c68/0x1cf0 lock_acquire+0xc5/0x200 flush_workqueue+0xf3/0x970 drain_workqueue+0xec/0x220 destroy_workqueue+0x23/0x350 sb_init_dio_done_wq+0x6a/0x80 do_blockdev_direct_IO+0x1f33/0x4be0 __blockdev_direct_IO+0x79/0x86 ext4_direct_IO+0x5df/0xbb0 generic_file_direct_write+0x119/0x220 __generic_file_write_iter+0x131/0x2d0 ext4_file_write_iter+0x3fa/0x710 aio_write+0x235/0x330 io_submit_one+0x510/0xeb0 __x64_sys_io_submit+0x122/0x340 do_syscall_64+0x71/0x220 entry_SYSCALL_64_after_hwframe+0x49/0xbe Signed-off-by: Bart Van Assche <bvanassche@acm.org> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Johannes Berg <johannes.berg@intel.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Tejun Heo <tj@kernel.org> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Waiman Long <longman@redhat.com> Cc: Will Deacon <will.deacon@arm.com> Link: https://lkml.kernel.org/r/20190214230058.196511-20-bvanassche@acm.org [ Reworked the changelog a bit. ] Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'kernel/workqueue.c')
-rw-r--r--kernel/workqueue.c59
1 files changed, 50 insertions, 9 deletions
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index fc5d23d752a5..e163e7a7f5e5 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -259,6 +259,8 @@ struct workqueue_struct {
259 struct wq_device *wq_dev; /* I: for sysfs interface */ 259 struct wq_device *wq_dev; /* I: for sysfs interface */
260#endif 260#endif
261#ifdef CONFIG_LOCKDEP 261#ifdef CONFIG_LOCKDEP
262 char *lock_name;
263 struct lock_class_key key;
262 struct lockdep_map lockdep_map; 264 struct lockdep_map lockdep_map;
263#endif 265#endif
264 char name[WQ_NAME_LEN]; /* I: workqueue name */ 266 char name[WQ_NAME_LEN]; /* I: workqueue name */
@@ -3337,11 +3339,49 @@ static int init_worker_pool(struct worker_pool *pool)
3337 return 0; 3339 return 0;
3338} 3340}
3339 3341
3342#ifdef CONFIG_LOCKDEP
3343static void wq_init_lockdep(struct workqueue_struct *wq)
3344{
3345 char *lock_name;
3346
3347 lockdep_register_key(&wq->key);
3348 lock_name = kasprintf(GFP_KERNEL, "%s%s", "(wq_completion)", wq->name);
3349 if (!lock_name)
3350 lock_name = wq->name;
3351 lockdep_init_map(&wq->lockdep_map, lock_name, &wq->key, 0);
3352}
3353
3354static void wq_unregister_lockdep(struct workqueue_struct *wq)
3355{
3356 lockdep_unregister_key(&wq->key);
3357}
3358
3359static void wq_free_lockdep(struct workqueue_struct *wq)
3360{
3361 if (wq->lock_name != wq->name)
3362 kfree(wq->lock_name);
3363}
3364#else
3365static void wq_init_lockdep(struct workqueue_struct *wq)
3366{
3367}
3368
3369static void wq_unregister_lockdep(struct workqueue_struct *wq)
3370{
3371}
3372
3373static void wq_free_lockdep(struct workqueue_struct *wq)
3374{
3375}
3376#endif
3377
3340static void rcu_free_wq(struct rcu_head *rcu) 3378static void rcu_free_wq(struct rcu_head *rcu)
3341{ 3379{
3342 struct workqueue_struct *wq = 3380 struct workqueue_struct *wq =
3343 container_of(rcu, struct workqueue_struct, rcu); 3381 container_of(rcu, struct workqueue_struct, rcu);
3344 3382
3383 wq_free_lockdep(wq);
3384
3345 if (!(wq->flags & WQ_UNBOUND)) 3385 if (!(wq->flags & WQ_UNBOUND))
3346 free_percpu(wq->cpu_pwqs); 3386 free_percpu(wq->cpu_pwqs);
3347 else 3387 else
@@ -3532,8 +3572,10 @@ static void pwq_unbound_release_workfn(struct work_struct *work)
3532 * If we're the last pwq going away, @wq is already dead and no one 3572 * If we're the last pwq going away, @wq is already dead and no one
3533 * is gonna access it anymore. Schedule RCU free. 3573 * is gonna access it anymore. Schedule RCU free.
3534 */ 3574 */
3535 if (is_last) 3575 if (is_last) {
3576 wq_unregister_lockdep(wq);
3536 call_rcu(&wq->rcu, rcu_free_wq); 3577 call_rcu(&wq->rcu, rcu_free_wq);
3578 }
3537} 3579}
3538 3580
3539/** 3581/**
@@ -4067,11 +4109,9 @@ static int init_rescuer(struct workqueue_struct *wq)
4067 return 0; 4109 return 0;
4068} 4110}
4069 4111
4070struct workqueue_struct *__alloc_workqueue_key(const char *fmt, 4112struct workqueue_struct *alloc_workqueue(const char *fmt,
4071 unsigned int flags, 4113 unsigned int flags,
4072 int max_active, 4114 int max_active, ...)
4073 struct lock_class_key *key,
4074 const char *lock_name, ...)
4075{ 4115{
4076 size_t tbl_size = 0; 4116 size_t tbl_size = 0;
4077 va_list args; 4117 va_list args;
@@ -4106,7 +4146,7 @@ struct workqueue_struct *__alloc_workqueue_key(const char *fmt,
4106 goto err_free_wq; 4146 goto err_free_wq;
4107 } 4147 }
4108 4148
4109 va_start(args, lock_name); 4149 va_start(args, max_active);
4110 vsnprintf(wq->name, sizeof(wq->name), fmt, args); 4150 vsnprintf(wq->name, sizeof(wq->name), fmt, args);
4111 va_end(args); 4151 va_end(args);
4112 4152
@@ -4123,7 +4163,7 @@ struct workqueue_struct *__alloc_workqueue_key(const char *fmt,
4123 INIT_LIST_HEAD(&wq->flusher_overflow); 4163 INIT_LIST_HEAD(&wq->flusher_overflow);
4124 INIT_LIST_HEAD(&wq->maydays); 4164 INIT_LIST_HEAD(&wq->maydays);
4125 4165
4126 lockdep_init_map(&wq->lockdep_map, lock_name, key, 0); 4166 wq_init_lockdep(wq);
4127 INIT_LIST_HEAD(&wq->list); 4167 INIT_LIST_HEAD(&wq->list);
4128 4168
4129 if (alloc_and_link_pwqs(wq) < 0) 4169 if (alloc_and_link_pwqs(wq) < 0)
@@ -4161,7 +4201,7 @@ err_destroy:
4161 destroy_workqueue(wq); 4201 destroy_workqueue(wq);
4162 return NULL; 4202 return NULL;
4163} 4203}
4164EXPORT_SYMBOL_GPL(__alloc_workqueue_key); 4204EXPORT_SYMBOL_GPL(alloc_workqueue);
4165 4205
4166/** 4206/**
4167 * destroy_workqueue - safely terminate a workqueue 4207 * destroy_workqueue - safely terminate a workqueue
@@ -4214,6 +4254,7 @@ void destroy_workqueue(struct workqueue_struct *wq)
4214 kthread_stop(wq->rescuer->task); 4254 kthread_stop(wq->rescuer->task);
4215 4255
4216 if (!(wq->flags & WQ_UNBOUND)) { 4256 if (!(wq->flags & WQ_UNBOUND)) {
4257 wq_unregister_lockdep(wq);
4217 /* 4258 /*
4218 * The base ref is never dropped on per-cpu pwqs. Directly 4259 * The base ref is never dropped on per-cpu pwqs. Directly
4219 * schedule RCU free. 4260 * schedule RCU free.