diff options
Diffstat (limited to 'kernel/lockdep.c')
-rw-r--r-- | kernel/lockdep.c | 48 |
1 files changed, 28 insertions, 20 deletions
diff --git a/kernel/lockdep.c b/kernel/lockdep.c index 9bb8d784eb02..b02032476dc2 100644 --- a/kernel/lockdep.c +++ b/kernel/lockdep.c | |||
@@ -140,13 +140,6 @@ void lockdep_on(void) | |||
140 | 140 | ||
141 | EXPORT_SYMBOL(lockdep_on); | 141 | EXPORT_SYMBOL(lockdep_on); |
142 | 142 | ||
143 | int lockdep_internal(void) | ||
144 | { | ||
145 | return current->lockdep_recursion != 0; | ||
146 | } | ||
147 | |||
148 | EXPORT_SYMBOL(lockdep_internal); | ||
149 | |||
150 | /* | 143 | /* |
151 | * Debugging switches: | 144 | * Debugging switches: |
152 | */ | 145 | */ |
@@ -233,8 +226,10 @@ static int save_trace(struct stack_trace *trace) | |||
233 | trace->max_entries = trace->nr_entries; | 226 | trace->max_entries = trace->nr_entries; |
234 | 227 | ||
235 | nr_stack_trace_entries += trace->nr_entries; | 228 | nr_stack_trace_entries += trace->nr_entries; |
236 | if (DEBUG_LOCKS_WARN_ON(nr_stack_trace_entries > MAX_STACK_TRACE_ENTRIES)) | 229 | if (DEBUG_LOCKS_WARN_ON(nr_stack_trace_entries > MAX_STACK_TRACE_ENTRIES)) { |
230 | __raw_spin_unlock(&hash_lock); | ||
237 | return 0; | 231 | return 0; |
232 | } | ||
238 | 233 | ||
239 | if (nr_stack_trace_entries == MAX_STACK_TRACE_ENTRIES) { | 234 | if (nr_stack_trace_entries == MAX_STACK_TRACE_ENTRIES) { |
240 | __raw_spin_unlock(&hash_lock); | 235 | __raw_spin_unlock(&hash_lock); |
@@ -353,7 +348,7 @@ get_usage_chars(struct lock_class *class, char *c1, char *c2, char *c3, char *c4 | |||
353 | 348 | ||
354 | static void print_lock_name(struct lock_class *class) | 349 | static void print_lock_name(struct lock_class *class) |
355 | { | 350 | { |
356 | char str[128], c1, c2, c3, c4; | 351 | char str[KSYM_NAME_LEN + 1], c1, c2, c3, c4; |
357 | const char *name; | 352 | const char *name; |
358 | 353 | ||
359 | get_usage_chars(class, &c1, &c2, &c3, &c4); | 354 | get_usage_chars(class, &c1, &c2, &c3, &c4); |
@@ -375,7 +370,7 @@ static void print_lock_name(struct lock_class *class) | |||
375 | static void print_lockdep_cache(struct lockdep_map *lock) | 370 | static void print_lockdep_cache(struct lockdep_map *lock) |
376 | { | 371 | { |
377 | const char *name; | 372 | const char *name; |
378 | char str[128]; | 373 | char str[KSYM_NAME_LEN + 1]; |
379 | 374 | ||
380 | name = lock->name; | 375 | name = lock->name; |
381 | if (!name) | 376 | if (!name) |
@@ -445,7 +440,9 @@ static void print_lock_dependencies(struct lock_class *class, int depth) | |||
445 | print_lock_class_header(class, depth); | 440 | print_lock_class_header(class, depth); |
446 | 441 | ||
447 | list_for_each_entry(entry, &class->locks_after, entry) { | 442 | list_for_each_entry(entry, &class->locks_after, entry) { |
448 | DEBUG_LOCKS_WARN_ON(!entry->class); | 443 | if (DEBUG_LOCKS_WARN_ON(!entry->class)) |
444 | return; | ||
445 | |||
449 | print_lock_dependencies(entry->class, depth + 1); | 446 | print_lock_dependencies(entry->class, depth + 1); |
450 | 447 | ||
451 | printk("%*s ... acquired at:\n",depth,""); | 448 | printk("%*s ... acquired at:\n",depth,""); |
@@ -470,7 +467,8 @@ static int add_lock_to_list(struct lock_class *class, struct lock_class *this, | |||
470 | return 0; | 467 | return 0; |
471 | 468 | ||
472 | entry->class = this; | 469 | entry->class = this; |
473 | save_trace(&entry->trace); | 470 | if (!save_trace(&entry->trace)) |
471 | return 0; | ||
474 | 472 | ||
475 | /* | 473 | /* |
476 | * Since we never remove from the dependency list, the list can | 474 | * Since we never remove from the dependency list, the list can |
@@ -558,8 +556,12 @@ static noinline int print_circular_bug_tail(void) | |||
558 | if (debug_locks_silent) | 556 | if (debug_locks_silent) |
559 | return 0; | 557 | return 0; |
560 | 558 | ||
559 | /* hash_lock unlocked by the header */ | ||
560 | __raw_spin_lock(&hash_lock); | ||
561 | this.class = check_source->class; | 561 | this.class = check_source->class; |
562 | save_trace(&this.trace); | 562 | if (!save_trace(&this.trace)) |
563 | return 0; | ||
564 | __raw_spin_unlock(&hash_lock); | ||
563 | print_circular_bug_entry(&this, 0); | 565 | print_circular_bug_entry(&this, 0); |
564 | 566 | ||
565 | printk("\nother info that might help us debug this:\n\n"); | 567 | printk("\nother info that might help us debug this:\n\n"); |
@@ -962,14 +964,11 @@ check_prev_add(struct task_struct *curr, struct held_lock *prev, | |||
962 | &prev->class->locks_after, next->acquire_ip); | 964 | &prev->class->locks_after, next->acquire_ip); |
963 | if (!ret) | 965 | if (!ret) |
964 | return 0; | 966 | return 0; |
965 | /* | 967 | |
966 | * Return value of 2 signals 'dependency already added', | ||
967 | * in that case we dont have to add the backlink either. | ||
968 | */ | ||
969 | if (ret == 2) | ||
970 | return 2; | ||
971 | ret = add_lock_to_list(next->class, prev->class, | 968 | ret = add_lock_to_list(next->class, prev->class, |
972 | &next->class->locks_before, next->acquire_ip); | 969 | &next->class->locks_before, next->acquire_ip); |
970 | if (!ret) | ||
971 | return 0; | ||
973 | 972 | ||
974 | /* | 973 | /* |
975 | * Debugging printouts: | 974 | * Debugging printouts: |
@@ -1021,7 +1020,8 @@ check_prevs_add(struct task_struct *curr, struct held_lock *next) | |||
1021 | * added: | 1020 | * added: |
1022 | */ | 1021 | */ |
1023 | if (hlock->read != 2) { | 1022 | if (hlock->read != 2) { |
1024 | check_prev_add(curr, hlock, next); | 1023 | if (!check_prev_add(curr, hlock, next)) |
1024 | return 0; | ||
1025 | /* | 1025 | /* |
1026 | * Stop after the first non-trylock entry, | 1026 | * Stop after the first non-trylock entry, |
1027 | * as non-trylock entries have added their | 1027 | * as non-trylock entries have added their |
@@ -1178,6 +1178,7 @@ register_lock_class(struct lockdep_map *lock, unsigned int subclass, int force) | |||
1178 | struct lockdep_subclass_key *key; | 1178 | struct lockdep_subclass_key *key; |
1179 | struct list_head *hash_head; | 1179 | struct list_head *hash_head; |
1180 | struct lock_class *class; | 1180 | struct lock_class *class; |
1181 | unsigned long flags; | ||
1181 | 1182 | ||
1182 | class = look_up_lock_class(lock, subclass); | 1183 | class = look_up_lock_class(lock, subclass); |
1183 | if (likely(class)) | 1184 | if (likely(class)) |
@@ -1199,6 +1200,7 @@ register_lock_class(struct lockdep_map *lock, unsigned int subclass, int force) | |||
1199 | key = lock->key->subkeys + subclass; | 1200 | key = lock->key->subkeys + subclass; |
1200 | hash_head = classhashentry(key); | 1201 | hash_head = classhashentry(key); |
1201 | 1202 | ||
1203 | raw_local_irq_save(flags); | ||
1202 | __raw_spin_lock(&hash_lock); | 1204 | __raw_spin_lock(&hash_lock); |
1203 | /* | 1205 | /* |
1204 | * We have to do the hash-walk again, to avoid races | 1206 | * We have to do the hash-walk again, to avoid races |
@@ -1213,6 +1215,7 @@ register_lock_class(struct lockdep_map *lock, unsigned int subclass, int force) | |||
1213 | */ | 1215 | */ |
1214 | if (nr_lock_classes >= MAX_LOCKDEP_KEYS) { | 1216 | if (nr_lock_classes >= MAX_LOCKDEP_KEYS) { |
1215 | __raw_spin_unlock(&hash_lock); | 1217 | __raw_spin_unlock(&hash_lock); |
1218 | raw_local_irq_restore(flags); | ||
1216 | debug_locks_off(); | 1219 | debug_locks_off(); |
1217 | printk("BUG: MAX_LOCKDEP_KEYS too low!\n"); | 1220 | printk("BUG: MAX_LOCKDEP_KEYS too low!\n"); |
1218 | printk("turning off the locking correctness validator.\n"); | 1221 | printk("turning off the locking correctness validator.\n"); |
@@ -1235,15 +1238,18 @@ register_lock_class(struct lockdep_map *lock, unsigned int subclass, int force) | |||
1235 | 1238 | ||
1236 | if (verbose(class)) { | 1239 | if (verbose(class)) { |
1237 | __raw_spin_unlock(&hash_lock); | 1240 | __raw_spin_unlock(&hash_lock); |
1241 | raw_local_irq_restore(flags); | ||
1238 | printk("\nnew class %p: %s", class->key, class->name); | 1242 | printk("\nnew class %p: %s", class->key, class->name); |
1239 | if (class->name_version > 1) | 1243 | if (class->name_version > 1) |
1240 | printk("#%d", class->name_version); | 1244 | printk("#%d", class->name_version); |
1241 | printk("\n"); | 1245 | printk("\n"); |
1242 | dump_stack(); | 1246 | dump_stack(); |
1247 | raw_local_irq_save(flags); | ||
1243 | __raw_spin_lock(&hash_lock); | 1248 | __raw_spin_lock(&hash_lock); |
1244 | } | 1249 | } |
1245 | out_unlock_set: | 1250 | out_unlock_set: |
1246 | __raw_spin_unlock(&hash_lock); | 1251 | __raw_spin_unlock(&hash_lock); |
1252 | raw_local_irq_restore(flags); | ||
1247 | 1253 | ||
1248 | if (!subclass || force) | 1254 | if (!subclass || force) |
1249 | lock->class_cache = class; | 1255 | lock->class_cache = class; |
@@ -1724,6 +1730,7 @@ static int mark_lock(struct task_struct *curr, struct held_lock *this, | |||
1724 | debug_atomic_dec(&nr_unused_locks); | 1730 | debug_atomic_dec(&nr_unused_locks); |
1725 | break; | 1731 | break; |
1726 | default: | 1732 | default: |
1733 | __raw_spin_unlock(&hash_lock); | ||
1727 | debug_locks_off(); | 1734 | debug_locks_off(); |
1728 | WARN_ON(1); | 1735 | WARN_ON(1); |
1729 | return 0; | 1736 | return 0; |
@@ -2641,6 +2648,7 @@ void debug_check_no_locks_freed(const void *mem_from, unsigned long mem_len) | |||
2641 | } | 2648 | } |
2642 | local_irq_restore(flags); | 2649 | local_irq_restore(flags); |
2643 | } | 2650 | } |
2651 | EXPORT_SYMBOL_GPL(debug_check_no_locks_freed); | ||
2644 | 2652 | ||
2645 | static void print_held_locks_bug(struct task_struct *curr) | 2653 | static void print_held_locks_bug(struct task_struct *curr) |
2646 | { | 2654 | { |