[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <20090820104956.29972.92662.stgit@warthog.procyon.org.uk>
Date: Thu, 20 Aug 2009 11:49:56 +0100
From: David Howells <dhowells@...hat.com>
To: torvalds@...l.org, akpm@...ux-foundation.org
Cc: dhowells@...hat.com, linux-kernel@...r.kernel.org
Subject: [PATCH 1/2] Allow the 'cut here' oops line to be displayed before
calling BUG()
Allow the 'cut here' oops line to be displayed before calling BUG() as useful
information is often displayed before BUG() is called. Also use this to limit
recursive oopsing.
Signed-off-by: David Howells <dhowells@...hat.com>
---
include/linux/bug.h | 8 ++++++++
include/linux/sched.h | 9 +++++++++
lib/bug.c | 31 +++++++++++++++++++++++++++++--
3 files changed, 46 insertions(+), 2 deletions(-)
diff --git a/include/linux/bug.h b/include/linux/bug.h
index d276b55..290309f 100644
--- a/include/linux/bug.h
+++ b/include/linux/bug.h
@@ -26,6 +26,8 @@ enum bug_trap_type report_bug(unsigned long bug_addr, struct pt_regs *regs);
/* These are defined by the architecture */
int is_valid_bugaddr(unsigned long addr);
+extern bool cut_here(void);
+
#else /* !CONFIG_GENERIC_BUG */
static inline enum bug_trap_type report_bug(unsigned long bug_addr,
@@ -34,5 +36,11 @@ static inline enum bug_trap_type report_bug(unsigned long bug_addr,
return BUG_TRAP_TYPE_BUG;
}
+static inline bool cut_here(void)
+{
+ return true;
+}
+
#endif /* CONFIG_GENERIC_BUG */
+
#endif /* _LINUX_BUG_H */
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 0f1ea4a..f4b9782 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1199,6 +1199,9 @@ struct task_struct {
*/
unsigned char fpu_counter;
s8 oomkilladj; /* OOM kill score adjustment (bit shift). */
+
+ unsigned char oopsing; /* oopsing state */
+
#ifdef CONFIG_BLK_DEV_IO_TRACE
unsigned int btrace_seq;
#endif
@@ -1700,6 +1703,12 @@ extern cputime_t task_gtime(struct task_struct *p);
#define PF_FREEZER_NOSIG 0x80000000 /* Freezer won't send signals to it */
/*
+ * current->oopsing flags
+ */
+#define OOPS_CUT_HERE 0x01 /* set if the "cut here" message is displayed */
+#define OOPS_REPORTED 0x02 /* recursion limiter */
+
+/*
* Only the _current_ task can read/write to tsk->flags, but other
* tasks can access tsk->flags in readonly mode for example
* with tsk_used_math (like during threaded core dumping).
diff --git a/lib/bug.c b/lib/bug.c
index 300e41a..2d0ed45 100644
--- a/lib/bug.c
+++ b/lib/bug.c
@@ -125,6 +125,31 @@ const struct bug_entry *find_bug(unsigned long bugaddr)
return module_find_bug(bugaddr);
}
+/**
+ * cut_here - Begin BUG() output
+ *
+ * Begin the outputting of a BUG() report with a 'cut here' line. This ensures
+ * we produce at most one 'cut here' line per process. This allows us to
+ * extend a BUG() report with extra information in front of it.
+ *
+ * We return true if the caller is free to go ahead and report their oops.
+ *
+ * We return false if we've detected a recursive oops - in which case the
+ * caller should take care, and possibly not do anything other than call BUG(),
+ * lest they cause further recursion. This is particularly true of things that
+ * might go wrong in the exit path.
+ */
+bool cut_here(void)
+{
+ if (!(current->oopsing & OOPS_CUT_HERE)) {
+ current->oopsing |= OOPS_CUT_HERE;
+ printk(KERN_EMERG "------------[ cut here ]------------\n");
+ }
+
+ return !(current->oopsing & OOPS_REPORTED);
+}
+EXPORT_SYMBOL(cut_here);
+
enum bug_trap_type report_bug(unsigned long bugaddr, struct pt_regs *regs)
{
const struct bug_entry *bug;
@@ -134,9 +159,9 @@ enum bug_trap_type report_bug(unsigned long bugaddr, struct pt_regs *regs)
if (!is_valid_bugaddr(bugaddr))
return BUG_TRAP_TYPE_NONE;
- bug = find_bug(bugaddr);
+ cut_here();
- printk(KERN_EMERG "------------[ cut here ]------------\n");
+ bug = find_bug(bugaddr);
file = NULL;
line = 0;
@@ -169,6 +194,8 @@ enum bug_trap_type report_bug(unsigned long bugaddr, struct pt_regs *regs)
return BUG_TRAP_TYPE_WARN;
}
+ current->oopsing |= OOPS_REPORTED;
+
if (file)
printk(KERN_CRIT "kernel BUG at %s:%u!\n",
file, line);
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Powered by blists - more mailing lists