From 1ff5683043196b9ad628a5de6bf8eeca52ee8bfd Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Fri, 17 Nov 2006 19:57:22 +0100 Subject: [PATCH] lockdep: fix static keys in module-allocated percpu areas lockdep got confused by certain locks in modules: INFO: trying to register non-static key. the code is fine but needs lockdep annotation. turning off the locking correctness validator. Call Trace: [] dump_trace+0xaa/0x3f2 [] show_trace+0x3a/0x60 [] dump_stack+0x15/0x17 [] __lock_acquire+0x724/0x9bb [] lock_acquire+0x4d/0x67 [] rt_spin_lock+0x3d/0x41 [] :ip_conntrack:__ip_ct_refresh_acct+0x131/0x174 [] :ip_conntrack:udp_packet+0xbf/0xcf [] :ip_conntrack:ip_conntrack_in+0x394/0x4a7 [] nf_iterate+0x41/0x7f [] nf_hook_slow+0x64/0xd5 [] ip_rcv+0x24e/0x506 [...] Steven Rostedt found the bug: static_obj() check did not take PERCPU_ENOUGH_ROOM into account, so in-module DEFINE_PER_CPU-area locks were triggering this message. Signed-off-by: Ingo Molnar Signed-off-by: Steven Rostedt Signed-off-by: Linus Torvalds --- kernel/lockdep.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'kernel/lockdep.c') diff --git a/kernel/lockdep.c b/kernel/lockdep.c index b739be2..c9fefdb 100644 --- a/kernel/lockdep.c +++ b/kernel/lockdep.c @@ -1081,7 +1081,8 @@ static int static_obj(void *obj) */ for_each_possible_cpu(i) { start = (unsigned long) &__per_cpu_start + per_cpu_offset(i); - end = (unsigned long) &__per_cpu_end + per_cpu_offset(i); + end = (unsigned long) &__per_cpu_start + PERCPU_ENOUGH_ROOM + + per_cpu_offset(i); if ((addr >= start) && (addr < end)) return 1; -- cgit v1.1 From eef5e0d185fc049bda11fa14ba286fbd357da896 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Thu, 7 Dec 2006 02:14:12 +0100 Subject: [PATCH] unwinder: Remove lockdep disabling of nested locks for unwinder Shouldn't be needed anymore since __kernel_text_address is used unconditionally on x86-64 Signed-off-by: Andi Kleen --- kernel/lockdep.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'kernel/lockdep.c') diff --git a/kernel/lockdep.c b/kernel/lockdep.c index c9fefdb..9bb8d78 100644 --- a/kernel/lockdep.c +++ b/kernel/lockdep.c @@ -228,11 +228,7 @@ static int save_trace(struct stack_trace *trace) trace->skip = 3; trace->all_contexts = 0; - /* Make sure to not recurse in case the the unwinder needs to tak -e locks. */ - lockdep_off(); save_stack_trace(trace, NULL); - lockdep_on(); trace->max_entries = trace->nr_entries; -- cgit v1.1 From ed07536ed6731775219c1df7fa26a7588753e693 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Wed, 6 Dec 2006 20:35:24 -0800 Subject: [PATCH] lockdep: annotate nfs/nfsd in-kernel sockets Stick NFS sockets in their own class to avoid some lockdep warnings. NFS sockets are never exposed to user-space, and will hence not trigger certain code paths that would otherwise pose deadlock scenarios. [akpm@osdl.org: cleanups] Signed-off-by: Peter Zijlstra Signed-off-by: Steven Dickson Acked-by: Ingo Molnar Cc: Trond Myklebust Acked-by: Neil Brown Cc: "David S. Miller" Signed-off-by: Andrew Morton [ Fixed patch corruption by quilt, pointed out by Peter Zijlstra ] Signed-off-by: Linus Torvalds --- kernel/lockdep.c | 1 + 1 file changed, 1 insertion(+) (limited to 'kernel/lockdep.c') diff --git a/kernel/lockdep.c b/kernel/lockdep.c index c9fefdb..e33f620 100644 --- a/kernel/lockdep.c +++ b/kernel/lockdep.c @@ -2645,6 +2645,7 @@ void debug_check_no_locks_freed(const void *mem_from, unsigned long mem_len) } local_irq_restore(flags); } +EXPORT_SYMBOL_GPL(debug_check_no_locks_freed); static void print_held_locks_bug(struct task_struct *curr) { -- cgit v1.1 From 910b1b2e6d7d10e1c3bffdd12a90ec82f535f9a5 Mon Sep 17 00:00:00 2001 From: Jarek Poplawski Date: Thu, 7 Dec 2006 10:45:25 +0100 Subject: [PATCH] lockdep: internal locking fixes Here are mainly some lockdep returns with 0 with unlocking fixes. Signed-off-by: Jarek Poplawski Signed-off-by: Andrew Morton Signed-off-by: Ingo Molnar Signed-off-by: Linus Torvalds --- kernel/lockdep.c | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) (limited to 'kernel/lockdep.c') diff --git a/kernel/lockdep.c b/kernel/lockdep.c index e33f620..f76a24f 100644 --- a/kernel/lockdep.c +++ b/kernel/lockdep.c @@ -237,8 +237,10 @@ e locks. */ trace->max_entries = trace->nr_entries; nr_stack_trace_entries += trace->nr_entries; - if (DEBUG_LOCKS_WARN_ON(nr_stack_trace_entries > MAX_STACK_TRACE_ENTRIES)) + if (DEBUG_LOCKS_WARN_ON(nr_stack_trace_entries > MAX_STACK_TRACE_ENTRIES)) { + __raw_spin_unlock(&hash_lock); return 0; + } if (nr_stack_trace_entries == MAX_STACK_TRACE_ENTRIES) { __raw_spin_unlock(&hash_lock); @@ -474,7 +476,8 @@ static int add_lock_to_list(struct lock_class *class, struct lock_class *this, return 0; entry->class = this; - save_trace(&entry->trace); + if (!save_trace(&entry->trace)) + return 0; /* * Since we never remove from the dependency list, the list can @@ -562,8 +565,12 @@ static noinline int print_circular_bug_tail(void) if (debug_locks_silent) return 0; + /* hash_lock unlocked by the header */ + __raw_spin_lock(&hash_lock); this.class = check_source->class; - save_trace(&this.trace); + if (!save_trace(&this.trace)) + return 0; + __raw_spin_unlock(&hash_lock); print_circular_bug_entry(&this, 0); printk("\nother info that might help us debug this:\n\n"); @@ -966,14 +973,11 @@ check_prev_add(struct task_struct *curr, struct held_lock *prev, &prev->class->locks_after, next->acquire_ip); if (!ret) return 0; - /* - * Return value of 2 signals 'dependency already added', - * in that case we dont have to add the backlink either. - */ - if (ret == 2) - return 2; + ret = add_lock_to_list(next->class, prev->class, &next->class->locks_before, next->acquire_ip); + if (!ret) + return 0; /* * Debugging printouts: @@ -1025,7 +1029,8 @@ check_prevs_add(struct task_struct *curr, struct held_lock *next) * added: */ if (hlock->read != 2) { - check_prev_add(curr, hlock, next); + if (!check_prev_add(curr, hlock, next)) + return 0; /* * Stop after the first non-trylock entry, * as non-trylock entries have added their -- cgit v1.1 From b23984d0a12a4821b2e9712c71550f321eb88bb5 Mon Sep 17 00:00:00 2001 From: Jarek Poplawski Date: Wed, 6 Dec 2006 20:36:23 -0800 Subject: [PATCH] lockdep: misc fixes in lockdep.c - numeric string size replaced with constant in print_lock_name and print_lockdep_cache, - return on null pointer in print_lock_dependencies, - one more lockdep return with 0 with unlocking fix in mark_lock. Signed-off-by: Jarek Poplawski Acked-by: Ingo Molnar Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/lockdep.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'kernel/lockdep.c') diff --git a/kernel/lockdep.c b/kernel/lockdep.c index f76a24f..300d61b 100644 --- a/kernel/lockdep.c +++ b/kernel/lockdep.c @@ -359,7 +359,7 @@ get_usage_chars(struct lock_class *class, char *c1, char *c2, char *c3, char *c4 static void print_lock_name(struct lock_class *class) { - char str[128], c1, c2, c3, c4; + char str[KSYM_NAME_LEN + 1], c1, c2, c3, c4; const char *name; get_usage_chars(class, &c1, &c2, &c3, &c4); @@ -381,7 +381,7 @@ static void print_lock_name(struct lock_class *class) static void print_lockdep_cache(struct lockdep_map *lock) { const char *name; - char str[128]; + char str[KSYM_NAME_LEN + 1]; name = lock->name; if (!name) @@ -451,7 +451,9 @@ static void print_lock_dependencies(struct lock_class *class, int depth) print_lock_class_header(class, depth); list_for_each_entry(entry, &class->locks_after, entry) { - DEBUG_LOCKS_WARN_ON(!entry->class); + if (DEBUG_LOCKS_WARN_ON(!entry->class)) + return; + print_lock_dependencies(entry->class, depth + 1); printk("%*s ... acquired at:\n",depth,""); @@ -1733,6 +1735,7 @@ static int mark_lock(struct task_struct *curr, struct held_lock *this, debug_atomic_dec(&nr_unused_locks); break; default: + __raw_spin_unlock(&hash_lock); debug_locks_off(); WARN_ON(1); return 0; -- cgit v1.1 From ebe7e5fe4b41deeb2731c5b52d8c8e6ac08b1f74 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Wed, 6 Dec 2006 20:38:21 -0800 Subject: [PATCH] remove kernel/lockdep.c:lockdep_internal Remove the no longer used lockdep_internal(). Signed-off-by: Adrian Bunk Acked-by: Ingo Molnar Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/lockdep.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'kernel/lockdep.c') diff --git a/kernel/lockdep.c b/kernel/lockdep.c index 300d61b..3926c36 100644 --- a/kernel/lockdep.c +++ b/kernel/lockdep.c @@ -140,13 +140,6 @@ void lockdep_on(void) EXPORT_SYMBOL(lockdep_on); -int lockdep_internal(void) -{ - return current->lockdep_recursion != 0; -} - -EXPORT_SYMBOL(lockdep_internal); - /* * Debugging switches: */ -- cgit v1.1 From 70e4506765602cca047cfa31933836e354c61a63 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 6 Dec 2006 20:40:50 -0800 Subject: [PATCH] lockdep: register_lock_class() fix The hash_lock must only ever be taken with irqs disabled. This happens in all the important places, except one codepath: register_lock_class(). The race should trigger rarely because register_lock_class() is quite rare and single-threaded (happens during init most of the time). The fix is to disable irqs. ( bug found live in -rt: there preemption is alot more agressive and preempting with the hash-lock held caused a lockup.) Signed-off-by: Ingo Molnar Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/lockdep.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'kernel/lockdep.c') diff --git a/kernel/lockdep.c b/kernel/lockdep.c index 3926c36..62e73ce 100644 --- a/kernel/lockdep.c +++ b/kernel/lockdep.c @@ -1182,6 +1182,7 @@ register_lock_class(struct lockdep_map *lock, unsigned int subclass, int force) struct lockdep_subclass_key *key; struct list_head *hash_head; struct lock_class *class; + unsigned long flags; class = look_up_lock_class(lock, subclass); if (likely(class)) @@ -1203,6 +1204,7 @@ register_lock_class(struct lockdep_map *lock, unsigned int subclass, int force) key = lock->key->subkeys + subclass; hash_head = classhashentry(key); + raw_local_irq_save(flags); __raw_spin_lock(&hash_lock); /* * We have to do the hash-walk again, to avoid races @@ -1217,6 +1219,7 @@ register_lock_class(struct lockdep_map *lock, unsigned int subclass, int force) */ if (nr_lock_classes >= MAX_LOCKDEP_KEYS) { __raw_spin_unlock(&hash_lock); + raw_local_irq_restore(flags); debug_locks_off(); printk("BUG: MAX_LOCKDEP_KEYS too low!\n"); printk("turning off the locking correctness validator.\n"); @@ -1239,15 +1242,18 @@ register_lock_class(struct lockdep_map *lock, unsigned int subclass, int force) if (verbose(class)) { __raw_spin_unlock(&hash_lock); + raw_local_irq_restore(flags); printk("\nnew class %p: %s", class->key, class->name); if (class->name_version > 1) printk("#%d", class->name_version); printk("\n"); dump_stack(); + raw_local_irq_save(flags); __raw_spin_lock(&hash_lock); } out_unlock_set: __raw_spin_unlock(&hash_lock); + raw_local_irq_restore(flags); if (!subclass || force) lock->class_cache = class; -- cgit v1.1