diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-07-21 13:34:13 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-07-21 13:34:13 -0400 |
commit | 9a2bc8603eca4ea4a3a01163593084c5c1b3e16a (patch) | |
tree | 359ec96e8c42b037b79d2efd4cd1ee87e24c0842 /kernel/printk.c | |
parent | d75e2c9ad97c40f6d2cdaf2e16381b2034d19a6f (diff) | |
parent | c064da47144b11be4697a4611f640086a663016a (diff) |
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
Diffstat (limited to 'kernel/printk.c')
-rw-r--r-- | kernel/printk.c | 83 |
1 files changed, 55 insertions, 28 deletions
diff --git a/kernel/printk.c b/kernel/printk.c index 177fa49357a5..ac4bc9e79465 100644 --- a/kernel/printk.c +++ b/kernel/printk.c | |||
@@ -1192,21 +1192,6 @@ SYSCALL_DEFINE3(syslog, int, type, char __user *, buf, int, len) | |||
1192 | return do_syslog(type, buf, len, SYSLOG_FROM_CALL); | 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 | static bool __read_mostly ignore_loglevel; | 1195 | static bool __read_mostly ignore_loglevel; |
1211 | 1196 | ||
1212 | static int __init ignore_loglevel_setup(char *str) | 1197 | static int __init ignore_loglevel_setup(char *str) |
@@ -2525,7 +2510,7 @@ void kmsg_dump(enum kmsg_dump_reason reason) | |||
2525 | } | 2510 | } |
2526 | 2511 | ||
2527 | /** | 2512 | /** |
2528 | * kmsg_dump_get_line - retrieve one kmsg log line | 2513 | * kmsg_dump_get_line_nolock - retrieve one kmsg log line (unlocked version) |
2529 | * @dumper: registered kmsg dumper | 2514 | * @dumper: registered kmsg dumper |
2530 | * @syslog: include the "<4>" prefixes | 2515 | * @syslog: include the "<4>" prefixes |
2531 | * @line: buffer to copy the line to | 2516 | * @line: buffer to copy the line to |
@@ -2540,11 +2525,12 @@ void kmsg_dump(enum kmsg_dump_reason reason) | |||
2540 | * | 2525 | * |
2541 | * A return value of FALSE indicates that there are no more records to | 2526 | * A return value of FALSE indicates that there are no more records to |
2542 | * read. | 2527 | * read. |
2528 | * | ||
2529 | * The function is similar to kmsg_dump_get_line(), but grabs no locks. | ||
2543 | */ | 2530 | */ |
2544 | bool kmsg_dump_get_line(struct kmsg_dumper *dumper, bool syslog, | 2531 | bool kmsg_dump_get_line_nolock(struct kmsg_dumper *dumper, bool syslog, |
2545 | char *line, size_t size, size_t *len) | 2532 | char *line, size_t size, size_t *len) |
2546 | { | 2533 | { |
2547 | unsigned long flags; | ||
2548 | struct log *msg; | 2534 | struct log *msg; |
2549 | size_t l = 0; | 2535 | size_t l = 0; |
2550 | bool ret = false; | 2536 | bool ret = false; |
@@ -2552,7 +2538,6 @@ bool kmsg_dump_get_line(struct kmsg_dumper *dumper, bool syslog, | |||
2552 | if (!dumper->active) | 2538 | if (!dumper->active) |
2553 | goto out; | 2539 | goto out; |
2554 | 2540 | ||
2555 | raw_spin_lock_irqsave(&logbuf_lock, flags); | ||
2556 | if (dumper->cur_seq < log_first_seq) { | 2541 | if (dumper->cur_seq < log_first_seq) { |
2557 | /* messages are gone, move to first available one */ | 2542 | /* messages are gone, move to first available one */ |
2558 | dumper->cur_seq = log_first_seq; | 2543 | dumper->cur_seq = log_first_seq; |
@@ -2560,10 +2545,8 @@ bool kmsg_dump_get_line(struct kmsg_dumper *dumper, bool syslog, | |||
2560 | } | 2545 | } |
2561 | 2546 | ||
2562 | /* last entry */ | 2547 | /* last entry */ |
2563 | if (dumper->cur_seq >= log_next_seq) { | 2548 | if (dumper->cur_seq >= log_next_seq) |
2564 | raw_spin_unlock_irqrestore(&logbuf_lock, flags); | ||
2565 | goto out; | 2549 | goto out; |
2566 | } | ||
2567 | 2550 | ||
2568 | msg = log_from_idx(dumper->cur_idx); | 2551 | msg = log_from_idx(dumper->cur_idx); |
2569 | l = msg_print_text(msg, 0, syslog, line, size); | 2552 | l = msg_print_text(msg, 0, syslog, line, size); |
@@ -2571,12 +2554,41 @@ bool kmsg_dump_get_line(struct kmsg_dumper *dumper, bool syslog, | |||
2571 | dumper->cur_idx = log_next(dumper->cur_idx); | 2554 | dumper->cur_idx = log_next(dumper->cur_idx); |
2572 | dumper->cur_seq++; | 2555 | dumper->cur_seq++; |
2573 | ret = true; | 2556 | ret = true; |
2574 | raw_spin_unlock_irqrestore(&logbuf_lock, flags); | ||
2575 | out: | 2557 | out: |
2576 | if (len) | 2558 | if (len) |
2577 | *len = l; | 2559 | *len = l; |
2578 | return ret; | 2560 | return ret; |
2579 | } | 2561 | } |
2562 | |||
2563 | /** | ||
2564 | * kmsg_dump_get_line - retrieve one kmsg log line | ||
2565 | * @dumper: registered kmsg dumper | ||
2566 | * @syslog: include the "<4>" prefixes | ||
2567 | * @line: buffer to copy the line to | ||
2568 | * @size: maximum size of the buffer | ||
2569 | * @len: length of line placed into buffer | ||
2570 | * | ||
2571 | * Start at the beginning of the kmsg buffer, with the oldest kmsg | ||
2572 | * record, and copy one record into the provided buffer. | ||
2573 | * | ||
2574 | * Consecutive calls will return the next available record moving | ||
2575 | * towards the end of the buffer with the youngest messages. | ||
2576 | * | ||
2577 | * A return value of FALSE indicates that there are no more records to | ||
2578 | * read. | ||
2579 | */ | ||
2580 | bool kmsg_dump_get_line(struct kmsg_dumper *dumper, bool syslog, | ||
2581 | char *line, size_t size, size_t *len) | ||
2582 | { | ||
2583 | unsigned long flags; | ||
2584 | bool ret; | ||
2585 | |||
2586 | raw_spin_lock_irqsave(&logbuf_lock, flags); | ||
2587 | ret = kmsg_dump_get_line_nolock(dumper, syslog, line, size, len); | ||
2588 | raw_spin_unlock_irqrestore(&logbuf_lock, flags); | ||
2589 | |||
2590 | return ret; | ||
2591 | } | ||
2580 | EXPORT_SYMBOL_GPL(kmsg_dump_get_line); | 2592 | EXPORT_SYMBOL_GPL(kmsg_dump_get_line); |
2581 | 2593 | ||
2582 | /** | 2594 | /** |
@@ -2679,6 +2691,24 @@ out: | |||
2679 | EXPORT_SYMBOL_GPL(kmsg_dump_get_buffer); | 2691 | EXPORT_SYMBOL_GPL(kmsg_dump_get_buffer); |
2680 | 2692 | ||
2681 | /** | 2693 | /** |
2694 | * kmsg_dump_rewind_nolock - reset the interator (unlocked version) | ||
2695 | * @dumper: registered kmsg dumper | ||
2696 | * | ||
2697 | * Reset the dumper's iterator so that kmsg_dump_get_line() and | ||
2698 | * kmsg_dump_get_buffer() can be called again and used multiple | ||
2699 | * times within the same dumper.dump() callback. | ||
2700 | * | ||
2701 | * The function is similar to kmsg_dump_rewind(), but grabs no locks. | ||
2702 | */ | ||
2703 | void kmsg_dump_rewind_nolock(struct kmsg_dumper *dumper) | ||
2704 | { | ||
2705 | dumper->cur_seq = clear_seq; | ||
2706 | dumper->cur_idx = clear_idx; | ||
2707 | dumper->next_seq = log_next_seq; | ||
2708 | dumper->next_idx = log_next_idx; | ||
2709 | } | ||
2710 | |||
2711 | /** | ||
2682 | * kmsg_dump_rewind - reset the interator | 2712 | * kmsg_dump_rewind - reset the interator |
2683 | * @dumper: registered kmsg dumper | 2713 | * @dumper: registered kmsg dumper |
2684 | * | 2714 | * |
@@ -2691,10 +2721,7 @@ void kmsg_dump_rewind(struct kmsg_dumper *dumper) | |||
2691 | unsigned long flags; | 2721 | unsigned long flags; |
2692 | 2722 | ||
2693 | raw_spin_lock_irqsave(&logbuf_lock, flags); | 2723 | raw_spin_lock_irqsave(&logbuf_lock, flags); |
2694 | dumper->cur_seq = clear_seq; | 2724 | kmsg_dump_rewind_nolock(dumper); |
2695 | dumper->cur_idx = clear_idx; | ||
2696 | dumper->next_seq = log_next_seq; | ||
2697 | dumper->next_idx = log_next_idx; | ||
2698 | raw_spin_unlock_irqrestore(&logbuf_lock, flags); | 2725 | raw_spin_unlock_irqrestore(&logbuf_lock, flags); |
2699 | } | 2726 | } |
2700 | EXPORT_SYMBOL_GPL(kmsg_dump_rewind); | 2727 | EXPORT_SYMBOL_GPL(kmsg_dump_rewind); |