diff options
Diffstat (limited to 'kernel/locking')
-rw-r--r-- | kernel/locking/lockdep.c | 76 |
1 files changed, 43 insertions, 33 deletions
diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c index ef27f98714c0..95932333a48b 100644 --- a/kernel/locking/lockdep.c +++ b/kernel/locking/lockdep.c | |||
@@ -138,6 +138,9 @@ static struct lock_list list_entries[MAX_LOCKDEP_ENTRIES]; | |||
138 | * get freed - this significantly simplifies the debugging code. | 138 | * get freed - this significantly simplifies the debugging code. |
139 | */ | 139 | */ |
140 | unsigned long nr_lock_classes; | 140 | unsigned long nr_lock_classes; |
141 | #ifndef CONFIG_DEBUG_LOCKDEP | ||
142 | static | ||
143 | #endif | ||
141 | struct lock_class lock_classes[MAX_LOCKDEP_KEYS]; | 144 | struct lock_class lock_classes[MAX_LOCKDEP_KEYS]; |
142 | 145 | ||
143 | static inline struct lock_class *hlock_class(struct held_lock *hlock) | 146 | static inline struct lock_class *hlock_class(struct held_lock *hlock) |
@@ -626,7 +629,8 @@ static int static_obj(void *obj) | |||
626 | 629 | ||
627 | /* | 630 | /* |
628 | * To make lock name printouts unique, we calculate a unique | 631 | * To make lock name printouts unique, we calculate a unique |
629 | * class->name_version generation counter: | 632 | * class->name_version generation counter. The caller must hold the graph |
633 | * lock. | ||
630 | */ | 634 | */ |
631 | static int count_matching_names(struct lock_class *new_class) | 635 | static int count_matching_names(struct lock_class *new_class) |
632 | { | 636 | { |
@@ -636,7 +640,7 @@ static int count_matching_names(struct lock_class *new_class) | |||
636 | if (!new_class->name) | 640 | if (!new_class->name) |
637 | return 0; | 641 | return 0; |
638 | 642 | ||
639 | list_for_each_entry_rcu(class, &all_lock_classes, lock_entry) { | 643 | list_for_each_entry(class, &all_lock_classes, lock_entry) { |
640 | if (new_class->key - new_class->subclass == class->key) | 644 | if (new_class->key - new_class->subclass == class->key) |
641 | return class->name_version; | 645 | return class->name_version; |
642 | if (class->name && !strcmp(class->name, new_class->name)) | 646 | if (class->name && !strcmp(class->name, new_class->name)) |
@@ -789,7 +793,6 @@ register_lock_class(struct lockdep_map *lock, unsigned int subclass, int force) | |||
789 | class->key = key; | 793 | class->key = key; |
790 | class->name = lock->name; | 794 | class->name = lock->name; |
791 | class->subclass = subclass; | 795 | class->subclass = subclass; |
792 | INIT_LIST_HEAD(&class->lock_entry); | ||
793 | INIT_LIST_HEAD(&class->locks_before); | 796 | INIT_LIST_HEAD(&class->locks_before); |
794 | INIT_LIST_HEAD(&class->locks_after); | 797 | INIT_LIST_HEAD(&class->locks_after); |
795 | class->name_version = count_matching_names(class); | 798 | class->name_version = count_matching_names(class); |
@@ -801,7 +804,7 @@ register_lock_class(struct lockdep_map *lock, unsigned int subclass, int force) | |||
801 | /* | 804 | /* |
802 | * Add it to the global list of classes: | 805 | * Add it to the global list of classes: |
803 | */ | 806 | */ |
804 | list_add_tail_rcu(&class->lock_entry, &all_lock_classes); | 807 | list_add_tail(&class->lock_entry, &all_lock_classes); |
805 | 808 | ||
806 | if (verbose(class)) { | 809 | if (verbose(class)) { |
807 | graph_unlock(); | 810 | graph_unlock(); |
@@ -3088,7 +3091,7 @@ static int mark_lock(struct task_struct *curr, struct held_lock *this, | |||
3088 | /* | 3091 | /* |
3089 | * Initialize a lock instance's lock-class mapping info: | 3092 | * Initialize a lock instance's lock-class mapping info: |
3090 | */ | 3093 | */ |
3091 | static void __lockdep_init_map(struct lockdep_map *lock, const char *name, | 3094 | void lockdep_init_map(struct lockdep_map *lock, const char *name, |
3092 | struct lock_class_key *key, int subclass) | 3095 | struct lock_class_key *key, int subclass) |
3093 | { | 3096 | { |
3094 | int i; | 3097 | int i; |
@@ -3144,12 +3147,6 @@ static void __lockdep_init_map(struct lockdep_map *lock, const char *name, | |||
3144 | raw_local_irq_restore(flags); | 3147 | raw_local_irq_restore(flags); |
3145 | } | 3148 | } |
3146 | } | 3149 | } |
3147 | |||
3148 | void lockdep_init_map(struct lockdep_map *lock, const char *name, | ||
3149 | struct lock_class_key *key, int subclass) | ||
3150 | { | ||
3151 | __lockdep_init_map(lock, name, key, subclass); | ||
3152 | } | ||
3153 | EXPORT_SYMBOL_GPL(lockdep_init_map); | 3150 | EXPORT_SYMBOL_GPL(lockdep_init_map); |
3154 | 3151 | ||
3155 | struct lock_class_key __lockdep_no_validate__; | 3152 | struct lock_class_key __lockdep_no_validate__; |
@@ -4126,6 +4123,9 @@ void lockdep_reset(void) | |||
4126 | raw_local_irq_restore(flags); | 4123 | raw_local_irq_restore(flags); |
4127 | } | 4124 | } |
4128 | 4125 | ||
4126 | /* | ||
4127 | * Remove all references to a lock class. The caller must hold the graph lock. | ||
4128 | */ | ||
4129 | static void zap_class(struct lock_class *class) | 4129 | static void zap_class(struct lock_class *class) |
4130 | { | 4130 | { |
4131 | int i; | 4131 | int i; |
@@ -4142,7 +4142,7 @@ static void zap_class(struct lock_class *class) | |||
4142 | * Unhash the class and remove it from the all_lock_classes list: | 4142 | * Unhash the class and remove it from the all_lock_classes list: |
4143 | */ | 4143 | */ |
4144 | hlist_del_rcu(&class->hash_entry); | 4144 | hlist_del_rcu(&class->hash_entry); |
4145 | list_del_rcu(&class->lock_entry); | 4145 | list_del(&class->lock_entry); |
4146 | 4146 | ||
4147 | RCU_INIT_POINTER(class->key, NULL); | 4147 | RCU_INIT_POINTER(class->key, NULL); |
4148 | RCU_INIT_POINTER(class->name, NULL); | 4148 | RCU_INIT_POINTER(class->name, NULL); |
@@ -4204,15 +4204,36 @@ void lockdep_free_key_range(void *start, unsigned long size) | |||
4204 | */ | 4204 | */ |
4205 | } | 4205 | } |
4206 | 4206 | ||
4207 | void lockdep_reset_lock(struct lockdep_map *lock) | 4207 | /* |
4208 | * Check whether any element of the @lock->class_cache[] array refers to a | ||
4209 | * registered lock class. The caller must hold either the graph lock or the | ||
4210 | * RCU read lock. | ||
4211 | */ | ||
4212 | static bool lock_class_cache_is_registered(struct lockdep_map *lock) | ||
4208 | { | 4213 | { |
4209 | struct lock_class *class; | 4214 | struct lock_class *class; |
4210 | struct hlist_head *head; | 4215 | struct hlist_head *head; |
4211 | unsigned long flags; | ||
4212 | int i, j; | 4216 | int i, j; |
4213 | int locked; | 4217 | |
4218 | for (i = 0; i < CLASSHASH_SIZE; i++) { | ||
4219 | head = classhash_table + i; | ||
4220 | hlist_for_each_entry_rcu(class, head, hash_entry) { | ||
4221 | for (j = 0; j < NR_LOCKDEP_CACHING_CLASSES; j++) | ||
4222 | if (lock->class_cache[j] == class) | ||
4223 | return true; | ||
4224 | } | ||
4225 | } | ||
4226 | return false; | ||
4227 | } | ||
4228 | |||
4229 | void lockdep_reset_lock(struct lockdep_map *lock) | ||
4230 | { | ||
4231 | struct lock_class *class; | ||
4232 | unsigned long flags; | ||
4233 | int j, locked; | ||
4214 | 4234 | ||
4215 | raw_local_irq_save(flags); | 4235 | raw_local_irq_save(flags); |
4236 | locked = graph_lock(); | ||
4216 | 4237 | ||
4217 | /* | 4238 | /* |
4218 | * Remove all classes this lock might have: | 4239 | * Remove all classes this lock might have: |
@@ -4229,25 +4250,14 @@ void lockdep_reset_lock(struct lockdep_map *lock) | |||
4229 | * Debug check: in the end all mapped classes should | 4250 | * Debug check: in the end all mapped classes should |
4230 | * be gone. | 4251 | * be gone. |
4231 | */ | 4252 | */ |
4232 | locked = graph_lock(); | 4253 | if (unlikely(lock_class_cache_is_registered(lock))) { |
4233 | for (i = 0; i < CLASSHASH_SIZE; i++) { | 4254 | if (debug_locks_off_graph_unlock()) { |
4234 | head = classhash_table + i; | 4255 | /* |
4235 | hlist_for_each_entry_rcu(class, head, hash_entry) { | 4256 | * We all just reset everything, how did it match? |
4236 | int match = 0; | 4257 | */ |
4237 | 4258 | WARN_ON(1); | |
4238 | for (j = 0; j < NR_LOCKDEP_CACHING_CLASSES; j++) | ||
4239 | match |= class == lock->class_cache[j]; | ||
4240 | |||
4241 | if (unlikely(match)) { | ||
4242 | if (debug_locks_off_graph_unlock()) { | ||
4243 | /* | ||
4244 | * We all just reset everything, how did it match? | ||
4245 | */ | ||
4246 | WARN_ON(1); | ||
4247 | } | ||
4248 | goto out_restore; | ||
4249 | } | ||
4250 | } | 4259 | } |
4260 | goto out_restore; | ||
4251 | } | 4261 | } |
4252 | if (locked) | 4262 | if (locked) |
4253 | graph_unlock(); | 4263 | graph_unlock(); |