From: Jim Keniston <jkenisto@us.ibm.com>
To: linuxppc-dev@lists.ozlabs.org
Subject: [PATCH 3/6] nvram: Always capture start of oops report to NVRAM
Date: Sat, 13 Nov 2010 20:15:27 -0800 [thread overview]
Message-ID: <20101114041527.9457.8308.stgit@localhost.localdomain> (raw)
In-Reply-To: <20101114041510.9457.92921.stgit@localhost.localdomain>
If we don't have room to capture the entire oops report, capture as much
as possible, starting 150 chars before the "Oops:" line.
Signed-off-by: Jim Keniston <jkenisto@us.ibm.com>
---
arch/powerpc/platforms/pseries/nvram.c | 91 ++++++++++++++++++++++++++++++++
1 files changed, 91 insertions(+), 0 deletions(-)
diff --git a/arch/powerpc/platforms/pseries/nvram.c b/arch/powerpc/platforms/pseries/nvram.c
index 6c88cda..e1bc1a4 100644
--- a/arch/powerpc/platforms/pseries/nvram.c
+++ b/arch/powerpc/platforms/pseries/nvram.c
@@ -446,6 +446,87 @@ static size_t capture_last_msgs(const char *old_msgs, size_t old_len,
}
}
+/* Find the last occurrence of needle in haystack, which is haystack_len long.*/
+static const char *strnrstr(const char *haystack, const char *needle,
+ size_t haystack_len)
+{
+ size_t needle_len = strlen(needle);
+ const char *haystack_end = haystack + haystack_len;
+ const char *prev, *next = NULL;
+ do {
+ prev = next;
+ next = strnstr(haystack, needle, haystack_len);
+ if (next) {
+ haystack = next + needle_len;
+ haystack_len = haystack_end - haystack;
+ }
+ } while (next);
+ return prev;
+}
+
+/* The preamble is the last bit of messages logged before the oops. */
+#define PREAMBLE_CHARS 150
+#define OOPS_TAG "Oops: "
+
+/*
+ * Find the beginning of the most recent oops report, back up PREAMBLE_CHARS
+ * characters, and copy up to captured_len characters from there to captured[].
+ * If we can't find the oops, just capture the end of the printk buffer,
+ * if we haven't already.
+ */
+static size_t capture_oops(const char *old_msgs, size_t old_len,
+ const char *new_msgs, size_t new_len,
+ char *captured, size_t capture_len,
+ size_t already_captured)
+{
+ const char *poops; /* Points to the 'O' in "Oops: ..." */
+ const char *preamble;
+ const char *old_end = old_msgs + old_len;
+ const char *new_end = new_msgs + new_len;
+ size_t nc1, nc2;
+
+ if ((poops = strnrstr(new_msgs, OOPS_TAG, new_len)) != NULL) {
+ /* Oops starts in new_msgs -- the most common case. */
+ preamble = poops - PREAMBLE_CHARS;
+ if (preamble >= new_msgs) {
+ /* preamble is also in new_msgs. */
+ nc1 = min(capture_len, (size_t)(new_end - preamble));
+ memcpy(captured, preamble, nc1);
+ nc2 = 0;
+ } else {
+ /* Have to get some of the preamble from old_msgs */
+ nc1 = min((size_t)(new_msgs - preamble), old_len);
+ memcpy(captured, (old_end - nc1), nc1);
+ nc2 = min(new_len, capture_len - nc1);
+ memcpy(captured + nc1, new_msgs, nc2);
+ }
+ } else if ((poops = strnrstr(old_msgs, OOPS_TAG, old_len)) != NULL) {
+ /* Oops starts in old_msgs. */
+ preamble = poops - PREAMBLE_CHARS;
+ if (preamble < old_msgs)
+ preamble = old_msgs;
+ nc1 = min(capture_len, (size_t)(old_end - preamble));
+ memcpy(captured, preamble, nc1);
+ nc2 = min((size_t)(capture_len - nc1), new_len);
+ memcpy(captured + nc1, new_msgs, nc2);
+ } else {
+ /*
+ * Either there was a VERY long oops report that scrolled
+ * out of the printk buffer, or the "Oops" tag is split
+ * across old_msgs and new_msgs, or oopses don't start with
+ * "Oops" anymore. Just capture as much of the last messages
+ * as we think we can squeeze into NVRAM.
+ */
+ if (already_captured)
+ return already_captured;
+ nc1 = capture_last_msgs(old_msgs, old_len, new_msgs,
+ new_len, captured, capture_len);
+ nc2 = 0;
+ }
+
+ return nc1 + nc2;
+}
+
/* our kmsg_dump callback */
static void oops_to_nvram(struct kmsg_dumper *dumper,
enum kmsg_dump_reason reason,
@@ -457,6 +538,16 @@ static void oops_to_nvram(struct kmsg_dumper *dumper,
text_len = capture_last_msgs(old_msgs, old_len, new_msgs, new_len,
oops_buf, oops_buf_sz);
+ if (reason == KMSG_DUMP_OOPS) {
+ /*
+ * Ensure that we have the start of the oops report,
+ * and the message(s) leading up to it.
+ */
+ const char *poops = strnrstr(oops_buf, OOPS_TAG, oops_buf_sz);
+ if (!poops || poops < oops_buf + PREAMBLE_CHARS)
+ text_len = capture_oops(old_msgs, old_len, new_msgs,
+ new_len, oops_buf, oops_buf_sz, text_len);
+ }
(void) nvram_write_os_partition(&oops_log_partition, oops_buf,
(int) text_len, ERR_TYPE_KERNEL_PANIC, ++oops_count);
}
next prev parent reply other threads:[~2010-11-14 4:15 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-11-14 4:15 [RFC PATCH 0/6] nvram: Capture oops/panic reports in NVRAM Jim Keniston
2010-11-14 4:15 ` [PATCH 1/6] nvram: Generalize code for OS partitions " Jim Keniston
2011-02-07 4:57 ` Benjamin Herrenschmidt
2011-02-09 22:43 ` Jim Keniston
2010-11-14 4:15 ` [PATCH 2/6] nvram: Capture oops/panic reports in ibm, oops-log partition Jim Keniston
2011-02-07 5:01 ` Benjamin Herrenschmidt
2011-02-09 23:00 ` Jim Keniston
2010-11-14 4:15 ` Jim Keniston [this message]
2010-11-14 4:15 ` [PATCH 4/6] nvram: Add compression to fit more printk output into NVRAM Jim Keniston
2010-11-14 4:15 ` [PATCH 5/6] nvram: Slim down zlib_deflate workspace when possible Jim Keniston
2011-02-07 4:39 ` Benjamin Herrenschmidt
2010-11-14 4:15 ` [PATCH 6/6] nvram: Shrink our zlib_deflate workspace from 268K to 24K Jim Keniston
2010-11-14 4:36 ` [RFC PATCH 0/6] nvram: Capture oops/panic reports in NVRAM Jim Keniston
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20101114041527.9457.8308.stgit@localhost.localdomain \
--to=jkenisto@us.ibm.com \
--cc=linuxppc-dev@lists.ozlabs.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).