diff options
Diffstat (limited to 'kernel/debug/kdb/kdb_main.c')
-rw-r--r-- | kernel/debug/kdb/kdb_main.c | 91 |
1 files changed, 33 insertions, 58 deletions
diff --git a/kernel/debug/kdb/kdb_main.c b/kernel/debug/kdb/kdb_main.c index 67b847dfa2bb..df17c935d3c6 100644 --- a/kernel/debug/kdb/kdb_main.c +++ b/kernel/debug/kdb/kdb_main.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/ctype.h> | 14 | #include <linux/ctype.h> |
15 | #include <linux/string.h> | 15 | #include <linux/string.h> |
16 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
17 | #include <linux/kmsg_dump.h> | ||
17 | #include <linux/reboot.h> | 18 | #include <linux/reboot.h> |
18 | #include <linux/sched.h> | 19 | #include <linux/sched.h> |
19 | #include <linux/sysrq.h> | 20 | #include <linux/sysrq.h> |
@@ -2040,8 +2041,15 @@ static int kdb_env(int argc, const char **argv) | |||
2040 | */ | 2041 | */ |
2041 | static int kdb_dmesg(int argc, const char **argv) | 2042 | static int kdb_dmesg(int argc, const char **argv) |
2042 | { | 2043 | { |
2043 | char *syslog_data[4], *start, *end, c = '\0', *p; | 2044 | int diag; |
2044 | int diag, logging, logsize, lines = 0, adjust = 0, n; | 2045 | int logging; |
2046 | int lines = 0; | ||
2047 | int adjust = 0; | ||
2048 | int n = 0; | ||
2049 | int skip = 0; | ||
2050 | struct kmsg_dumper dumper = { .active = 1 }; | ||
2051 | size_t len; | ||
2052 | char buf[201]; | ||
2045 | 2053 | ||
2046 | if (argc > 2) | 2054 | if (argc > 2) |
2047 | return KDB_ARGCOUNT; | 2055 | return KDB_ARGCOUNT; |
@@ -2064,22 +2072,10 @@ static int kdb_dmesg(int argc, const char **argv) | |||
2064 | kdb_set(2, setargs); | 2072 | kdb_set(2, setargs); |
2065 | } | 2073 | } |
2066 | 2074 | ||
2067 | /* syslog_data[0,1] physical start, end+1. syslog_data[2,3] | 2075 | kmsg_dump_rewind(&dumper); |
2068 | * logical start, end+1. */ | 2076 | while (kmsg_dump_get_line(&dumper, 1, NULL, 0, NULL)) |
2069 | kdb_syslog_data(syslog_data); | 2077 | n++; |
2070 | if (syslog_data[2] == syslog_data[3]) | 2078 | |
2071 | return 0; | ||
2072 | logsize = syslog_data[1] - syslog_data[0]; | ||
2073 | start = syslog_data[2]; | ||
2074 | end = syslog_data[3]; | ||
2075 | #define KDB_WRAP(p) (((p - syslog_data[0]) % logsize) + syslog_data[0]) | ||
2076 | for (n = 0, p = start; p < end; ++p) { | ||
2077 | c = *KDB_WRAP(p); | ||
2078 | if (c == '\n') | ||
2079 | ++n; | ||
2080 | } | ||
2081 | if (c != '\n') | ||
2082 | ++n; | ||
2083 | if (lines < 0) { | 2079 | if (lines < 0) { |
2084 | if (adjust >= n) | 2080 | if (adjust >= n) |
2085 | kdb_printf("buffer only contains %d lines, nothing " | 2081 | kdb_printf("buffer only contains %d lines, nothing " |
@@ -2087,21 +2083,11 @@ static int kdb_dmesg(int argc, const char **argv) | |||
2087 | else if (adjust - lines >= n) | 2083 | else if (adjust - lines >= n) |
2088 | kdb_printf("buffer only contains %d lines, last %d " | 2084 | kdb_printf("buffer only contains %d lines, last %d " |
2089 | "lines printed\n", n, n - adjust); | 2085 | "lines printed\n", n, n - adjust); |
2090 | if (adjust) { | 2086 | skip = adjust; |
2091 | for (; start < end && adjust; ++start) { | 2087 | lines = abs(lines); |
2092 | if (*KDB_WRAP(start) == '\n') | ||
2093 | --adjust; | ||
2094 | } | ||
2095 | if (start < end) | ||
2096 | ++start; | ||
2097 | } | ||
2098 | for (p = start; p < end && lines; ++p) { | ||
2099 | if (*KDB_WRAP(p) == '\n') | ||
2100 | ++lines; | ||
2101 | } | ||
2102 | end = p; | ||
2103 | } else if (lines > 0) { | 2088 | } else if (lines > 0) { |
2104 | int skip = n - (adjust + lines); | 2089 | skip = n - lines - adjust; |
2090 | lines = abs(lines); | ||
2105 | if (adjust >= n) { | 2091 | if (adjust >= n) { |
2106 | kdb_printf("buffer only contains %d lines, " | 2092 | kdb_printf("buffer only contains %d lines, " |
2107 | "nothing printed\n", n); | 2093 | "nothing printed\n", n); |
@@ -2112,35 +2098,24 @@ static int kdb_dmesg(int argc, const char **argv) | |||
2112 | kdb_printf("buffer only contains %d lines, first " | 2098 | kdb_printf("buffer only contains %d lines, first " |
2113 | "%d lines printed\n", n, lines); | 2099 | "%d lines printed\n", n, lines); |
2114 | } | 2100 | } |
2115 | for (; start < end && skip; ++start) { | 2101 | } else { |
2116 | if (*KDB_WRAP(start) == '\n') | 2102 | lines = n; |
2117 | --skip; | ||
2118 | } | ||
2119 | for (p = start; p < end && lines; ++p) { | ||
2120 | if (*KDB_WRAP(p) == '\n') | ||
2121 | --lines; | ||
2122 | } | ||
2123 | end = p; | ||
2124 | } | 2103 | } |
2125 | /* Do a line at a time (max 200 chars) to reduce protocol overhead */ | 2104 | |
2126 | c = '\n'; | 2105 | if (skip >= n || skip < 0) |
2127 | while (start != end) { | 2106 | return 0; |
2128 | char buf[201]; | 2107 | |
2129 | p = buf; | 2108 | kmsg_dump_rewind(&dumper); |
2130 | if (KDB_FLAG(CMD_INTERRUPT)) | 2109 | while (kmsg_dump_get_line(&dumper, 1, buf, sizeof(buf), &len)) { |
2131 | return 0; | 2110 | if (skip) { |
2132 | while (start < end && (c = *KDB_WRAP(start)) && | 2111 | skip--; |
2133 | (p - buf) < sizeof(buf)-1) { | 2112 | continue; |
2134 | ++start; | ||
2135 | *p++ = c; | ||
2136 | if (c == '\n') | ||
2137 | break; | ||
2138 | } | 2113 | } |
2139 | *p = '\0'; | 2114 | if (!lines--) |
2140 | kdb_printf("%s", buf); | 2115 | break; |
2116 | |||
2117 | kdb_printf("%.*s\n", (int)len - 1, buf); | ||
2141 | } | 2118 | } |
2142 | if (c != '\n') | ||
2143 | kdb_printf("\n"); | ||
2144 | 2119 | ||
2145 | return 0; | 2120 | return 0; |
2146 | } | 2121 | } |