LOCKDEP: fix mismatched lockdep_depth/curr_chain_hash
PATCH 1/1 LOCKDEP: fix mismatched lockdep_depth/curr_chain_hash
Doh! I guess there should be a rule about sending patches out after midnight ;)
The original patch I worked on was written before the code was moved to validate_chain(), so my previous posting didnt quite translate when I merged with git HEAD. Here is an updated patch. Sorry for the confusion.
Regards,
-Greg
---
kernel/lockdep.c | 10 +++++----- 1 files changed, 5 insertions(+), 5 deletions(-)
kernel/lockdep.c +5 -5
@@ -1521,7 +1521,7 @@ cache_hit: }static int validate_chain (struct task_struct *curr,struct lockdep_map *lock, -struct held_lock *hlock,int chain_head) +struct held_lock *hlock,int chain_head,u64 chain_key) {/* * 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,* graph_lock for us) */ if (!hlock->trylock && (hlock->check ==2 ) && -lookup_chain_cache (curr->curr_chain_key, hlock->class)) { +lookup_chain_cache (chain_key, hlock->class)) {/* * Check whether last held lock: *
@@ -1576,7 +1576,7 @@ static int validate_chain(struct task_struct *curr, struct lockdep_map *lock,#else static inline int validate_chain (struct task_struct *curr,struct lockdep_map *lock,struct held_lock *hlock, -int chain_head) +int chain_head,u64 chain_key) {return 1 ; }
@@ -2450,11 +2450,11 @@ static int __lock_acquire(struct lockdep_map *lock, unsigned int subclass, chain_head =1 ; } chain_key =iterate_chain_key (chain_key, id); - curr->curr_chain_key = chain_key; -if (!validate_chain (curr, lock, hlock, chain_head)) +if (!validate_chain (curr, lock, hlock, chain_head, chain_key))return 0 ; + curr->curr_chain_key = chain_key; curr->lockdep_depth++;check_chain_key (curr);#ifdef CONFIG_DEBUG_LOCKDEP
PATCH 1/1 lockdep: fix mismatched lockdep_depth/curr_chain_hash
Ouch!
Thanks Gregory for finding this!
I'll send your initial patch to the stable team for .22.
---
Subject: lockdep: fix mismatched lockdep_depth/curr_chain_hash
From: Gregory Haskins <[email protected]>
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.
[ peterz: this might explain some of the lockdep is so _slow_ complaints. ] [ mingo: this does not impact the correctness of validation, but may slow
down future operations significantly, if the chain gets very long. ]
--- kernel/lockdep.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
kernel/lockdep.c +5 -5
@@ -1521,7 +1521,7 @@ cache_hit: }static int validate_chain (struct task_struct *curr,struct lockdep_map *lock, -struct held_lock *hlock,int chain_head) +struct held_lock *hlock,int chain_head,u64 chain_key) {/* * Trylock needs to maintain the stack of held locks, but it
@@ -1534,7 +1534,7 @@ static int validate_chain(struct task_st* graph_lock for us) */ if (!hlock->trylock && (hlock->check ==2 ) && -lookup_chain_cache (curr->curr_chain_key, hlock->class)) { +lookup_chain_cache (chain_key, hlock->class)) {/* * Check whether last held lock: *
@@ -1576,7 +1576,7 @@ static int validate_chain(struct task_st#else static inline int validate_chain (struct task_struct *curr,struct lockdep_map *lock,struct held_lock *hlock, -int chain_head) +int chain_head,u64 chain_key) {return 1 ; }
@@ -2450,11 +2450,11 @@ static int __lock_acquire(struct lockdep chain_head =1 ; } chain_key =iterate_chain_key (chain_key, id); - curr->curr_chain_key = chain_key; -if (!validate_chain (curr, lock, hlock, chain_head)) +if (!validate_chain (curr, lock, hlock, chain_head, chain_key))return 0 ; + curr->curr_chain_key = chain_key; curr->lockdep_depth++;check_chain_key (curr);#ifdef CONFIG_DEBUG_LOCKDEP