diff options
Diffstat (limited to 'kernel/printk.c')
-rw-r--r-- | kernel/printk.c | 57 |
1 files changed, 41 insertions, 16 deletions
diff --git a/kernel/printk.c b/kernel/printk.c index 89011bf8c106..423a8c765a57 100644 --- a/kernel/printk.c +++ b/kernel/printk.c | |||
@@ -573,11 +573,6 @@ static int __init printk_time_setup(char *str) | |||
573 | 573 | ||
574 | __setup("time", printk_time_setup); | 574 | __setup("time", printk_time_setup); |
575 | 575 | ||
576 | __attribute__((weak)) unsigned long long printk_clock(void) | ||
577 | { | ||
578 | return sched_clock(); | ||
579 | } | ||
580 | |||
581 | /* Check if we have any console registered that can be called early in boot. */ | 576 | /* Check if we have any console registered that can be called early in boot. */ |
582 | static int have_callable_console(void) | 577 | static int have_callable_console(void) |
583 | { | 578 | { |
@@ -628,30 +623,57 @@ asmlinkage int printk(const char *fmt, ...) | |||
628 | /* cpu currently holding logbuf_lock */ | 623 | /* cpu currently holding logbuf_lock */ |
629 | static volatile unsigned int printk_cpu = UINT_MAX; | 624 | static volatile unsigned int printk_cpu = UINT_MAX; |
630 | 625 | ||
626 | const char printk_recursion_bug_msg [] = | ||
627 | KERN_CRIT "BUG: recent printk recursion!\n"; | ||
628 | static int printk_recursion_bug; | ||
629 | |||
631 | asmlinkage int vprintk(const char *fmt, va_list args) | 630 | asmlinkage int vprintk(const char *fmt, va_list args) |
632 | { | 631 | { |
632 | static int log_level_unknown = 1; | ||
633 | static char printk_buf[1024]; | ||
634 | |||
633 | unsigned long flags; | 635 | unsigned long flags; |
634 | int printed_len; | 636 | int printed_len = 0; |
637 | int this_cpu; | ||
635 | char *p; | 638 | char *p; |
636 | static char printk_buf[1024]; | ||
637 | static int log_level_unknown = 1; | ||
638 | 639 | ||
639 | boot_delay_msec(); | 640 | boot_delay_msec(); |
640 | 641 | ||
641 | preempt_disable(); | 642 | preempt_disable(); |
642 | if (unlikely(oops_in_progress) && printk_cpu == smp_processor_id()) | ||
643 | /* If a crash is occurring during printk() on this CPU, | ||
644 | * make sure we can't deadlock */ | ||
645 | zap_locks(); | ||
646 | |||
647 | /* This stops the holder of console_sem just where we want him */ | 643 | /* This stops the holder of console_sem just where we want him */ |
648 | raw_local_irq_save(flags); | 644 | raw_local_irq_save(flags); |
645 | this_cpu = smp_processor_id(); | ||
646 | |||
647 | /* | ||
648 | * Ouch, printk recursed into itself! | ||
649 | */ | ||
650 | if (unlikely(printk_cpu == this_cpu)) { | ||
651 | /* | ||
652 | * If a crash is occurring during printk() on this CPU, | ||
653 | * then try to get the crash message out but make sure | ||
654 | * we can't deadlock. Otherwise just return to avoid the | ||
655 | * recursion and return - but flag the recursion so that | ||
656 | * it can be printed at the next appropriate moment: | ||
657 | */ | ||
658 | if (!oops_in_progress) { | ||
659 | printk_recursion_bug = 1; | ||
660 | goto out_restore_irqs; | ||
661 | } | ||
662 | zap_locks(); | ||
663 | } | ||
664 | |||
649 | lockdep_off(); | 665 | lockdep_off(); |
650 | spin_lock(&logbuf_lock); | 666 | spin_lock(&logbuf_lock); |
651 | printk_cpu = smp_processor_id(); | 667 | printk_cpu = this_cpu; |
652 | 668 | ||
669 | if (printk_recursion_bug) { | ||
670 | printk_recursion_bug = 0; | ||
671 | strcpy(printk_buf, printk_recursion_bug_msg); | ||
672 | printed_len = sizeof(printk_recursion_bug_msg); | ||
673 | } | ||
653 | /* Emit the output into the temporary buffer */ | 674 | /* Emit the output into the temporary buffer */ |
654 | printed_len = vscnprintf(printk_buf, sizeof(printk_buf), fmt, args); | 675 | printed_len += vscnprintf(printk_buf + printed_len, |
676 | sizeof(printk_buf), fmt, args); | ||
655 | 677 | ||
656 | /* | 678 | /* |
657 | * Copy the output into log_buf. If the caller didn't provide | 679 | * Copy the output into log_buf. If the caller didn't provide |
@@ -680,7 +702,9 @@ asmlinkage int vprintk(const char *fmt, va_list args) | |||
680 | loglev_char = default_message_loglevel | 702 | loglev_char = default_message_loglevel |
681 | + '0'; | 703 | + '0'; |
682 | } | 704 | } |
683 | t = printk_clock(); | 705 | t = 0; |
706 | if (system_state != SYSTEM_BOOTING) | ||
707 | t = ktime_to_ns(ktime_get()); | ||
684 | nanosec_rem = do_div(t, 1000000000); | 708 | nanosec_rem = do_div(t, 1000000000); |
685 | tlen = sprintf(tbuf, | 709 | tlen = sprintf(tbuf, |
686 | "<%c>[%5lu.%06lu] ", | 710 | "<%c>[%5lu.%06lu] ", |
@@ -744,6 +768,7 @@ asmlinkage int vprintk(const char *fmt, va_list args) | |||
744 | printk_cpu = UINT_MAX; | 768 | printk_cpu = UINT_MAX; |
745 | spin_unlock(&logbuf_lock); | 769 | spin_unlock(&logbuf_lock); |
746 | lockdep_on(); | 770 | lockdep_on(); |
771 | out_restore_irqs: | ||
747 | raw_local_irq_restore(flags); | 772 | raw_local_irq_restore(flags); |
748 | } | 773 | } |
749 | 774 | ||