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(); |
