Commit bc792e61 authored by Anton Vorontsov's avatar Anton Vorontsov Committed by Linus Torvalds

kdb: Revive dmesg command

The kgdb dmesg command is broken after the printk rework.  The old logic
in kdb code makes no sense in terms of current printk/logging storage
format, and KDB simply hangs forever.

This patch revives the command by switching to kmsg_dumper iterator.

The code is now much more simpler and shorter.
Signed-off-by: default avatarAnton Vorontsov <anton.vorontsov@linaro.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 84a1caf1
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include <linux/ctype.h> #include <linux/ctype.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/kmsg_dump.h>
#include <linux/reboot.h> #include <linux/reboot.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/sysrq.h> #include <linux/sysrq.h>
...@@ -2040,8 +2041,15 @@ static int kdb_env(int argc, const char **argv) ...@@ -2040,8 +2041,15 @@ static int kdb_env(int argc, const char **argv)
*/ */
static int kdb_dmesg(int argc, const char **argv) static int kdb_dmesg(int argc, const char **argv)
{ {
char *syslog_data[4], *start, *end, c = '\0', *p; int diag;
int diag, logging, logsize, lines = 0, adjust = 0, n; int logging;
int lines = 0;
int adjust = 0;
int n = 0;
int skip = 0;
struct kmsg_dumper dumper = { .active = 1 };
size_t len;
char buf[201];
if (argc > 2) if (argc > 2)
return KDB_ARGCOUNT; return KDB_ARGCOUNT;
...@@ -2064,22 +2072,10 @@ static int kdb_dmesg(int argc, const char **argv) ...@@ -2064,22 +2072,10 @@ static int kdb_dmesg(int argc, const char **argv)
kdb_set(2, setargs); kdb_set(2, setargs);
} }
/* syslog_data[0,1] physical start, end+1. syslog_data[2,3] kmsg_dump_rewind(&dumper);
* logical start, end+1. */ while (kmsg_dump_get_line(&dumper, 1, NULL, 0, NULL))
kdb_syslog_data(syslog_data); n++;
if (syslog_data[2] == syslog_data[3])
return 0;
logsize = syslog_data[1] - syslog_data[0];
start = syslog_data[2];
end = syslog_data[3];
#define KDB_WRAP(p) (((p - syslog_data[0]) % logsize) + syslog_data[0])
for (n = 0, p = start; p < end; ++p) {
c = *KDB_WRAP(p);
if (c == '\n')
++n;
}
if (c != '\n')
++n;
if (lines < 0) { if (lines < 0) {
if (adjust >= n) if (adjust >= n)
kdb_printf("buffer only contains %d lines, nothing " kdb_printf("buffer only contains %d lines, nothing "
...@@ -2087,21 +2083,11 @@ static int kdb_dmesg(int argc, const char **argv) ...@@ -2087,21 +2083,11 @@ static int kdb_dmesg(int argc, const char **argv)
else if (adjust - lines >= n) else if (adjust - lines >= n)
kdb_printf("buffer only contains %d lines, last %d " kdb_printf("buffer only contains %d lines, last %d "
"lines printed\n", n, n - adjust); "lines printed\n", n, n - adjust);
if (adjust) { skip = adjust;
for (; start < end && adjust; ++start) { lines = abs(lines);
if (*KDB_WRAP(start) == '\n')
--adjust;
}
if (start < end)
++start;
}
for (p = start; p < end && lines; ++p) {
if (*KDB_WRAP(p) == '\n')
++lines;
}
end = p;
} else if (lines > 0) { } else if (lines > 0) {
int skip = n - (adjust + lines); skip = n - lines - adjust;
lines = abs(lines);
if (adjust >= n) { if (adjust >= n) {
kdb_printf("buffer only contains %d lines, " kdb_printf("buffer only contains %d lines, "
"nothing printed\n", n); "nothing printed\n", n);
...@@ -2112,35 +2098,24 @@ static int kdb_dmesg(int argc, const char **argv) ...@@ -2112,35 +2098,24 @@ static int kdb_dmesg(int argc, const char **argv)
kdb_printf("buffer only contains %d lines, first " kdb_printf("buffer only contains %d lines, first "
"%d lines printed\n", n, lines); "%d lines printed\n", n, lines);
} }
for (; start < end && skip; ++start) { } else {
if (*KDB_WRAP(start) == '\n') lines = n;
--skip;
}
for (p = start; p < end && lines; ++p) {
if (*KDB_WRAP(p) == '\n')
--lines;
}
end = p;
} }
/* Do a line at a time (max 200 chars) to reduce protocol overhead */
c = '\n'; if (skip >= n || skip < 0)
while (start != end) {
char buf[201];
p = buf;
if (KDB_FLAG(CMD_INTERRUPT))
return 0; return 0;
while (start < end && (c = *KDB_WRAP(start)) &&
(p - buf) < sizeof(buf)-1) { kmsg_dump_rewind(&dumper);
++start; while (kmsg_dump_get_line(&dumper, 1, buf, sizeof(buf), &len)) {
*p++ = c; if (skip) {
if (c == '\n') skip--;
break; continue;
} }
*p = '\0'; if (!lines--)
kdb_printf("%s", buf); break;
kdb_printf("%.*s\n", (int)len - 1, buf);
} }
if (c != '\n')
kdb_printf("\n");
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment