summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKay Sievers <kay@vrfy.org>2012-05-30 13:21:23 +0200
committerKay Sievers <kay@vrfy.org>2012-05-30 13:21:23 +0200
commit87194496259865729be1fccde58309002ce851c0 (patch)
tree16fd4795a53b70668754dbbd5e4f1c89536772c5
parent607b6e8fa7ca61dd385d632fe51c6afc5f5374b7 (diff)
downloadpatches-87194496259865729be1fccde58309002ce851c0.tar.gz
update
-rw-r--r--kmsg_dump.patch168
1 files changed, 114 insertions, 54 deletions
diff --git a/kmsg_dump.patch b/kmsg_dump.patch
index f3ee532..e706dca 100644
--- a/kmsg_dump.patch
+++ b/kmsg_dump.patch
@@ -1,11 +1,11 @@
---
- arch/powerpc/platforms/pseries/nvram.c | 60 +---------
- arch/x86/platform/mrst/early_printk_mrst.c | 13 --
- drivers/mtd/mtdoops.c | 22 ---
- fs/pstore/platform.c | 34 ++---
- include/linux/kmsg_dump.h | 39 +++++-
- kernel/printk.c | 173 ++++++++++++++++++++++++-----
- 6 files changed, 204 insertions(+), 137 deletions(-)
+ arch/powerpc/platforms/pseries/nvram.c | 61 -------
+ arch/x86/platform/mrst/early_printk_mrst.c | 13 -
+ drivers/mtd/mtdoops.c | 22 --
+ fs/pstore/platform.c | 34 +---
+ include/linux/kmsg_dump.h | 45 ++++-
+ kernel/printk.c | 222 +++++++++++++++++++++++++----
+ 6 files changed, 259 insertions(+), 138 deletions(-)
--- a/arch/powerpc/platforms/pseries/nvram.c
+++ b/arch/powerpc/platforms/pseries/nvram.c
@@ -88,7 +88,7 @@
{
static unsigned int oops_count = 0;
static bool panicking = false;
-@@ -660,14 +613,13 @@ static void oops_to_nvram(struct kmsg_du
+@@ -660,14 +613,14 @@ static void oops_to_nvram(struct kmsg_du
return;
if (big_oops_buf) {
@@ -102,6 +102,7 @@
if (rc != 0) {
- text_len = capture_last_msgs(old_msgs, old_len,
- new_msgs, new_len, oops_data, oops_data_sz);
++ kmsg_dump_rewind(dumper);
+ kmsg_dump_get_buffer(dumper, true,
+ oops_data, oops_data_sz, &text_len);
err_type = ERR_TYPE_KERNEL_PANIC;
@@ -256,7 +257,7 @@
KMSG_DUMP_PANIC,
KMSG_DUMP_OOPS,
KMSG_DUMP_EMERG,
-@@ -31,23 +32,35 @@ enum kmsg_dump_reason {
+@@ -31,23 +32,37 @@ enum kmsg_dump_reason {
/**
* struct kmsg_dumper - kernel crash message dumper structure
@@ -291,15 +292,17 @@
void kmsg_dump(enum kmsg_dump_reason reason);
+bool kmsg_dump_get_line(struct kmsg_dumper *dumper, bool syslog,
-+ char *line, size_t size, size_t *len);
++ char *line, size_t size, size_t *len);
+
+bool kmsg_dump_get_buffer(struct kmsg_dumper *dumper, bool syslog,
+ char *buf, size_t size, size_t *len);
+
++void kmsg_dump_rewind(struct kmsg_dumper *dumper);
++
int kmsg_dump_register(struct kmsg_dumper *dumper);
int kmsg_dump_unregister(struct kmsg_dumper *dumper);
-@@ -56,6 +69,18 @@ static inline void kmsg_dump(enum kmsg_d
+@@ -56,6 +71,22 @@ static inline void kmsg_dump(enum kmsg_d
{
}
@@ -315,6 +318,10 @@
+ return false;
+}
+
++void kmsg_dump_rewind(struct kmsg_dumper *dumper)
++{
++}
++
static inline int kmsg_dump_register(struct kmsg_dumper *dumper)
{
return -EINVAL;
@@ -347,7 +354,15 @@
next_seq = log_next_seq;
len = 0;
-@@ -2305,43 +2307,158 @@ module_param_named(always_kmsg_dump, alw
+@@ -2300,48 +2302,210 @@ module_param_named(always_kmsg_dump, alw
+ * kmsg_dump - dump kernel log to kernel message dumpers.
+ * @reason: the reason (oops, panic etc) for dumping
+ *
+- * Iterate through each of the dump devices and call the oops/panic
+- * callbacks with the log buffer.
++ * Call each of the registered dumper's dump() callback, which can
++ * retrieve the kmsg records with kmsg_dump_get_line() or
++ * kmsg_dump_get_buffer().
*/
void kmsg_dump(enum kmsg_dump_reason reason)
{
@@ -367,46 +382,42 @@
+ list_for_each_entry_rcu(dumper, &dump_list, list) {
+ if (dumper->max_reason && reason > dumper->max_reason)
+ continue;
-
-- raw_spin_lock_irqsave(&logbuf_lock, flags);
-- if (syslog_seq < log_first_seq)
-- idx = syslog_idx;
-- else
-- idx = log_first_idx;
--
-- if (idx > log_next_idx) {
-- s1 = log_buf;
-- l1 = log_next_idx;
++
+ /* initialize iterator with data about the stored records */
+ dumper->active = true;
-
-- s2 = log_buf + idx;
-- l2 = log_buf_len - idx;
-- } else {
-- s1 = "";
-- l1 = 0;
++
+ raw_spin_lock_irqsave(&logbuf_lock, flags);
+ dumper->cur_seq = clear_seq;
+ dumper->cur_idx = clear_idx;
+ dumper->next_seq = log_next_seq;
+ dumper->next_idx = log_next_idx;
+ raw_spin_unlock_irqrestore(&logbuf_lock, flags);
-
-- s2 = log_buf + idx;
-- l2 = log_next_idx - idx;
++
+ /* invoke dumper which will iterate over records */
+ dumper->dump(dumper, reason);
+
+ /* reset iterator */
+ dumper->active = false;
- }
++ }
+ rcu_read_unlock();
+}
+
-+/*
-+ * Start at the *oldest* kmsg record, and print one line into the provided
-+ * buffer. Repeated calls will return the next record. A return value of
-+ * FALSE indicates that all records are read including the youngest one.
++/**
++ * kmsg_dump_get_line - retrieve one kmsg log line
++ * @dumper: registered kmsg dumper
++ * @syslog: include the "<4>" prefixes
++ * @line: buffer to copy the line to
++ * @size: maximum size of the buffer
++ * @len: length of line placed into buffer
++ *
++ * Start at the beginning of the kmsg buffer, with the oldest kmsg
++ * record, and copy one record into the provided buffer.
++ *
++ * Consecutive calls will return the next available record moving
++ * towards the end of the buffer with the youngest messages.
++ *
++ * A return value of FALSE indicate that there are no more records to
++ * read.
+ */
+bool kmsg_dump_get_line(struct kmsg_dumper *dumper, bool syslog,
+ char *line, size_t size, size_t *len)
@@ -418,20 +429,35 @@
+
+ if (!dumper->active)
+ goto out;
-+
-+ raw_spin_lock_irqsave(&logbuf_lock, flags);
+
+ raw_spin_lock_irqsave(&logbuf_lock, flags);
+- if (syslog_seq < log_first_seq)
+- idx = syslog_idx;
+- else
+- idx = log_first_idx;
+-
+- if (idx > log_next_idx) {
+- s1 = log_buf;
+- l1 = log_next_idx;
+ if (dumper->cur_seq < log_first_seq) {
+ /* messages are gone, move to first available one */
+ dumper->cur_seq = log_first_seq;
+ dumper->cur_idx = log_first_idx;
+ }
-+
+
+- s2 = log_buf + idx;
+- l2 = log_buf_len - idx;
+- } else {
+- s1 = "";
+- l1 = 0;
+ /* last entry */
+ if (dumper->cur_seq >= log_next_seq) {
+ raw_spin_unlock_irqrestore(&logbuf_lock, flags);
+ goto out;
+ }
-+
+
+- s2 = log_buf + idx;
+- l2 = log_next_idx - idx;
+ msg = log_from_idx(dumper->cur_idx);
+ l = msg_print_text(msg, syslog,
+ line, size);
@@ -439,23 +465,32 @@
+ dumper->cur_idx = log_next(dumper->cur_idx);
+ dumper->cur_seq++;
+ ret = true;
- raw_spin_unlock_irqrestore(&logbuf_lock, flags);
++ raw_spin_unlock_irqrestore(&logbuf_lock, flags);
+out:
+ if (len)
+ *len = l;
+ return ret;
+}
+EXPORT_SYMBOL_GPL(kmsg_dump_get_line);
-
-- rcu_read_lock();
-- list_for_each_entry_rcu(dumper, &dump_list, list)
-- dumper->dump(dumper, reason, s1, l1, s2, l2);
-- rcu_read_unlock();
-+/*
-+ * Fill the provided buffer with as many of the the *youngest* kmsg records
-+ * that fit into it. Repeated calls will fill the buffer with the next block
-+ * of older records, not including the former ones. A return value of FALSE
-+ * indicate that all records are read, including the oldest one.
++
++/**
++ * kmsg_dump_get_buffer - copy kmsg log lines
++ * @dumper: registered kmsg dumper
++ * @syslog: include the "<4>" prefixes
++ * @line: buffer to copy the line to
++ * @size: maximum size of the buffer
++ * @len: length of line placed into buffer
++ *
++ * Start at the end of the kmsg buffer and fill the provided buffer
++ * with as many of the the *youngest* kmsg records that fit into it.
++ * If the buffer is large enough, all available kmsg records will be
++ * copied with a single call.
++ *
++ * Consecutive calls will fill the buffer with the next block of
++ * available older records, not including the earlier retrieved ones.
++ *
++ * A return value of FALSE indicate that there are no more records to
++ * read.
+ */
+bool kmsg_dump_get_buffer(struct kmsg_dumper *dumper, bool syslog,
+ char *buf, size_t size, size_t *len)
@@ -519,16 +554,41 @@
+
+ idx = log_next(idx);
+ seq++;
-+ }
+ }
+
+ dumper->next_seq = next_seq;
+ dumper->next_idx = next_idx;
+ ret = true;
-+ raw_spin_unlock_irqrestore(&logbuf_lock, flags);
+ raw_spin_unlock_irqrestore(&logbuf_lock, flags);
+out:
+ if (len)
+ *len = l;
+ return ret;
- }
++}
+EXPORT_SYMBOL_GPL(kmsg_dump_get_buffer);
+
+- rcu_read_lock();
+- list_for_each_entry_rcu(dumper, &dump_list, list)
+- dumper->dump(dumper, reason, s1, l1, s2, l2);
+- rcu_read_unlock();
++/**
++ * kmsg_dump_rewind - reset the interator
++ * @dumper: registered kmsg dumper
++ *
++ * Reset the dumper's iterator so that kmsg_dump_get_line() and
++ * kmsg_dump_get_buffer() can be called again and used multiple
++ * times within the same dumper.dump() callback.
++ */
++void kmsg_dump_rewind(struct kmsg_dumper *dumper)
++{
++ unsigned long flags;
++
++ raw_spin_lock_irqsave(&logbuf_lock, flags);
++ dumper->cur_seq = clear_seq;
++ dumper->cur_idx = clear_idx;
++ dumper->next_seq = log_next_seq;
++ dumper->next_idx = log_next_idx;
++ raw_spin_unlock_irqrestore(&logbuf_lock, flags);
+ }
++EXPORT_SYMBOL_GPL(kmsg_dump_rewind);
#endif