aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/printk.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2008-07-14 18:27:43 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-07-14 18:27:43 -0400
commit4bb0057f996b1491f93a64879f4c53c83bc0f0c7 (patch)
treef216e244a6f88ede277a3687499dbb1762a3c37a /kernel/printk.c
parent116a9fb3ed98c19d1ee0c6c55971f5b753949393 (diff)
parent9e4144abf8a30ae221311368bbb10690ebdb4b76 (diff)
Merge branch 'core/printk' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
* 'core/printk' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip: x86, generic: mark early_printk as asmlinkage printk: export console_drivers printk: remember the message level for multi-line output printk: refactor processing of line severity tokens printk: don't prefer unsuited consoles on registration printk: clean up recursion check related static variables namespacecheck: more kernel/printk.c fixes namespacecheck: fix kernel printk.c
Diffstat (limited to 'kernel/printk.c')
-rw-r--r--kernel/printk.c105
1 files changed, 43 insertions, 62 deletions
diff --git a/kernel/printk.c b/kernel/printk.c
index 5d81a11321fd..07ad9e7f7a66 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -38,7 +38,7 @@
38/* 38/*
39 * Architectures can override it: 39 * Architectures can override it:
40 */ 40 */
41void __attribute__((weak)) early_printk(const char *fmt, ...) 41void asmlinkage __attribute__((weak)) early_printk(const char *fmt, ...)
42{ 42{
43} 43}
44 44
@@ -235,7 +235,7 @@ static inline void boot_delay_msec(void)
235/* 235/*
236 * Return the number of unread characters in the log buffer. 236 * Return the number of unread characters in the log buffer.
237 */ 237 */
238int log_buf_get_len(void) 238static int log_buf_get_len(void)
239{ 239{
240 return logged_chars; 240 return logged_chars;
241} 241}
@@ -272,19 +272,6 @@ int log_buf_copy(char *dest, int idx, int len)
272} 272}
273 273
274/* 274/*
275 * Extract a single character from the log buffer.
276 */
277int log_buf_read(int idx)
278{
279 char ret;
280
281 if (log_buf_copy(&ret, idx, 1) == 1)
282 return ret;
283 else
284 return -1;
285}
286
287/*
288 * Commands to do_syslog: 275 * Commands to do_syslog:
289 * 276 *
290 * 0 -- Close the log. Currently a NOP. 277 * 0 -- Close the log. Currently a NOP.
@@ -669,18 +656,17 @@ static int acquire_console_semaphore_for_printk(unsigned int cpu)
669 spin_unlock(&logbuf_lock); 656 spin_unlock(&logbuf_lock);
670 return retval; 657 return retval;
671} 658}
672 659static const char recursion_bug_msg [] =
673static const char printk_recursion_bug_msg [] = 660 KERN_CRIT "BUG: recent printk recursion!\n";
674 KERN_CRIT "BUG: recent printk recursion!\n"; 661static int recursion_bug;
675static int printk_recursion_bug; 662 static int new_text_line = 1;
663static char printk_buf[1024];
676 664
677asmlinkage int vprintk(const char *fmt, va_list args) 665asmlinkage int vprintk(const char *fmt, va_list args)
678{ 666{
679 static int log_level_unknown = 1;
680 static char printk_buf[1024];
681
682 unsigned long flags;
683 int printed_len = 0; 667 int printed_len = 0;
668 int current_log_level = default_message_loglevel;
669 unsigned long flags;
684 int this_cpu; 670 int this_cpu;
685 char *p; 671 char *p;
686 672
@@ -703,7 +689,7 @@ asmlinkage int vprintk(const char *fmt, va_list args)
703 * it can be printed at the next appropriate moment: 689 * it can be printed at the next appropriate moment:
704 */ 690 */
705 if (!oops_in_progress) { 691 if (!oops_in_progress) {
706 printk_recursion_bug = 1; 692 recursion_bug = 1;
707 goto out_restore_irqs; 693 goto out_restore_irqs;
708 } 694 }
709 zap_locks(); 695 zap_locks();
@@ -713,70 +699,62 @@ asmlinkage int vprintk(const char *fmt, va_list args)
713 spin_lock(&logbuf_lock); 699 spin_lock(&logbuf_lock);
714 printk_cpu = this_cpu; 700 printk_cpu = this_cpu;
715 701
716 if (printk_recursion_bug) { 702 if (recursion_bug) {
717 printk_recursion_bug = 0; 703 recursion_bug = 0;
718 strcpy(printk_buf, printk_recursion_bug_msg); 704 strcpy(printk_buf, recursion_bug_msg);
719 printed_len = sizeof(printk_recursion_bug_msg); 705 printed_len = sizeof(recursion_bug_msg);
720 } 706 }
721 /* Emit the output into the temporary buffer */ 707 /* Emit the output into the temporary buffer */
722 printed_len += vscnprintf(printk_buf + printed_len, 708 printed_len += vscnprintf(printk_buf + printed_len,
723 sizeof(printk_buf) - printed_len, fmt, args); 709 sizeof(printk_buf) - printed_len, fmt, args);
724 710
711
725 /* 712 /*
726 * Copy the output into log_buf. If the caller didn't provide 713 * Copy the output into log_buf. If the caller didn't provide
727 * appropriate log level tags, we insert them here 714 * appropriate log level tags, we insert them here
728 */ 715 */
729 for (p = printk_buf; *p; p++) { 716 for (p = printk_buf; *p; p++) {
730 if (log_level_unknown) { 717 if (new_text_line) {
731 /* log_level_unknown signals the start of a new line */ 718 /* If a token, set current_log_level and skip over */
719 if (p[0] == '<' && p[1] >= '0' && p[1] <= '7' &&
720 p[2] == '>') {
721 current_log_level = p[1] - '0';
722 p += 3;
723 printed_len -= 3;
724 }
725
726 /* Always output the token */
727 emit_log_char('<');
728 emit_log_char(current_log_level + '0');
729 emit_log_char('>');
730 printed_len += 3;
731 new_text_line = 0;
732
732 if (printk_time) { 733 if (printk_time) {
733 int loglev_char; 734 /* Follow the token with the time */
734 char tbuf[50], *tp; 735 char tbuf[50], *tp;
735 unsigned tlen; 736 unsigned tlen;
736 unsigned long long t; 737 unsigned long long t;
737 unsigned long nanosec_rem; 738 unsigned long nanosec_rem;
738 739
739 /*
740 * force the log level token to be
741 * before the time output.
742 */
743 if (p[0] == '<' && p[1] >='0' &&
744 p[1] <= '7' && p[2] == '>') {
745 loglev_char = p[1];
746 p += 3;
747 printed_len -= 3;
748 } else {
749 loglev_char = default_message_loglevel
750 + '0';
751 }
752 t = cpu_clock(printk_cpu); 740 t = cpu_clock(printk_cpu);
753 nanosec_rem = do_div(t, 1000000000); 741 nanosec_rem = do_div(t, 1000000000);
754 tlen = sprintf(tbuf, 742 tlen = sprintf(tbuf, "[%5lu.%06lu] ",
755 "<%c>[%5lu.%06lu] ", 743 (unsigned long) t,
756 loglev_char, 744 nanosec_rem / 1000);
757 (unsigned long)t,
758 nanosec_rem/1000);
759 745
760 for (tp = tbuf; tp < tbuf + tlen; tp++) 746 for (tp = tbuf; tp < tbuf + tlen; tp++)
761 emit_log_char(*tp); 747 emit_log_char(*tp);
762 printed_len += tlen; 748 printed_len += tlen;
763 } else {
764 if (p[0] != '<' || p[1] < '0' ||
765 p[1] > '7' || p[2] != '>') {
766 emit_log_char('<');
767 emit_log_char(default_message_loglevel
768 + '0');
769 emit_log_char('>');
770 printed_len += 3;
771 }
772 } 749 }
773 log_level_unknown = 0; 750
774 if (!*p) 751 if (!*p)
775 break; 752 break;
776 } 753 }
754
777 emit_log_char(*p); 755 emit_log_char(*p);
778 if (*p == '\n') 756 if (*p == '\n')
779 log_level_unknown = 1; 757 new_text_line = 1;
780 } 758 }
781 759
782 /* 760 /*
@@ -1179,8 +1157,11 @@ void register_console(struct console *console)
1179 console->index = 0; 1157 console->index = 0;
1180 if (console->setup == NULL || 1158 if (console->setup == NULL ||
1181 console->setup(console, NULL) == 0) { 1159 console->setup(console, NULL) == 0) {
1182 console->flags |= CON_ENABLED | CON_CONSDEV; 1160 console->flags |= CON_ENABLED;
1183 preferred_console = 0; 1161 if (console->device) {
1162 console->flags |= CON_CONSDEV;
1163 preferred_console = 0;
1164 }
1184 } 1165 }
1185 } 1166 }
1186 1167