aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorJason Wessel <jason.wessel@windriver.com>2010-05-20 22:04:27 -0400
committerJason Wessel <jason.wessel@windriver.com>2010-05-20 22:04:27 -0400
commitd37d39ae3b4a8f9a21114921fb344fe7cadb1abd (patch)
tree2c20219725a12c343429758ec378b5c9d08b04bd /kernel
parentefe2f29e324fd20e0449bcd6dc6dbe4734c2ba94 (diff)
printk,kdb: capture printk() when in kdb shell
Certain calls from the kdb shell will call out to printk(), and any of these calls should get vectored back to the kdb_printf() so that the kdb pager and processing can be used, as well as to properly channel I/O to the polled I/O devices. CC: Randy Dunlap <rdunlap@xenotime.net> Signed-off-by: Jason Wessel <jason.wessel@windriver.com> Acked-by: Andrew Morton <akpm@linux-foundation.org>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/debug/kdb/kdb_bt.c2
-rw-r--r--kernel/debug/kdb/kdb_io.c24
-rw-r--r--kernel/debug/kdb/kdb_main.c4
-rw-r--r--kernel/printk.c9
4 files changed, 35 insertions, 4 deletions
diff --git a/kernel/debug/kdb/kdb_bt.c b/kernel/debug/kdb/kdb_bt.c
index 483fa4e7aaac..2f62fe85f16a 100644
--- a/kernel/debug/kdb/kdb_bt.c
+++ b/kernel/debug/kdb/kdb_bt.c
@@ -23,6 +23,7 @@ static void kdb_show_stack(struct task_struct *p, void *addr)
23{ 23{
24 int old_lvl = console_loglevel; 24 int old_lvl = console_loglevel;
25 console_loglevel = 15; 25 console_loglevel = 15;
26 kdb_trap_printk++;
26 kdb_set_current_task(p); 27 kdb_set_current_task(p);
27 if (addr) { 28 if (addr) {
28 show_stack((struct task_struct *)p, addr); 29 show_stack((struct task_struct *)p, addr);
@@ -36,6 +37,7 @@ static void kdb_show_stack(struct task_struct *p, void *addr)
36 show_stack(p, NULL); 37 show_stack(p, NULL);
37 } 38 }
38 console_loglevel = old_lvl; 39 console_loglevel = old_lvl;
40 kdb_trap_printk--;
39} 41}
40 42
41/* 43/*
diff --git a/kernel/debug/kdb/kdb_io.c b/kernel/debug/kdb/kdb_io.c
index 58be7e9c9e95..c9b7f4f90bba 100644
--- a/kernel/debug/kdb/kdb_io.c
+++ b/kernel/debug/kdb/kdb_io.c
@@ -29,6 +29,7 @@
29#define CMD_BUFLEN 256 29#define CMD_BUFLEN 256
30char kdb_prompt_str[CMD_BUFLEN]; 30char kdb_prompt_str[CMD_BUFLEN];
31 31
32int kdb_trap_printk;
32 33
33static void kgdb_transition_check(char *buffer) 34static void kgdb_transition_check(char *buffer)
34{ 35{
@@ -533,12 +534,12 @@ static int kdb_search_string(char *searched, char *searchfor)
533 return 0; 534 return 0;
534} 535}
535 536
536int kdb_printf(const char *fmt, ...) 537int vkdb_printf(const char *fmt, va_list ap)
537{ 538{
538 va_list ap;
539 int diag; 539 int diag;
540 int linecount; 540 int linecount;
541 int logging, saved_loglevel = 0; 541 int logging, saved_loglevel = 0;
542 int saved_trap_printk;
542 int got_printf_lock = 0; 543 int got_printf_lock = 0;
543 int retlen = 0; 544 int retlen = 0;
544 int fnd, len; 545 int fnd, len;
@@ -549,6 +550,9 @@ int kdb_printf(const char *fmt, ...)
549 unsigned long uninitialized_var(flags); 550 unsigned long uninitialized_var(flags);
550 551
551 preempt_disable(); 552 preempt_disable();
553 saved_trap_printk = kdb_trap_printk;
554 kdb_trap_printk = 0;
555
552 /* Serialize kdb_printf if multiple cpus try to write at once. 556 /* Serialize kdb_printf if multiple cpus try to write at once.
553 * But if any cpu goes recursive in kdb, just print the output, 557 * But if any cpu goes recursive in kdb, just print the output,
554 * even if it is interleaved with any other text. 558 * even if it is interleaved with any other text.
@@ -575,9 +579,7 @@ int kdb_printf(const char *fmt, ...)
575 next_avail = kdb_buffer; 579 next_avail = kdb_buffer;
576 size_avail = sizeof(kdb_buffer); 580 size_avail = sizeof(kdb_buffer);
577 } 581 }
578 va_start(ap, fmt);
579 vsnprintf(next_avail, size_avail, fmt, ap); 582 vsnprintf(next_avail, size_avail, fmt, ap);
580 va_end(ap);
581 583
582 /* 584 /*
583 * If kdb_parse() found that the command was cmd xxx | grep yyy 585 * If kdb_parse() found that the command was cmd xxx | grep yyy
@@ -805,6 +807,20 @@ kdb_print_out:
805 } else { 807 } else {
806 __release(kdb_printf_lock); 808 __release(kdb_printf_lock);
807 } 809 }
810 kdb_trap_printk = saved_trap_printk;
808 preempt_enable(); 811 preempt_enable();
809 return retlen; 812 return retlen;
810} 813}
814
815int kdb_printf(const char *fmt, ...)
816{
817 va_list ap;
818 int r;
819
820 va_start(ap, fmt);
821 r = vkdb_printf(fmt, ap);
822 va_end(ap);
823
824 return r;
825}
826
diff --git a/kernel/debug/kdb/kdb_main.c b/kernel/debug/kdb/kdb_main.c
index 64ef9ac14ba9..b724c791b6d4 100644
--- a/kernel/debug/kdb/kdb_main.c
+++ b/kernel/debug/kdb/kdb_main.c
@@ -1056,7 +1056,9 @@ static void kdb_dumpregs(struct pt_regs *regs)
1056{ 1056{
1057 int old_lvl = console_loglevel; 1057 int old_lvl = console_loglevel;
1058 console_loglevel = 15; 1058 console_loglevel = 15;
1059 kdb_trap_printk++;
1059 show_regs(regs); 1060 show_regs(regs);
1061 kdb_trap_printk--;
1060 kdb_printf("\n"); 1062 kdb_printf("\n");
1061 console_loglevel = old_lvl; 1063 console_loglevel = old_lvl;
1062} 1064}
@@ -1819,7 +1821,9 @@ static int kdb_sr(int argc, const char **argv)
1819 if (argc != 1) 1821 if (argc != 1)
1820 return KDB_ARGCOUNT; 1822 return KDB_ARGCOUNT;
1821 sysrq_toggle_support(1); 1823 sysrq_toggle_support(1);
1824 kdb_trap_printk++;
1822 handle_sysrq(*argv[1], NULL); 1825 handle_sysrq(*argv[1], NULL);
1826 kdb_trap_printk--;
1823 1827
1824 return 0; 1828 return 0;
1825} 1829}
diff --git a/kernel/printk.c b/kernel/printk.c
index 9213b8b5bb4f..444b770c9595 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -33,6 +33,7 @@
33#include <linux/bootmem.h> 33#include <linux/bootmem.h>
34#include <linux/syscalls.h> 34#include <linux/syscalls.h>
35#include <linux/kexec.h> 35#include <linux/kexec.h>
36#include <linux/kdb.h>
36#include <linux/ratelimit.h> 37#include <linux/ratelimit.h>
37#include <linux/kmsg_dump.h> 38#include <linux/kmsg_dump.h>
38#include <linux/syslog.h> 39#include <linux/syslog.h>
@@ -602,6 +603,14 @@ asmlinkage int printk(const char *fmt, ...)
602 va_list args; 603 va_list args;
603 int r; 604 int r;
604 605
606#ifdef CONFIG_KGDB_KDB
607 if (unlikely(kdb_trap_printk)) {
608 va_start(args, fmt);
609 r = vkdb_printf(fmt, args);
610 va_end(args);
611 return r;
612 }
613#endif
605 va_start(args, fmt); 614 va_start(args, fmt);
606 r = vprintk(fmt, args); 615 r = vprintk(fmt, args);
607 va_end(args); 616 va_end(args);