Hi,
I found there is a 'log' command problem related to handling the ring
buffer, and this patch fixes it.
The ring buffer can be cleared by klogctl(2) from a user process, but
current crash utility does not consider this case. The following output
of current crash utility is example of this case. You see there is the
panic message "SysRq : Trigger a crashdump" inside even if it should be
output in the end:
crash > log
[snip]
exception[8291] trap divide error rip:4004c0 rsp:7fffb56cdf60 error:0
exception[8293] trap divide error rip:4004c0 rsp:7fffbb0628f0 error:0
SysRq : Trigger a crashdump
14 15) *0, disabled.
ACPI: PCI Interrupt Link [LNKF] (IRQs 4 5 6 7 10 14 15) *0, disabled.
ACPI: PCI Interrupt Link [LNKG] (IRQs 3 4 5 6 7 10 14 15) *0, disabled.
[snip]
crash >
This patch fixes this invalid output to the folloing:
crash > log
[snip]
exception[8291] trap divide error rip:4004c0 rsp:7fffb56cdf60 error:0
exception[8293] trap divide error rip:4004c0 rsp:7fffbb0628f0 error:0
SysRq : Trigger a crashdump
crash>
I have one concern about this fixing:
If applying this patch, 'log' command outputs the log data from the time
of klogctl(2) call for the log clearance. If making the other patch, we
will be able to extract the former log data, because a kernel does not
clear the ring buffer and it just clears "logged_chars" internally.
I feel this patch is better, because the log data can be cleared only by
a root user and he decided the former log data is unnecessary.
What do you think of this?
Thanks
Ken'ichi Ohmichi
Signed-off-by: Ken'ichi Ohmichi <oomichi(a)mxs.nes.nec.co.jp>
---
--- crash-4.0-7.7/kernel.c.orig 2009-02-06 01:13:43.000000000 +0900
+++ crash-4.0-7.7/kernel.c 2009-02-17 12:07:33.000000000 +0900
@@ -3364,13 +3364,13 @@ cmd_log(void)
void
dump_log(int msg_level)
{
- int i;
+ int i, j;
ulong log_buf, logged_chars;
char *buf;
char last;
ulong index;
struct syment *nsp;
- int log_wrap, loglevel, log_buf_len;
+ int loglevel, log_buf_len;
if (symbol_exists("log_buf_len")) {
get_symbol_data("log_buf_len", sizeof(int), &log_buf_len);
@@ -3391,29 +3391,28 @@ dump_log(int msg_level)
}
buf = GETBUF(log_buf_len);
- log_wrap = FALSE;
get_symbol_data("logged_chars", sizeof(ulong), &logged_chars);
readmem(log_buf, KVADDR, buf,
log_buf_len, "log_buf contents", FAULT_ON_ERROR);
+ get_symbol_data("log_end", sizeof(ulong), &index);
+ index &= (log_buf_len - 1);
if (logged_chars < log_buf_len) {
- index = 0;
- } else {
- get_symbol_data("log_end", sizeof(ulong), &index);
- index &= log_buf_len-1;
- }
+ if (logged_chars <= index)
+ index -= logged_chars;
+ else
+ index = log_buf_len - (logged_chars - index);
+ }
if ((logged_chars < log_buf_len) && (index == 0) && (buf[index] ==
'<'))
loglevel = TRUE;
else
loglevel = FALSE;
- if (index != 0)
- log_wrap = TRUE;
+ for (i = index, j = 0; j < logged_chars; i++, j++) {
+ if (i >= log_buf_len)
+ i = 0;
-wrap_around:
-
- for (i = index; i < log_buf_len; i++) {
if (loglevel && !msg_level) {
switch (buf[i])
{
@@ -3444,13 +3443,6 @@ wrap_around:
}
}
- if (log_wrap) {
- log_buf_len = index;
- index = 0;
- log_wrap = FALSE;
- goto wrap_around;
- }
-
if (last != '\n')
fprintf(fp, "\n");