Skip to content

Commit

Permalink
kdb: Revive dmesg command
Browse files Browse the repository at this point in the history
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: Anton Vorontsov <anton.vorontsov@linaro.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
  • Loading branch information
Anton Vorontsov authored and Linus Torvalds committed Jul 21, 2012
1 parent 84a1caf commit bc792e6
Showing 1 changed file with 33 additions and 58 deletions.
91 changes: 33 additions & 58 deletions kernel/debug/kdb/kdb_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include <linux/ctype.h>
#include <linux/string.h>
#include <linux/kernel.h>
#include <linux/kmsg_dump.h>
#include <linux/reboot.h>
#include <linux/sched.h>
#include <linux/sysrq.h>
Expand Down Expand Up @@ -2040,8 +2041,15 @@ static int kdb_env(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, logging, logsize, lines = 0, adjust = 0, n;
int diag;
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)
return KDB_ARGCOUNT;
Expand All @@ -2064,44 +2072,22 @@ static int kdb_dmesg(int argc, const char **argv)
kdb_set(2, setargs);
}

/* syslog_data[0,1] physical start, end+1. syslog_data[2,3]
* logical start, end+1. */
kdb_syslog_data(syslog_data);
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;
kmsg_dump_rewind(&dumper);
while (kmsg_dump_get_line(&dumper, 1, NULL, 0, NULL))
n++;

if (lines < 0) {
if (adjust >= n)
kdb_printf("buffer only contains %d lines, nothing "
"printed\n", n);
else if (adjust - lines >= n)
kdb_printf("buffer only contains %d lines, last %d "
"lines printed\n", n, n - adjust);
if (adjust) {
for (; start < end && adjust; ++start) {
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;
skip = adjust;
lines = abs(lines);
} else if (lines > 0) {
int skip = n - (adjust + lines);
skip = n - lines - adjust;
lines = abs(lines);
if (adjust >= n) {
kdb_printf("buffer only contains %d lines, "
"nothing printed\n", n);
Expand All @@ -2112,35 +2098,24 @@ static int kdb_dmesg(int argc, const char **argv)
kdb_printf("buffer only contains %d lines, first "
"%d lines printed\n", n, lines);
}
for (; start < end && skip; ++start) {
if (*KDB_WRAP(start) == '\n')
--skip;
}
for (p = start; p < end && lines; ++p) {
if (*KDB_WRAP(p) == '\n')
--lines;
}
end = p;
} else {
lines = n;
}
/* Do a line at a time (max 200 chars) to reduce protocol overhead */
c = '\n';
while (start != end) {
char buf[201];
p = buf;
if (KDB_FLAG(CMD_INTERRUPT))
return 0;
while (start < end && (c = *KDB_WRAP(start)) &&
(p - buf) < sizeof(buf)-1) {
++start;
*p++ = c;
if (c == '\n')
break;

if (skip >= n || skip < 0)
return 0;

kmsg_dump_rewind(&dumper);
while (kmsg_dump_get_line(&dumper, 1, buf, sizeof(buf), &len)) {
if (skip) {
skip--;
continue;
}
*p = '\0';
kdb_printf("%s", buf);
if (!lines--)
break;

kdb_printf("%.*s\n", (int)len - 1, buf);
}
if (c != '\n')
kdb_printf("\n");

return 0;
}
Expand Down

0 comments on commit bc792e6

Please sign in to comment.