diff options
Diffstat (limited to 'kernel/locking/lockdep.c')
-rw-r--r-- | kernel/locking/lockdep.c | 79 |
1 files changed, 77 insertions, 2 deletions
diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c index 53ab2f85d77e..2324ba5310db 100644 --- a/kernel/locking/lockdep.c +++ b/kernel/locking/lockdep.c | |||
@@ -2000,6 +2000,77 @@ static inline int get_first_held_lock(struct task_struct *curr, | |||
2000 | } | 2000 | } |
2001 | 2001 | ||
2002 | /* | 2002 | /* |
2003 | * Returns the next chain_key iteration | ||
2004 | */ | ||
2005 | static u64 print_chain_key_iteration(int class_idx, u64 chain_key) | ||
2006 | { | ||
2007 | u64 new_chain_key = iterate_chain_key(chain_key, class_idx); | ||
2008 | |||
2009 | printk(" class_idx:%d -> chain_key:%016Lx", | ||
2010 | class_idx, | ||
2011 | (unsigned long long)new_chain_key); | ||
2012 | return new_chain_key; | ||
2013 | } | ||
2014 | |||
2015 | static void | ||
2016 | print_chain_keys_held_locks(struct task_struct *curr, struct held_lock *hlock_next) | ||
2017 | { | ||
2018 | struct held_lock *hlock; | ||
2019 | u64 chain_key = 0; | ||
2020 | int depth = curr->lockdep_depth; | ||
2021 | int i; | ||
2022 | |||
2023 | printk("depth: %u\n", depth + 1); | ||
2024 | for (i = get_first_held_lock(curr, hlock_next); i < depth; i++) { | ||
2025 | hlock = curr->held_locks + i; | ||
2026 | chain_key = print_chain_key_iteration(hlock->class_idx, chain_key); | ||
2027 | |||
2028 | print_lock(hlock); | ||
2029 | } | ||
2030 | |||
2031 | print_chain_key_iteration(hlock_next->class_idx, chain_key); | ||
2032 | print_lock(hlock_next); | ||
2033 | } | ||
2034 | |||
2035 | static void print_chain_keys_chain(struct lock_chain *chain) | ||
2036 | { | ||
2037 | int i; | ||
2038 | u64 chain_key = 0; | ||
2039 | int class_id; | ||
2040 | |||
2041 | printk("depth: %u\n", chain->depth); | ||
2042 | for (i = 0; i < chain->depth; i++) { | ||
2043 | class_id = chain_hlocks[chain->base + i]; | ||
2044 | chain_key = print_chain_key_iteration(class_id + 1, chain_key); | ||
2045 | |||
2046 | print_lock_name(lock_classes + class_id); | ||
2047 | printk("\n"); | ||
2048 | } | ||
2049 | } | ||
2050 | |||
2051 | static void print_collision(struct task_struct *curr, | ||
2052 | struct held_lock *hlock_next, | ||
2053 | struct lock_chain *chain) | ||
2054 | { | ||
2055 | printk("\n"); | ||
2056 | printk("======================\n"); | ||
2057 | printk("[chain_key collision ]\n"); | ||
2058 | print_kernel_ident(); | ||
2059 | printk("----------------------\n"); | ||
2060 | printk("%s/%d: ", current->comm, task_pid_nr(current)); | ||
2061 | printk("Hash chain already cached but the contents don't match!\n"); | ||
2062 | |||
2063 | printk("Held locks:"); | ||
2064 | print_chain_keys_held_locks(curr, hlock_next); | ||
2065 | |||
2066 | printk("Locks in cached chain:"); | ||
2067 | print_chain_keys_chain(chain); | ||
2068 | |||
2069 | printk("\nstack backtrace:\n"); | ||
2070 | dump_stack(); | ||
2071 | } | ||
2072 | |||
2073 | /* | ||
2003 | * Checks whether the chain and the current held locks are consistent | 2074 | * Checks whether the chain and the current held locks are consistent |
2004 | * in depth and also in content. If they are not it most likely means | 2075 | * in depth and also in content. If they are not it most likely means |
2005 | * that there was a collision during the calculation of the chain_key. | 2076 | * that there was a collision during the calculation of the chain_key. |
@@ -2014,14 +2085,18 @@ static int check_no_collision(struct task_struct *curr, | |||
2014 | 2085 | ||
2015 | i = get_first_held_lock(curr, hlock); | 2086 | i = get_first_held_lock(curr, hlock); |
2016 | 2087 | ||
2017 | if (DEBUG_LOCKS_WARN_ON(chain->depth != curr->lockdep_depth - (i - 1))) | 2088 | if (DEBUG_LOCKS_WARN_ON(chain->depth != curr->lockdep_depth - (i - 1))) { |
2089 | print_collision(curr, hlock, chain); | ||
2018 | return 0; | 2090 | return 0; |
2091 | } | ||
2019 | 2092 | ||
2020 | for (j = 0; j < chain->depth - 1; j++, i++) { | 2093 | for (j = 0; j < chain->depth - 1; j++, i++) { |
2021 | id = curr->held_locks[i].class_idx - 1; | 2094 | id = curr->held_locks[i].class_idx - 1; |
2022 | 2095 | ||
2023 | if (DEBUG_LOCKS_WARN_ON(chain_hlocks[chain->base + j] != id)) | 2096 | if (DEBUG_LOCKS_WARN_ON(chain_hlocks[chain->base + j] != id)) { |
2097 | print_collision(curr, hlock, chain); | ||
2024 | return 0; | 2098 | return 0; |
2099 | } | ||
2025 | } | 2100 | } |
2026 | #endif | 2101 | #endif |
2027 | return 1; | 2102 | return 1; |