2019-05-30 07:57:47 +08:00
|
|
|
// SPDX-License-Identifier: GPL-2.0-only
|
2010-12-29 06:25:21 +08:00
|
|
|
/*
|
|
|
|
* Persistent Storage - platform driver interface parts.
|
|
|
|
*
|
2012-05-26 21:20:19 +08:00
|
|
|
* Copyright (C) 2007-2008 Google, Inc.
|
2010-12-29 06:25:21 +08:00
|
|
|
* Copyright (C) 2010 Intel Corporation <tony.luck@intel.com>
|
|
|
|
*/
|
|
|
|
|
2014-06-07 05:37:31 +08:00
|
|
|
#define pr_fmt(fmt) "pstore: " fmt
|
|
|
|
|
2010-12-29 06:25:21 +08:00
|
|
|
#include <linux/atomic.h>
|
|
|
|
#include <linux/types.h>
|
|
|
|
#include <linux/errno.h>
|
|
|
|
#include <linux/init.h>
|
|
|
|
#include <linux/kmsg_dump.h>
|
2012-05-26 21:20:19 +08:00
|
|
|
#include <linux/console.h>
|
2010-12-29 06:25:21 +08:00
|
|
|
#include <linux/module.h>
|
|
|
|
#include <linux/pstore.h>
|
2018-03-15 23:34:08 +08:00
|
|
|
#if IS_ENABLED(CONFIG_PSTORE_LZO_COMPRESS)
|
2016-02-18 22:04:22 +08:00
|
|
|
#include <linux/lzo.h>
|
|
|
|
#endif
|
2018-03-15 23:34:08 +08:00
|
|
|
#if IS_ENABLED(CONFIG_PSTORE_LZ4_COMPRESS) || IS_ENABLED(CONFIG_PSTORE_LZ4HC_COMPRESS)
|
2016-02-18 22:04:22 +08:00
|
|
|
#include <linux/lz4.h>
|
|
|
|
#endif
|
2018-08-01 19:23:37 +08:00
|
|
|
#if IS_ENABLED(CONFIG_PSTORE_ZSTD_COMPRESS)
|
|
|
|
#include <linux/zstd.h>
|
|
|
|
#endif
|
pstore: Use crypto compress API
In the pstore compression part, we use zlib/lzo/lz4/lz4hc/842
compression algorithm API to implement pstore compression backends. But
there are many repeat codes in these implementations. This patch uses
crypto compress API to simplify these codes.
1) rewrite allocate_buf_for_compression, free_buf_for_compression,
pstore_compress, pstore_decompress functions using crypto compress API.
2) drop compress, decompress, allocate, free functions in pstore_zbackend,
and add zbufsize function to get each different compress buffer size.
3) use late_initcall to call ramoops_init later, to make sure the crypto
subsystem has already initialized.
4) use 'unsigned int' type instead of 'size_t' in pstore_compress,
pstore_decompress functions' length arguments.
5) rename 'zlib' to 'deflate' to follow the crypto API's name convention.
Signed-off-by: Geliang Tang <geliangtang@gmail.com>
[kees: tweaked error messages on allocation failures and Kconfig help]
Signed-off-by: Kees Cook <keescook@chromium.org>
2018-03-09 18:51:07 +08:00
|
|
|
#include <linux/crypto.h>
|
2010-12-29 06:25:21 +08:00
|
|
|
#include <linux/string.h>
|
2011-08-12 06:14:39 +08:00
|
|
|
#include <linux/timer.h>
|
2010-12-29 06:25:21 +08:00
|
|
|
#include <linux/slab.h>
|
|
|
|
#include <linux/uaccess.h>
|
2012-05-26 21:20:28 +08:00
|
|
|
#include <linux/jiffies.h>
|
2011-08-12 06:14:39 +08:00
|
|
|
#include <linux/workqueue.h>
|
2010-12-29 06:25:21 +08:00
|
|
|
|
|
|
|
#include "internal.h"
|
|
|
|
|
2011-08-12 06:14:39 +08:00
|
|
|
/*
|
|
|
|
* We defer making "oops" entries appear in pstore - see
|
|
|
|
* whether the system is actually still running well enough
|
|
|
|
* to let someone see the entry
|
|
|
|
*/
|
pstore/platform: Disable automatic updates by default
Having automatic updates seems pointless for production system, and
even dangerous and thus counter-productive:
1. If we can mount pstore, or read files, we can as well read
/proc/kmsg. So, there's little point in duplicating the
functionality and present the same information but via another
userland ABI;
2. Expecting the kernel to behave sanely after oops/panic is naive.
It might work, but you'd rather not try it. Screwed up kernel
can do rather bad things, like recursive faults[1]; and pstore
rather provoking bad things to happen. It uses:
1. Timers (assumes sane interrupts state);
2. Workqueues and mutexes (assumes scheduler in a sane state);
3. kzalloc (a working slab allocator);
That's too much for a dead kernel, so the debugging facility
itself might just make debugging harder, which is not what
we want.
Maybe for non-oops message types it would make sense to re-enable
automatic updates, but so far I don't see any use case for this.
Even for tracing, it has its own run-time/normal ABI, so we're
only interested in pstore upon next boot, to retrieve what has
gone wrong with HW or SW.
So, let's disable the updates by default.
[1]
BUG: unable to handle kernel paging request at fffffffffffffff8
IP: [<ffffffff8104801b>] kthread_data+0xb/0x20
[...]
Process kworker/0:1 (pid: 14, threadinfo ffff8800072c0000, task ffff88000725b100)
[...
Call Trace:
[<ffffffff81043710>] wq_worker_sleeping+0x10/0xa0
[<ffffffff813687a8>] __schedule+0x568/0x7d0
[<ffffffff8106c24d>] ? trace_hardirqs_on+0xd/0x10
[<ffffffff81087e22>] ? call_rcu_sched+0x12/0x20
[<ffffffff8102b596>] ? release_task+0x156/0x2d0
[<ffffffff8102b45e>] ? release_task+0x1e/0x2d0
[<ffffffff8106c24d>] ? trace_hardirqs_on+0xd/0x10
[<ffffffff81368ac4>] schedule+0x24/0x70
[<ffffffff8102cba8>] do_exit+0x1f8/0x370
[<ffffffff810051e7>] oops_end+0x77/0xb0
[<ffffffff8135c301>] no_context+0x1a6/0x1b5
[<ffffffff8135c4de>] __bad_area_nosemaphore+0x1ce/0x1ed
[<ffffffff81053156>] ? ttwu_queue+0xc6/0xe0
[<ffffffff8135c50b>] bad_area_nosemaphore+0xe/0x10
[<ffffffff8101fa47>] do_page_fault+0x2c7/0x450
[<ffffffff8106e34b>] ? __lock_release+0x6b/0xe0
[<ffffffff8106bf21>] ? mark_held_locks+0x61/0x140
[<ffffffff810502fe>] ? __wake_up+0x4e/0x70
[<ffffffff81185f7d>] ? trace_hardirqs_off_thunk+0x3a/0x3c
[<ffffffff81158970>] ? pstore_register+0x120/0x120
[<ffffffff8136a37f>] page_fault+0x1f/0x30
[<ffffffff81158970>] ? pstore_register+0x120/0x120
[<ffffffff81185ab8>] ? memcpy+0x68/0x110
[<ffffffff8115875a>] ? pstore_get_records+0x3a/0x130
[<ffffffff811590f4>] ? persistent_ram_copy_old+0x64/0x90
[<ffffffff81158bf4>] ramoops_pstore_read+0x84/0x130
[<ffffffff81158799>] pstore_get_records+0x79/0x130
[<ffffffff81042536>] ? process_one_work+0x116/0x450
[<ffffffff81158970>] ? pstore_register+0x120/0x120
[<ffffffff8115897e>] pstore_dowork+0xe/0x10
[<ffffffff81042594>] process_one_work+0x174/0x450
[<ffffffff81042536>] ? process_one_work+0x116/0x450
[<ffffffff81042e13>] worker_thread+0x123/0x2d0
[<ffffffff81042cf0>] ? manage_workers.isra.28+0x120/0x120
[<ffffffff81047d8e>] kthread+0x8e/0xa0
[<ffffffff8136ba74>] kernel_thread_helper+0x4/0x10
[<ffffffff8136a199>] ? retint_restore_args+0xe/0xe
[<ffffffff81047d00>] ? __init_kthread_worker+0x70/0x70
[<ffffffff8136ba70>] ? gs_change+0xb/0xb
Code: be e2 00 00 00 48 c7 c7 d1 2a 4e 81 e8 bf fb fd ff 48 8b 5d f0 4c 8b 65 f8 c9 c3 0f 1f 44 00 00 48 8b 87 08 02 00 00 55 48 89 e5 <48> 8b 40 f8 5d c3 66 66 66 66 66 66 2e 0f 1f 84 00 00 00 00 00
RIP [<ffffffff8104801b>] kthread_data+0xb/0x20
RSP <ffff8800072c1888>
CR2: fffffffffffffff8
---[ end trace 996a332dc399111d ]---
Fixing recursive fault but reboot is needed!
Signed-off-by: Anton Vorontsov <anton.vorontsov@linaro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2012-05-26 21:20:29 +08:00
|
|
|
static int pstore_update_ms = -1;
|
2012-05-26 21:20:28 +08:00
|
|
|
module_param_named(update_ms, pstore_update_ms, int, 0600);
|
|
|
|
MODULE_PARM_DESC(update_ms, "milliseconds before pstore updates its content "
|
pstore/platform: Disable automatic updates by default
Having automatic updates seems pointless for production system, and
even dangerous and thus counter-productive:
1. If we can mount pstore, or read files, we can as well read
/proc/kmsg. So, there's little point in duplicating the
functionality and present the same information but via another
userland ABI;
2. Expecting the kernel to behave sanely after oops/panic is naive.
It might work, but you'd rather not try it. Screwed up kernel
can do rather bad things, like recursive faults[1]; and pstore
rather provoking bad things to happen. It uses:
1. Timers (assumes sane interrupts state);
2. Workqueues and mutexes (assumes scheduler in a sane state);
3. kzalloc (a working slab allocator);
That's too much for a dead kernel, so the debugging facility
itself might just make debugging harder, which is not what
we want.
Maybe for non-oops message types it would make sense to re-enable
automatic updates, but so far I don't see any use case for this.
Even for tracing, it has its own run-time/normal ABI, so we're
only interested in pstore upon next boot, to retrieve what has
gone wrong with HW or SW.
So, let's disable the updates by default.
[1]
BUG: unable to handle kernel paging request at fffffffffffffff8
IP: [<ffffffff8104801b>] kthread_data+0xb/0x20
[...]
Process kworker/0:1 (pid: 14, threadinfo ffff8800072c0000, task ffff88000725b100)
[...
Call Trace:
[<ffffffff81043710>] wq_worker_sleeping+0x10/0xa0
[<ffffffff813687a8>] __schedule+0x568/0x7d0
[<ffffffff8106c24d>] ? trace_hardirqs_on+0xd/0x10
[<ffffffff81087e22>] ? call_rcu_sched+0x12/0x20
[<ffffffff8102b596>] ? release_task+0x156/0x2d0
[<ffffffff8102b45e>] ? release_task+0x1e/0x2d0
[<ffffffff8106c24d>] ? trace_hardirqs_on+0xd/0x10
[<ffffffff81368ac4>] schedule+0x24/0x70
[<ffffffff8102cba8>] do_exit+0x1f8/0x370
[<ffffffff810051e7>] oops_end+0x77/0xb0
[<ffffffff8135c301>] no_context+0x1a6/0x1b5
[<ffffffff8135c4de>] __bad_area_nosemaphore+0x1ce/0x1ed
[<ffffffff81053156>] ? ttwu_queue+0xc6/0xe0
[<ffffffff8135c50b>] bad_area_nosemaphore+0xe/0x10
[<ffffffff8101fa47>] do_page_fault+0x2c7/0x450
[<ffffffff8106e34b>] ? __lock_release+0x6b/0xe0
[<ffffffff8106bf21>] ? mark_held_locks+0x61/0x140
[<ffffffff810502fe>] ? __wake_up+0x4e/0x70
[<ffffffff81185f7d>] ? trace_hardirqs_off_thunk+0x3a/0x3c
[<ffffffff81158970>] ? pstore_register+0x120/0x120
[<ffffffff8136a37f>] page_fault+0x1f/0x30
[<ffffffff81158970>] ? pstore_register+0x120/0x120
[<ffffffff81185ab8>] ? memcpy+0x68/0x110
[<ffffffff8115875a>] ? pstore_get_records+0x3a/0x130
[<ffffffff811590f4>] ? persistent_ram_copy_old+0x64/0x90
[<ffffffff81158bf4>] ramoops_pstore_read+0x84/0x130
[<ffffffff81158799>] pstore_get_records+0x79/0x130
[<ffffffff81042536>] ? process_one_work+0x116/0x450
[<ffffffff81158970>] ? pstore_register+0x120/0x120
[<ffffffff8115897e>] pstore_dowork+0xe/0x10
[<ffffffff81042594>] process_one_work+0x174/0x450
[<ffffffff81042536>] ? process_one_work+0x116/0x450
[<ffffffff81042e13>] worker_thread+0x123/0x2d0
[<ffffffff81042cf0>] ? manage_workers.isra.28+0x120/0x120
[<ffffffff81047d8e>] kthread+0x8e/0xa0
[<ffffffff8136ba74>] kernel_thread_helper+0x4/0x10
[<ffffffff8136a199>] ? retint_restore_args+0xe/0xe
[<ffffffff81047d00>] ? __init_kthread_worker+0x70/0x70
[<ffffffff8136ba70>] ? gs_change+0xb/0xb
Code: be e2 00 00 00 48 c7 c7 d1 2a 4e 81 e8 bf fb fd ff 48 8b 5d f0 4c 8b 65 f8 c9 c3 0f 1f 44 00 00 48 8b 87 08 02 00 00 55 48 89 e5 <48> 8b 40 f8 5d c3 66 66 66 66 66 66 2e 0f 1f 84 00 00 00 00 00
RIP [<ffffffff8104801b>] kthread_data+0xb/0x20
RSP <ffff8800072c1888>
CR2: fffffffffffffff8
---[ end trace 996a332dc399111d ]---
Fixing recursive fault but reboot is needed!
Signed-off-by: Anton Vorontsov <anton.vorontsov@linaro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2012-05-26 21:20:29 +08:00
|
|
|
"(default is -1, which means runtime updates are disabled; "
|
|
|
|
"enabling this option is not safe, it may lead to further "
|
|
|
|
"corruption on Oopses)");
|
2011-08-12 06:14:39 +08:00
|
|
|
|
2018-11-04 07:38:16 +08:00
|
|
|
/* Names should be in the same order as the enum pstore_type_id */
|
|
|
|
static const char * const pstore_type_names[] = {
|
|
|
|
"dmesg",
|
|
|
|
"mce",
|
|
|
|
"console",
|
|
|
|
"ftrace",
|
|
|
|
"rtas",
|
|
|
|
"powerpc-ofw",
|
|
|
|
"powerpc-common",
|
|
|
|
"pmsg",
|
|
|
|
"powerpc-opal",
|
|
|
|
};
|
|
|
|
|
2011-08-12 06:14:39 +08:00
|
|
|
static int pstore_new_entry;
|
|
|
|
|
2017-08-29 02:28:21 +08:00
|
|
|
static void pstore_timefunc(struct timer_list *);
|
2017-10-05 07:27:04 +08:00
|
|
|
static DEFINE_TIMER(pstore_timer, pstore_timefunc);
|
2011-08-12 06:14:39 +08:00
|
|
|
|
|
|
|
static void pstore_dowork(struct work_struct *);
|
|
|
|
static DECLARE_WORK(pstore_work, pstore_dowork);
|
|
|
|
|
2010-12-29 06:25:21 +08:00
|
|
|
/*
|
|
|
|
* pstore_lock just protects "psinfo" during
|
|
|
|
* calls to pstore_register()
|
|
|
|
*/
|
|
|
|
static DEFINE_SPINLOCK(pstore_lock);
|
2012-07-10 08:10:41 +08:00
|
|
|
struct pstore_info *psinfo;
|
2010-12-29 06:25:21 +08:00
|
|
|
|
2011-07-22 04:57:55 +08:00
|
|
|
static char *backend;
|
2018-03-07 07:57:38 +08:00
|
|
|
static char *compress =
|
|
|
|
#ifdef CONFIG_PSTORE_COMPRESS_DEFAULT
|
|
|
|
CONFIG_PSTORE_COMPRESS_DEFAULT;
|
|
|
|
#else
|
|
|
|
NULL;
|
|
|
|
#endif
|
2011-07-22 04:57:55 +08:00
|
|
|
|
2013-08-17 04:53:10 +08:00
|
|
|
/* Compression parameters */
|
pstore: Use crypto compress API
In the pstore compression part, we use zlib/lzo/lz4/lz4hc/842
compression algorithm API to implement pstore compression backends. But
there are many repeat codes in these implementations. This patch uses
crypto compress API to simplify these codes.
1) rewrite allocate_buf_for_compression, free_buf_for_compression,
pstore_compress, pstore_decompress functions using crypto compress API.
2) drop compress, decompress, allocate, free functions in pstore_zbackend,
and add zbufsize function to get each different compress buffer size.
3) use late_initcall to call ramoops_init later, to make sure the crypto
subsystem has already initialized.
4) use 'unsigned int' type instead of 'size_t' in pstore_compress,
pstore_decompress functions' length arguments.
5) rename 'zlib' to 'deflate' to follow the crypto API's name convention.
Signed-off-by: Geliang Tang <geliangtang@gmail.com>
[kees: tweaked error messages on allocation failures and Kconfig help]
Signed-off-by: Kees Cook <keescook@chromium.org>
2018-03-09 18:51:07 +08:00
|
|
|
static struct crypto_comp *tfm;
|
2016-02-18 22:04:22 +08:00
|
|
|
|
|
|
|
struct pstore_zbackend {
|
pstore: Use crypto compress API
In the pstore compression part, we use zlib/lzo/lz4/lz4hc/842
compression algorithm API to implement pstore compression backends. But
there are many repeat codes in these implementations. This patch uses
crypto compress API to simplify these codes.
1) rewrite allocate_buf_for_compression, free_buf_for_compression,
pstore_compress, pstore_decompress functions using crypto compress API.
2) drop compress, decompress, allocate, free functions in pstore_zbackend,
and add zbufsize function to get each different compress buffer size.
3) use late_initcall to call ramoops_init later, to make sure the crypto
subsystem has already initialized.
4) use 'unsigned int' type instead of 'size_t' in pstore_compress,
pstore_decompress functions' length arguments.
5) rename 'zlib' to 'deflate' to follow the crypto API's name convention.
Signed-off-by: Geliang Tang <geliangtang@gmail.com>
[kees: tweaked error messages on allocation failures and Kconfig help]
Signed-off-by: Kees Cook <keescook@chromium.org>
2018-03-09 18:51:07 +08:00
|
|
|
int (*zbufsize)(size_t size);
|
2016-02-18 22:04:22 +08:00
|
|
|
const char *name;
|
|
|
|
};
|
2013-08-17 04:53:10 +08:00
|
|
|
|
|
|
|
static char *big_oops_buf;
|
|
|
|
static size_t big_oops_buf_sz;
|
|
|
|
|
2011-03-19 06:33:43 +08:00
|
|
|
/* How much of the console log to snapshot */
|
2017-07-05 23:24:34 +08:00
|
|
|
unsigned long kmsg_bytes = PSTORE_DEFAULT_KMSG_BYTES;
|
2010-12-29 06:25:21 +08:00
|
|
|
|
2011-03-19 06:33:43 +08:00
|
|
|
void pstore_set_kmsg_bytes(int bytes)
|
2010-12-29 06:25:21 +08:00
|
|
|
{
|
2011-03-19 06:33:43 +08:00
|
|
|
kmsg_bytes = bytes;
|
2010-12-29 06:25:21 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Tag each group of saved records with a sequence number */
|
|
|
|
static int oopscount;
|
|
|
|
|
2018-11-04 07:38:16 +08:00
|
|
|
const char *pstore_type_to_name(enum pstore_type_id type)
|
|
|
|
{
|
|
|
|
BUILD_BUG_ON(ARRAY_SIZE(pstore_type_names) != PSTORE_TYPE_MAX);
|
|
|
|
|
|
|
|
if (WARN_ON_ONCE(type >= PSTORE_TYPE_MAX))
|
|
|
|
return "unknown";
|
|
|
|
|
|
|
|
return pstore_type_names[type];
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(pstore_type_to_name);
|
|
|
|
|
|
|
|
enum pstore_type_id pstore_name_to_type(const char *name)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < PSTORE_TYPE_MAX; i++) {
|
|
|
|
if (!strcmp(pstore_type_names[i], name))
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
|
|
|
return PSTORE_TYPE_MAX;
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(pstore_name_to_type);
|
|
|
|
|
2012-03-17 06:36:59 +08:00
|
|
|
static const char *get_reason_str(enum kmsg_dump_reason reason)
|
|
|
|
{
|
|
|
|
switch (reason) {
|
|
|
|
case KMSG_DUMP_PANIC:
|
|
|
|
return "Panic";
|
|
|
|
case KMSG_DUMP_OOPS:
|
|
|
|
return "Oops";
|
|
|
|
case KMSG_DUMP_EMERG:
|
|
|
|
return "Emergency";
|
|
|
|
case KMSG_DUMP_RESTART:
|
|
|
|
return "Restart";
|
|
|
|
case KMSG_DUMP_HALT:
|
|
|
|
return "Halt";
|
|
|
|
case KMSG_DUMP_POWEROFF:
|
|
|
|
return "Poweroff";
|
|
|
|
default:
|
|
|
|
return "Unknown";
|
|
|
|
}
|
|
|
|
}
|
2011-03-23 07:01:49 +08:00
|
|
|
|
2018-12-01 06:36:58 +08:00
|
|
|
/*
|
|
|
|
* Should pstore_dump() wait for a concurrent pstore_dump()? If
|
|
|
|
* not, the current pstore_dump() will report a failure to dump
|
|
|
|
* and return.
|
|
|
|
*/
|
|
|
|
static bool pstore_cannot_wait(enum kmsg_dump_reason reason)
|
pstore: Avoid deadlock in panic and emergency-restart path
[Issue]
When pstore is in panic and emergency-restart paths, it may be blocked
in those paths because it simply takes spin_lock.
This is an example scenario which pstore may hang up in a panic path:
- cpuA grabs psinfo->buf_lock
- cpuB panics and calls smp_send_stop
- smp_send_stop sends IRQ to cpuA
- after 1 second, cpuB gives up on cpuA and sends an NMI instead
- cpuA is now in an NMI handler while still holding buf_lock
- cpuB is deadlocked
This case may happen if a firmware has a bug and
cpuA is stuck talking with it more than one second.
Also, this is a similar scenario in an emergency-restart path:
- cpuA grabs psinfo->buf_lock and stucks in a firmware
- cpuB kicks emergency-restart via either sysrq-b or hangcheck timer.
And then, cpuB is deadlocked by taking psinfo->buf_lock again.
[Solution]
This patch avoids the deadlocking issues in both panic and emergency_restart
paths by introducing a function, is_non_blocking_path(), to check if a cpu
can be blocked in current path.
With this patch, pstore is not blocked even if another cpu has
taken a spin_lock, in those paths by changing from spin_lock_irqsave
to spin_trylock_irqsave.
In addition, according to a comment of emergency_restart() in kernel/sys.c,
spin_lock shouldn't be taken in an emergency_restart path to avoid
deadlock. This patch fits the comment below.
<snip>
/**
* emergency_restart - reboot the system
*
* Without shutting down any hardware or taking any locks
* reboot the system. This is called when we know we are in
* trouble so this is our best effort to reboot. This is
* safe to call in interrupt context.
*/
void emergency_restart(void)
<snip>
Signed-off-by: Seiji Aguchi <seiji.aguchi@hds.com>
Acked-by: Don Zickus <dzickus@redhat.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>
2013-01-12 02:09:41 +08:00
|
|
|
{
|
2018-12-01 06:36:58 +08:00
|
|
|
/* In NMI path, pstore shouldn't block regardless of reason. */
|
pstore: Avoid deadlock in panic and emergency-restart path
[Issue]
When pstore is in panic and emergency-restart paths, it may be blocked
in those paths because it simply takes spin_lock.
This is an example scenario which pstore may hang up in a panic path:
- cpuA grabs psinfo->buf_lock
- cpuB panics and calls smp_send_stop
- smp_send_stop sends IRQ to cpuA
- after 1 second, cpuB gives up on cpuA and sends an NMI instead
- cpuA is now in an NMI handler while still holding buf_lock
- cpuB is deadlocked
This case may happen if a firmware has a bug and
cpuA is stuck talking with it more than one second.
Also, this is a similar scenario in an emergency-restart path:
- cpuA grabs psinfo->buf_lock and stucks in a firmware
- cpuB kicks emergency-restart via either sysrq-b or hangcheck timer.
And then, cpuB is deadlocked by taking psinfo->buf_lock again.
[Solution]
This patch avoids the deadlocking issues in both panic and emergency_restart
paths by introducing a function, is_non_blocking_path(), to check if a cpu
can be blocked in current path.
With this patch, pstore is not blocked even if another cpu has
taken a spin_lock, in those paths by changing from spin_lock_irqsave
to spin_trylock_irqsave.
In addition, according to a comment of emergency_restart() in kernel/sys.c,
spin_lock shouldn't be taken in an emergency_restart path to avoid
deadlock. This patch fits the comment below.
<snip>
/**
* emergency_restart - reboot the system
*
* Without shutting down any hardware or taking any locks
* reboot the system. This is called when we know we are in
* trouble so this is our best effort to reboot. This is
* safe to call in interrupt context.
*/
void emergency_restart(void)
<snip>
Signed-off-by: Seiji Aguchi <seiji.aguchi@hds.com>
Acked-by: Don Zickus <dzickus@redhat.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>
2013-01-12 02:09:41 +08:00
|
|
|
if (in_nmi())
|
|
|
|
return true;
|
|
|
|
|
|
|
|
switch (reason) {
|
|
|
|
/* In panic case, other cpus are stopped by smp_send_stop(). */
|
|
|
|
case KMSG_DUMP_PANIC:
|
2018-12-01 06:36:58 +08:00
|
|
|
/* Emergency restart shouldn't be blocked. */
|
pstore: Avoid deadlock in panic and emergency-restart path
[Issue]
When pstore is in panic and emergency-restart paths, it may be blocked
in those paths because it simply takes spin_lock.
This is an example scenario which pstore may hang up in a panic path:
- cpuA grabs psinfo->buf_lock
- cpuB panics and calls smp_send_stop
- smp_send_stop sends IRQ to cpuA
- after 1 second, cpuB gives up on cpuA and sends an NMI instead
- cpuA is now in an NMI handler while still holding buf_lock
- cpuB is deadlocked
This case may happen if a firmware has a bug and
cpuA is stuck talking with it more than one second.
Also, this is a similar scenario in an emergency-restart path:
- cpuA grabs psinfo->buf_lock and stucks in a firmware
- cpuB kicks emergency-restart via either sysrq-b or hangcheck timer.
And then, cpuB is deadlocked by taking psinfo->buf_lock again.
[Solution]
This patch avoids the deadlocking issues in both panic and emergency_restart
paths by introducing a function, is_non_blocking_path(), to check if a cpu
can be blocked in current path.
With this patch, pstore is not blocked even if another cpu has
taken a spin_lock, in those paths by changing from spin_lock_irqsave
to spin_trylock_irqsave.
In addition, according to a comment of emergency_restart() in kernel/sys.c,
spin_lock shouldn't be taken in an emergency_restart path to avoid
deadlock. This patch fits the comment below.
<snip>
/**
* emergency_restart - reboot the system
*
* Without shutting down any hardware or taking any locks
* reboot the system. This is called when we know we are in
* trouble so this is our best effort to reboot. This is
* safe to call in interrupt context.
*/
void emergency_restart(void)
<snip>
Signed-off-by: Seiji Aguchi <seiji.aguchi@hds.com>
Acked-by: Don Zickus <dzickus@redhat.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>
2013-01-12 02:09:41 +08:00
|
|
|
case KMSG_DUMP_EMERG:
|
|
|
|
return true;
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-03-15 23:34:08 +08:00
|
|
|
#if IS_ENABLED(CONFIG_PSTORE_DEFLATE_COMPRESS)
|
pstore: Use crypto compress API
In the pstore compression part, we use zlib/lzo/lz4/lz4hc/842
compression algorithm API to implement pstore compression backends. But
there are many repeat codes in these implementations. This patch uses
crypto compress API to simplify these codes.
1) rewrite allocate_buf_for_compression, free_buf_for_compression,
pstore_compress, pstore_decompress functions using crypto compress API.
2) drop compress, decompress, allocate, free functions in pstore_zbackend,
and add zbufsize function to get each different compress buffer size.
3) use late_initcall to call ramoops_init later, to make sure the crypto
subsystem has already initialized.
4) use 'unsigned int' type instead of 'size_t' in pstore_compress,
pstore_decompress functions' length arguments.
5) rename 'zlib' to 'deflate' to follow the crypto API's name convention.
Signed-off-by: Geliang Tang <geliangtang@gmail.com>
[kees: tweaked error messages on allocation failures and Kconfig help]
Signed-off-by: Kees Cook <keescook@chromium.org>
2018-03-09 18:51:07 +08:00
|
|
|
static int zbufsize_deflate(size_t size)
|
2013-08-17 04:53:28 +08:00
|
|
|
{
|
2013-09-12 01:57:41 +08:00
|
|
|
size_t cmpr;
|
|
|
|
|
pstore: Use crypto compress API
In the pstore compression part, we use zlib/lzo/lz4/lz4hc/842
compression algorithm API to implement pstore compression backends. But
there are many repeat codes in these implementations. This patch uses
crypto compress API to simplify these codes.
1) rewrite allocate_buf_for_compression, free_buf_for_compression,
pstore_compress, pstore_decompress functions using crypto compress API.
2) drop compress, decompress, allocate, free functions in pstore_zbackend,
and add zbufsize function to get each different compress buffer size.
3) use late_initcall to call ramoops_init later, to make sure the crypto
subsystem has already initialized.
4) use 'unsigned int' type instead of 'size_t' in pstore_compress,
pstore_decompress functions' length arguments.
5) rename 'zlib' to 'deflate' to follow the crypto API's name convention.
Signed-off-by: Geliang Tang <geliangtang@gmail.com>
[kees: tweaked error messages on allocation failures and Kconfig help]
Signed-off-by: Kees Cook <keescook@chromium.org>
2018-03-09 18:51:07 +08:00
|
|
|
switch (size) {
|
2013-09-12 01:57:41 +08:00
|
|
|
/* buffer range for efivars */
|
|
|
|
case 1000 ... 2000:
|
|
|
|
cmpr = 56;
|
|
|
|
break;
|
|
|
|
case 2001 ... 3000:
|
|
|
|
cmpr = 54;
|
|
|
|
break;
|
|
|
|
case 3001 ... 3999:
|
|
|
|
cmpr = 52;
|
|
|
|
break;
|
|
|
|
/* buffer range for nvram, erst */
|
|
|
|
case 4000 ... 10000:
|
|
|
|
cmpr = 45;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
cmpr = 60;
|
|
|
|
break;
|
|
|
|
}
|
2013-08-17 04:53:10 +08:00
|
|
|
|
pstore: Use crypto compress API
In the pstore compression part, we use zlib/lzo/lz4/lz4hc/842
compression algorithm API to implement pstore compression backends. But
there are many repeat codes in these implementations. This patch uses
crypto compress API to simplify these codes.
1) rewrite allocate_buf_for_compression, free_buf_for_compression,
pstore_compress, pstore_decompress functions using crypto compress API.
2) drop compress, decompress, allocate, free functions in pstore_zbackend,
and add zbufsize function to get each different compress buffer size.
3) use late_initcall to call ramoops_init later, to make sure the crypto
subsystem has already initialized.
4) use 'unsigned int' type instead of 'size_t' in pstore_compress,
pstore_decompress functions' length arguments.
5) rename 'zlib' to 'deflate' to follow the crypto API's name convention.
Signed-off-by: Geliang Tang <geliangtang@gmail.com>
[kees: tweaked error messages on allocation failures and Kconfig help]
Signed-off-by: Kees Cook <keescook@chromium.org>
2018-03-09 18:51:07 +08:00
|
|
|
return (size * 100) / cmpr;
|
2016-02-18 22:04:22 +08:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2018-03-15 23:34:08 +08:00
|
|
|
#if IS_ENABLED(CONFIG_PSTORE_LZO_COMPRESS)
|
pstore: Use crypto compress API
In the pstore compression part, we use zlib/lzo/lz4/lz4hc/842
compression algorithm API to implement pstore compression backends. But
there are many repeat codes in these implementations. This patch uses
crypto compress API to simplify these codes.
1) rewrite allocate_buf_for_compression, free_buf_for_compression,
pstore_compress, pstore_decompress functions using crypto compress API.
2) drop compress, decompress, allocate, free functions in pstore_zbackend,
and add zbufsize function to get each different compress buffer size.
3) use late_initcall to call ramoops_init later, to make sure the crypto
subsystem has already initialized.
4) use 'unsigned int' type instead of 'size_t' in pstore_compress,
pstore_decompress functions' length arguments.
5) rename 'zlib' to 'deflate' to follow the crypto API's name convention.
Signed-off-by: Geliang Tang <geliangtang@gmail.com>
[kees: tweaked error messages on allocation failures and Kconfig help]
Signed-off-by: Kees Cook <keescook@chromium.org>
2018-03-09 18:51:07 +08:00
|
|
|
static int zbufsize_lzo(size_t size)
|
2016-02-18 22:04:22 +08:00
|
|
|
{
|
pstore: Use crypto compress API
In the pstore compression part, we use zlib/lzo/lz4/lz4hc/842
compression algorithm API to implement pstore compression backends. But
there are many repeat codes in these implementations. This patch uses
crypto compress API to simplify these codes.
1) rewrite allocate_buf_for_compression, free_buf_for_compression,
pstore_compress, pstore_decompress functions using crypto compress API.
2) drop compress, decompress, allocate, free functions in pstore_zbackend,
and add zbufsize function to get each different compress buffer size.
3) use late_initcall to call ramoops_init later, to make sure the crypto
subsystem has already initialized.
4) use 'unsigned int' type instead of 'size_t' in pstore_compress,
pstore_decompress functions' length arguments.
5) rename 'zlib' to 'deflate' to follow the crypto API's name convention.
Signed-off-by: Geliang Tang <geliangtang@gmail.com>
[kees: tweaked error messages on allocation failures and Kconfig help]
Signed-off-by: Kees Cook <keescook@chromium.org>
2018-03-09 18:51:07 +08:00
|
|
|
return lzo1x_worst_compress(size);
|
2016-02-18 22:04:22 +08:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2018-03-15 23:34:08 +08:00
|
|
|
#if IS_ENABLED(CONFIG_PSTORE_LZ4_COMPRESS) || IS_ENABLED(CONFIG_PSTORE_LZ4HC_COMPRESS)
|
pstore: Use crypto compress API
In the pstore compression part, we use zlib/lzo/lz4/lz4hc/842
compression algorithm API to implement pstore compression backends. But
there are many repeat codes in these implementations. This patch uses
crypto compress API to simplify these codes.
1) rewrite allocate_buf_for_compression, free_buf_for_compression,
pstore_compress, pstore_decompress functions using crypto compress API.
2) drop compress, decompress, allocate, free functions in pstore_zbackend,
and add zbufsize function to get each different compress buffer size.
3) use late_initcall to call ramoops_init later, to make sure the crypto
subsystem has already initialized.
4) use 'unsigned int' type instead of 'size_t' in pstore_compress,
pstore_decompress functions' length arguments.
5) rename 'zlib' to 'deflate' to follow the crypto API's name convention.
Signed-off-by: Geliang Tang <geliangtang@gmail.com>
[kees: tweaked error messages on allocation failures and Kconfig help]
Signed-off-by: Kees Cook <keescook@chromium.org>
2018-03-09 18:51:07 +08:00
|
|
|
static int zbufsize_lz4(size_t size)
|
2016-02-18 22:04:22 +08:00
|
|
|
{
|
pstore: Use crypto compress API
In the pstore compression part, we use zlib/lzo/lz4/lz4hc/842
compression algorithm API to implement pstore compression backends. But
there are many repeat codes in these implementations. This patch uses
crypto compress API to simplify these codes.
1) rewrite allocate_buf_for_compression, free_buf_for_compression,
pstore_compress, pstore_decompress functions using crypto compress API.
2) drop compress, decompress, allocate, free functions in pstore_zbackend,
and add zbufsize function to get each different compress buffer size.
3) use late_initcall to call ramoops_init later, to make sure the crypto
subsystem has already initialized.
4) use 'unsigned int' type instead of 'size_t' in pstore_compress,
pstore_decompress functions' length arguments.
5) rename 'zlib' to 'deflate' to follow the crypto API's name convention.
Signed-off-by: Geliang Tang <geliangtang@gmail.com>
[kees: tweaked error messages on allocation failures and Kconfig help]
Signed-off-by: Kees Cook <keescook@chromium.org>
2018-03-09 18:51:07 +08:00
|
|
|
return LZ4_compressBound(size);
|
2016-02-18 22:04:22 +08:00
|
|
|
}
|
2018-02-13 14:40:39 +08:00
|
|
|
#endif
|
|
|
|
|
2018-03-15 23:34:08 +08:00
|
|
|
#if IS_ENABLED(CONFIG_PSTORE_842_COMPRESS)
|
pstore: Use crypto compress API
In the pstore compression part, we use zlib/lzo/lz4/lz4hc/842
compression algorithm API to implement pstore compression backends. But
there are many repeat codes in these implementations. This patch uses
crypto compress API to simplify these codes.
1) rewrite allocate_buf_for_compression, free_buf_for_compression,
pstore_compress, pstore_decompress functions using crypto compress API.
2) drop compress, decompress, allocate, free functions in pstore_zbackend,
and add zbufsize function to get each different compress buffer size.
3) use late_initcall to call ramoops_init later, to make sure the crypto
subsystem has already initialized.
4) use 'unsigned int' type instead of 'size_t' in pstore_compress,
pstore_decompress functions' length arguments.
5) rename 'zlib' to 'deflate' to follow the crypto API's name convention.
Signed-off-by: Geliang Tang <geliangtang@gmail.com>
[kees: tweaked error messages on allocation failures and Kconfig help]
Signed-off-by: Kees Cook <keescook@chromium.org>
2018-03-09 18:51:07 +08:00
|
|
|
static int zbufsize_842(size_t size)
|
2018-02-13 14:40:39 +08:00
|
|
|
{
|
2018-03-07 07:15:24 +08:00
|
|
|
return size;
|
2018-02-13 14:40:39 +08:00
|
|
|
}
|
2016-02-18 22:04:22 +08:00
|
|
|
#endif
|
|
|
|
|
2018-08-01 19:23:37 +08:00
|
|
|
#if IS_ENABLED(CONFIG_PSTORE_ZSTD_COMPRESS)
|
|
|
|
static int zbufsize_zstd(size_t size)
|
|
|
|
{
|
|
|
|
return ZSTD_compressBound(size);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2018-03-07 07:57:38 +08:00
|
|
|
static const struct pstore_zbackend *zbackend __ro_after_init;
|
|
|
|
|
|
|
|
static const struct pstore_zbackend zbackends[] = {
|
2018-03-15 23:34:08 +08:00
|
|
|
#if IS_ENABLED(CONFIG_PSTORE_DEFLATE_COMPRESS)
|
2018-03-07 07:57:38 +08:00
|
|
|
{
|
pstore: Use crypto compress API
In the pstore compression part, we use zlib/lzo/lz4/lz4hc/842
compression algorithm API to implement pstore compression backends. But
there are many repeat codes in these implementations. This patch uses
crypto compress API to simplify these codes.
1) rewrite allocate_buf_for_compression, free_buf_for_compression,
pstore_compress, pstore_decompress functions using crypto compress API.
2) drop compress, decompress, allocate, free functions in pstore_zbackend,
and add zbufsize function to get each different compress buffer size.
3) use late_initcall to call ramoops_init later, to make sure the crypto
subsystem has already initialized.
4) use 'unsigned int' type instead of 'size_t' in pstore_compress,
pstore_decompress functions' length arguments.
5) rename 'zlib' to 'deflate' to follow the crypto API's name convention.
Signed-off-by: Geliang Tang <geliangtang@gmail.com>
[kees: tweaked error messages on allocation failures and Kconfig help]
Signed-off-by: Kees Cook <keescook@chromium.org>
2018-03-09 18:51:07 +08:00
|
|
|
.zbufsize = zbufsize_deflate,
|
|
|
|
.name = "deflate",
|
2018-03-07 07:57:38 +08:00
|
|
|
},
|
|
|
|
#endif
|
2018-03-15 23:34:08 +08:00
|
|
|
#if IS_ENABLED(CONFIG_PSTORE_LZO_COMPRESS)
|
2018-03-07 07:57:38 +08:00
|
|
|
{
|
pstore: Use crypto compress API
In the pstore compression part, we use zlib/lzo/lz4/lz4hc/842
compression algorithm API to implement pstore compression backends. But
there are many repeat codes in these implementations. This patch uses
crypto compress API to simplify these codes.
1) rewrite allocate_buf_for_compression, free_buf_for_compression,
pstore_compress, pstore_decompress functions using crypto compress API.
2) drop compress, decompress, allocate, free functions in pstore_zbackend,
and add zbufsize function to get each different compress buffer size.
3) use late_initcall to call ramoops_init later, to make sure the crypto
subsystem has already initialized.
4) use 'unsigned int' type instead of 'size_t' in pstore_compress,
pstore_decompress functions' length arguments.
5) rename 'zlib' to 'deflate' to follow the crypto API's name convention.
Signed-off-by: Geliang Tang <geliangtang@gmail.com>
[kees: tweaked error messages on allocation failures and Kconfig help]
Signed-off-by: Kees Cook <keescook@chromium.org>
2018-03-09 18:51:07 +08:00
|
|
|
.zbufsize = zbufsize_lzo,
|
2018-03-07 07:57:38 +08:00
|
|
|
.name = "lzo",
|
|
|
|
},
|
|
|
|
#endif
|
2018-03-15 23:34:08 +08:00
|
|
|
#if IS_ENABLED(CONFIG_PSTORE_LZ4_COMPRESS)
|
2018-03-07 07:57:38 +08:00
|
|
|
{
|
pstore: Use crypto compress API
In the pstore compression part, we use zlib/lzo/lz4/lz4hc/842
compression algorithm API to implement pstore compression backends. But
there are many repeat codes in these implementations. This patch uses
crypto compress API to simplify these codes.
1) rewrite allocate_buf_for_compression, free_buf_for_compression,
pstore_compress, pstore_decompress functions using crypto compress API.
2) drop compress, decompress, allocate, free functions in pstore_zbackend,
and add zbufsize function to get each different compress buffer size.
3) use late_initcall to call ramoops_init later, to make sure the crypto
subsystem has already initialized.
4) use 'unsigned int' type instead of 'size_t' in pstore_compress,
pstore_decompress functions' length arguments.
5) rename 'zlib' to 'deflate' to follow the crypto API's name convention.
Signed-off-by: Geliang Tang <geliangtang@gmail.com>
[kees: tweaked error messages on allocation failures and Kconfig help]
Signed-off-by: Kees Cook <keescook@chromium.org>
2018-03-09 18:51:07 +08:00
|
|
|
.zbufsize = zbufsize_lz4,
|
2018-03-07 07:57:38 +08:00
|
|
|
.name = "lz4",
|
|
|
|
},
|
|
|
|
#endif
|
2018-03-15 23:34:08 +08:00
|
|
|
#if IS_ENABLED(CONFIG_PSTORE_LZ4HC_COMPRESS)
|
2018-03-07 07:57:38 +08:00
|
|
|
{
|
pstore: Use crypto compress API
In the pstore compression part, we use zlib/lzo/lz4/lz4hc/842
compression algorithm API to implement pstore compression backends. But
there are many repeat codes in these implementations. This patch uses
crypto compress API to simplify these codes.
1) rewrite allocate_buf_for_compression, free_buf_for_compression,
pstore_compress, pstore_decompress functions using crypto compress API.
2) drop compress, decompress, allocate, free functions in pstore_zbackend,
and add zbufsize function to get each different compress buffer size.
3) use late_initcall to call ramoops_init later, to make sure the crypto
subsystem has already initialized.
4) use 'unsigned int' type instead of 'size_t' in pstore_compress,
pstore_decompress functions' length arguments.
5) rename 'zlib' to 'deflate' to follow the crypto API's name convention.
Signed-off-by: Geliang Tang <geliangtang@gmail.com>
[kees: tweaked error messages on allocation failures and Kconfig help]
Signed-off-by: Kees Cook <keescook@chromium.org>
2018-03-09 18:51:07 +08:00
|
|
|
.zbufsize = zbufsize_lz4,
|
2018-03-07 07:57:38 +08:00
|
|
|
.name = "lz4hc",
|
|
|
|
},
|
2016-02-18 22:04:22 +08:00
|
|
|
#endif
|
2018-03-15 23:34:08 +08:00
|
|
|
#if IS_ENABLED(CONFIG_PSTORE_842_COMPRESS)
|
2018-03-07 07:57:38 +08:00
|
|
|
{
|
pstore: Use crypto compress API
In the pstore compression part, we use zlib/lzo/lz4/lz4hc/842
compression algorithm API to implement pstore compression backends. But
there are many repeat codes in these implementations. This patch uses
crypto compress API to simplify these codes.
1) rewrite allocate_buf_for_compression, free_buf_for_compression,
pstore_compress, pstore_decompress functions using crypto compress API.
2) drop compress, decompress, allocate, free functions in pstore_zbackend,
and add zbufsize function to get each different compress buffer size.
3) use late_initcall to call ramoops_init later, to make sure the crypto
subsystem has already initialized.
4) use 'unsigned int' type instead of 'size_t' in pstore_compress,
pstore_decompress functions' length arguments.
5) rename 'zlib' to 'deflate' to follow the crypto API's name convention.
Signed-off-by: Geliang Tang <geliangtang@gmail.com>
[kees: tweaked error messages on allocation failures and Kconfig help]
Signed-off-by: Kees Cook <keescook@chromium.org>
2018-03-09 18:51:07 +08:00
|
|
|
.zbufsize = zbufsize_842,
|
2018-03-07 07:57:38 +08:00
|
|
|
.name = "842",
|
|
|
|
},
|
2018-08-01 19:23:37 +08:00
|
|
|
#endif
|
|
|
|
#if IS_ENABLED(CONFIG_PSTORE_ZSTD_COMPRESS)
|
|
|
|
{
|
|
|
|
.zbufsize = zbufsize_zstd,
|
|
|
|
.name = "zstd",
|
|
|
|
},
|
2018-03-07 07:57:38 +08:00
|
|
|
#endif
|
|
|
|
{ }
|
|
|
|
};
|
2016-02-18 22:04:22 +08:00
|
|
|
|
|
|
|
static int pstore_compress(const void *in, void *out,
|
pstore: Use crypto compress API
In the pstore compression part, we use zlib/lzo/lz4/lz4hc/842
compression algorithm API to implement pstore compression backends. But
there are many repeat codes in these implementations. This patch uses
crypto compress API to simplify these codes.
1) rewrite allocate_buf_for_compression, free_buf_for_compression,
pstore_compress, pstore_decompress functions using crypto compress API.
2) drop compress, decompress, allocate, free functions in pstore_zbackend,
and add zbufsize function to get each different compress buffer size.
3) use late_initcall to call ramoops_init later, to make sure the crypto
subsystem has already initialized.
4) use 'unsigned int' type instead of 'size_t' in pstore_compress,
pstore_decompress functions' length arguments.
5) rename 'zlib' to 'deflate' to follow the crypto API's name convention.
Signed-off-by: Geliang Tang <geliangtang@gmail.com>
[kees: tweaked error messages on allocation failures and Kconfig help]
Signed-off-by: Kees Cook <keescook@chromium.org>
2018-03-09 18:51:07 +08:00
|
|
|
unsigned int inlen, unsigned int outlen)
|
2016-02-18 22:04:22 +08:00
|
|
|
{
|
pstore: Use crypto compress API
In the pstore compression part, we use zlib/lzo/lz4/lz4hc/842
compression algorithm API to implement pstore compression backends. But
there are many repeat codes in these implementations. This patch uses
crypto compress API to simplify these codes.
1) rewrite allocate_buf_for_compression, free_buf_for_compression,
pstore_compress, pstore_decompress functions using crypto compress API.
2) drop compress, decompress, allocate, free functions in pstore_zbackend,
and add zbufsize function to get each different compress buffer size.
3) use late_initcall to call ramoops_init later, to make sure the crypto
subsystem has already initialized.
4) use 'unsigned int' type instead of 'size_t' in pstore_compress,
pstore_decompress functions' length arguments.
5) rename 'zlib' to 'deflate' to follow the crypto API's name convention.
Signed-off-by: Geliang Tang <geliangtang@gmail.com>
[kees: tweaked error messages on allocation failures and Kconfig help]
Signed-off-by: Kees Cook <keescook@chromium.org>
2018-03-09 18:51:07 +08:00
|
|
|
int ret;
|
|
|
|
|
2024-06-11 20:26:44 +08:00
|
|
|
if (!IS_ENABLED(CONFIG_PSTORE_COMPRESS))
|
|
|
|
return -EINVAL;
|
|
|
|
|
pstore: Use crypto compress API
In the pstore compression part, we use zlib/lzo/lz4/lz4hc/842
compression algorithm API to implement pstore compression backends. But
there are many repeat codes in these implementations. This patch uses
crypto compress API to simplify these codes.
1) rewrite allocate_buf_for_compression, free_buf_for_compression,
pstore_compress, pstore_decompress functions using crypto compress API.
2) drop compress, decompress, allocate, free functions in pstore_zbackend,
and add zbufsize function to get each different compress buffer size.
3) use late_initcall to call ramoops_init later, to make sure the crypto
subsystem has already initialized.
4) use 'unsigned int' type instead of 'size_t' in pstore_compress,
pstore_decompress functions' length arguments.
5) rename 'zlib' to 'deflate' to follow the crypto API's name convention.
Signed-off-by: Geliang Tang <geliangtang@gmail.com>
[kees: tweaked error messages on allocation failures and Kconfig help]
Signed-off-by: Kees Cook <keescook@chromium.org>
2018-03-09 18:51:07 +08:00
|
|
|
ret = crypto_comp_compress(tfm, in, inlen, out, &outlen);
|
|
|
|
if (ret) {
|
|
|
|
pr_err("crypto_comp_compress failed, ret = %d!\n", ret);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
return outlen;
|
2016-02-18 22:04:22 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void allocate_buf_for_compression(void)
|
|
|
|
{
|
2018-10-18 05:00:12 +08:00
|
|
|
struct crypto_comp *ctx;
|
|
|
|
int size;
|
|
|
|
char *buf;
|
|
|
|
|
|
|
|
/* Skip if not built-in or compression backend not selected yet. */
|
2018-04-06 15:25:17 +08:00
|
|
|
if (!IS_ENABLED(CONFIG_PSTORE_COMPRESS) || !zbackend)
|
pstore: Use crypto compress API
In the pstore compression part, we use zlib/lzo/lz4/lz4hc/842
compression algorithm API to implement pstore compression backends. But
there are many repeat codes in these implementations. This patch uses
crypto compress API to simplify these codes.
1) rewrite allocate_buf_for_compression, free_buf_for_compression,
pstore_compress, pstore_decompress functions using crypto compress API.
2) drop compress, decompress, allocate, free functions in pstore_zbackend,
and add zbufsize function to get each different compress buffer size.
3) use late_initcall to call ramoops_init later, to make sure the crypto
subsystem has already initialized.
4) use 'unsigned int' type instead of 'size_t' in pstore_compress,
pstore_decompress functions' length arguments.
5) rename 'zlib' to 'deflate' to follow the crypto API's name convention.
Signed-off-by: Geliang Tang <geliangtang@gmail.com>
[kees: tweaked error messages on allocation failures and Kconfig help]
Signed-off-by: Kees Cook <keescook@chromium.org>
2018-03-09 18:51:07 +08:00
|
|
|
return;
|
|
|
|
|
2018-10-18 05:00:12 +08:00
|
|
|
/* Skip if no pstore backend yet or compression init already done. */
|
|
|
|
if (!psinfo || tfm)
|
|
|
|
return;
|
|
|
|
|
pstore: Use crypto compress API
In the pstore compression part, we use zlib/lzo/lz4/lz4hc/842
compression algorithm API to implement pstore compression backends. But
there are many repeat codes in these implementations. This patch uses
crypto compress API to simplify these codes.
1) rewrite allocate_buf_for_compression, free_buf_for_compression,
pstore_compress, pstore_decompress functions using crypto compress API.
2) drop compress, decompress, allocate, free functions in pstore_zbackend,
and add zbufsize function to get each different compress buffer size.
3) use late_initcall to call ramoops_init later, to make sure the crypto
subsystem has already initialized.
4) use 'unsigned int' type instead of 'size_t' in pstore_compress,
pstore_decompress functions' length arguments.
5) rename 'zlib' to 'deflate' to follow the crypto API's name convention.
Signed-off-by: Geliang Tang <geliangtang@gmail.com>
[kees: tweaked error messages on allocation failures and Kconfig help]
Signed-off-by: Kees Cook <keescook@chromium.org>
2018-03-09 18:51:07 +08:00
|
|
|
if (!crypto_has_comp(zbackend->name, 0, 0)) {
|
2018-10-18 05:00:12 +08:00
|
|
|
pr_err("Unknown compression: %s\n", zbackend->name);
|
pstore: Use crypto compress API
In the pstore compression part, we use zlib/lzo/lz4/lz4hc/842
compression algorithm API to implement pstore compression backends. But
there are many repeat codes in these implementations. This patch uses
crypto compress API to simplify these codes.
1) rewrite allocate_buf_for_compression, free_buf_for_compression,
pstore_compress, pstore_decompress functions using crypto compress API.
2) drop compress, decompress, allocate, free functions in pstore_zbackend,
and add zbufsize function to get each different compress buffer size.
3) use late_initcall to call ramoops_init later, to make sure the crypto
subsystem has already initialized.
4) use 'unsigned int' type instead of 'size_t' in pstore_compress,
pstore_decompress functions' length arguments.
5) rename 'zlib' to 'deflate' to follow the crypto API's name convention.
Signed-off-by: Geliang Tang <geliangtang@gmail.com>
[kees: tweaked error messages on allocation failures and Kconfig help]
Signed-off-by: Kees Cook <keescook@chromium.org>
2018-03-09 18:51:07 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-10-18 05:00:12 +08:00
|
|
|
size = zbackend->zbufsize(psinfo->bufsize);
|
|
|
|
if (size <= 0) {
|
|
|
|
pr_err("Invalid compression size for %s: %d\n",
|
|
|
|
zbackend->name, size);
|
pstore: Use crypto compress API
In the pstore compression part, we use zlib/lzo/lz4/lz4hc/842
compression algorithm API to implement pstore compression backends. But
there are many repeat codes in these implementations. This patch uses
crypto compress API to simplify these codes.
1) rewrite allocate_buf_for_compression, free_buf_for_compression,
pstore_compress, pstore_decompress functions using crypto compress API.
2) drop compress, decompress, allocate, free functions in pstore_zbackend,
and add zbufsize function to get each different compress buffer size.
3) use late_initcall to call ramoops_init later, to make sure the crypto
subsystem has already initialized.
4) use 'unsigned int' type instead of 'size_t' in pstore_compress,
pstore_decompress functions' length arguments.
5) rename 'zlib' to 'deflate' to follow the crypto API's name convention.
Signed-off-by: Geliang Tang <geliangtang@gmail.com>
[kees: tweaked error messages on allocation failures and Kconfig help]
Signed-off-by: Kees Cook <keescook@chromium.org>
2018-03-09 18:51:07 +08:00
|
|
|
return;
|
2018-10-18 05:00:12 +08:00
|
|
|
}
|
pstore: Use crypto compress API
In the pstore compression part, we use zlib/lzo/lz4/lz4hc/842
compression algorithm API to implement pstore compression backends. But
there are many repeat codes in these implementations. This patch uses
crypto compress API to simplify these codes.
1) rewrite allocate_buf_for_compression, free_buf_for_compression,
pstore_compress, pstore_decompress functions using crypto compress API.
2) drop compress, decompress, allocate, free functions in pstore_zbackend,
and add zbufsize function to get each different compress buffer size.
3) use late_initcall to call ramoops_init later, to make sure the crypto
subsystem has already initialized.
4) use 'unsigned int' type instead of 'size_t' in pstore_compress,
pstore_decompress functions' length arguments.
5) rename 'zlib' to 'deflate' to follow the crypto API's name convention.
Signed-off-by: Geliang Tang <geliangtang@gmail.com>
[kees: tweaked error messages on allocation failures and Kconfig help]
Signed-off-by: Kees Cook <keescook@chromium.org>
2018-03-09 18:51:07 +08:00
|
|
|
|
2018-10-18 05:00:12 +08:00
|
|
|
buf = kmalloc(size, GFP_KERNEL);
|
|
|
|
if (!buf) {
|
|
|
|
pr_err("Failed %d byte compression buffer allocation for: %s\n",
|
|
|
|
size, zbackend->name);
|
pstore: Use crypto compress API
In the pstore compression part, we use zlib/lzo/lz4/lz4hc/842
compression algorithm API to implement pstore compression backends. But
there are many repeat codes in these implementations. This patch uses
crypto compress API to simplify these codes.
1) rewrite allocate_buf_for_compression, free_buf_for_compression,
pstore_compress, pstore_decompress functions using crypto compress API.
2) drop compress, decompress, allocate, free functions in pstore_zbackend,
and add zbufsize function to get each different compress buffer size.
3) use late_initcall to call ramoops_init later, to make sure the crypto
subsystem has already initialized.
4) use 'unsigned int' type instead of 'size_t' in pstore_compress,
pstore_decompress functions' length arguments.
5) rename 'zlib' to 'deflate' to follow the crypto API's name convention.
Signed-off-by: Geliang Tang <geliangtang@gmail.com>
[kees: tweaked error messages on allocation failures and Kconfig help]
Signed-off-by: Kees Cook <keescook@chromium.org>
2018-03-09 18:51:07 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-10-18 05:00:12 +08:00
|
|
|
ctx = crypto_alloc_comp(zbackend->name, 0, 0);
|
|
|
|
if (IS_ERR_OR_NULL(ctx)) {
|
|
|
|
kfree(buf);
|
|
|
|
pr_err("crypto_alloc_comp('%s') failed: %ld\n", zbackend->name,
|
|
|
|
PTR_ERR(ctx));
|
pstore: Use crypto compress API
In the pstore compression part, we use zlib/lzo/lz4/lz4hc/842
compression algorithm API to implement pstore compression backends. But
there are many repeat codes in these implementations. This patch uses
crypto compress API to simplify these codes.
1) rewrite allocate_buf_for_compression, free_buf_for_compression,
pstore_compress, pstore_decompress functions using crypto compress API.
2) drop compress, decompress, allocate, free functions in pstore_zbackend,
and add zbufsize function to get each different compress buffer size.
3) use late_initcall to call ramoops_init later, to make sure the crypto
subsystem has already initialized.
4) use 'unsigned int' type instead of 'size_t' in pstore_compress,
pstore_decompress functions' length arguments.
5) rename 'zlib' to 'deflate' to follow the crypto API's name convention.
Signed-off-by: Geliang Tang <geliangtang@gmail.com>
[kees: tweaked error messages on allocation failures and Kconfig help]
Signed-off-by: Kees Cook <keescook@chromium.org>
2018-03-09 18:51:07 +08:00
|
|
|
return;
|
2016-02-18 22:04:22 +08:00
|
|
|
}
|
2018-10-18 05:00:12 +08:00
|
|
|
|
|
|
|
/* A non-NULL big_oops_buf indicates compression is available. */
|
|
|
|
tfm = ctx;
|
|
|
|
big_oops_buf_sz = size;
|
|
|
|
big_oops_buf = buf;
|
|
|
|
|
2018-11-02 05:03:07 +08:00
|
|
|
pr_info("Using crash dump compression: %s\n", zbackend->name);
|
2016-02-18 22:04:22 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void free_buf_for_compression(void)
|
|
|
|
{
|
2019-05-20 14:51:19 +08:00
|
|
|
if (IS_ENABLED(CONFIG_PSTORE_COMPRESS) && tfm) {
|
pstore: Use crypto compress API
In the pstore compression part, we use zlib/lzo/lz4/lz4hc/842
compression algorithm API to implement pstore compression backends. But
there are many repeat codes in these implementations. This patch uses
crypto compress API to simplify these codes.
1) rewrite allocate_buf_for_compression, free_buf_for_compression,
pstore_compress, pstore_decompress functions using crypto compress API.
2) drop compress, decompress, allocate, free functions in pstore_zbackend,
and add zbufsize function to get each different compress buffer size.
3) use late_initcall to call ramoops_init later, to make sure the crypto
subsystem has already initialized.
4) use 'unsigned int' type instead of 'size_t' in pstore_compress,
pstore_decompress functions' length arguments.
5) rename 'zlib' to 'deflate' to follow the crypto API's name convention.
Signed-off-by: Geliang Tang <geliangtang@gmail.com>
[kees: tweaked error messages on allocation failures and Kconfig help]
Signed-off-by: Kees Cook <keescook@chromium.org>
2018-03-09 18:51:07 +08:00
|
|
|
crypto_free_comp(tfm);
|
2019-05-20 14:51:19 +08:00
|
|
|
tfm = NULL;
|
|
|
|
}
|
pstore: Use crypto compress API
In the pstore compression part, we use zlib/lzo/lz4/lz4hc/842
compression algorithm API to implement pstore compression backends. But
there are many repeat codes in these implementations. This patch uses
crypto compress API to simplify these codes.
1) rewrite allocate_buf_for_compression, free_buf_for_compression,
pstore_compress, pstore_decompress functions using crypto compress API.
2) drop compress, decompress, allocate, free functions in pstore_zbackend,
and add zbufsize function to get each different compress buffer size.
3) use late_initcall to call ramoops_init later, to make sure the crypto
subsystem has already initialized.
4) use 'unsigned int' type instead of 'size_t' in pstore_compress,
pstore_decompress functions' length arguments.
5) rename 'zlib' to 'deflate' to follow the crypto API's name convention.
Signed-off-by: Geliang Tang <geliangtang@gmail.com>
[kees: tweaked error messages on allocation failures and Kconfig help]
Signed-off-by: Kees Cook <keescook@chromium.org>
2018-03-09 18:51:07 +08:00
|
|
|
kfree(big_oops_buf);
|
|
|
|
big_oops_buf = NULL;
|
|
|
|
big_oops_buf_sz = 0;
|
2015-10-20 15:39:03 +08:00
|
|
|
}
|
|
|
|
|
2013-08-17 04:53:10 +08:00
|
|
|
/*
|
|
|
|
* Called when compression fails, since the printk buffer
|
|
|
|
* would be fetched for compression calling it again when
|
|
|
|
* compression fails would have moved the iterator of
|
|
|
|
* printk buffer which results in fetching old contents.
|
|
|
|
* Copy the recent messages from big_oops_buf to psinfo->buf
|
|
|
|
*/
|
|
|
|
static size_t copy_kmsg_to_buffer(int hsize, size_t len)
|
|
|
|
{
|
|
|
|
size_t total_len;
|
|
|
|
size_t diff;
|
|
|
|
|
|
|
|
total_len = hsize + len;
|
|
|
|
|
|
|
|
if (total_len > psinfo->bufsize) {
|
|
|
|
diff = total_len - psinfo->bufsize + hsize;
|
|
|
|
memcpy(psinfo->buf, big_oops_buf, hsize);
|
|
|
|
memcpy(psinfo->buf + hsize, big_oops_buf + diff,
|
|
|
|
psinfo->bufsize - hsize);
|
|
|
|
total_len = psinfo->bufsize;
|
|
|
|
} else
|
|
|
|
memcpy(psinfo->buf, big_oops_buf, total_len);
|
|
|
|
|
|
|
|
return total_len;
|
|
|
|
}
|
|
|
|
|
2017-05-20 06:10:31 +08:00
|
|
|
void pstore_record_init(struct pstore_record *record,
|
|
|
|
struct pstore_info *psinfo)
|
|
|
|
{
|
|
|
|
memset(record, 0, sizeof(*record));
|
|
|
|
|
|
|
|
record->psi = psinfo;
|
2017-05-20 06:29:10 +08:00
|
|
|
|
|
|
|
/* Report zeroed timestamp if called before timekeeping has resumed. */
|
2018-05-15 06:50:52 +08:00
|
|
|
record->time = ns_to_timespec64(ktime_get_real_fast_ns());
|
2017-05-20 06:10:31 +08:00
|
|
|
}
|
|
|
|
|
2010-12-29 06:25:21 +08:00
|
|
|
/*
|
2018-11-02 05:03:07 +08:00
|
|
|
* callback from kmsg_dump. Save as much as we can (up to kmsg_bytes) from the
|
|
|
|
* end of the buffer.
|
2010-12-29 06:25:21 +08:00
|
|
|
*/
|
|
|
|
static void pstore_dump(struct kmsg_dumper *dumper,
|
2012-06-15 20:07:51 +08:00
|
|
|
enum kmsg_dump_reason reason)
|
2010-12-29 06:25:21 +08:00
|
|
|
{
|
2012-06-15 20:07:51 +08:00
|
|
|
unsigned long total = 0;
|
2012-03-17 06:36:59 +08:00
|
|
|
const char *why;
|
2011-07-22 04:57:54 +08:00
|
|
|
unsigned int part = 1;
|
2012-06-15 20:07:51 +08:00
|
|
|
int ret;
|
2010-12-29 06:25:21 +08:00
|
|
|
|
2012-03-17 06:36:59 +08:00
|
|
|
why = get_reason_str(reason);
|
2011-03-23 07:01:49 +08:00
|
|
|
|
2018-12-01 06:36:58 +08:00
|
|
|
if (down_trylock(&psinfo->buf_lock)) {
|
|
|
|
/* Failed to acquire lock: give up if we cannot wait. */
|
|
|
|
if (pstore_cannot_wait(reason)) {
|
|
|
|
pr_err("dump skipped in %s path: may corrupt error record\n",
|
|
|
|
in_nmi() ? "NMI" : why);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (down_interruptible(&psinfo->buf_lock)) {
|
|
|
|
pr_err("could not grab semaphore?!\n");
|
2016-11-05 10:15:59 +08:00
|
|
|
return;
|
pstore: Avoid deadlock in panic and emergency-restart path
[Issue]
When pstore is in panic and emergency-restart paths, it may be blocked
in those paths because it simply takes spin_lock.
This is an example scenario which pstore may hang up in a panic path:
- cpuA grabs psinfo->buf_lock
- cpuB panics and calls smp_send_stop
- smp_send_stop sends IRQ to cpuA
- after 1 second, cpuB gives up on cpuA and sends an NMI instead
- cpuA is now in an NMI handler while still holding buf_lock
- cpuB is deadlocked
This case may happen if a firmware has a bug and
cpuA is stuck talking with it more than one second.
Also, this is a similar scenario in an emergency-restart path:
- cpuA grabs psinfo->buf_lock and stucks in a firmware
- cpuB kicks emergency-restart via either sysrq-b or hangcheck timer.
And then, cpuB is deadlocked by taking psinfo->buf_lock again.
[Solution]
This patch avoids the deadlocking issues in both panic and emergency_restart
paths by introducing a function, is_non_blocking_path(), to check if a cpu
can be blocked in current path.
With this patch, pstore is not blocked even if another cpu has
taken a spin_lock, in those paths by changing from spin_lock_irqsave
to spin_trylock_irqsave.
In addition, according to a comment of emergency_restart() in kernel/sys.c,
spin_lock shouldn't be taken in an emergency_restart path to avoid
deadlock. This patch fits the comment below.
<snip>
/**
* emergency_restart - reboot the system
*
* Without shutting down any hardware or taking any locks
* reboot the system. This is called when we know we are in
* trouble so this is our best effort to reboot. This is
* safe to call in interrupt context.
*/
void emergency_restart(void)
<snip>
Signed-off-by: Seiji Aguchi <seiji.aguchi@hds.com>
Acked-by: Don Zickus <dzickus@redhat.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>
2013-01-12 02:09:41 +08:00
|
|
|
}
|
2016-05-18 20:00:05 +08:00
|
|
|
}
|
2018-12-01 06:36:58 +08:00
|
|
|
|
2010-12-29 06:25:21 +08:00
|
|
|
oopscount++;
|
|
|
|
while (total < kmsg_bytes) {
|
2012-06-15 20:07:51 +08:00
|
|
|
char *dst;
|
2017-03-04 15:28:53 +08:00
|
|
|
size_t dst_size;
|
|
|
|
int header_size;
|
2013-08-17 04:53:10 +08:00
|
|
|
int zipped_len = -1;
|
2017-03-04 15:28:53 +08:00
|
|
|
size_t dump_size;
|
2017-05-20 06:10:31 +08:00
|
|
|
struct pstore_record record;
|
|
|
|
|
|
|
|
pstore_record_init(&record, psinfo);
|
|
|
|
record.type = PSTORE_TYPE_DMESG;
|
|
|
|
record.count = oopscount;
|
|
|
|
record.reason = reason;
|
|
|
|
record.part = part;
|
|
|
|
record.buf = psinfo->buf;
|
2012-06-15 20:07:51 +08:00
|
|
|
|
2018-12-01 06:36:58 +08:00
|
|
|
if (big_oops_buf) {
|
2013-08-17 04:53:10 +08:00
|
|
|
dst = big_oops_buf;
|
2017-03-04 15:28:53 +08:00
|
|
|
dst_size = big_oops_buf_sz;
|
2016-05-18 20:00:06 +08:00
|
|
|
} else {
|
|
|
|
dst = psinfo->buf;
|
2017-03-04 15:28:53 +08:00
|
|
|
dst_size = psinfo->bufsize;
|
2016-05-18 20:00:06 +08:00
|
|
|
}
|
|
|
|
|
2017-03-04 15:28:53 +08:00
|
|
|
/* Write dump header. */
|
|
|
|
header_size = snprintf(dst, dst_size, "%s#%d Part%u\n", why,
|
|
|
|
oopscount, part);
|
|
|
|
dst_size -= header_size;
|
2010-12-29 06:25:21 +08:00
|
|
|
|
2017-03-04 15:28:53 +08:00
|
|
|
/* Write dump contents. */
|
|
|
|
if (!kmsg_dump_get_buffer(dumper, true, dst + header_size,
|
|
|
|
dst_size, &dump_size))
|
2016-05-18 20:00:06 +08:00
|
|
|
break;
|
2013-08-17 04:53:10 +08:00
|
|
|
|
2018-12-01 06:36:58 +08:00
|
|
|
if (big_oops_buf) {
|
2013-08-17 04:53:10 +08:00
|
|
|
zipped_len = pstore_compress(dst, psinfo->buf,
|
2017-03-04 15:28:53 +08:00
|
|
|
header_size + dump_size,
|
|
|
|
psinfo->bufsize);
|
2013-08-17 04:53:10 +08:00
|
|
|
|
|
|
|
if (zipped_len > 0) {
|
2017-03-04 15:28:53 +08:00
|
|
|
record.compressed = true;
|
|
|
|
record.size = zipped_len;
|
2013-08-17 04:53:10 +08:00
|
|
|
} else {
|
2017-03-04 15:28:53 +08:00
|
|
|
record.size = copy_kmsg_to_buffer(header_size,
|
|
|
|
dump_size);
|
2013-08-17 04:53:10 +08:00
|
|
|
}
|
|
|
|
} else {
|
2017-03-04 15:28:53 +08:00
|
|
|
record.size = header_size + dump_size;
|
2013-08-17 04:53:10 +08:00
|
|
|
}
|
2010-12-29 06:25:21 +08:00
|
|
|
|
2017-03-04 15:28:53 +08:00
|
|
|
ret = psinfo->write(&record);
|
2011-10-13 00:17:24 +08:00
|
|
|
if (ret == 0 && reason == KMSG_DUMP_OOPS && pstore_is_mounted())
|
2011-08-12 06:14:39 +08:00
|
|
|
pstore_new_entry = 1;
|
2012-06-15 20:07:51 +08:00
|
|
|
|
2017-03-04 15:28:53 +08:00
|
|
|
total += record.size;
|
2011-07-22 04:57:53 +08:00
|
|
|
part++;
|
2010-12-29 06:25:21 +08:00
|
|
|
}
|
2018-12-01 06:36:58 +08:00
|
|
|
|
|
|
|
up(&psinfo->buf_lock);
|
2010-12-29 06:25:21 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static struct kmsg_dumper pstore_dumper = {
|
|
|
|
.dump = pstore_dump,
|
|
|
|
};
|
|
|
|
|
2015-10-31 23:23:15 +08:00
|
|
|
/*
|
|
|
|
* Register with kmsg_dump to save last part of console log on panic.
|
|
|
|
*/
|
2015-10-20 15:39:02 +08:00
|
|
|
static void pstore_register_kmsg(void)
|
|
|
|
{
|
|
|
|
kmsg_dump_register(&pstore_dumper);
|
|
|
|
}
|
|
|
|
|
2015-10-20 15:39:03 +08:00
|
|
|
static void pstore_unregister_kmsg(void)
|
|
|
|
{
|
|
|
|
kmsg_dump_unregister(&pstore_dumper);
|
|
|
|
}
|
|
|
|
|
2012-05-26 21:20:19 +08:00
|
|
|
#ifdef CONFIG_PSTORE_CONSOLE
|
|
|
|
static void pstore_console_write(struct console *con, const char *s, unsigned c)
|
|
|
|
{
|
2018-11-02 05:08:07 +08:00
|
|
|
struct pstore_record record;
|
2012-05-26 21:20:19 +08:00
|
|
|
|
2019-01-31 18:12:46 +08:00
|
|
|
if (!c)
|
|
|
|
return;
|
|
|
|
|
2018-11-02 05:08:07 +08:00
|
|
|
pstore_record_init(&record, psinfo);
|
|
|
|
record.type = PSTORE_TYPE_CONSOLE;
|
2012-09-18 01:43:44 +08:00
|
|
|
|
2018-11-02 05:08:07 +08:00
|
|
|
record.buf = (char *)s;
|
|
|
|
record.size = c;
|
|
|
|
psinfo->write(&record);
|
2012-05-26 21:20:19 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
2015-10-20 15:39:03 +08:00
|
|
|
|
|
|
|
static void pstore_unregister_console(void)
|
|
|
|
{
|
|
|
|
unregister_console(&pstore_console);
|
|
|
|
}
|
2012-05-26 21:20:19 +08:00
|
|
|
#else
|
|
|
|
static void pstore_register_console(void) {}
|
2015-10-20 15:39:03 +08:00
|
|
|
static void pstore_unregister_console(void) {}
|
2012-05-26 21:20:19 +08:00
|
|
|
#endif
|
|
|
|
|
2017-03-06 14:41:10 +08:00
|
|
|
static int pstore_write_user_compat(struct pstore_record *record,
|
|
|
|
const char __user *buf)
|
2016-09-01 23:13:46 +08:00
|
|
|
{
|
2017-03-08 05:57:11 +08:00
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
if (record->buf)
|
|
|
|
return -EINVAL;
|
|
|
|
|
2017-04-29 09:45:16 +08:00
|
|
|
record->buf = memdup_user(buf, record->size);
|
2017-09-26 02:21:27 +08:00
|
|
|
if (IS_ERR(record->buf)) {
|
2017-04-29 09:45:16 +08:00
|
|
|
ret = PTR_ERR(record->buf);
|
2017-03-08 05:57:11 +08:00
|
|
|
goto out;
|
2016-09-01 23:13:46 +08:00
|
|
|
}
|
2017-03-08 05:57:11 +08:00
|
|
|
|
|
|
|
ret = record->psi->write(record);
|
|
|
|
|
|
|
|
kfree(record->buf);
|
2017-04-29 09:45:16 +08:00
|
|
|
out:
|
2017-03-08 05:57:11 +08:00
|
|
|
record->buf = NULL;
|
|
|
|
|
|
|
|
return unlikely(ret < 0) ? ret : record->size;
|
2016-09-01 23:13:46 +08:00
|
|
|
}
|
|
|
|
|
2010-12-29 06:25:21 +08:00
|
|
|
/*
|
|
|
|
* platform specific persistent storage driver registers with
|
|
|
|
* us here. If pstore is already mounted, call the platform
|
|
|
|
* read function right away to populate the file system. If not
|
|
|
|
* then the pstore mount code will call us later to fill out
|
|
|
|
* the file system.
|
|
|
|
*/
|
|
|
|
int pstore_register(struct pstore_info *psi)
|
|
|
|
{
|
|
|
|
struct module *owner = psi->owner;
|
|
|
|
|
2017-03-04 04:11:40 +08:00
|
|
|
if (backend && strcmp(backend, psi->name)) {
|
|
|
|
pr_warn("ignoring unexpected backend '%s'\n", psi->name);
|
2013-06-29 05:11:33 +08:00
|
|
|
return -EPERM;
|
2017-03-04 04:11:40 +08:00
|
|
|
}
|
2013-06-29 05:11:33 +08:00
|
|
|
|
2017-03-06 14:41:10 +08:00
|
|
|
/* Sanity check flags. */
|
|
|
|
if (!psi->flags) {
|
|
|
|
pr_warn("backend '%s' must support at least one frontend\n",
|
|
|
|
psi->name);
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check for required functions. */
|
|
|
|
if (!psi->read || !psi->write) {
|
|
|
|
pr_warn("backend '%s' must implement read() and write()\n",
|
|
|
|
psi->name);
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
2010-12-29 06:25:21 +08:00
|
|
|
spin_lock(&pstore_lock);
|
|
|
|
if (psinfo) {
|
2017-03-04 04:11:40 +08:00
|
|
|
pr_warn("backend '%s' already loaded: ignoring '%s'\n",
|
|
|
|
psinfo->name, psi->name);
|
2010-12-29 06:25:21 +08:00
|
|
|
spin_unlock(&pstore_lock);
|
|
|
|
return -EBUSY;
|
|
|
|
}
|
2011-07-22 04:57:55 +08:00
|
|
|
|
2017-03-06 14:41:10 +08:00
|
|
|
if (!psi->write_user)
|
|
|
|
psi->write_user = pstore_write_user_compat;
|
2010-12-29 06:25:21 +08:00
|
|
|
psinfo = psi;
|
2011-11-18 04:58:07 +08:00
|
|
|
mutex_init(&psinfo->read_mutex);
|
2018-12-01 06:36:58 +08:00
|
|
|
sema_init(&psinfo->buf_lock, 1);
|
2010-12-29 06:25:21 +08:00
|
|
|
spin_unlock(&pstore_lock);
|
|
|
|
|
|
|
|
if (owner && !try_module_get(owner)) {
|
|
|
|
psinfo = NULL;
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
2019-05-31 14:37:29 +08:00
|
|
|
if (psi->flags & PSTORE_FLAGS_DMESG)
|
|
|
|
allocate_buf_for_compression();
|
2013-08-17 04:53:10 +08:00
|
|
|
|
2010-12-29 06:25:21 +08:00
|
|
|
if (pstore_is_mounted())
|
2011-08-12 06:14:39 +08:00
|
|
|
pstore_get_records(0);
|
2010-12-29 06:25:21 +08:00
|
|
|
|
2016-07-27 23:08:25 +08:00
|
|
|
if (psi->flags & PSTORE_FLAGS_DMESG)
|
|
|
|
pstore_register_kmsg();
|
|
|
|
if (psi->flags & PSTORE_FLAGS_CONSOLE)
|
2013-12-19 07:17:10 +08:00
|
|
|
pstore_register_console();
|
2016-07-27 23:08:25 +08:00
|
|
|
if (psi->flags & PSTORE_FLAGS_FTRACE)
|
2013-12-19 07:17:10 +08:00
|
|
|
pstore_register_ftrace();
|
2016-07-27 23:08:25 +08:00
|
|
|
if (psi->flags & PSTORE_FLAGS_PMSG)
|
2015-01-17 08:01:10 +08:00
|
|
|
pstore_register_pmsg();
|
2010-12-29 06:25:21 +08:00
|
|
|
|
2017-03-07 04:42:12 +08:00
|
|
|
/* Start watching for new records, if desired. */
|
2012-05-26 21:20:28 +08:00
|
|
|
if (pstore_update_ms >= 0) {
|
|
|
|
pstore_timer.expires = jiffies +
|
|
|
|
msecs_to_jiffies(pstore_update_ms);
|
|
|
|
add_timer(&pstore_timer);
|
|
|
|
}
|
2011-08-12 06:14:39 +08:00
|
|
|
|
2015-05-22 00:34:22 +08:00
|
|
|
/*
|
|
|
|
* Update the module parameter backend, so it is visible
|
|
|
|
* through /sys/module/pstore/parameters/backend
|
|
|
|
*/
|
|
|
|
backend = psi->name;
|
|
|
|
|
2014-06-07 05:37:31 +08:00
|
|
|
pr_info("Registered %s as persistent store backend\n", psi->name);
|
2013-06-29 05:11:33 +08:00
|
|
|
|
2017-03-04 09:45:38 +08:00
|
|
|
module_put(owner);
|
|
|
|
|
2010-12-29 06:25:21 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(pstore_register);
|
|
|
|
|
2015-10-20 15:39:03 +08:00
|
|
|
void pstore_unregister(struct pstore_info *psi)
|
|
|
|
{
|
2017-03-07 04:42:12 +08:00
|
|
|
/* Stop timer and make sure all work has finished. */
|
|
|
|
pstore_update_ms = -1;
|
|
|
|
del_timer_sync(&pstore_timer);
|
|
|
|
flush_work(&pstore_work);
|
|
|
|
|
2016-07-27 23:08:25 +08:00
|
|
|
if (psi->flags & PSTORE_FLAGS_PMSG)
|
2016-05-19 22:59:03 +08:00
|
|
|
pstore_unregister_pmsg();
|
2016-07-27 23:08:25 +08:00
|
|
|
if (psi->flags & PSTORE_FLAGS_FTRACE)
|
2016-05-19 22:59:03 +08:00
|
|
|
pstore_unregister_ftrace();
|
2016-07-27 23:08:25 +08:00
|
|
|
if (psi->flags & PSTORE_FLAGS_CONSOLE)
|
2016-05-19 22:59:03 +08:00
|
|
|
pstore_unregister_console();
|
2016-07-27 23:08:25 +08:00
|
|
|
if (psi->flags & PSTORE_FLAGS_DMESG)
|
|
|
|
pstore_unregister_kmsg();
|
2015-10-20 15:39:03 +08:00
|
|
|
|
|
|
|
free_buf_for_compression();
|
|
|
|
|
|
|
|
psinfo = NULL;
|
|
|
|
backend = NULL;
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(pstore_unregister);
|
|
|
|
|
2017-03-04 09:35:25 +08:00
|
|
|
static void decompress_record(struct pstore_record *record)
|
|
|
|
{
|
2018-10-26 16:17:07 +08:00
|
|
|
int ret;
|
2017-03-04 09:35:25 +08:00
|
|
|
int unzipped_len;
|
2018-10-26 16:17:07 +08:00
|
|
|
char *unzipped, *workspace;
|
2017-03-04 09:35:25 +08:00
|
|
|
|
2024-06-11 20:26:44 +08:00
|
|
|
if (!IS_ENABLED(CONFIG_PSTORE_COMPRESS) || !record->compressed)
|
2017-05-23 13:46:52 +08:00
|
|
|
return;
|
|
|
|
|
2017-03-04 09:35:25 +08:00
|
|
|
/* Only PSTORE_TYPE_DMESG support compression. */
|
2017-05-23 13:46:52 +08:00
|
|
|
if (record->type != PSTORE_TYPE_DMESG) {
|
2017-03-04 09:35:25 +08:00
|
|
|
pr_warn("ignored compressed record type %d\n", record->type);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-10-26 16:17:07 +08:00
|
|
|
/* Missing compression buffer means compression was not initialized. */
|
2017-03-04 09:35:25 +08:00
|
|
|
if (!big_oops_buf) {
|
2018-10-26 16:17:07 +08:00
|
|
|
pr_warn("no decompression method initialized!\n");
|
2017-03-04 09:35:25 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-10-26 16:17:07 +08:00
|
|
|
/* Allocate enough space to hold max decompression and ECC. */
|
|
|
|
unzipped_len = big_oops_buf_sz;
|
|
|
|
workspace = kmalloc(unzipped_len + record->ecc_notice_size,
|
|
|
|
GFP_KERNEL);
|
|
|
|
if (!workspace)
|
2017-03-05 14:28:46 +08:00
|
|
|
return;
|
|
|
|
|
2018-10-26 16:17:07 +08:00
|
|
|
/* After decompression "unzipped_len" is almost certainly smaller. */
|
|
|
|
ret = crypto_comp_decompress(tfm, record->buf, record->size,
|
|
|
|
workspace, &unzipped_len);
|
|
|
|
if (ret) {
|
|
|
|
pr_err("crypto_comp_decompress failed, ret = %d!\n", ret);
|
|
|
|
kfree(workspace);
|
2017-03-05 14:28:46 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Append ECC notice to decompressed buffer. */
|
2018-10-26 16:17:07 +08:00
|
|
|
memcpy(workspace + unzipped_len, record->buf + record->size,
|
2017-03-05 14:28:46 +08:00
|
|
|
record->ecc_notice_size);
|
|
|
|
|
2018-10-26 16:17:07 +08:00
|
|
|
/* Copy decompressed contents into an minimum-sized allocation. */
|
|
|
|
unzipped = kmemdup(workspace, unzipped_len + record->ecc_notice_size,
|
|
|
|
GFP_KERNEL);
|
|
|
|
kfree(workspace);
|
|
|
|
if (!unzipped)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* Swap out compressed contents with decompressed contents. */
|
2017-03-05 14:28:46 +08:00
|
|
|
kfree(record->buf);
|
2018-10-26 16:17:07 +08:00
|
|
|
record->buf = unzipped;
|
2017-03-05 14:28:46 +08:00
|
|
|
record->size = unzipped_len;
|
|
|
|
record->compressed = false;
|
2017-03-04 09:35:25 +08:00
|
|
|
}
|
|
|
|
|
2010-12-29 06:25:21 +08:00
|
|
|
/*
|
2017-04-28 06:53:21 +08:00
|
|
|
* Read all the records from one persistent store backend. Create
|
2011-08-12 06:14:39 +08:00
|
|
|
* files in our filesystem. Don't warn about -EEXIST errors
|
|
|
|
* when we are re-scanning the backing store looking to add new
|
|
|
|
* error records.
|
2010-12-29 06:25:21 +08:00
|
|
|
*/
|
2017-04-28 06:53:21 +08:00
|
|
|
void pstore_get_backend_records(struct pstore_info *psi,
|
|
|
|
struct dentry *root, int quiet)
|
2010-12-29 06:25:21 +08:00
|
|
|
{
|
2017-03-05 14:57:26 +08:00
|
|
|
int failed = 0;
|
2017-05-17 03:03:31 +08:00
|
|
|
unsigned int stop_loop = 65536;
|
2010-12-29 06:25:21 +08:00
|
|
|
|
2017-04-28 06:53:21 +08:00
|
|
|
if (!psi || !root)
|
2010-12-29 06:25:21 +08:00
|
|
|
return;
|
|
|
|
|
2011-11-18 04:58:07 +08:00
|
|
|
mutex_lock(&psi->read_mutex);
|
2011-11-19 05:49:00 +08:00
|
|
|
if (psi->open && psi->open(psi))
|
2011-05-17 02:00:27 +08:00
|
|
|
goto out;
|
|
|
|
|
2017-03-05 14:46:41 +08:00
|
|
|
/*
|
|
|
|
* Backend callback read() allocates record.buf. decompress_record()
|
|
|
|
* may reallocate record.buf. On success, pstore_mkfile() will keep
|
|
|
|
* the record.buf, so free it only on failure.
|
|
|
|
*/
|
2017-05-17 03:03:31 +08:00
|
|
|
for (; stop_loop; stop_loop--) {
|
2017-03-05 14:57:26 +08:00
|
|
|
struct pstore_record *record;
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
record = kzalloc(sizeof(*record), GFP_KERNEL);
|
|
|
|
if (!record) {
|
|
|
|
pr_err("out of memory creating record\n");
|
|
|
|
break;
|
|
|
|
}
|
2017-05-20 06:10:31 +08:00
|
|
|
pstore_record_init(record, psi);
|
2017-03-05 14:57:26 +08:00
|
|
|
|
|
|
|
record->size = psi->read(record);
|
|
|
|
|
|
|
|
/* No more records left in backend? */
|
2017-05-31 06:50:38 +08:00
|
|
|
if (record->size <= 0) {
|
|
|
|
kfree(record);
|
2017-03-05 14:57:26 +08:00
|
|
|
break;
|
2017-05-31 06:50:38 +08:00
|
|
|
}
|
2017-03-05 14:57:26 +08:00
|
|
|
|
|
|
|
decompress_record(record);
|
2017-04-28 06:53:21 +08:00
|
|
|
rc = pstore_mkfile(root, record);
|
2017-03-05 14:46:41 +08:00
|
|
|
if (rc) {
|
2017-03-05 15:12:24 +08:00
|
|
|
/* pstore_mkfile() did not take record, so free it. */
|
2017-03-05 14:57:26 +08:00
|
|
|
kfree(record->buf);
|
2017-03-05 15:12:24 +08:00
|
|
|
kfree(record);
|
2017-03-05 14:46:41 +08:00
|
|
|
if (rc != -EEXIST || !quiet)
|
|
|
|
failed++;
|
|
|
|
}
|
2010-12-29 06:25:21 +08:00
|
|
|
}
|
2011-11-19 05:49:00 +08:00
|
|
|
if (psi->close)
|
|
|
|
psi->close(psi);
|
2011-05-17 02:00:27 +08:00
|
|
|
out:
|
2011-11-18 04:58:07 +08:00
|
|
|
mutex_unlock(&psi->read_mutex);
|
2010-12-29 06:25:21 +08:00
|
|
|
|
|
|
|
if (failed)
|
2017-05-17 03:03:31 +08:00
|
|
|
pr_warn("failed to create %d record(s) from '%s'\n",
|
2014-06-07 05:37:31 +08:00
|
|
|
failed, psi->name);
|
2017-05-17 03:03:31 +08:00
|
|
|
if (!stop_loop)
|
|
|
|
pr_err("looping? Too many records seen from '%s'\n",
|
|
|
|
psi->name);
|
2010-12-29 06:25:21 +08:00
|
|
|
}
|
|
|
|
|
2011-08-12 06:14:39 +08:00
|
|
|
static void pstore_dowork(struct work_struct *work)
|
|
|
|
{
|
|
|
|
pstore_get_records(1);
|
|
|
|
}
|
|
|
|
|
2017-08-29 02:28:21 +08:00
|
|
|
static void pstore_timefunc(struct timer_list *unused)
|
2011-08-12 06:14:39 +08:00
|
|
|
{
|
|
|
|
if (pstore_new_entry) {
|
|
|
|
pstore_new_entry = 0;
|
|
|
|
schedule_work(&pstore_work);
|
|
|
|
}
|
|
|
|
|
2017-03-07 04:42:12 +08:00
|
|
|
if (pstore_update_ms >= 0)
|
|
|
|
mod_timer(&pstore_timer,
|
|
|
|
jiffies + msecs_to_jiffies(pstore_update_ms));
|
2011-08-12 06:14:39 +08:00
|
|
|
}
|
|
|
|
|
2018-03-07 07:57:38 +08:00
|
|
|
void __init pstore_choose_compression(void)
|
|
|
|
{
|
|
|
|
const struct pstore_zbackend *step;
|
|
|
|
|
|
|
|
if (!compress)
|
|
|
|
return;
|
|
|
|
|
|
|
|
for (step = zbackends; step->name; step++) {
|
|
|
|
if (!strcmp(compress, step->name)) {
|
|
|
|
zbackend = step;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-10-19 02:17:42 +08:00
|
|
|
static int __init pstore_init(void)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
pstore_choose_compression();
|
|
|
|
|
2018-10-17 18:13:55 +08:00
|
|
|
/*
|
|
|
|
* Check if any pstore backends registered earlier but did not
|
|
|
|
* initialize compression because crypto was not ready. If so,
|
|
|
|
* initialize compression now.
|
|
|
|
*/
|
2018-10-18 05:00:12 +08:00
|
|
|
allocate_buf_for_compression();
|
2018-10-17 18:13:55 +08:00
|
|
|
|
2018-10-19 02:17:42 +08:00
|
|
|
ret = pstore_init_fs();
|
|
|
|
if (ret)
|
2024-06-11 20:26:44 +08:00
|
|
|
free_buf_for_compression();
|
2018-10-19 02:17:42 +08:00
|
|
|
|
2024-06-11 20:26:44 +08:00
|
|
|
return ret;
|
2018-10-19 02:17:42 +08:00
|
|
|
}
|
2018-10-17 18:13:55 +08:00
|
|
|
late_initcall(pstore_init);
|
2018-10-19 02:17:42 +08:00
|
|
|
|
|
|
|
static void __exit pstore_exit(void)
|
|
|
|
{
|
|
|
|
pstore_exit_fs();
|
|
|
|
}
|
|
|
|
module_exit(pstore_exit)
|
|
|
|
|
2018-03-07 07:57:38 +08:00
|
|
|
module_param(compress, charp, 0444);
|
|
|
|
MODULE_PARM_DESC(compress, "Pstore compression to use");
|
|
|
|
|
2011-07-22 04:57:55 +08:00
|
|
|
module_param(backend, charp, 0444);
|
|
|
|
MODULE_PARM_DESC(backend, "Pstore backend to use");
|
2018-10-19 02:17:42 +08:00
|
|
|
|
|
|
|
MODULE_AUTHOR("Tony Luck <tony.luck@intel.com>");
|
|
|
|
MODULE_LICENSE("GPL");
|