History

Merge branch 'locking-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull locking fixes from Ingo Molnar: "Two lockdep fixes" * 'locking-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: lockdep: Fix lock_chain::base size locking/lockdep: Fix ->irq_context calculation

Linus Torvalds committed 10 years ago

Commit 2113cae2 parents 8f3603a 75dd6023 files · +41 −6Browse files

Unified · Split

3 files
  1. include/linux/lockdep.h +5 −3
  2. kernel/locking/lockdep.c +34 −3
  3. kernel/locking/lockdep_proc.c +2 −0
include/linux/lockdep.h+5−3
@@ -196,9 +196,11 @@ struct lock_list { · 195 unmodified lines
196196 * We record lock dependency chains, so that we can cache them:
197197 */
198198 struct lock_chain {
199− u8 irq_context;
200− u8 depth;
201− u16 base;
199+ /* see BUILD_BUG_ON()s in lookup_chain_cache() */
200+ unsigned int irq_context : 2,
201+ depth : 6,
202+ base : 24;
203+ /* 4 byte hole */
202204 struct hlist_node entry;
203205 u64 chain_key;
204206 };
kernel/locking/lockdep.c+34−3
@@ -2176,15 +2176,37 @@ cache_hit: · 2175 unmodified lines
21762176 chain->irq_context = hlock->irq_context;
21772177 i = get_first_held_lock(curr, hlock);
21782178 chain->depth = curr->lockdep_depth + 1 - i;
2179+
2180+ BUILD_BUG_ON((1UL << 24) <= ARRAY_SIZE(chain_hlocks));
2181+ BUILD_BUG_ON((1UL << 6) <= ARRAY_SIZE(curr->held_locks));
2182+ BUILD_BUG_ON((1UL << 8*sizeof(chain_hlocks[0])) <= ARRAY_SIZE(lock_classes));
2183+
21792184 if (likely(nr_chain_hlocks + chain->depth <= MAX_LOCKDEP_CHAIN_HLOCKS)) {
21802185 chain->base = nr_chain_hlocks;
2181− nr_chain_hlocks += chain->depth;
21822186 for (j = 0; j < chain->depth - 1; j++, i++) {
21832187 int lock_id = curr->held_locks[i].class_idx - 1;
21842188 chain_hlocks[chain->base + j] = lock_id;
21852189 }
21862190 chain_hlocks[chain->base + j] = class - lock_classes;
21872191 }
2192+
2193+ if (nr_chain_hlocks < MAX_LOCKDEP_CHAIN_HLOCKS)
2194+ nr_chain_hlocks += chain->depth;
2195+
2196+#ifdef CONFIG_DEBUG_LOCKDEP
2197+ /*
2198+ * Important for check_no_collision().
2199+ */
2200+ if (unlikely(nr_chain_hlocks > MAX_LOCKDEP_CHAIN_HLOCKS)) {
2201+ if (debug_locks_off_graph_unlock())
2202+ return 0;
2203+
2204+ print_lockdep_off("BUG: MAX_LOCKDEP_CHAIN_HLOCKS too low!");
2205+ dump_stack();
2206+ return 0;
2207+ }
2208+#endif
2209+
21882210 hlist_add_head_rcu(&chain->entry, hash_head);
21892211 debug_atomic_inc(chain_lookup_misses);
21902212 inc_chains();
@@ -2932,6 +2954,11 @@ static int mark_irqflags(struct task_struct *curr, struct held_lock *hlock) · 741 unmodified lines
29322954 return 1;
29332955 }
29342956
2957+static inline unsigned int task_irq_context(struct task_struct *task)
2958+{
2959+ return 2 * !!task->hardirq_context + !!task->softirq_context;
2960+}
2961+
29352962 static int separate_irq_context(struct task_struct *curr,
29362963 struct held_lock *hlock)
29372964 {
@@ -2940,8 +2967,6 @@ static int separate_irq_context(struct task_struct *curr, · 2 unmodified lines
29402967 /*
29412968 * Keep track of points where we cross into an interrupt context:
29422969 */
2943− hlock->irq_context = 2*(curr->hardirq_context ? 1 : 0) +
2944− curr->softirq_context;
29452970 if (depth) {
29462971 struct held_lock *prev_hlock;
29472972
@@ -2973,6 +2998,11 @@ static inline int mark_irqflags(struct task_struct *curr, · 25 unmodified lines
29732998 return 1;
29742999 }
29753000
3001+static inline unsigned int task_irq_context(struct task_struct *task)
3002+{
3003+ return 0;
3004+}
3005+
29763006 static inline int separate_irq_context(struct task_struct *curr,
29773007 struct held_lock *hlock)
29783008 {
@@ -3241,6 +3271,7 @@ static int __lock_acquire(struct lockdep_map *lock, unsigned int subclass, · 262 unmodified lines
32413271 hlock->acquire_ip = ip;
32423272 hlock->instance = lock;
32433273 hlock->nest_lock = nest_lock;
3274+ hlock->irq_context = task_irq_context(curr);
32443275 hlock->trylock = trylock;
32453276 hlock->read = read;
32463277 hlock->check = check;
kernel/locking/lockdep_proc.c+2−0
@@ -141,6 +141,8 @@ static int lc_show(struct seq_file *m, void *v) · 140 unmodified lines
141141 int i;
142142
143143 if (v == SEQ_START_TOKEN) {
144+ if (nr_chain_hlocks > MAX_LOCKDEP_CHAIN_HLOCKS)
145+ seq_printf(m, "(buggered) ");
144146 seq_printf(m, "all lock chains:\n");
145147 return 0;
146148 }