aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/printk.c
diff options
context:
space:
mode:
authorAnton Vorontsov <anton.vorontsov@linaro.org>2012-07-20 20:28:07 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-07-21 13:34:00 -0400
commit533827c921c34310f63e859e1d6d0feec439657d (patch)
tree6aaba38b5604be6ad3e9f7aa40239b5c3f9444e1 /kernel/printk.c
parent1b499d05eecbe04969516717a8e15afb6ad80689 (diff)
printk: Implement some unlocked kmsg_dump functions
If used from KDB, the locked variants are prone to deadlocks (suppose we got to the debugger w/ the logbuf lock held). So, we have to implement a few routines that grab no logbuf lock. Yet we don't need these functions in modules, so we don't export them. Signed-off-by: Anton Vorontsov <anton.vorontsov@linaro.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'kernel/printk.c')
-rw-r--r--kernel/printk.c68
1 files changed, 55 insertions, 13 deletions
diff --git a/kernel/printk.c b/kernel/printk.c
index c8129678dfbf..ac4bc9e79465 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -2510,7 +2510,7 @@ void kmsg_dump(enum kmsg_dump_reason reason)
2510} 2510}
2511 2511
2512/** 2512/**
2513 * kmsg_dump_get_line - retrieve one kmsg log line 2513 * kmsg_dump_get_line_nolock - retrieve one kmsg log line (unlocked version)
2514 * @dumper: registered kmsg dumper 2514 * @dumper: registered kmsg dumper
2515 * @syslog: include the "<4>" prefixes 2515 * @syslog: include the "<4>" prefixes
2516 * @line: buffer to copy the line to 2516 * @line: buffer to copy the line to
@@ -2525,11 +2525,12 @@ void kmsg_dump(enum kmsg_dump_reason reason)
2525 * 2525 *
2526 * 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
2527 * read. 2527 * read.
2528 *
2529 * The function is similar to kmsg_dump_get_line(), but grabs no locks.
2528 */ 2530 */
2529bool kmsg_dump_get_line(struct kmsg_dumper *dumper, bool syslog, 2531bool kmsg_dump_get_line_nolock(struct kmsg_dumper *dumper, bool syslog,
2530 char *line, size_t size, size_t *len) 2532 char *line, size_t size, size_t *len)
2531{ 2533{
2532 unsigned long flags;
2533 struct log *msg; 2534 struct log *msg;
2534 size_t l = 0; 2535 size_t l = 0;
2535 bool ret = false; 2536 bool ret = false;
@@ -2537,7 +2538,6 @@ bool kmsg_dump_get_line(struct kmsg_dumper *dumper, bool syslog,
2537 if (!dumper->active) 2538 if (!dumper->active)
2538 goto out; 2539 goto out;
2539 2540
2540 raw_spin_lock_irqsave(&logbuf_lock, flags);
2541 if (dumper->cur_seq < log_first_seq) { 2541 if (dumper->cur_seq < log_first_seq) {
2542 /* messages are gone, move to first available one */ 2542 /* messages are gone, move to first available one */
2543 dumper->cur_seq = log_first_seq; 2543 dumper->cur_seq = log_first_seq;
@@ -2545,10 +2545,8 @@ bool kmsg_dump_get_line(struct kmsg_dumper *dumper, bool syslog,
2545 } 2545 }
2546 2546
2547 /* last entry */ 2547 /* last entry */
2548 if (dumper->cur_seq >= log_next_seq) { 2548 if (dumper->cur_seq >= log_next_seq)
2549 raw_spin_unlock_irqrestore(&logbuf_lock, flags);
2550 goto out; 2549 goto out;
2551 }
2552 2550
2553 msg = log_from_idx(dumper->cur_idx); 2551 msg = log_from_idx(dumper->cur_idx);
2554 l = msg_print_text(msg, 0, syslog, line, size); 2552 l = msg_print_text(msg, 0, syslog, line, size);
@@ -2556,12 +2554,41 @@ bool kmsg_dump_get_line(struct kmsg_dumper *dumper, bool syslog,
2556 dumper->cur_idx = log_next(dumper->cur_idx); 2554 dumper->cur_idx = log_next(dumper->cur_idx);
2557 dumper->cur_seq++; 2555 dumper->cur_seq++;
2558 ret = true; 2556 ret = true;
2559 raw_spin_unlock_irqrestore(&logbuf_lock, flags);
2560out: 2557out:
2561 if (len) 2558 if (len)
2562 *len = l; 2559 *len = l;
2563 return ret; 2560 return ret;
2564} 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 */
2580bool 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}
2565EXPORT_SYMBOL_GPL(kmsg_dump_get_line); 2592EXPORT_SYMBOL_GPL(kmsg_dump_get_line);
2566 2593
2567/** 2594/**
@@ -2664,6 +2691,24 @@ out:
2664EXPORT_SYMBOL_GPL(kmsg_dump_get_buffer); 2691EXPORT_SYMBOL_GPL(kmsg_dump_get_buffer);
2665 2692
2666/** 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 */
2703void 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/**
2667 * kmsg_dump_rewind - reset the interator 2712 * kmsg_dump_rewind - reset the interator
2668 * @dumper: registered kmsg dumper 2713 * @dumper: registered kmsg dumper
2669 * 2714 *
@@ -2676,10 +2721,7 @@ void kmsg_dump_rewind(struct kmsg_dumper *dumper)
2676 unsigned long flags; 2721 unsigned long flags;
2677 2722
2678 raw_spin_lock_irqsave(&logbuf_lock, flags); 2723 raw_spin_lock_irqsave(&logbuf_lock, flags);
2679 dumper->cur_seq = clear_seq; 2724 kmsg_dump_rewind_nolock(dumper);
2680 dumper->cur_idx = clear_idx;
2681 dumper->next_seq = log_next_seq;
2682 dumper->next_idx = log_next_idx;
2683 raw_spin_unlock_irqrestore(&logbuf_lock, flags); 2725 raw_spin_unlock_irqrestore(&logbuf_lock, flags);
2684} 2726}
2685EXPORT_SYMBOL_GPL(kmsg_dump_rewind); 2727EXPORT_SYMBOL_GPL(kmsg_dump_rewind);