2019-03-01 14:56:18

by Thomas Renninger

[permalink] [raw]
Subject: [PATCH] pstore: automatically dump and clean dmesg entries

From: Torsten Duwe <[email protected]>

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 <[email protected]>
CC: Thomas Renninger <[email protected]>

---
fs/pstore/inode.c | 6 +++---
fs/pstore/internal.h | 11 +++++++++--
fs/pstore/platform.c | 33 +++++++++++++++++++++++++++------
3 files changed, 39 insertions(+), 11 deletions(-)

Index: test_pstore/fs/pstore/inode.c
===================================================================
--- test_pstore.orig/fs/pstore/inode.c 2019-03-01 13:55:50.561322896 +0100
+++ test_pstore/fs/pstore/inode.c 2019-03-01 13:56:05.349323693 +0100
@@ -374,7 +374,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;
@@ -385,7 +385,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));
}

@@ -415,7 +415,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;
}
Index: test_pstore/fs/pstore/internal.h
===================================================================
--- test_pstore.orig/fs/pstore/internal.h 2019-03-01 13:55:50.565322897 +0100
+++ test_pstore/fs/pstore/internal.h 2019-03-01 13:56:05.349323693 +0100
@@ -28,9 +28,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);
Index: test_pstore/fs/pstore/platform.c
===================================================================
--- test_pstore.orig/fs/pstore/platform.c 2019-03-01 13:55:50.565322897 +0100
+++ test_pstore/fs/pstore/platform.c 2019-03-01 13:59:06.077333431 +0100
@@ -87,6 +87,11 @@ static DECLARE_WORK(pstore_work, pstore_
static DEFINE_SPINLOCK(pstore_lock);
struct pstore_info *psinfo;

+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");
+
static char *backend;
static char *compress =
#ifdef CONFIG_PSTORE_COMPRESS_DEFAULT
@@ -108,6 +113,8 @@ static size_t big_oops_buf_sz;

/* How much of the console log to snapshot */
unsigned long kmsg_bytes = PSTORE_DEFAULT_KMSG_BYTES;
+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)
{
@@ -606,7 +613,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();
@@ -723,7 +734,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;
unsigned int stop_loop = 65536;
@@ -742,7 +753,7 @@ void pstore_get_backend_records(struct p
*/
for (; stop_loop; stop_loop--) {
struct pstore_record *record;
- int rc;
+ int rc = 0;

record = kzalloc(sizeof(*record), GFP_KERNEL);
if (!record) {
@@ -760,12 +771,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++;
}
}
@@ -784,7 +806,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(struct timer_list *unused)



2019-03-01 14:59:23

by Thomas Renninger

[permalink] [raw]
Subject: Re: [PATCH] pstore: automatically dump and clean dmesg entries

On Friday, March 1, 2019 3:53:25 PM CET Thomas Renninger wrote:
> From: Torsten Duwe <[email protected]>
>
> 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 <[email protected]>
> CC: Thomas Renninger <[email protected]>

This is a patch which is (was) part of the SUSE kernel for quite a while.
Iirc someone from Fujitsu requested this.

Anyway, it has not been sent upstream yet, but looks useful.
Please consider to merge this one if you like it.
Otherwise it will probably get dropped to Nirvana as we only keep upstream
accepted (not SuSE specific) patches.

I adjusted the patch to latest linux-2.6 git HEAD state and gave it a test
compile.

Thanks,

Thomas