Skip to content

Commit 836bd74

Browse files
Waiman-LongIngo Molnar
authored andcommitted
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: Waiman Long <longman@redhat.com> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Signed-off-by: Ingo Molnar <mingo@kernel.org> Link: https://lkml.kernel.org/r/20200206152408.24165-5-longman@redhat.com
1 parent 1d44bcb commit 836bd74

File tree

3 files changed

+7
-36
lines changed

3 files changed

+7
-36
lines changed

kernel/locking/lockdep.c

Lines changed: 4 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -2625,8 +2625,8 @@ check_prevs_add(struct task_struct *curr, struct held_lock *next)
26252625

26262626
struct lock_chain lock_chains[MAX_LOCKDEP_CHAINS];
26272627
static DECLARE_BITMAP(lock_chains_in_use, MAX_LOCKDEP_CHAINS);
2628-
int nr_chain_hlocks;
26292628
static u16 chain_hlocks[MAX_LOCKDEP_CHAIN_HLOCKS];
2629+
unsigned int nr_chain_hlocks;
26302630

26312631
struct lock_class *lock_chain_get_class(struct lock_chain *chain, int i)
26322632
{
@@ -4772,36 +4772,23 @@ static void remove_class_from_lock_chain(struct pending_free *pf,
47724772
struct lock_class *class)
47734773
{
47744774
#ifdef CONFIG_PROVE_LOCKING
4775-
struct lock_chain *new_chain;
4776-
u64 chain_key;
47774775
int i;
47784776

47794777
for (i = chain->base; i < chain->base + chain->depth; i++) {
47804778
if (chain_hlocks[i] != class - lock_classes)
47814779
continue;
4782-
/* The code below leaks one chain_hlock[] entry. */
4783-
if (--chain->depth > 0) {
4784-
memmove(&chain_hlocks[i], &chain_hlocks[i + 1],
4785-
(chain->base + chain->depth - i) *
4786-
sizeof(chain_hlocks[0]));
4787-
}
47884780
/*
47894781
* Each lock class occurs at most once in a lock chain so once
47904782
* we found a match we can break out of this loop.
47914783
*/
4792-
goto recalc;
4784+
goto free_lock_chain;
47934785
}
47944786
/* Since the chain has not been modified, return. */
47954787
return;
47964788

4797-
recalc:
4798-
chain_key = INITIAL_CHAIN_KEY;
4799-
for (i = chain->base; i < chain->base + chain->depth; i++)
4800-
chain_key = iterate_chain_key(chain_key, chain_hlocks[i]);
4801-
if (chain->depth && chain->chain_key == chain_key)
4802-
return;
4789+
free_lock_chain:
48034790
/* Overwrite the chain key for concurrent RCU readers. */
4804-
WRITE_ONCE(chain->chain_key, chain_key);
4791+
WRITE_ONCE(chain->chain_key, INITIAL_CHAIN_KEY);
48054792
dec_chains(chain->irq_context);
48064793

48074794
/*
@@ -4810,22 +4797,6 @@ static void remove_class_from_lock_chain(struct pending_free *pf,
48104797
*/
48114798
hlist_del_rcu(&chain->entry);
48124799
__set_bit(chain - lock_chains, pf->lock_chains_being_freed);
4813-
if (chain->depth == 0)
4814-
return;
4815-
/*
4816-
* If the modified lock chain matches an existing lock chain, drop
4817-
* the modified lock chain.
4818-
*/
4819-
if (lookup_chain_cache(chain_key))
4820-
return;
4821-
new_chain = alloc_lock_chain();
4822-
if (WARN_ON_ONCE(!new_chain)) {
4823-
debug_locks_off();
4824-
return;
4825-
}
4826-
*new_chain = *chain;
4827-
hlist_add_head_rcu(&new_chain->entry, chainhashentry(chain_key));
4828-
inc_chains(new_chain->irq_context);
48294800
#endif
48304801
}
48314802

kernel/locking/lockdep_internals.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,14 +134,14 @@ extern unsigned long nr_zapped_classes;
134134
extern unsigned long nr_list_entries;
135135
long lockdep_next_lockchain(long i);
136136
unsigned long lock_chain_count(void);
137-
extern int nr_chain_hlocks;
138137
extern unsigned long nr_stack_trace_entries;
139138

140139
extern unsigned int nr_hardirq_chains;
141140
extern unsigned int nr_softirq_chains;
142141
extern unsigned int nr_process_chains;
143-
extern unsigned int max_lockdep_depth;
142+
extern unsigned int nr_chain_hlocks;
144143

144+
extern unsigned int max_lockdep_depth;
145145
extern unsigned int max_bfs_queue_depth;
146146

147147
#ifdef CONFIG_PROVE_LOCKING

kernel/locking/lockdep_proc.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,7 @@ static int lockdep_stats_show(struct seq_file *m, void *v)
278278
#ifdef CONFIG_PROVE_LOCKING
279279
seq_printf(m, " dependency chains: %11lu [max: %lu]\n",
280280
lock_chain_count(), MAX_LOCKDEP_CHAINS);
281-
seq_printf(m, " dependency chain hlocks: %11d [max: %lu]\n",
281+
seq_printf(m, " dependency chain hlocks: %11u [max: %lu]\n",
282282
nr_chain_hlocks, MAX_LOCKDEP_CHAIN_HLOCKS);
283283
#endif
284284

0 commit comments

Comments
 (0)