diff options
Diffstat (limited to 'kernel/lockdep.c')
-rw-r--r-- | kernel/lockdep.c | 46 |
1 files changed, 24 insertions, 22 deletions
diff --git a/kernel/lockdep.c b/kernel/lockdep.c index 259db207b5d9..6a3bccba7e7d 100644 --- a/kernel/lockdep.c +++ b/kernel/lockdep.c | |||
@@ -380,6 +380,13 @@ static int verbose(struct lock_class *class) | |||
380 | unsigned long nr_stack_trace_entries; | 380 | unsigned long nr_stack_trace_entries; |
381 | static unsigned long stack_trace[MAX_STACK_TRACE_ENTRIES]; | 381 | static unsigned long stack_trace[MAX_STACK_TRACE_ENTRIES]; |
382 | 382 | ||
383 | static void print_lockdep_off(const char *bug_msg) | ||
384 | { | ||
385 | printk(KERN_DEBUG "%s\n", bug_msg); | ||
386 | printk(KERN_DEBUG "turning off the locking correctness validator.\n"); | ||
387 | printk(KERN_DEBUG "Please attach the output of /proc/lock_stat to the bug report\n"); | ||
388 | } | ||
389 | |||
383 | static int save_trace(struct stack_trace *trace) | 390 | static int save_trace(struct stack_trace *trace) |
384 | { | 391 | { |
385 | trace->nr_entries = 0; | 392 | trace->nr_entries = 0; |
@@ -409,8 +416,7 @@ static int save_trace(struct stack_trace *trace) | |||
409 | if (!debug_locks_off_graph_unlock()) | 416 | if (!debug_locks_off_graph_unlock()) |
410 | return 0; | 417 | return 0; |
411 | 418 | ||
412 | printk("BUG: MAX_STACK_TRACE_ENTRIES too low!\n"); | 419 | print_lockdep_off("BUG: MAX_STACK_TRACE_ENTRIES too low!"); |
413 | printk("turning off the locking correctness validator.\n"); | ||
414 | dump_stack(); | 420 | dump_stack(); |
415 | 421 | ||
416 | return 0; | 422 | return 0; |
@@ -763,8 +769,7 @@ register_lock_class(struct lockdep_map *lock, unsigned int subclass, int force) | |||
763 | } | 769 | } |
764 | raw_local_irq_restore(flags); | 770 | raw_local_irq_restore(flags); |
765 | 771 | ||
766 | printk("BUG: MAX_LOCKDEP_KEYS too low!\n"); | 772 | print_lockdep_off("BUG: MAX_LOCKDEP_KEYS too low!"); |
767 | printk("turning off the locking correctness validator.\n"); | ||
768 | dump_stack(); | 773 | dump_stack(); |
769 | return NULL; | 774 | return NULL; |
770 | } | 775 | } |
@@ -834,8 +839,7 @@ static struct lock_list *alloc_list_entry(void) | |||
834 | if (!debug_locks_off_graph_unlock()) | 839 | if (!debug_locks_off_graph_unlock()) |
835 | return NULL; | 840 | return NULL; |
836 | 841 | ||
837 | printk("BUG: MAX_LOCKDEP_ENTRIES too low!\n"); | 842 | print_lockdep_off("BUG: MAX_LOCKDEP_ENTRIES too low!"); |
838 | printk("turning off the locking correctness validator.\n"); | ||
839 | dump_stack(); | 843 | dump_stack(); |
840 | return NULL; | 844 | return NULL; |
841 | } | 845 | } |
@@ -2000,7 +2004,7 @@ static inline int lookup_chain_cache(struct task_struct *curr, | |||
2000 | struct lock_class *class = hlock_class(hlock); | 2004 | struct lock_class *class = hlock_class(hlock); |
2001 | struct list_head *hash_head = chainhashentry(chain_key); | 2005 | struct list_head *hash_head = chainhashentry(chain_key); |
2002 | struct lock_chain *chain; | 2006 | struct lock_chain *chain; |
2003 | struct held_lock *hlock_curr, *hlock_next; | 2007 | struct held_lock *hlock_curr; |
2004 | int i, j; | 2008 | int i, j; |
2005 | 2009 | ||
2006 | /* | 2010 | /* |
@@ -2048,8 +2052,7 @@ cache_hit: | |||
2048 | if (!debug_locks_off_graph_unlock()) | 2052 | if (!debug_locks_off_graph_unlock()) |
2049 | return 0; | 2053 | return 0; |
2050 | 2054 | ||
2051 | printk("BUG: MAX_LOCKDEP_CHAINS too low!\n"); | 2055 | print_lockdep_off("BUG: MAX_LOCKDEP_CHAINS too low!"); |
2052 | printk("turning off the locking correctness validator.\n"); | ||
2053 | dump_stack(); | 2056 | dump_stack(); |
2054 | return 0; | 2057 | return 0; |
2055 | } | 2058 | } |
@@ -2057,12 +2060,10 @@ cache_hit: | |||
2057 | chain->chain_key = chain_key; | 2060 | chain->chain_key = chain_key; |
2058 | chain->irq_context = hlock->irq_context; | 2061 | chain->irq_context = hlock->irq_context; |
2059 | /* Find the first held_lock of current chain */ | 2062 | /* Find the first held_lock of current chain */ |
2060 | hlock_next = hlock; | ||
2061 | for (i = curr->lockdep_depth - 1; i >= 0; i--) { | 2063 | for (i = curr->lockdep_depth - 1; i >= 0; i--) { |
2062 | hlock_curr = curr->held_locks + i; | 2064 | hlock_curr = curr->held_locks + i; |
2063 | if (hlock_curr->irq_context != hlock_next->irq_context) | 2065 | if (hlock_curr->irq_context != hlock->irq_context) |
2064 | break; | 2066 | break; |
2065 | hlock_next = hlock; | ||
2066 | } | 2067 | } |
2067 | i++; | 2068 | i++; |
2068 | chain->depth = curr->lockdep_depth + 1 - i; | 2069 | chain->depth = curr->lockdep_depth + 1 - i; |
@@ -3190,9 +3191,9 @@ static int __lock_acquire(struct lockdep_map *lock, unsigned int subclass, | |||
3190 | #endif | 3191 | #endif |
3191 | if (unlikely(curr->lockdep_depth >= MAX_LOCK_DEPTH)) { | 3192 | if (unlikely(curr->lockdep_depth >= MAX_LOCK_DEPTH)) { |
3192 | debug_locks_off(); | 3193 | debug_locks_off(); |
3193 | printk("BUG: MAX_LOCK_DEPTH too low, depth: %i max: %lu!\n", | 3194 | print_lockdep_off("BUG: MAX_LOCK_DEPTH too low!"); |
3195 | printk(KERN_DEBUG "depth: %i max: %lu!\n", | ||
3194 | curr->lockdep_depth, MAX_LOCK_DEPTH); | 3196 | curr->lockdep_depth, MAX_LOCK_DEPTH); |
3195 | printk("turning off the locking correctness validator.\n"); | ||
3196 | 3197 | ||
3197 | lockdep_print_held_locks(current); | 3198 | lockdep_print_held_locks(current); |
3198 | debug_show_all_locks(); | 3199 | debug_show_all_locks(); |
@@ -4088,7 +4089,7 @@ void debug_check_no_locks_freed(const void *mem_from, unsigned long mem_len) | |||
4088 | } | 4089 | } |
4089 | EXPORT_SYMBOL_GPL(debug_check_no_locks_freed); | 4090 | EXPORT_SYMBOL_GPL(debug_check_no_locks_freed); |
4090 | 4091 | ||
4091 | static void print_held_locks_bug(void) | 4092 | static void print_held_locks_bug(struct task_struct *curr) |
4092 | { | 4093 | { |
4093 | if (!debug_locks_off()) | 4094 | if (!debug_locks_off()) |
4094 | return; | 4095 | return; |
@@ -4097,21 +4098,22 @@ static void print_held_locks_bug(void) | |||
4097 | 4098 | ||
4098 | printk("\n"); | 4099 | printk("\n"); |
4099 | printk("=====================================\n"); | 4100 | printk("=====================================\n"); |
4100 | printk("[ BUG: %s/%d still has locks held! ]\n", | 4101 | printk("[ BUG: lock held at task exit time! ]\n"); |
4101 | current->comm, task_pid_nr(current)); | ||
4102 | print_kernel_ident(); | 4102 | print_kernel_ident(); |
4103 | printk("-------------------------------------\n"); | 4103 | printk("-------------------------------------\n"); |
4104 | lockdep_print_held_locks(current); | 4104 | printk("%s/%d is exiting with locks still held!\n", |
4105 | curr->comm, task_pid_nr(curr)); | ||
4106 | lockdep_print_held_locks(curr); | ||
4107 | |||
4105 | printk("\nstack backtrace:\n"); | 4108 | printk("\nstack backtrace:\n"); |
4106 | dump_stack(); | 4109 | dump_stack(); |
4107 | } | 4110 | } |
4108 | 4111 | ||
4109 | void debug_check_no_locks_held(void) | 4112 | void debug_check_no_locks_held(struct task_struct *task) |
4110 | { | 4113 | { |
4111 | if (unlikely(current->lockdep_depth > 0)) | 4114 | if (unlikely(task->lockdep_depth > 0)) |
4112 | print_held_locks_bug(); | 4115 | print_held_locks_bug(task); |
4113 | } | 4116 | } |
4114 | EXPORT_SYMBOL_GPL(debug_check_no_locks_held); | ||
4115 | 4117 | ||
4116 | void debug_show_all_locks(void) | 4118 | void debug_show_all_locks(void) |
4117 | { | 4119 | { |