aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/lockdep.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/lockdep.c')
-rw-r--r--kernel/lockdep.c42
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
71static inline int graph_unlock(void) 71static 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 */
489static int add_lock_to_list(struct lock_class *class, struct lock_class *this, 492static 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 */
901static int 908static int
902check_prev_add(struct task_struct *curr, struct held_lock *prev, 909check_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
2766EXPORT_SYMBOL_GPL(debug_show_held_locks); 2787EXPORT_SYMBOL_GPL(debug_show_held_locks);
2767