diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-07-22 19:43:49 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-07-22 19:43:49 -0400 |
| commit | 391d6276db9fbdedfbc30e1b56390414f0e55988 (patch) | |
| tree | d22cd2482f5452d616ee981e954074ffc6ae094d /kernel | |
| parent | 75b56ec294b074d70f8a676ab02611a3fea76cab (diff) | |
| parent | dd4e5d3ac4a76b868daf30e35bd572def96c30ed (diff) | |
Merge branch 'core-printk-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
* 'core-printk-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
lockdep: Fix trace_[soft,hard]irqs_[on,off]() recursion
printk: Fix console_sem vs logbuf_lock unlock race
printk: Release console_sem after logbuf_lock
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/lockdep.c | 30 | ||||
| -rw-r--r-- | kernel/printk.c | 24 |
2 files changed, 41 insertions, 13 deletions
diff --git a/kernel/lockdep.c b/kernel/lockdep.c index 628276d05915..3956f5149e25 100644 --- a/kernel/lockdep.c +++ b/kernel/lockdep.c | |||
| @@ -2481,15 +2481,10 @@ mark_held_locks(struct task_struct *curr, enum mark_type mark) | |||
| 2481 | /* | 2481 | /* |
| 2482 | * Hardirqs will be enabled: | 2482 | * Hardirqs will be enabled: |
| 2483 | */ | 2483 | */ |
| 2484 | void trace_hardirqs_on_caller(unsigned long ip) | 2484 | static void __trace_hardirqs_on_caller(unsigned long ip) |
| 2485 | { | 2485 | { |
| 2486 | struct task_struct *curr = current; | 2486 | struct task_struct *curr = current; |
| 2487 | 2487 | ||
| 2488 | time_hardirqs_on(CALLER_ADDR0, ip); | ||
| 2489 | |||
| 2490 | if (unlikely(!debug_locks || current->lockdep_recursion)) | ||
| 2491 | return; | ||
| 2492 | |||
| 2493 | if (DEBUG_LOCKS_WARN_ON(unlikely(early_boot_irqs_disabled))) | 2488 | if (DEBUG_LOCKS_WARN_ON(unlikely(early_boot_irqs_disabled))) |
| 2494 | return; | 2489 | return; |
| 2495 | 2490 | ||
| @@ -2505,8 +2500,6 @@ void trace_hardirqs_on_caller(unsigned long ip) | |||
| 2505 | /* we'll do an OFF -> ON transition: */ | 2500 | /* we'll do an OFF -> ON transition: */ |
| 2506 | curr->hardirqs_enabled = 1; | 2501 | curr->hardirqs_enabled = 1; |
| 2507 | 2502 | ||
| 2508 | if (DEBUG_LOCKS_WARN_ON(!irqs_disabled())) | ||
| 2509 | return; | ||
| 2510 | if (DEBUG_LOCKS_WARN_ON(current->hardirq_context)) | 2503 | if (DEBUG_LOCKS_WARN_ON(current->hardirq_context)) |
| 2511 | return; | 2504 | return; |
| 2512 | /* | 2505 | /* |
| @@ -2528,6 +2521,21 @@ void trace_hardirqs_on_caller(unsigned long ip) | |||
| 2528 | curr->hardirq_enable_event = ++curr->irq_events; | 2521 | curr->hardirq_enable_event = ++curr->irq_events; |
| 2529 | debug_atomic_inc(hardirqs_on_events); | 2522 | debug_atomic_inc(hardirqs_on_events); |
| 2530 | } | 2523 | } |
| 2524 | |||
| 2525 | void trace_hardirqs_on_caller(unsigned long ip) | ||
| 2526 | { | ||
| 2527 | time_hardirqs_on(CALLER_ADDR0, ip); | ||
| 2528 | |||
| 2529 | if (unlikely(!debug_locks || current->lockdep_recursion)) | ||
| 2530 | return; | ||
| 2531 | |||
| 2532 | if (DEBUG_LOCKS_WARN_ON(!irqs_disabled())) | ||
| 2533 | return; | ||
| 2534 | |||
| 2535 | current->lockdep_recursion = 1; | ||
| 2536 | __trace_hardirqs_on_caller(ip); | ||
| 2537 | current->lockdep_recursion = 0; | ||
| 2538 | } | ||
| 2531 | EXPORT_SYMBOL(trace_hardirqs_on_caller); | 2539 | EXPORT_SYMBOL(trace_hardirqs_on_caller); |
| 2532 | 2540 | ||
| 2533 | void trace_hardirqs_on(void) | 2541 | void trace_hardirqs_on(void) |
| @@ -2577,7 +2585,7 @@ void trace_softirqs_on(unsigned long ip) | |||
| 2577 | { | 2585 | { |
| 2578 | struct task_struct *curr = current; | 2586 | struct task_struct *curr = current; |
| 2579 | 2587 | ||
| 2580 | if (unlikely(!debug_locks)) | 2588 | if (unlikely(!debug_locks || current->lockdep_recursion)) |
| 2581 | return; | 2589 | return; |
| 2582 | 2590 | ||
| 2583 | if (DEBUG_LOCKS_WARN_ON(!irqs_disabled())) | 2591 | if (DEBUG_LOCKS_WARN_ON(!irqs_disabled())) |
| @@ -2588,6 +2596,7 @@ void trace_softirqs_on(unsigned long ip) | |||
| 2588 | return; | 2596 | return; |
| 2589 | } | 2597 | } |
| 2590 | 2598 | ||
| 2599 | current->lockdep_recursion = 1; | ||
| 2591 | /* | 2600 | /* |
| 2592 | * We'll do an OFF -> ON transition: | 2601 | * We'll do an OFF -> ON transition: |
| 2593 | */ | 2602 | */ |
| @@ -2602,6 +2611,7 @@ void trace_softirqs_on(unsigned long ip) | |||
| 2602 | */ | 2611 | */ |
| 2603 | if (curr->hardirqs_enabled) | 2612 | if (curr->hardirqs_enabled) |
| 2604 | mark_held_locks(curr, SOFTIRQ); | 2613 | mark_held_locks(curr, SOFTIRQ); |
| 2614 | current->lockdep_recursion = 0; | ||
| 2605 | } | 2615 | } |
| 2606 | 2616 | ||
| 2607 | /* | 2617 | /* |
| @@ -2611,7 +2621,7 @@ void trace_softirqs_off(unsigned long ip) | |||
| 2611 | { | 2621 | { |
| 2612 | struct task_struct *curr = current; | 2622 | struct task_struct *curr = current; |
| 2613 | 2623 | ||
| 2614 | if (unlikely(!debug_locks)) | 2624 | if (unlikely(!debug_locks || current->lockdep_recursion)) |
| 2615 | return; | 2625 | return; |
| 2616 | 2626 | ||
| 2617 | if (DEBUG_LOCKS_WARN_ON(!irqs_disabled())) | 2627 | if (DEBUG_LOCKS_WARN_ON(!irqs_disabled())) |
diff --git a/kernel/printk.c b/kernel/printk.c index 35185392173f..37dff3429adb 100644 --- a/kernel/printk.c +++ b/kernel/printk.c | |||
| @@ -782,7 +782,7 @@ static inline int can_use_console(unsigned int cpu) | |||
| 782 | static int console_trylock_for_printk(unsigned int cpu) | 782 | static int console_trylock_for_printk(unsigned int cpu) |
| 783 | __releases(&logbuf_lock) | 783 | __releases(&logbuf_lock) |
| 784 | { | 784 | { |
| 785 | int retval = 0; | 785 | int retval = 0, wake = 0; |
| 786 | 786 | ||
| 787 | if (console_trylock()) { | 787 | if (console_trylock()) { |
| 788 | retval = 1; | 788 | retval = 1; |
| @@ -795,12 +795,14 @@ static int console_trylock_for_printk(unsigned int cpu) | |||
| 795 | */ | 795 | */ |
| 796 | if (!can_use_console(cpu)) { | 796 | if (!can_use_console(cpu)) { |
| 797 | console_locked = 0; | 797 | console_locked = 0; |
| 798 | up(&console_sem); | 798 | wake = 1; |
| 799 | retval = 0; | 799 | retval = 0; |
| 800 | } | 800 | } |
| 801 | } | 801 | } |
| 802 | printk_cpu = UINT_MAX; | 802 | printk_cpu = UINT_MAX; |
| 803 | spin_unlock(&logbuf_lock); | 803 | spin_unlock(&logbuf_lock); |
| 804 | if (wake) | ||
| 805 | up(&console_sem); | ||
| 804 | return retval; | 806 | return retval; |
| 805 | } | 807 | } |
| 806 | static const char recursion_bug_msg [] = | 808 | static const char recursion_bug_msg [] = |
| @@ -1242,7 +1244,7 @@ void console_unlock(void) | |||
| 1242 | { | 1244 | { |
| 1243 | unsigned long flags; | 1245 | unsigned long flags; |
| 1244 | unsigned _con_start, _log_end; | 1246 | unsigned _con_start, _log_end; |
| 1245 | unsigned wake_klogd = 0; | 1247 | unsigned wake_klogd = 0, retry = 0; |
| 1246 | 1248 | ||
| 1247 | if (console_suspended) { | 1249 | if (console_suspended) { |
| 1248 | up(&console_sem); | 1250 | up(&console_sem); |
| @@ -1251,6 +1253,7 @@ void console_unlock(void) | |||
| 1251 | 1253 | ||
| 1252 | console_may_schedule = 0; | 1254 | console_may_schedule = 0; |
| 1253 | 1255 | ||
| 1256 | again: | ||
| 1254 | for ( ; ; ) { | 1257 | for ( ; ; ) { |
| 1255 | spin_lock_irqsave(&logbuf_lock, flags); | 1258 | spin_lock_irqsave(&logbuf_lock, flags); |
| 1256 | wake_klogd |= log_start - log_end; | 1259 | wake_klogd |= log_start - log_end; |
| @@ -1271,8 +1274,23 @@ void console_unlock(void) | |||
| 1271 | if (unlikely(exclusive_console)) | 1274 | if (unlikely(exclusive_console)) |
| 1272 | exclusive_console = NULL; | 1275 | exclusive_console = NULL; |
| 1273 | 1276 | ||
| 1277 | spin_unlock(&logbuf_lock); | ||
| 1278 | |||
| 1274 | up(&console_sem); | 1279 | up(&console_sem); |
| 1280 | |||
| 1281 | /* | ||
| 1282 | * Someone could have filled up the buffer again, so re-check if there's | ||
| 1283 | * something to flush. In case we cannot trylock the console_sem again, | ||
| 1284 | * there's a new owner and the console_unlock() from them will do the | ||
| 1285 | * flush, no worries. | ||
| 1286 | */ | ||
| 1287 | spin_lock(&logbuf_lock); | ||
| 1288 | if (con_start != log_end) | ||
| 1289 | retry = 1; | ||
| 1275 | spin_unlock_irqrestore(&logbuf_lock, flags); | 1290 | spin_unlock_irqrestore(&logbuf_lock, flags); |
| 1291 | if (retry && console_trylock()) | ||
| 1292 | goto again; | ||
| 1293 | |||
| 1276 | if (wake_klogd) | 1294 | if (wake_klogd) |
| 1277 | wake_up_klogd(); | 1295 | wake_up_klogd(); |
| 1278 | } | 1296 | } |
