From: Peter Zijlstra Workqueue functions should not leak locks, assert so, printing the last function ran. Use macros in lockdep.h to avoid include dependency pains. Signed-off-by: Peter Zijlstra Cc: Ingo Molnar Signed-off-by: Andrew Morton --- include/linux/lockdep.h | 5 +++++ kernel/workqueue.c | 12 ++++++++++++ 2 files changed, 17 insertions(+) diff -puN include/linux/lockdep.h~debug-workqueue-locking-sanity include/linux/lockdep.h --- a/include/linux/lockdep.h~debug-workqueue-locking-sanity +++ a/include/linux/lockdep.h @@ -243,6 +243,8 @@ extern void lock_release(struct lockdep_ # define INIT_LOCKDEP .lockdep_recursion = 0, +#define lockdep_depth(tsk) ((tsk)->lockdep_depth) + #else /* !LOCKDEP */ static inline void lockdep_off(void) @@ -277,6 +279,9 @@ static inline int lockdep_internal(void) * The class key takes no space if lockdep is disabled: */ struct lock_class_key { }; + +#define lockdep_depth(tsk) (0) + #endif /* !LOCKDEP */ #if defined(CONFIG_TRACE_IRQFLAGS) && defined(CONFIG_GENERIC_HARDIRQS) diff -puN kernel/workqueue.c~debug-workqueue-locking-sanity kernel/workqueue.c --- a/kernel/workqueue.c~debug-workqueue-locking-sanity +++ a/kernel/workqueue.c @@ -29,6 +29,7 @@ #include #include #include +#include /* * The per-CPU workqueue (if single thread, we always use the first @@ -222,6 +223,17 @@ static void run_workqueue(struct cpu_wor clear_bit(0, &work->pending); f(data); + if (unlikely(in_atomic() || lockdep_depth(current) > 0)) { + printk(KERN_ERR "BUG: workqueue leaked lock or atomic: " + "%s/0x%08x/%d\n", + current->comm, preempt_count(), + current->pid); + printk(KERN_ERR " last function: "); + print_symbol("%s\n", (unsigned long)f); + debug_show_held_locks(current); + dump_stack(); + } + spin_lock_irqsave(&cwq->lock, flags); cwq->remove_sequence++; wake_up(&cwq->work_done); _