Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'anton-kgdb' (kgdb dmesg fixups)

Merge emailed kgdb dmesg fixups patches from Anton Vorontsov:
"The dmesg command appears to be broken after the printk rework. The
old logic in the kdb code makes no sense in terms of current
printk/logging storage format, and KDB simply hangs forever upon
entering 'dmesg' command.

The first patch revives the command by switching to kmsg_dumper
iterator. As a side-effect, the code is now much more simpler.

A few changes were needed in the printk.c: we needed unlocked variant
of the kmsg_dumper iterator, but these can surely wait for 3.6.

It's probably too late even for the first patch to go to 3.5, but I'll
try to convince otherwise. :-) Here we go:

- The current code is broken for sure, and has no hope to work at
all. It is a regression
- The new code works for me, and probably works for everyone else;
- If it compiles (and I urge everyone to compile-test it on your
setup), it hardly can make things worse."

* Merge emailed patches from Anton Vorontsov: (4 commits)
kdb: Switch to nolock variants of kmsg_dump functions
printk: Implement some unlocked kmsg_dump functions
printk: Remove kdb_syslog_data
kdb: Revive dmesg command

+122 -105
+16
include/linux/kmsg_dump.h
··· 55 55 #ifdef CONFIG_PRINTK 56 56 void kmsg_dump(enum kmsg_dump_reason reason); 57 57 58 + bool kmsg_dump_get_line_nolock(struct kmsg_dumper *dumper, bool syslog, 59 + char *line, size_t size, size_t *len); 60 + 58 61 bool kmsg_dump_get_line(struct kmsg_dumper *dumper, bool syslog, 59 62 char *line, size_t size, size_t *len); 60 63 61 64 bool kmsg_dump_get_buffer(struct kmsg_dumper *dumper, bool syslog, 62 65 char *buf, size_t size, size_t *len); 66 + 67 + void kmsg_dump_rewind_nolock(struct kmsg_dumper *dumper); 63 68 64 69 void kmsg_dump_rewind(struct kmsg_dumper *dumper); 65 70 ··· 74 69 #else 75 70 static inline void kmsg_dump(enum kmsg_dump_reason reason) 76 71 { 72 + } 73 + 74 + static inline bool kmsg_dump_get_line_nolock(struct kmsg_dumper *dumper, 75 + bool syslog, const char *line, 76 + size_t size, size_t *len) 77 + { 78 + return false; 77 79 } 78 80 79 81 static inline bool kmsg_dump_get_line(struct kmsg_dumper *dumper, bool syslog, ··· 93 81 char *buf, size_t size, size_t *len) 94 82 { 95 83 return false; 84 + } 85 + 86 + static inline void kmsg_dump_rewind_nolock(struct kmsg_dumper *dumper) 87 + { 96 88 } 97 89 98 90 static inline void kmsg_dump_rewind(struct kmsg_dumper *dumper)
+33 -58
kernel/debug/kdb/kdb_main.c
··· 14 14 #include <linux/ctype.h> 15 15 #include <linux/string.h> 16 16 #include <linux/kernel.h> 17 + #include <linux/kmsg_dump.h> 17 18 #include <linux/reboot.h> 18 19 #include <linux/sched.h> 19 20 #include <linux/sysrq.h> ··· 2041 2040 */ 2042 2041 static int kdb_dmesg(int argc, const char **argv) 2043 2042 { 2044 - char *syslog_data[4], *start, *end, c = '\0', *p; 2045 - int diag, logging, logsize, lines = 0, adjust = 0, n; 2043 + int diag; 2044 + int logging; 2045 + int lines = 0; 2046 + int adjust = 0; 2047 + int n = 0; 2048 + int skip = 0; 2049 + struct kmsg_dumper dumper = { .active = 1 }; 2050 + size_t len; 2051 + char buf[201]; 2046 2052 2047 2053 if (argc > 2) 2048 2054 return KDB_ARGCOUNT; ··· 2072 2064 kdb_set(2, setargs); 2073 2065 } 2074 2066 2075 - /* syslog_data[0,1] physical start, end+1. syslog_data[2,3] 2076 - * logical start, end+1. */ 2077 - kdb_syslog_data(syslog_data); 2078 - if (syslog_data[2] == syslog_data[3]) 2079 - return 0; 2080 - logsize = syslog_data[1] - syslog_data[0]; 2081 - start = syslog_data[2]; 2082 - end = syslog_data[3]; 2083 - #define KDB_WRAP(p) (((p - syslog_data[0]) % logsize) + syslog_data[0]) 2084 - for (n = 0, p = start; p < end; ++p) { 2085 - c = *KDB_WRAP(p); 2086 - if (c == '\n') 2087 - ++n; 2088 - } 2089 - if (c != '\n') 2090 - ++n; 2067 + kmsg_dump_rewind_nolock(&dumper); 2068 + while (kmsg_dump_get_line_nolock(&dumper, 1, NULL, 0, NULL)) 2069 + n++; 2070 + 2091 2071 if (lines < 0) { 2092 2072 if (adjust >= n) 2093 2073 kdb_printf("buffer only contains %d lines, nothing " ··· 2083 2087 else if (adjust - lines >= n) 2084 2088 kdb_printf("buffer only contains %d lines, last %d " 2085 2089 "lines printed\n", n, n - adjust); 2086 - if (adjust) { 2087 - for (; start < end && adjust; ++start) { 2088 - if (*KDB_WRAP(start) == '\n') 2089 - --adjust; 2090 - } 2091 - if (start < end) 2092 - ++start; 2093 - } 2094 - for (p = start; p < end && lines; ++p) { 2095 - if (*KDB_WRAP(p) == '\n') 2096 - ++lines; 2097 - } 2098 - end = p; 2090 + skip = adjust; 2091 + lines = abs(lines); 2099 2092 } else if (lines > 0) { 2100 - int skip = n - (adjust + lines); 2093 + skip = n - lines - adjust; 2094 + lines = abs(lines); 2101 2095 if (adjust >= n) { 2102 2096 kdb_printf("buffer only contains %d lines, " 2103 2097 "nothing printed\n", n); ··· 2098 2112 kdb_printf("buffer only contains %d lines, first " 2099 2113 "%d lines printed\n", n, lines); 2100 2114 } 2101 - for (; start < end && skip; ++start) { 2102 - if (*KDB_WRAP(start) == '\n') 2103 - --skip; 2104 - } 2105 - for (p = start; p < end && lines; ++p) { 2106 - if (*KDB_WRAP(p) == '\n') 2107 - --lines; 2108 - } 2109 - end = p; 2115 + } else { 2116 + lines = n; 2110 2117 } 2111 - /* Do a line at a time (max 200 chars) to reduce protocol overhead */ 2112 - c = '\n'; 2113 - while (start != end) { 2114 - char buf[201]; 2115 - p = buf; 2116 - if (KDB_FLAG(CMD_INTERRUPT)) 2117 - return 0; 2118 - while (start < end && (c = *KDB_WRAP(start)) && 2119 - (p - buf) < sizeof(buf)-1) { 2120 - ++start; 2121 - *p++ = c; 2122 - if (c == '\n') 2123 - break; 2118 + 2119 + if (skip >= n || skip < 0) 2120 + return 0; 2121 + 2122 + kmsg_dump_rewind_nolock(&dumper); 2123 + while (kmsg_dump_get_line_nolock(&dumper, 1, buf, sizeof(buf), &len)) { 2124 + if (skip) { 2125 + skip--; 2126 + continue; 2124 2127 } 2125 - *p = '\0'; 2126 - kdb_printf("%s", buf); 2128 + if (!lines--) 2129 + break; 2130 + 2131 + kdb_printf("%.*s\n", (int)len - 1, buf); 2127 2132 } 2128 - if (c != '\n') 2129 - kdb_printf("\n"); 2130 2133 2131 2134 return 0; 2132 2135 }
-1
kernel/debug/kdb/kdb_private.h
··· 205 205 extern int kdb_grep_leading; 206 206 extern int kdb_grep_trailing; 207 207 extern char *kdb_cmds[]; 208 - extern void kdb_syslog_data(char *syslog_data[]); 209 208 extern unsigned long kdb_task_state_string(const char *); 210 209 extern char kdb_task_state_char (const struct task_struct *); 211 210 extern unsigned long kdb_task_state(const struct task_struct *p,
+73 -46
kernel/printk.c
··· 1192 1192 return do_syslog(type, buf, len, SYSLOG_FROM_CALL); 1193 1193 } 1194 1194 1195 - #ifdef CONFIG_KGDB_KDB 1196 - /* kdb dmesg command needs access to the syslog buffer. do_syslog() 1197 - * uses locks so it cannot be used during debugging. Just tell kdb 1198 - * where the start and end of the physical and logical logs are. This 1199 - * is equivalent to do_syslog(3). 1200 - */ 1201 - void kdb_syslog_data(char *syslog_data[4]) 1202 - { 1203 - syslog_data[0] = log_buf; 1204 - syslog_data[1] = log_buf + log_buf_len; 1205 - syslog_data[2] = log_buf + log_first_idx; 1206 - syslog_data[3] = log_buf + log_next_idx; 1207 - } 1208 - #endif /* CONFIG_KGDB_KDB */ 1209 - 1210 1195 static bool __read_mostly ignore_loglevel; 1211 1196 1212 1197 static int __init ignore_loglevel_setup(char *str) ··· 2510 2525 } 2511 2526 2512 2527 /** 2528 + * kmsg_dump_get_line_nolock - retrieve one kmsg log line (unlocked version) 2529 + * @dumper: registered kmsg dumper 2530 + * @syslog: include the "<4>" prefixes 2531 + * @line: buffer to copy the line to 2532 + * @size: maximum size of the buffer 2533 + * @len: length of line placed into buffer 2534 + * 2535 + * Start at the beginning of the kmsg buffer, with the oldest kmsg 2536 + * record, and copy one record into the provided buffer. 2537 + * 2538 + * Consecutive calls will return the next available record moving 2539 + * towards the end of the buffer with the youngest messages. 2540 + * 2541 + * A return value of FALSE indicates that there are no more records to 2542 + * read. 2543 + * 2544 + * The function is similar to kmsg_dump_get_line(), but grabs no locks. 2545 + */ 2546 + bool kmsg_dump_get_line_nolock(struct kmsg_dumper *dumper, bool syslog, 2547 + char *line, size_t size, size_t *len) 2548 + { 2549 + struct log *msg; 2550 + size_t l = 0; 2551 + bool ret = false; 2552 + 2553 + if (!dumper->active) 2554 + goto out; 2555 + 2556 + if (dumper->cur_seq < log_first_seq) { 2557 + /* messages are gone, move to first available one */ 2558 + dumper->cur_seq = log_first_seq; 2559 + dumper->cur_idx = log_first_idx; 2560 + } 2561 + 2562 + /* last entry */ 2563 + if (dumper->cur_seq >= log_next_seq) 2564 + goto out; 2565 + 2566 + msg = log_from_idx(dumper->cur_idx); 2567 + l = msg_print_text(msg, 0, syslog, line, size); 2568 + 2569 + dumper->cur_idx = log_next(dumper->cur_idx); 2570 + dumper->cur_seq++; 2571 + ret = true; 2572 + out: 2573 + if (len) 2574 + *len = l; 2575 + return ret; 2576 + } 2577 + 2578 + /** 2513 2579 * kmsg_dump_get_line - retrieve one kmsg log line 2514 2580 * @dumper: registered kmsg dumper 2515 2581 * @syslog: include the "<4>" prefixes ··· 2581 2545 char *line, size_t size, size_t *len) 2582 2546 { 2583 2547 unsigned long flags; 2584 - struct log *msg; 2585 - size_t l = 0; 2586 - bool ret = false; 2587 - 2588 - if (!dumper->active) 2589 - goto out; 2548 + bool ret; 2590 2549 2591 2550 raw_spin_lock_irqsave(&logbuf_lock, flags); 2592 - if (dumper->cur_seq < log_first_seq) { 2593 - /* messages are gone, move to first available one */ 2594 - dumper->cur_seq = log_first_seq; 2595 - dumper->cur_idx = log_first_idx; 2596 - } 2597 - 2598 - /* last entry */ 2599 - if (dumper->cur_seq >= log_next_seq) { 2600 - raw_spin_unlock_irqrestore(&logbuf_lock, flags); 2601 - goto out; 2602 - } 2603 - 2604 - msg = log_from_idx(dumper->cur_idx); 2605 - l = msg_print_text(msg, 0, syslog, line, size); 2606 - 2607 - dumper->cur_idx = log_next(dumper->cur_idx); 2608 - dumper->cur_seq++; 2609 - ret = true; 2551 + ret = kmsg_dump_get_line_nolock(dumper, syslog, line, size, len); 2610 2552 raw_spin_unlock_irqrestore(&logbuf_lock, flags); 2611 - out: 2612 - if (len) 2613 - *len = l; 2553 + 2614 2554 return ret; 2615 2555 } 2616 2556 EXPORT_SYMBOL_GPL(kmsg_dump_get_line); ··· 2691 2679 EXPORT_SYMBOL_GPL(kmsg_dump_get_buffer); 2692 2680 2693 2681 /** 2682 + * kmsg_dump_rewind_nolock - reset the interator (unlocked version) 2683 + * @dumper: registered kmsg dumper 2684 + * 2685 + * Reset the dumper's iterator so that kmsg_dump_get_line() and 2686 + * kmsg_dump_get_buffer() can be called again and used multiple 2687 + * times within the same dumper.dump() callback. 2688 + * 2689 + * The function is similar to kmsg_dump_rewind(), but grabs no locks. 2690 + */ 2691 + void kmsg_dump_rewind_nolock(struct kmsg_dumper *dumper) 2692 + { 2693 + dumper->cur_seq = clear_seq; 2694 + dumper->cur_idx = clear_idx; 2695 + dumper->next_seq = log_next_seq; 2696 + dumper->next_idx = log_next_idx; 2697 + } 2698 + 2699 + /** 2694 2700 * kmsg_dump_rewind - reset the interator 2695 2701 * @dumper: registered kmsg dumper 2696 2702 * ··· 2721 2691 unsigned long flags; 2722 2692 2723 2693 raw_spin_lock_irqsave(&logbuf_lock, flags); 2724 - dumper->cur_seq = clear_seq; 2725 - dumper->cur_idx = clear_idx; 2726 - dumper->next_seq = log_next_seq; 2727 - dumper->next_idx = log_next_idx; 2694 + kmsg_dump_rewind_nolock(dumper); 2728 2695 raw_spin_unlock_irqrestore(&logbuf_lock, flags); 2729 2696 } 2730 2697 EXPORT_SYMBOL_GPL(kmsg_dump_rewind);