locking fixes
Linus,
Please pull the latest locking-urgent-for-linus git tree from:
git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git locking-urgent-for-linus
# HEAD: 75dd602a5198a6e5f75534db52b6e6fbaabb33d1 lockdep: Fix lock_chain::base size
Two lockdep fixes.
Thanks,
Ingo
------------------>
Boqun Feng (1):
locking/lockdep: Fix ->irq_context calculation
Peter Zijlstra (1):
lockdep: Fix lock_chain::base size
include/linux/lockdep.h | 8 +++++--- kernel/locking/lockdep.c | 37 ++++++++++++++++++++++++++++++++++--- kernel/locking/lockdep_proc.c | 2 ++ 3 files changed, 41 insertions(+), 6 deletions(-)
include/linux/lockdep.h +5 -3
@@ -196,9 +196,11 @@ struct lock_list {* We record lock dependency chains, so that we can cache them: */ struct lock_chain { -u8 irq_context; -u8 depth; -u16 base; +/* see BUILD_BUG_ON()s in lookup_chain_cache() */ +unsigned int irq_context :2 , + depth :6 , + base :24 ; +/* 4 byte hole */ struct hlist_node entry;u64 chain_key; };
kernel/locking/lockdep.c +34 -3
@@ -2176,15 +2176,37 @@ static inline int lookup_chain_cache(struct task_struct *curr, chain->irq_context = hlock->irq_context; i =get_first_held_lock (curr, hlock); chain->depth = curr->lockdep_depth +1 - i; + +BUILD_BUG_ON ((1UL <<24 ) <=ARRAY_SIZE (chain_hlocks)); +BUILD_BUG_ON ((1UL <<6 ) <=ARRAY_SIZE (curr->held_locks)); +BUILD_BUG_ON ((1UL <<8 *sizeof (chain_hlocks[0 ])) <=ARRAY_SIZE (lock_classes)); +if (likely (nr_chain_hlocks + chain->depth <=MAX_LOCKDEP_CHAIN_HLOCKS )) { chain->base = nr_chain_hlocks; - nr_chain_hlocks += chain->depth;for (j =0 ; j < chain->depth -1 ; j++, i++) {int lock_id = curr->held_locks[i].class_idx -1 ; chain_hlocks[chain->base + j] = lock_id; } chain_hlocks[chain->base + j] = class - lock_classes; } + +if (nr_chain_hlocks <MAX_LOCKDEP_CHAIN_HLOCKS ) + nr_chain_hlocks += chain->depth; + +#ifdef CONFIG_DEBUG_LOCKDEP +/* +* Important for check_no_collision(). +*/ +if (unlikely (nr_chain_hlocks >MAX_LOCKDEP_CHAIN_HLOCKS )) { +if (debug_locks_off_graph_unlock ()) +return 0 ; + +print_lockdep_off ("BUG: MAX_LOCKDEP_CHAIN_HLOCKS too low!" ); +dump_stack (); +return 0 ; + } +#endif +hlist_add_head_rcu (&chain->entry, hash_head);debug_atomic_inc (chain_lookup_misses);inc_chains ();
@@ -2932,6 +2954,11 @@ static int mark_irqflags(struct task_struct *curr, struct held_lock *hlock)return 1 ; } +static inline unsigned int task_irq_context (struct task_struct *task) +{ +return 2 * !!task->hardirq_context + !!task->softirq_context; +} +static int separate_irq_context (struct task_struct *curr,struct held_lock *hlock) {
@@ -2940,8 +2967,6 @@ static int separate_irq_context(struct task_struct *curr,/* * Keep track of points where we cross into an interrupt context: */ - hlock->irq_context =2 *(curr->hardirq_context ?1 :0 ) + - curr->softirq_context;if (depth) {struct held_lock *prev_hlock;
@@ -2973,6 +2998,11 @@ static inline int mark_irqflags(struct task_struct *curr,return 1 ; } +static inline unsigned int task_irq_context (struct task_struct *task) +{ +return 0 ; +} +static inline int separate_irq_context (struct task_struct *curr,struct held_lock *hlock) {
@@ -3241,6 +3271,7 @@ static int __lock_acquire(struct lockdep_map *lock, unsigned int subclass, hlock->acquire_ip = ip; hlock->instance = lock; hlock->nest_lock = nest_lock; + hlock->irq_context =task_irq_context (curr); hlock->trylock = trylock; hlock->read = read; hlock->check = check;
kernel/locking/lockdep_proc.c +2 -0
@@ -141,6 +141,8 @@ static int lc_show(struct seq_file *m, void *v)int i;if (v ==SEQ_START_TOKEN ) { +if (nr_chain_hlocks >MAX_LOCKDEP_CHAIN_HLOCKS ) +seq_printf (m,"(buggered) " );seq_printf (m,"all lock chains:\n" );return 0 ; }