Skip to content

Commit

Permalink
printk,kdb: capture printk() when in kdb shell
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
jwessel committed May 21, 2010
1 parent efe2f29 commit d37d39a
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 4 deletions.
3 changes: 3 additions & 0 deletions include/linux/kdb.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@ typedef enum {
KDB_REASON_SSTEP, /* Single Step trap. - regs valid */
} kdb_reason_t;

extern int kdb_trap_printk;
extern int vkdb_printf(const char *fmt, va_list args)
__attribute__ ((format (printf, 1, 0)));
extern int kdb_printf(const char *, ...)
__attribute__ ((format (printf, 1, 2)));
typedef int (*kdb_printf_t)(const char *, ...)
Expand Down
2 changes: 2 additions & 0 deletions kernel/debug/kdb/kdb_bt.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ static void kdb_show_stack(struct task_struct *p, void *addr)
{
int old_lvl = console_loglevel;
console_loglevel = 15;
kdb_trap_printk++;
kdb_set_current_task(p);
if (addr) {
show_stack((struct task_struct *)p, addr);
Expand All @@ -36,6 +37,7 @@ static void kdb_show_stack(struct task_struct *p, void *addr)
show_stack(p, NULL);
}
console_loglevel = old_lvl;
kdb_trap_printk--;
}

/*
Expand Down
24 changes: 20 additions & 4 deletions kernel/debug/kdb/kdb_io.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#define CMD_BUFLEN 256
char kdb_prompt_str[CMD_BUFLEN];

int kdb_trap_printk;

static void kgdb_transition_check(char *buffer)
{
Expand Down Expand Up @@ -533,12 +534,12 @@ static int kdb_search_string(char *searched, char *searchfor)
return 0;
}

int kdb_printf(const char *fmt, ...)
int vkdb_printf(const char *fmt, va_list ap)
{
va_list ap;
int diag;
int linecount;
int logging, saved_loglevel = 0;
int saved_trap_printk;
int got_printf_lock = 0;
int retlen = 0;
int fnd, len;
Expand All @@ -549,6 +550,9 @@ int kdb_printf(const char *fmt, ...)
unsigned long uninitialized_var(flags);

preempt_disable();
saved_trap_printk = kdb_trap_printk;
kdb_trap_printk = 0;

/* Serialize kdb_printf if multiple cpus try to write at once.
* But if any cpu goes recursive in kdb, just print the output,
* even if it is interleaved with any other text.
Expand All @@ -575,9 +579,7 @@ int kdb_printf(const char *fmt, ...)
next_avail = kdb_buffer;
size_avail = sizeof(kdb_buffer);
}
va_start(ap, fmt);
vsnprintf(next_avail, size_avail, fmt, ap);
va_end(ap);

/*
* If kdb_parse() found that the command was cmd xxx | grep yyy
Expand Down Expand Up @@ -805,6 +807,20 @@ int kdb_printf(const char *fmt, ...)
} else {
__release(kdb_printf_lock);
}
kdb_trap_printk = saved_trap_printk;
preempt_enable();
return retlen;
}

int kdb_printf(const char *fmt, ...)
{
va_list ap;
int r;

va_start(ap, fmt);
r = vkdb_printf(fmt, ap);
va_end(ap);

return r;
}

4 changes: 4 additions & 0 deletions kernel/debug/kdb/kdb_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -1056,7 +1056,9 @@ static void kdb_dumpregs(struct pt_regs *regs)
{
int old_lvl = console_loglevel;
console_loglevel = 15;
kdb_trap_printk++;
show_regs(regs);
kdb_trap_printk--;
kdb_printf("\n");
console_loglevel = old_lvl;
}
Expand Down Expand Up @@ -1819,7 +1821,9 @@ static int kdb_sr(int argc, const char **argv)
if (argc != 1)
return KDB_ARGCOUNT;
sysrq_toggle_support(1);
kdb_trap_printk++;
handle_sysrq(*argv[1], NULL);
kdb_trap_printk--;

return 0;
}
Expand Down
9 changes: 9 additions & 0 deletions kernel/printk.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#include <linux/bootmem.h>
#include <linux/syscalls.h>
#include <linux/kexec.h>
#include <linux/kdb.h>
#include <linux/ratelimit.h>
#include <linux/kmsg_dump.h>
#include <linux/syslog.h>
Expand Down Expand Up @@ -602,6 +603,14 @@ asmlinkage int printk(const char *fmt, ...)
va_list args;
int r;

#ifdef CONFIG_KGDB_KDB
if (unlikely(kdb_trap_printk)) {
va_start(args, fmt);
r = vkdb_printf(fmt, args);
va_end(args);
return r;
}
#endif
va_start(args, fmt);
r = vprintk(fmt, args);
va_end(args);
Expand Down

0 comments on commit d37d39a

Please sign in to comment.