From patchwork Tue Oct 13 13:22:35 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Kagstrom X-Patchwork-Id: 35855 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from bombadil.infradead.org (bombadil.infradead.org [18.85.46.34]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 87001B7B8C for ; Wed, 14 Oct 2009 00:26:40 +1100 (EST) Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.69 #1 (Red Hat Linux)) id 1MxhKw-00083A-DH; Tue, 13 Oct 2009 13:22:46 +0000 Received: from ernst.netinsight.se ([194.16.221.21]) by bombadil.infradead.org with smtp (Exim 4.69 #1 (Red Hat Linux)) id 1MxhKq-00081N-Ci for linux-mtd@lists.infradead.org; Tue, 13 Oct 2009 13:22:44 +0000 Received: from marrow.netinsight.se (unverified [10.100.3.78]) by ernst.netinsight.se (EMWAC SMTPRS 0.83) with SMTP id ; Tue, 13 Oct 2009 15:22:32 +0200 Date: Tue, 13 Oct 2009 15:22:35 +0200 From: Simon Kagstrom To: Linus Torvalds , linux-mtd Subject: [PATCH/RFC v5 4/5]: core: Add dump device to call on oopses and panics Message-ID: <20091013152235.188059d2@marrow.netinsight.se> In-Reply-To: <20091013151751.59e217a7@marrow.netinsight.se> References: <20091012113758.GB11035@elte.hu> <20091012140149.6789efab@marrow.netinsight.se> <20091012120951.GA16799@elte.hu> <1255349748.10605.13.camel@macbook.infradead.org> <20091012122023.GA19365@elte.hu> <20091012150650.51a4b4dc@marrow.netinsight.se> <20091012131528.GC25464@elte.hu> <20091012153937.0dcd73e5@marrow.netinsight.se> <20091012110954.67d7d8d8.akpm@linux-foundation.org> <20091012182346.GH17138@elte.hu> <20091013151751.59e217a7@marrow.netinsight.se> X-Mailer: Claws Mail 3.7.3 (GTK+ 2.16.1; i486-pc-linux-gnu) Mime-Version: 1.0 X-CRM114-Version: 20090807-BlameThorstenAndJenny ( TRE 0.7.6 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20091013_092240_649067_4FF658B2 X-CRM114-Status: GOOD ( 23.10 ) X-Spam-Score: 0.0 (/) X-Spam-Report: SpamAssassin version 3.2.5 on bombadil.infradead.org summary: Content analysis details: (0.0 points) pts rule name description ---- ---------------------- -------------------------------------------------- _SUMMARY_ Cc: Artem Bityutskiy , LKML , "Koskinen Aaro \(Nokia-D/Helsinki\)" , Ingo Molnar , David Woodhouse , Andrew Morton , Alan Cox X-BeenThere: linux-mtd@lists.infradead.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: Linux MTD discussion mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: linux-mtd-bounces@lists.infradead.org Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org The core functionality is implemented as per Linus suggestion from http://lists.infradead.org/pipermail/linux-mtd/2009-October/027620.html a struct dump_device type has been added which contains callbacks to dump the kernel log buffers on crashes. The dump_kmsg function gets called from oops_exit() and panic() and invokes these callbacks. Signed-off-by: Simon Kagstrom --- include/linux/dump_device.h | 33 +++++++++++++++++ kernel/panic.c | 3 ++ kernel/printk.c | 83 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 119 insertions(+), 0 deletions(-) create mode 100644 include/linux/dump_device.h diff --git a/include/linux/dump_device.h b/include/linux/dump_device.h new file mode 100644 index 0000000..8c3f378 --- /dev/null +++ b/include/linux/dump_device.h @@ -0,0 +1,33 @@ +/* + * linux/include/dump_device.h + * + * Copyright (C) 2009 Net Insight + * + * Author: Simon Kagstrom + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive + * for more details. + */ +#ifndef _LINUX_DUMP_DEVICE_H +#define _LINUX_DUMP_DEVICE_H + +#include + +struct dump_device { + void (*oops)(struct dump_device *, const char *, unsigned long, + const char *, unsigned long); + void (*panic)(struct dump_device *, const char *, unsigned long, + const char *, unsigned long); + int (*setup)(struct dump_device *); + void *priv; + struct list_head list; +}; + +void dump_kmsg(int panic); + +int register_dumpdevice(struct dump_device *dump, void *priv); + +void unregister_dumpdevice(struct dump_device *dump); + +#endif /* _LINUX_DUMP_DEVICE_H */ diff --git a/kernel/panic.c b/kernel/panic.c index c0b33b8..e7dbf2b 100644 --- a/kernel/panic.c +++ b/kernel/panic.c @@ -8,6 +8,7 @@ * This function is used through-out the kernel (including mm and fs) * to indicate a major problem. */ +#include #include #include #include @@ -76,6 +77,7 @@ NORET_TYPE void panic(const char * fmt, ...) dump_stack(); #endif + dump_kmsg(1); /* * If we have crashed and we have a crash kernel loaded let it handle * everything else. @@ -341,6 +343,7 @@ void oops_exit(void) { do_oops_enter_exit(); print_oops_end_marker(); + dump_kmsg(0); } #ifdef WANT_WARN_ON_SLOWPATH diff --git a/kernel/printk.c b/kernel/printk.c index f38b07f..5e1fe73 100644 --- a/kernel/printk.c +++ b/kernel/printk.c @@ -33,6 +33,7 @@ #include #include #include +#include #include @@ -1405,3 +1406,85 @@ bool printk_timed_ratelimit(unsigned long *caller_jiffies, } EXPORT_SYMBOL(printk_timed_ratelimit); #endif + +static LIST_HEAD(dump_list); +static DEFINE_RWLOCK(dump_list_lock); + +/** + * register_dump_device - register a dumpdevice. + * @dump: pointer to the dump structure + * @priv: private data for the structure + * + * Adds a dump device to the system. The oops and panic callbacks + * in the structure will be called when the kernel oopses and panics + * respectively. At least one of these must be set. Returns zero on + * success and -EINVAL otherwise. + */ +int register_dumpdevice(struct dump_device *dump, void *priv) +{ + /* We need at least one of these set */ + if (!dump->oops && !dump->panic) + return -EINVAL; + if (dump->setup && dump->setup(dump) != 0) + return -EINVAL; + dump->priv = priv; + + INIT_LIST_HEAD(&dump->list); + write_lock(&dump_list_lock); + list_add(&dump->list, &dump_list); + write_unlock(&dump_list_lock); + return 0; +} +EXPORT_SYMBOL(register_dumpdevice); + +/** + * unregister_dump_device - unregister a dumpdevice. + * @dump: pointer to the dump structure + * + * Removes a dump device from the system. + */ +void unregister_dumpdevice(struct dump_device *dump) +{ + write_lock(&dump_list_lock); + list_del(&dump->list); + write_unlock(&dump_list_lock); +} +EXPORT_SYMBOL(unregister_dumpdevice); + +/** + * dump_kmsg - dump kernel log to dump devices. + * @panic: if this is a panic (1) or an oops (0) + * + * Iterate through each of the dump devices and call the oops/panic + * callbacks with the log buffer. + */ +void dump_kmsg(int panic) +{ + unsigned long len = ACCESS_ONCE(log_end); + struct dump_device *dump; + const char *s1, *s2; + unsigned long l1, l2; + + s1 = ""; + l1 = 0; + s2 = log_buf; + l2 = len; + + /* Have we rotated around the circular buffer? */ + if (len > log_buf_len) { + unsigned long pos = (len & LOG_BUF_MASK); + + s1 = log_buf + pos; + l1 = log_buf_len - pos; + + s2 = log_buf; + l2 = pos; + } + + list_for_each_entry(dump, &dump_list, list) { + if (panic && dump->panic) + dump->panic(dump, s1, l1, s2, l2); + else if (!panic && dump->oops) + dump->oops(dump, s1, l1, s2, l2); + } +}