diff options
Diffstat (limited to 'kernel/lockdep.c')
-rw-r--r-- | kernel/lockdep.c | 42 |
1 files changed, 31 insertions, 11 deletions
diff --git a/kernel/lockdep.c b/kernel/lockdep.c index 509efd49540f..592c576d77a7 100644 --- a/kernel/lockdep.c +++ b/kernel/lockdep.c | |||
@@ -70,6 +70,9 @@ static int graph_lock(void) | |||
70 | 70 | ||
71 | static inline int graph_unlock(void) | 71 | static inline int graph_unlock(void) |
72 | { | 72 | { |
73 | if (debug_locks && !__raw_spin_is_locked(&lockdep_lock)) | ||
74 | return DEBUG_LOCKS_WARN_ON(1); | ||
75 | |||
73 | __raw_spin_unlock(&lockdep_lock); | 76 | __raw_spin_unlock(&lockdep_lock); |
74 | return 0; | 77 | return 0; |
75 | } | 78 | } |
@@ -487,7 +490,7 @@ static void print_lock_dependencies(struct lock_class *class, int depth) | |||
487 | * Add a new dependency to the head of the list: | 490 | * Add a new dependency to the head of the list: |
488 | */ | 491 | */ |
489 | static int add_lock_to_list(struct lock_class *class, struct lock_class *this, | 492 | static int add_lock_to_list(struct lock_class *class, struct lock_class *this, |
490 | struct list_head *head, unsigned long ip) | 493 | struct list_head *head, unsigned long ip, int distance) |
491 | { | 494 | { |
492 | struct lock_list *entry; | 495 | struct lock_list *entry; |
493 | /* | 496 | /* |
@@ -499,6 +502,7 @@ static int add_lock_to_list(struct lock_class *class, struct lock_class *this, | |||
499 | return 0; | 502 | return 0; |
500 | 503 | ||
501 | entry->class = this; | 504 | entry->class = this; |
505 | entry->distance = distance; | ||
502 | if (!save_trace(&entry->trace)) | 506 | if (!save_trace(&entry->trace)) |
503 | return 0; | 507 | return 0; |
504 | 508 | ||
@@ -712,6 +716,9 @@ find_usage_backwards(struct lock_class *source, unsigned int depth) | |||
712 | struct lock_list *entry; | 716 | struct lock_list *entry; |
713 | int ret; | 717 | int ret; |
714 | 718 | ||
719 | if (!__raw_spin_is_locked(&lockdep_lock)) | ||
720 | return DEBUG_LOCKS_WARN_ON(1); | ||
721 | |||
715 | if (depth > max_recursion_depth) | 722 | if (depth > max_recursion_depth) |
716 | max_recursion_depth = depth; | 723 | max_recursion_depth = depth; |
717 | if (depth >= RECURSION_LIMIT) | 724 | if (depth >= RECURSION_LIMIT) |
@@ -900,7 +907,7 @@ check_deadlock(struct task_struct *curr, struct held_lock *next, | |||
900 | */ | 907 | */ |
901 | static int | 908 | static int |
902 | check_prev_add(struct task_struct *curr, struct held_lock *prev, | 909 | check_prev_add(struct task_struct *curr, struct held_lock *prev, |
903 | struct held_lock *next) | 910 | struct held_lock *next, int distance) |
904 | { | 911 | { |
905 | struct lock_list *entry; | 912 | struct lock_list *entry; |
906 | int ret; | 913 | int ret; |
@@ -978,8 +985,11 @@ check_prev_add(struct task_struct *curr, struct held_lock *prev, | |||
978 | * L2 added to its dependency list, due to the first chain.) | 985 | * L2 added to its dependency list, due to the first chain.) |
979 | */ | 986 | */ |
980 | list_for_each_entry(entry, &prev->class->locks_after, entry) { | 987 | list_for_each_entry(entry, &prev->class->locks_after, entry) { |
981 | if (entry->class == next->class) | 988 | if (entry->class == next->class) { |
989 | if (distance == 1) | ||
990 | entry->distance = 1; | ||
982 | return 2; | 991 | return 2; |
992 | } | ||
983 | } | 993 | } |
984 | 994 | ||
985 | /* | 995 | /* |
@@ -987,12 +997,13 @@ check_prev_add(struct task_struct *curr, struct held_lock *prev, | |||
987 | * to the previous lock's dependency list: | 997 | * to the previous lock's dependency list: |
988 | */ | 998 | */ |
989 | ret = add_lock_to_list(prev->class, next->class, | 999 | ret = add_lock_to_list(prev->class, next->class, |
990 | &prev->class->locks_after, next->acquire_ip); | 1000 | &prev->class->locks_after, next->acquire_ip, distance); |
1001 | |||
991 | if (!ret) | 1002 | if (!ret) |
992 | return 0; | 1003 | return 0; |
993 | 1004 | ||
994 | ret = add_lock_to_list(next->class, prev->class, | 1005 | ret = add_lock_to_list(next->class, prev->class, |
995 | &next->class->locks_before, next->acquire_ip); | 1006 | &next->class->locks_before, next->acquire_ip, distance); |
996 | if (!ret) | 1007 | if (!ret) |
997 | return 0; | 1008 | return 0; |
998 | 1009 | ||
@@ -1040,13 +1051,14 @@ check_prevs_add(struct task_struct *curr, struct held_lock *next) | |||
1040 | goto out_bug; | 1051 | goto out_bug; |
1041 | 1052 | ||
1042 | for (;;) { | 1053 | for (;;) { |
1054 | int distance = curr->lockdep_depth - depth + 1; | ||
1043 | hlock = curr->held_locks + depth-1; | 1055 | hlock = curr->held_locks + depth-1; |
1044 | /* | 1056 | /* |
1045 | * Only non-recursive-read entries get new dependencies | 1057 | * Only non-recursive-read entries get new dependencies |
1046 | * added: | 1058 | * added: |
1047 | */ | 1059 | */ |
1048 | if (hlock->read != 2) { | 1060 | if (hlock->read != 2) { |
1049 | if (!check_prev_add(curr, hlock, next)) | 1061 | if (!check_prev_add(curr, hlock, next, distance)) |
1050 | return 0; | 1062 | return 0; |
1051 | /* | 1063 | /* |
1052 | * Stop after the first non-trylock entry, | 1064 | * Stop after the first non-trylock entry, |
@@ -1293,7 +1305,8 @@ out_unlock_set: | |||
1293 | if (!subclass || force) | 1305 | if (!subclass || force) |
1294 | lock->class_cache = class; | 1306 | lock->class_cache = class; |
1295 | 1307 | ||
1296 | DEBUG_LOCKS_WARN_ON(class->subclass != subclass); | 1308 | if (DEBUG_LOCKS_WARN_ON(class->subclass != subclass)) |
1309 | return NULL; | ||
1297 | 1310 | ||
1298 | return class; | 1311 | return class; |
1299 | } | 1312 | } |
@@ -1308,7 +1321,8 @@ static inline int lookup_chain_cache(u64 chain_key, struct lock_class *class) | |||
1308 | struct list_head *hash_head = chainhashentry(chain_key); | 1321 | struct list_head *hash_head = chainhashentry(chain_key); |
1309 | struct lock_chain *chain; | 1322 | struct lock_chain *chain; |
1310 | 1323 | ||
1311 | DEBUG_LOCKS_WARN_ON(!irqs_disabled()); | 1324 | if (DEBUG_LOCKS_WARN_ON(!irqs_disabled())) |
1325 | return 0; | ||
1312 | /* | 1326 | /* |
1313 | * We can walk it lock-free, because entries only get added | 1327 | * We can walk it lock-free, because entries only get added |
1314 | * to the hash: | 1328 | * to the hash: |
@@ -1394,7 +1408,9 @@ static void check_chain_key(struct task_struct *curr) | |||
1394 | return; | 1408 | return; |
1395 | } | 1409 | } |
1396 | id = hlock->class - lock_classes; | 1410 | id = hlock->class - lock_classes; |
1397 | DEBUG_LOCKS_WARN_ON(id >= MAX_LOCKDEP_KEYS); | 1411 | if (DEBUG_LOCKS_WARN_ON(id >= MAX_LOCKDEP_KEYS)) |
1412 | return; | ||
1413 | |||
1398 | if (prev_hlock && (prev_hlock->irq_context != | 1414 | if (prev_hlock && (prev_hlock->irq_context != |
1399 | hlock->irq_context)) | 1415 | hlock->irq_context)) |
1400 | chain_key = 0; | 1416 | chain_key = 0; |
@@ -2205,7 +2221,11 @@ out_calc_hash: | |||
2205 | if (!check_prevs_add(curr, hlock)) | 2221 | if (!check_prevs_add(curr, hlock)) |
2206 | return 0; | 2222 | return 0; |
2207 | graph_unlock(); | 2223 | graph_unlock(); |
2208 | } | 2224 | } else |
2225 | /* after lookup_chain_cache(): */ | ||
2226 | if (unlikely(!debug_locks)) | ||
2227 | return 0; | ||
2228 | |||
2209 | curr->lockdep_depth++; | 2229 | curr->lockdep_depth++; |
2210 | check_chain_key(curr); | 2230 | check_chain_key(curr); |
2211 | if (unlikely(curr->lockdep_depth >= MAX_LOCK_DEPTH)) { | 2231 | if (unlikely(curr->lockdep_depth >= MAX_LOCK_DEPTH)) { |
@@ -2214,6 +2234,7 @@ out_calc_hash: | |||
2214 | printk("turning off the locking correctness validator.\n"); | 2234 | printk("turning off the locking correctness validator.\n"); |
2215 | return 0; | 2235 | return 0; |
2216 | } | 2236 | } |
2237 | |||
2217 | if (unlikely(curr->lockdep_depth > max_lockdep_depth)) | 2238 | if (unlikely(curr->lockdep_depth > max_lockdep_depth)) |
2218 | max_lockdep_depth = curr->lockdep_depth; | 2239 | max_lockdep_depth = curr->lockdep_depth; |
2219 | 2240 | ||
@@ -2764,4 +2785,3 @@ void debug_show_held_locks(struct task_struct *task) | |||
2764 | } | 2785 | } |
2765 | 2786 | ||
2766 | EXPORT_SYMBOL_GPL(debug_show_held_locks); | 2787 | EXPORT_SYMBOL_GPL(debug_show_held_locks); |
2767 | |||