From: Torsten Duwe <duwe@suse.de>
Subject: pstore: automatically dump and clean dmesg entries
Patch-mainline: not yet, <NEEDS A REASON>
References: fate#315232
Dump a previous oops or panic, which has made it to pstore,
to the new syslog after reboot, optionally deleting it.
This can happen automatically, without user land interaction.
Signed-off-by: Torsten Duwe <duwe@suse.de>
---
fs/pstore/inode.c | 6 +++---
fs/pstore/internal.h | 11 +++++++++--
fs/pstore/platform.c | 33 +++++++++++++++++++++++++++------
3 files changed, 39 insertions(+), 11 deletions(-)
--- a/fs/pstore/inode.c
+++ b/fs/pstore/inode.c
@@ -429,7 +429,7 @@ fail:
* when we are re-scanning the backing store looking to add new
* error records.
*/
-void pstore_get_records(int quiet)
+void pstore_get_records(unsigned flags)
{
struct pstore_info *psi = psinfo;
struct dentry *root;
@@ -440,7 +440,7 @@ void pstore_get_records(int quiet)
root = pstore_sb->s_root;
inode_lock(d_inode(root));
- pstore_get_backend_records(psi, root, quiet);
+ pstore_get_backend_records(psi, root, flags);
inode_unlock(d_inode(root));
}
@@ -472,7 +472,7 @@ static int pstore_fill_super(struct supe
if (!sb->s_root)
return -ENOMEM;
- pstore_get_records(0);
+ pstore_get_records(PGR_VERBOSE|PGR_POPULATE);
return 0;
}
--- a/fs/pstore/internal.h
+++ b/fs/pstore/internal.h
@@ -24,9 +24,16 @@ static inline void pstore_unregister_pms
extern struct pstore_info *psinfo;
extern void pstore_set_kmsg_bytes(int);
-extern void pstore_get_records(int);
+extern void pstore_get_records(unsigned);
+/* Flags for the pstore iterator pstore_get_records() */
+#define PGR_QUIET 0
+#define PGR_VERBOSE 1
+#define PGR_POPULATE 2
+#define PGR_SYSLOG 4
+#define PGR_CLEAR 8
+
extern void pstore_get_backend_records(struct pstore_info *psi,
- struct dentry *root, int quiet);
+ struct dentry *root, unsigned flags);
extern int pstore_mkfile(struct dentry *root,
struct pstore_record *record);
extern bool pstore_is_mounted(void);
--- a/fs/pstore/platform.c
+++ b/fs/pstore/platform.c
@@ -75,6 +75,10 @@ static DEFINE_SPINLOCK(pstore_lock);
struct pstore_info *psinfo;
static char *backend;
+static int auto_action=0;
+module_param(auto_action, int, 0664);
+MODULE_PARM_DESC(auto_action, "action to take on backend "
+ "registration: 0=nothing, 1=print, 2=print+clear");
/* Compression parameters */
#ifdef CONFIG_PSTORE_ZLIB_COMPRESS
@@ -100,6 +104,8 @@ static size_t big_oops_buf_sz;
/* How much of the console log to snapshot */
static unsigned long kmsg_bytes = 10240;
+module_param(kmsg_bytes, ulong, 0644);
+MODULE_PARM_DESC(kmsg_bytes, "maximum size to save of a crash dump");
void pstore_set_kmsg_bytes(int bytes)
{
@@ -717,7 +723,11 @@ int pstore_register(struct pstore_info *
allocate_buf_for_compression();
if (pstore_is_mounted())
- pstore_get_records(0);
+ pstore_get_records(PGR_VERBOSE|PGR_POPULATE);
+
+ if (auto_action)
+ pstore_get_records(PGR_SYSLOG|
+ ((auto_action>1)?PGR_CLEAR:0));
if (psi->flags & PSTORE_FLAGS_DMESG)
pstore_register_kmsg();
@@ -823,7 +833,7 @@ static void decompress_record(struct pst
* error records.
*/
void pstore_get_backend_records(struct pstore_info *psi,
- struct dentry *root, int quiet)
+ struct dentry *root, unsigned flags)
{
int failed = 0;
@@ -841,7 +851,7 @@ void pstore_get_backend_records(struct p
*/
for (;;) {
struct pstore_record *record;
- int rc;
+ int rc = 0;
record = kzalloc(sizeof(*record), GFP_KERNEL);
if (!record) {
@@ -859,12 +869,23 @@ void pstore_get_backend_records(struct p
}
decompress_record(record);
- rc = pstore_mkfile(root, record);
+ if (flags & PGR_POPULATE)
+ rc = pstore_mkfile(root, record);
+ if (record->type == PSTORE_TYPE_DMESG) {
+ if (flags & PGR_SYSLOG) {
+ pr_notice("---------- pstore: ----------\n");
+ pr_notice("%.*s\n", (int)record->size,
+ record->buf);
+ pr_notice("-----------------------------\n");
+ }
+ if (flags & PGR_CLEAR && psi->erase)
+ psi->erase(record);
+ }
if (rc) {
/* pstore_mkfile() did not take record, so free it. */
kfree(record->buf);
kfree(record);
- if (rc != -EEXIST || !quiet)
+ if (rc != -EEXIST || (flags & PGR_VERBOSE))
failed++;
}
}
@@ -880,7 +901,7 @@ out:
static void pstore_dowork(struct work_struct *work)
{
- pstore_get_records(1);
+ pstore_get_records(PGR_QUIET|PGR_POPULATE);
}
static void pstore_timefunc(unsigned long dummy)