All of lore.kernel.org
 help / color / mirror / Atom feed
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);
 }

  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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.