diff options
author | Gregory Haskins <ghaskins@novell.com> | 2007-10-11 16:11:11 -0400 |
---|---|---|
committer | Peter Zijlstra <a.p.zijlstra@chello.nl> | 2007-10-11 16:11:11 -0400 |
commit | 3aa416b07f0adf01c090baab26fb70c35ec17623 (patch) | |
tree | a2c2c2f7bd8445b138b293ba6661833f970954ee /kernel/lockdep.c | |
parent | 94c61c0aeffe64452e742087cf803d0347ef8418 (diff) |
lockdep: fix mismatched lockdep_depth/curr_chain_hash
It is possible for the current->curr_chain_key to become inconsistent with the
current index if the chain fails to validate. The end result is that future
lock_acquire() operations may inadvertently fail to find a hit in the cache
resulting in a new node being added to the graph for every acquire.
Signed-off-by: Gregory Haskins <ghaskins@novell.com>
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel/lockdep.c')
-rw-r--r-- | kernel/lockdep.c | 10 |
1 files changed, 5 insertions, 5 deletions
diff --git a/kernel/lockdep.c b/kernel/lockdep.c index 734da579ad13..42ae4a5ab4dc 100644 --- a/kernel/lockdep.c +++ b/kernel/lockdep.c | |||
@@ -1521,7 +1521,7 @@ cache_hit: | |||
1521 | } | 1521 | } |
1522 | 1522 | ||
1523 | static int validate_chain(struct task_struct *curr, struct lockdep_map *lock, | 1523 | static int validate_chain(struct task_struct *curr, struct lockdep_map *lock, |
1524 | struct held_lock *hlock, int chain_head) | 1524 | struct held_lock *hlock, int chain_head, u64 chain_key) |
1525 | { | 1525 | { |
1526 | /* | 1526 | /* |
1527 | * Trylock needs to maintain the stack of held locks, but it | 1527 | * Trylock needs to maintain the stack of held locks, but it |
@@ -1534,7 +1534,7 @@ static int validate_chain(struct task_struct *curr, struct lockdep_map *lock, | |||
1534 | * graph_lock for us) | 1534 | * graph_lock for us) |
1535 | */ | 1535 | */ |
1536 | if (!hlock->trylock && (hlock->check == 2) && | 1536 | if (!hlock->trylock && (hlock->check == 2) && |
1537 | lookup_chain_cache(curr->curr_chain_key, hlock->class)) { | 1537 | lookup_chain_cache(chain_key, hlock->class)) { |
1538 | /* | 1538 | /* |
1539 | * Check whether last held lock: | 1539 | * Check whether last held lock: |
1540 | * | 1540 | * |
@@ -1576,7 +1576,7 @@ static int validate_chain(struct task_struct *curr, struct lockdep_map *lock, | |||
1576 | #else | 1576 | #else |
1577 | static inline int validate_chain(struct task_struct *curr, | 1577 | static inline int validate_chain(struct task_struct *curr, |
1578 | struct lockdep_map *lock, struct held_lock *hlock, | 1578 | struct lockdep_map *lock, struct held_lock *hlock, |
1579 | int chain_head) | 1579 | int chain_head, u64 chain_key) |
1580 | { | 1580 | { |
1581 | return 1; | 1581 | return 1; |
1582 | } | 1582 | } |
@@ -2450,11 +2450,11 @@ static int __lock_acquire(struct lockdep_map *lock, unsigned int subclass, | |||
2450 | chain_head = 1; | 2450 | chain_head = 1; |
2451 | } | 2451 | } |
2452 | chain_key = iterate_chain_key(chain_key, id); | 2452 | chain_key = iterate_chain_key(chain_key, id); |
2453 | curr->curr_chain_key = chain_key; | ||
2454 | 2453 | ||
2455 | if (!validate_chain(curr, lock, hlock, chain_head)) | 2454 | if (!validate_chain(curr, lock, hlock, chain_head, chain_key)) |
2456 | return 0; | 2455 | return 0; |
2457 | 2456 | ||
2457 | curr->curr_chain_key = chain_key; | ||
2458 | curr->lockdep_depth++; | 2458 | curr->lockdep_depth++; |
2459 | check_chain_key(curr); | 2459 | check_chain_key(curr); |
2460 | #ifdef CONFIG_DEBUG_LOCKDEP | 2460 | #ifdef CONFIG_DEBUG_LOCKDEP |