diff options
| author | Anton Vorontsov <anton.vorontsov@linaro.org> | 2012-05-26 06:20:19 -0700 | 
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-06-13 16:59:27 -0700 | 
| commit | f29e5956aebafe63f81e80f972c44c4a666e5c7f (patch) | |
| tree | 16b1c8c095f8a1d0d12bd2e6cb66e29ab4c1e516 | |
| parent | 89a86a2da30a6a90dda719874092905cd762b7ef (diff) | |
| download | olio-linux-3.10-f29e5956aebafe63f81e80f972c44c4a666e5c7f.tar.xz olio-linux-3.10-f29e5956aebafe63f81e80f972c44c4a666e5c7f.zip  | |
pstore: Add console log messages support
Pstore doesn't support logging kernel messages in run-time, it only
dumps dmesg when kernel oopses/panics. This makes pstore useless for
debugging hangs caused by HW issues or improper use of HW (e.g.
weird device inserted -> driver tried to write a reserved bits ->
SoC hanged. In that case we don't get any messages in the pstore.
Therefore, let's add a runtime logging support: PSTORE_TYPE_CONSOLE.
Signed-off-by: Anton Vorontsov <anton.vorontsov@linaro.org>
Acked-by: Kees Cook <keescook@chromium.org>
Acked-by: Colin Cross <ccross@android.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
| -rw-r--r-- | fs/pstore/Kconfig | 7 | ||||
| -rw-r--r-- | fs/pstore/inode.c | 3 | ||||
| -rw-r--r-- | fs/pstore/platform.c | 37 | ||||
| -rw-r--r-- | include/linux/pstore.h | 1 | 
4 files changed, 48 insertions, 0 deletions
diff --git a/fs/pstore/Kconfig b/fs/pstore/Kconfig index 23ade2680a4..d044de6ee30 100644 --- a/fs/pstore/Kconfig +++ b/fs/pstore/Kconfig @@ -12,6 +12,13 @@ config PSTORE  	   If you don't have a platform persistent store driver,  	   say N. +config PSTORE_CONSOLE +	bool "Log kernel console messages" +	depends on PSTORE +	help +	  When the option is enabled, pstore will log all kernel +	  messages, even if no oops or panic happened. +  config PSTORE_RAM  	tristate "Log panic/oops to a RAM buffer"  	depends on PSTORE diff --git a/fs/pstore/inode.c b/fs/pstore/inode.c index 11a2aa2a56c..45bff5441b0 100644 --- a/fs/pstore/inode.c +++ b/fs/pstore/inode.c @@ -212,6 +212,9 @@ int pstore_mkfile(enum pstore_type_id type, char *psname, u64 id,  	case PSTORE_TYPE_DMESG:  		sprintf(name, "dmesg-%s-%lld", psname, id);  		break; +	case PSTORE_TYPE_CONSOLE: +		sprintf(name, "console-%s", psname); +		break;  	case PSTORE_TYPE_MCE:  		sprintf(name, "mce-%s-%lld", psname, id);  		break; diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c index 82c585f715e..61461ed9b6c 100644 --- a/fs/pstore/platform.c +++ b/fs/pstore/platform.c @@ -1,6 +1,7 @@  /*   * Persistent Storage - platform driver interface parts.   * + * Copyright (C) 2007-2008 Google, Inc.   * Copyright (C) 2010 Intel Corporation <tony.luck@intel.com>   *   *  This program is free software; you can redistribute it and/or modify @@ -22,6 +23,7 @@  #include <linux/errno.h>  #include <linux/init.h>  #include <linux/kmsg_dump.h> +#include <linux/console.h>  #include <linux/module.h>  #include <linux/pstore.h>  #include <linux/string.h> @@ -156,6 +158,40 @@ static struct kmsg_dumper pstore_dumper = {  	.dump = pstore_dump,  }; +#ifdef CONFIG_PSTORE_CONSOLE +static void pstore_console_write(struct console *con, const char *s, unsigned c) +{ +	const char *e = s + c; + +	while (s < e) { +		unsigned long flags; + +		if (c > psinfo->bufsize) +			c = psinfo->bufsize; +		spin_lock_irqsave(&psinfo->buf_lock, flags); +		memcpy(psinfo->buf, s, c); +		psinfo->write(PSTORE_TYPE_CONSOLE, 0, NULL, 0, c, psinfo); +		spin_unlock_irqrestore(&psinfo->buf_lock, flags); +		s += c; +		c = e - s; +	} +} + +static struct console pstore_console = { +	.name	= "pstore", +	.write	= pstore_console_write, +	.flags	= CON_PRINTBUFFER | CON_ENABLED | CON_ANYTIME, +	.index	= -1, +}; + +static void pstore_register_console(void) +{ +	register_console(&pstore_console); +} +#else +static void pstore_register_console(void) {} +#endif +  /*   * platform specific persistent storage driver registers with   * us here. If pstore is already mounted, call the platform @@ -193,6 +229,7 @@ int pstore_register(struct pstore_info *psi)  		pstore_get_records(0);  	kmsg_dump_register(&pstore_dumper); +	pstore_register_console();  	pstore_timer.expires = jiffies + PSTORE_INTERVAL;  	add_timer(&pstore_timer); diff --git a/include/linux/pstore.h b/include/linux/pstore.h index e1461e143be..1bd014b8e43 100644 --- a/include/linux/pstore.h +++ b/include/linux/pstore.h @@ -29,6 +29,7 @@  enum pstore_type_id {  	PSTORE_TYPE_DMESG	= 0,  	PSTORE_TYPE_MCE		= 1, +	PSTORE_TYPE_CONSOLE	= 2,  	PSTORE_TYPE_UNKNOWN	= 255  };  |