Messages in this thread Patch in this message | | | Date | Tue, 5 Dec 2006 12:31:03 +0100 | From | Ingo Molnar <> | Subject | [patch] lockdep: register_lock_class() fix |
| |
Subject: [patch] lockdep: register_lock_class() fix From: Ingo Molnar <mingo@elte.hu>
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 <mingo@elte.hu> --- kernel/lockdep.c | 6 ++++++ 1 file changed, 6 insertions(+)
Index: linux-mm-genapic.q/kernel/lockdep.c =================================================================== --- linux-mm-genapic.q.orig/kernel/lockdep.c +++ linux-mm-genapic.q/kernel/lockdep.c @@ -1183,6 +1183,7 @@ register_lock_class(struct lockdep_map * 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)) @@ -1204,6 +1205,7 @@ register_lock_class(struct lockdep_map * 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 @@ -1218,6 +1220,7 @@ register_lock_class(struct lockdep_map * */ 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"); @@ -1240,15 +1243,18 @@ register_lock_class(struct lockdep_map * 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; - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
| |