diff options
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/lockdep.c | 70 |
1 files changed, 70 insertions, 0 deletions
diff --git a/kernel/lockdep.c b/kernel/lockdep.c index 53a68956f131..7b2ffeedcebd 100644 --- a/kernel/lockdep.c +++ b/kernel/lockdep.c | |||
| @@ -490,6 +490,18 @@ void get_usage_chars(struct lock_class *class, char usage[LOCK_USAGE_CHARS]) | |||
| 490 | usage[i] = '\0'; | 490 | usage[i] = '\0'; |
| 491 | } | 491 | } |
| 492 | 492 | ||
| 493 | static int __print_lock_name(struct lock_class *class) | ||
| 494 | { | ||
| 495 | char str[KSYM_NAME_LEN]; | ||
| 496 | const char *name; | ||
| 497 | |||
| 498 | name = class->name; | ||
| 499 | if (!name) | ||
| 500 | name = __get_key_name(class->key, str); | ||
| 501 | |||
| 502 | return printk("%s", name); | ||
| 503 | } | ||
| 504 | |||
| 493 | static void print_lock_name(struct lock_class *class) | 505 | static void print_lock_name(struct lock_class *class) |
| 494 | { | 506 | { |
| 495 | char str[KSYM_NAME_LEN], usage[LOCK_USAGE_CHARS]; | 507 | char str[KSYM_NAME_LEN], usage[LOCK_USAGE_CHARS]; |
| @@ -1325,6 +1337,62 @@ print_shortest_lock_dependencies(struct lock_list *leaf, | |||
| 1325 | return; | 1337 | return; |
| 1326 | } | 1338 | } |
| 1327 | 1339 | ||
| 1340 | static void | ||
| 1341 | print_irq_lock_scenario(struct lock_list *safe_entry, | ||
| 1342 | struct lock_list *unsafe_entry, | ||
| 1343 | struct held_lock *prev, | ||
| 1344 | struct held_lock *next) | ||
| 1345 | { | ||
| 1346 | struct lock_class *safe_class = safe_entry->class; | ||
| 1347 | struct lock_class *unsafe_class = unsafe_entry->class; | ||
| 1348 | struct lock_class *middle_class = hlock_class(prev); | ||
| 1349 | |||
| 1350 | if (middle_class == safe_class) | ||
| 1351 | middle_class = hlock_class(next); | ||
| 1352 | |||
| 1353 | /* | ||
| 1354 | * A direct locking problem where unsafe_class lock is taken | ||
| 1355 | * directly by safe_class lock, then all we need to show | ||
| 1356 | * is the deadlock scenario, as it is obvious that the | ||
| 1357 | * unsafe lock is taken under the safe lock. | ||
| 1358 | * | ||
| 1359 | * But if there is a chain instead, where the safe lock takes | ||
| 1360 | * an intermediate lock (middle_class) where this lock is | ||
| 1361 | * not the same as the safe lock, then the lock chain is | ||
| 1362 | * used to describe the problem. Otherwise we would need | ||
| 1363 | * to show a different CPU case for each link in the chain | ||
| 1364 | * from the safe_class lock to the unsafe_class lock. | ||
| 1365 | */ | ||
| 1366 | if (middle_class != unsafe_class) { | ||
| 1367 | printk("Chain exists of:\n "); | ||
| 1368 | __print_lock_name(safe_class); | ||
| 1369 | printk(" --> "); | ||
| 1370 | __print_lock_name(middle_class); | ||
| 1371 | printk(" --> "); | ||
| 1372 | __print_lock_name(unsafe_class); | ||
| 1373 | printk("\n\n"); | ||
| 1374 | } | ||
| 1375 | |||
| 1376 | printk(" Possible interrupt unsafe locking scenario:\n\n"); | ||
| 1377 | printk(" CPU0 CPU1\n"); | ||
| 1378 | printk(" ---- ----\n"); | ||
| 1379 | printk(" lock("); | ||
| 1380 | __print_lock_name(unsafe_class); | ||
| 1381 | printk(");\n"); | ||
| 1382 | printk(" local_irq_disable();\n"); | ||
| 1383 | printk(" lock("); | ||
| 1384 | __print_lock_name(safe_class); | ||
| 1385 | printk(");\n"); | ||
| 1386 | printk(" lock("); | ||
| 1387 | __print_lock_name(middle_class); | ||
| 1388 | printk(");\n"); | ||
| 1389 | printk(" <Interrupt>\n"); | ||
| 1390 | printk(" lock("); | ||
| 1391 | __print_lock_name(safe_class); | ||
| 1392 | printk(");\n"); | ||
| 1393 | printk("\n *** DEADLOCK ***\n\n"); | ||
| 1394 | } | ||
| 1395 | |||
| 1328 | static int | 1396 | static int |
| 1329 | print_bad_irq_dependency(struct task_struct *curr, | 1397 | print_bad_irq_dependency(struct task_struct *curr, |
| 1330 | struct lock_list *prev_root, | 1398 | struct lock_list *prev_root, |
| @@ -1376,6 +1444,8 @@ print_bad_irq_dependency(struct task_struct *curr, | |||
| 1376 | print_stack_trace(forwards_entry->class->usage_traces + bit2, 1); | 1444 | print_stack_trace(forwards_entry->class->usage_traces + bit2, 1); |
| 1377 | 1445 | ||
| 1378 | printk("\nother info that might help us debug this:\n\n"); | 1446 | printk("\nother info that might help us debug this:\n\n"); |
| 1447 | print_irq_lock_scenario(backwards_entry, forwards_entry, prev, next); | ||
| 1448 | |||
| 1379 | lockdep_print_held_locks(curr); | 1449 | lockdep_print_held_locks(curr); |
| 1380 | 1450 | ||
| 1381 | printk("\nthe dependencies between %s-irq-safe lock", irqclass); | 1451 | printk("\nthe dependencies between %s-irq-safe lock", irqclass); |
