Commit 836bd74b authored by Waiman Long's avatar Waiman Long Committed by Ingo Molnar

locking/lockdep: Throw away all lock chains with zapped class

If a lock chain contains a class that is zapped, the whole lock chain is
likely to be invalid. If the zapped class is at the end of the chain,
the partial chain without the zapped class should have been stored
already as the current code will store all its predecessor chains. If
the zapped class is somewhere in the middle, there is no guarantee that
the partial chain will actually happen. It may just clutter up the hash
and make searching slower. I would rather prefer storing the chain only
when it actually happens.

So just dump the corresponding chain_hlocks entries for now. A latter
patch will try to reuse the freed chain_hlocks entries.

This patch also changes the type of nr_chain_hlocks to unsigned integer
to be consistent with the other counters.
Signed-off-by: default avatarWaiman Long <longman@redhat.com>
Signed-off-by: default avatarPeter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
Link: https://lkml.kernel.org/r/20200206152408.24165-5-longman@redhat.com
parent 1d44bcb4
...@@ -2625,8 +2625,8 @@ check_prevs_add(struct task_struct *curr, struct held_lock *next) ...@@ -2625,8 +2625,8 @@ check_prevs_add(struct task_struct *curr, struct held_lock *next)
struct lock_chain lock_chains[MAX_LOCKDEP_CHAINS]; struct lock_chain lock_chains[MAX_LOCKDEP_CHAINS];
static DECLARE_BITMAP(lock_chains_in_use, MAX_LOCKDEP_CHAINS); static DECLARE_BITMAP(lock_chains_in_use, MAX_LOCKDEP_CHAINS);
int nr_chain_hlocks;
static u16 chain_hlocks[MAX_LOCKDEP_CHAIN_HLOCKS]; static u16 chain_hlocks[MAX_LOCKDEP_CHAIN_HLOCKS];
unsigned int nr_chain_hlocks;
struct lock_class *lock_chain_get_class(struct lock_chain *chain, int i) struct lock_class *lock_chain_get_class(struct lock_chain *chain, int i)
{ {
...@@ -4772,36 +4772,23 @@ static void remove_class_from_lock_chain(struct pending_free *pf, ...@@ -4772,36 +4772,23 @@ static void remove_class_from_lock_chain(struct pending_free *pf,
struct lock_class *class) struct lock_class *class)
{ {
#ifdef CONFIG_PROVE_LOCKING #ifdef CONFIG_PROVE_LOCKING
struct lock_chain *new_chain;
u64 chain_key;
int i; int i;
for (i = chain->base; i < chain->base + chain->depth; i++) { for (i = chain->base; i < chain->base + chain->depth; i++) {
if (chain_hlocks[i] != class - lock_classes) if (chain_hlocks[i] != class - lock_classes)
continue; continue;
/* The code below leaks one chain_hlock[] entry. */
if (--chain->depth > 0) {
memmove(&chain_hlocks[i], &chain_hlocks[i + 1],
(chain->base + chain->depth - i) *
sizeof(chain_hlocks[0]));
}
/* /*
* Each lock class occurs at most once in a lock chain so once * Each lock class occurs at most once in a lock chain so once
* we found a match we can break out of this loop. * we found a match we can break out of this loop.
*/ */
goto recalc; goto free_lock_chain;
} }
/* Since the chain has not been modified, return. */ /* Since the chain has not been modified, return. */
return; return;
recalc: free_lock_chain:
chain_key = INITIAL_CHAIN_KEY;
for (i = chain->base; i < chain->base + chain->depth; i++)
chain_key = iterate_chain_key(chain_key, chain_hlocks[i]);
if (chain->depth && chain->chain_key == chain_key)
return;
/* Overwrite the chain key for concurrent RCU readers. */ /* Overwrite the chain key for concurrent RCU readers. */
WRITE_ONCE(chain->chain_key, chain_key); WRITE_ONCE(chain->chain_key, INITIAL_CHAIN_KEY);
dec_chains(chain->irq_context); dec_chains(chain->irq_context);
/* /*
...@@ -4810,22 +4797,6 @@ static void remove_class_from_lock_chain(struct pending_free *pf, ...@@ -4810,22 +4797,6 @@ static void remove_class_from_lock_chain(struct pending_free *pf,
*/ */
hlist_del_rcu(&chain->entry); hlist_del_rcu(&chain->entry);
__set_bit(chain - lock_chains, pf->lock_chains_being_freed); __set_bit(chain - lock_chains, pf->lock_chains_being_freed);
if (chain->depth == 0)
return;
/*
* If the modified lock chain matches an existing lock chain, drop
* the modified lock chain.
*/
if (lookup_chain_cache(chain_key))
return;
new_chain = alloc_lock_chain();
if (WARN_ON_ONCE(!new_chain)) {
debug_locks_off();
return;
}
*new_chain = *chain;
hlist_add_head_rcu(&new_chain->entry, chainhashentry(chain_key));
inc_chains(new_chain->irq_context);
#endif #endif
} }
......
...@@ -134,14 +134,14 @@ extern unsigned long nr_zapped_classes; ...@@ -134,14 +134,14 @@ extern unsigned long nr_zapped_classes;
extern unsigned long nr_list_entries; extern unsigned long nr_list_entries;
long lockdep_next_lockchain(long i); long lockdep_next_lockchain(long i);
unsigned long lock_chain_count(void); unsigned long lock_chain_count(void);
extern int nr_chain_hlocks;
extern unsigned long nr_stack_trace_entries; extern unsigned long nr_stack_trace_entries;
extern unsigned int nr_hardirq_chains; extern unsigned int nr_hardirq_chains;
extern unsigned int nr_softirq_chains; extern unsigned int nr_softirq_chains;
extern unsigned int nr_process_chains; extern unsigned int nr_process_chains;
extern unsigned int max_lockdep_depth; extern unsigned int nr_chain_hlocks;
extern unsigned int max_lockdep_depth;
extern unsigned int max_bfs_queue_depth; extern unsigned int max_bfs_queue_depth;
#ifdef CONFIG_PROVE_LOCKING #ifdef CONFIG_PROVE_LOCKING
......
...@@ -278,7 +278,7 @@ static int lockdep_stats_show(struct seq_file *m, void *v) ...@@ -278,7 +278,7 @@ static int lockdep_stats_show(struct seq_file *m, void *v)
#ifdef CONFIG_PROVE_LOCKING #ifdef CONFIG_PROVE_LOCKING
seq_printf(m, " dependency chains: %11lu [max: %lu]\n", seq_printf(m, " dependency chains: %11lu [max: %lu]\n",
lock_chain_count(), MAX_LOCKDEP_CHAINS); lock_chain_count(), MAX_LOCKDEP_CHAINS);
seq_printf(m, " dependency chain hlocks: %11d [max: %lu]\n", seq_printf(m, " dependency chain hlocks: %11u [max: %lu]\n",
nr_chain_hlocks, MAX_LOCKDEP_CHAIN_HLOCKS); nr_chain_hlocks, MAX_LOCKDEP_CHAIN_HLOCKS);
#endif #endif
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment