Merge branch 'locking-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
authorLinus Torvalds <torvalds@linux-foundation.org>
Sun, 14 Feb 2016 20:02:05 +0000 (12:02 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sun, 14 Feb 2016 20:02:05 +0000 (12:02 -0800)
Pull lockdep fix from Thomas Gleixner:
 "A single fix for the stack trace caching logic in lockdep, where the
  duplicate avoidance managed to store no back trace at all"

* 'locking-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  locking/lockdep: Fix stack trace caching logic

1  2 
kernel/locking/lockdep.c

diff --combined kernel/locking/lockdep.c
@@@ -292,7 -292,7 +292,7 @@@ LIST_HEAD(all_lock_classes)
  #define __classhashfn(key)    hash_long((unsigned long)key, CLASSHASH_BITS)
  #define classhashentry(key)   (classhash_table + __classhashfn((key)))
  
 -static struct list_head classhash_table[CLASSHASH_SIZE];
 +static struct hlist_head classhash_table[CLASSHASH_SIZE];
  
  /*
   * We put the lock dependency chains into a hash-table as well, to cache
  #define __chainhashfn(chain)  hash_long(chain, CHAINHASH_BITS)
  #define chainhashentry(chain) (chainhash_table + __chainhashfn((chain)))
  
 -static struct list_head chainhash_table[CHAINHASH_SIZE];
 +static struct hlist_head chainhash_table[CHAINHASH_SIZE];
  
  /*
   * The hash key of the lock dependency chains is a hash itself too:
@@@ -666,7 -666,7 +666,7 @@@ static inline struct lock_class 
  look_up_lock_class(struct lockdep_map *lock, unsigned int subclass)
  {
        struct lockdep_subclass_key *key;
 -      struct list_head *hash_head;
 +      struct hlist_head *hash_head;
        struct lock_class *class;
  
  #ifdef CONFIG_DEBUG_LOCKDEP
        if (DEBUG_LOCKS_WARN_ON(!irqs_disabled()))
                return NULL;
  
 -      list_for_each_entry_rcu(class, hash_head, hash_entry) {
 +      hlist_for_each_entry_rcu(class, hash_head, hash_entry) {
                if (class->key == key) {
                        /*
                         * Huh! same key, different name? Did someone trample
@@@ -742,7 -742,7 +742,7 @@@ static inline struct lock_class 
  register_lock_class(struct lockdep_map *lock, unsigned int subclass, int force)
  {
        struct lockdep_subclass_key *key;
 -      struct list_head *hash_head;
 +      struct hlist_head *hash_head;
        struct lock_class *class;
  
        DEBUG_LOCKS_WARN_ON(!irqs_disabled());
         * We have to do the hash-walk again, to avoid races
         * with another CPU:
         */
 -      list_for_each_entry_rcu(class, hash_head, hash_entry) {
 +      hlist_for_each_entry_rcu(class, hash_head, hash_entry) {
                if (class->key == key)
                        goto out_unlock_set;
        }
         * We use RCU's safe list-add method to make
         * parallel walking of the hash-list safe:
         */
 -      list_add_tail_rcu(&class->hash_entry, hash_head);
 +      hlist_add_head_rcu(&class->hash_entry, hash_head);
        /*
         * Add it to the global list of classes:
         */
@@@ -1822,7 -1822,7 +1822,7 @@@ check_deadlock(struct task_struct *curr
   */
  static int
  check_prev_add(struct task_struct *curr, struct held_lock *prev,
-              struct held_lock *next, int distance, int trylock_loop)
+              struct held_lock *next, int distance, int *stack_saved)
  {
        struct lock_list *entry;
        int ret;
                }
        }
  
-       if (!trylock_loop && !save_trace(&trace))
-               return 0;
+       if (!*stack_saved) {
+               if (!save_trace(&trace))
+                       return 0;
+               *stack_saved = 1;
+       }
  
        /*
         * Ok, all validations passed, add the new lock
         * Debugging printouts:
         */
        if (verbose(hlock_class(prev)) || verbose(hlock_class(next))) {
+               /* We drop graph lock, so another thread can overwrite trace. */
+               *stack_saved = 0;
                graph_unlock();
                printk("\n new dependency: ");
                print_lock_name(hlock_class(prev));
@@@ -1929,7 -1934,7 +1934,7 @@@ static in
  check_prevs_add(struct task_struct *curr, struct held_lock *next)
  {
        int depth = curr->lockdep_depth;
-       int trylock_loop = 0;
+       int stack_saved = 0;
        struct held_lock *hlock;
  
        /*
                 */
                if (hlock->read != 2 && hlock->check) {
                        if (!check_prev_add(curr, hlock, next,
-                                               distance, trylock_loop))
+                                               distance, &stack_saved))
                                return 0;
                        /*
                         * Stop after the first non-trylock entry,
                if (curr->held_locks[depth].irq_context !=
                                curr->held_locks[depth-1].irq_context)
                        break;
-               trylock_loop = 1;
        }
        return 1;
  out_bug:
@@@ -2017,7 -2021,7 +2021,7 @@@ static inline int lookup_chain_cache(st
                                     u64 chain_key)
  {
        struct lock_class *class = hlock_class(hlock);
 -      struct list_head *hash_head = chainhashentry(chain_key);
 +      struct hlist_head *hash_head = chainhashentry(chain_key);
        struct lock_chain *chain;
        struct held_lock *hlock_curr;
        int i, j;
         * We can walk it lock-free, because entries only get added
         * to the hash:
         */
 -      list_for_each_entry_rcu(chain, hash_head, entry) {
 +      hlist_for_each_entry_rcu(chain, hash_head, entry) {
                if (chain->chain_key == chain_key) {
  cache_hit:
                        debug_atomic_inc(chain_lookup_hits);
        /*
         * We have to walk the chain again locked - to avoid duplicates:
         */
 -      list_for_each_entry(chain, hash_head, entry) {
 +      hlist_for_each_entry(chain, hash_head, entry) {
                if (chain->chain_key == chain_key) {
                        graph_unlock();
                        goto cache_hit;
                }
                chain_hlocks[chain->base + j] = class - lock_classes;
        }
 -      list_add_tail_rcu(&chain->entry, hash_head);
 +      hlist_add_head_rcu(&chain->entry, hash_head);
        debug_atomic_inc(chain_lookup_misses);
        inc_chains();
  
@@@ -3875,7 -3879,7 +3879,7 @@@ void lockdep_reset(void
        nr_process_chains = 0;
        debug_locks = 1;
        for (i = 0; i < CHAINHASH_SIZE; i++)
 -              INIT_LIST_HEAD(chainhash_table + i);
 +              INIT_HLIST_HEAD(chainhash_table + i);
        raw_local_irq_restore(flags);
  }
  
@@@ -3894,7 -3898,7 +3898,7 @@@ static void zap_class(struct lock_clas
        /*
         * Unhash the class and remove it from the all_lock_classes list:
         */
 -      list_del_rcu(&class->hash_entry);
 +      hlist_del_rcu(&class->hash_entry);
        list_del_rcu(&class->lock_entry);
  
        RCU_INIT_POINTER(class->key, NULL);
@@@ -3917,7 -3921,7 +3921,7 @@@ static inline int within(const void *ad
  void lockdep_free_key_range(void *start, unsigned long size)
  {
        struct lock_class *class;
 -      struct list_head *head;
 +      struct hlist_head *head;
        unsigned long flags;
        int i;
        int locked;
         */
        for (i = 0; i < CLASSHASH_SIZE; i++) {
                head = classhash_table + i;
 -              if (list_empty(head))
 -                      continue;
 -              list_for_each_entry_rcu(class, head, hash_entry) {
 +              hlist_for_each_entry_rcu(class, head, hash_entry) {
                        if (within(class->key, start, size))
                                zap_class(class);
                        else if (within(class->name, start, size))
  void lockdep_reset_lock(struct lockdep_map *lock)
  {
        struct lock_class *class;
 -      struct list_head *head;
 +      struct hlist_head *head;
        unsigned long flags;
        int i, j;
        int locked;
        locked = graph_lock();
        for (i = 0; i < CLASSHASH_SIZE; i++) {
                head = classhash_table + i;
 -              if (list_empty(head))
 -                      continue;
 -              list_for_each_entry_rcu(class, head, hash_entry) {
 +              hlist_for_each_entry_rcu(class, head, hash_entry) {
                        int match = 0;
  
                        for (j = 0; j < NR_LOCKDEP_CACHING_CLASSES; j++)
@@@ -4023,10 -4031,10 +4027,10 @@@ void lockdep_init(void
                return;
  
        for (i = 0; i < CLASSHASH_SIZE; i++)
 -              INIT_LIST_HEAD(classhash_table + i);
 +              INIT_HLIST_HEAD(classhash_table + i);
  
        for (i = 0; i < CHAINHASH_SIZE; i++)
 -              INIT_LIST_HEAD(chainhash_table + i);
 +              INIT_HLIST_HEAD(chainhash_table + i);
  
        lockdep_initialized = 1;
  }