[Mod] Support the automatic mounting of pstore/ram.
This commit is contained in:
@ -531,12 +531,21 @@ CONFIG_BT_HCIUART_H4=y
|
||||
# CONFIG_BT_MRVL is not set
|
||||
# CONFIG_BT_MTKSDIO is not set
|
||||
|
||||
# 死锁检测
|
||||
CONFIG_LOCK_STAT=y
|
||||
CONFIG_PROVE_LOCKING=y
|
||||
|
||||
# Ftracer
|
||||
CONFIG_FUNCTION_TRACER=y
|
||||
CONFIG_PSTORE_FTRACE=y
|
||||
|
||||
# Sysrq
|
||||
CONFIG_MAGIC_SYSRQ=y
|
||||
|
||||
# Pstore
|
||||
CONFIG_PSTORE=y
|
||||
CONFIG_PSTORE_CONSOLE=y
|
||||
CONFIG_PSTORE_RAM=m
|
||||
# Frontend
|
||||
CONFIG_PSTORE_PMSG=y
|
||||
|
||||
#CONFIG_FUNCTION_TRACER=y
|
||||
#CONFIG_PSTORE_FTRACE=y
|
||||
CONFIG_PSTORE_CONSOLE=y
|
||||
# Backend
|
||||
CONFIG_PSTORE_RAM=y
|
||||
|
||||
@ -7,3 +7,4 @@ tmpfs /tmp tmpfs mode=1777 0 0
|
||||
tmpfs /run tmpfs mode=0755,nosuid,nodev 0 0
|
||||
sysfs /sys sysfs defaults 0 0
|
||||
debug /sys/kernel/debug debugfs defaults 0 0
|
||||
pstore /sys/fs/pstore pstore defaults 0 0
|
||||
|
||||
@ -378,6 +378,42 @@ void pstore_record_init(struct pstore_record *record,
|
||||
record->time = ns_to_timespec64(ktime_get_real_fast_ns());
|
||||
}
|
||||
|
||||
static const char *key_words[] = {
|
||||
// faults
|
||||
"Unable to handle kernel",
|
||||
"Unhandled fault",
|
||||
"Unhandled prefetch abort",
|
||||
// panic
|
||||
"Kernel panic",
|
||||
// oom
|
||||
"invoked oom-killer",
|
||||
NULL,
|
||||
};
|
||||
|
||||
static size_t kmsg_data_strip(char *data, int len)
|
||||
{
|
||||
char *tmp, *first = NULL;
|
||||
int i;
|
||||
size_t ret = 0;
|
||||
|
||||
for (i=0; key_words[i]; i++) {
|
||||
tmp = strnstr(data, key_words[i], len);
|
||||
if (tmp) {
|
||||
if (!first || (tmp < first)) {
|
||||
ret = len - (first - data);
|
||||
first = tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (first && ret > 0)
|
||||
memmove(data, first, ret);
|
||||
else
|
||||
ret = len;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* callback from kmsg_dump. Save as much as we can (up to kmsg_bytes) from the
|
||||
* end of the buffer.
|
||||
@ -439,6 +475,8 @@ static void pstore_dump(struct kmsg_dumper *dumper,
|
||||
dst_size, &dump_size))
|
||||
break;
|
||||
|
||||
// dump_size = kmsg_data_strip(dst + header_size, dump_size);
|
||||
|
||||
if (big_oops_buf) {
|
||||
zipped_len = pstore_compress(dst, psinfo->buf,
|
||||
header_size + dump_size,
|
||||
|
||||
@ -1,15 +1,18 @@
|
||||
#include "asm-generic/int-ll64.h"
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/rcupdate.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/mutex.h>
|
||||
|
||||
static unsigned int test_type;
|
||||
module_param(test_type, uint, 0400);
|
||||
MODULE_PARM_DESC(test_type, "set to 1 to try to OOM (default 0)");
|
||||
|
||||
static int trigger_oops(void) {
|
||||
static int trigger_oops(void)
|
||||
{
|
||||
int *ptr = (int *)0; // 强制类型转换0地址为指针并尝试读取
|
||||
|
||||
printk(KERN_ALERT "Dereferenced NULL pointer value: %d\n", *ptr);
|
||||
@ -17,7 +20,8 @@ static int trigger_oops(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int trigger_oom(void) {
|
||||
static int trigger_oom(void)
|
||||
{
|
||||
void *memory = NULL;
|
||||
size_t memory_size = 0;
|
||||
|
||||
@ -38,18 +42,99 @@ static int trigger_oom(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int test_data = 0;
|
||||
static struct rcu_head test_rcu_head;
|
||||
|
||||
static void bad_rcu_callback(struct rcu_head *head)
|
||||
{
|
||||
// 违规操作:在RCU回调函数中睡眠,这可能导致RCU grace period过长
|
||||
msleep(1000);
|
||||
|
||||
// 违规操作:修改被RCU保护的数据结构
|
||||
test_data++; // 不应在RCU回调中修改全局变量
|
||||
|
||||
pr_info("Bad RCU callback executed\n");
|
||||
}
|
||||
|
||||
static void trigger_rcu(void)
|
||||
{
|
||||
pr_info("RCU error module loaded\n");
|
||||
|
||||
call_rcu(&test_rcu_head, bad_rcu_callback);
|
||||
}
|
||||
|
||||
static int is_ready_thread1, is_ready_thread2;
|
||||
static struct task_struct *thread1;
|
||||
static struct task_struct *thread2;
|
||||
|
||||
static DEFINE_MUTEX(mutex_a);
|
||||
static DEFINE_MUTEX(mutex_b);
|
||||
|
||||
static int thread_func(void *data)
|
||||
{
|
||||
char *name = (char *) data;
|
||||
|
||||
if (!strcmp(name, "Thread1")) {
|
||||
printk(KERN_INFO "%s: Acquiring mutex A...\n", name);
|
||||
mutex_lock(&mutex_a);
|
||||
is_ready_thread1 = 1;
|
||||
while (!is_ready_thread2);
|
||||
printk(KERN_INFO "%s: Got mutex A. Now trying to acquire mutex B...\n", name);
|
||||
mutex_lock(&mutex_b); // This will block, causing deadlock
|
||||
printk(KERN_INFO "%s: Got mutex B.\n", name);
|
||||
} else {
|
||||
printk(KERN_INFO "%s: Acquiring mutex B...\n", name);
|
||||
mutex_lock(&mutex_b);
|
||||
is_ready_thread2 = 1;
|
||||
while (!is_ready_thread1);
|
||||
printk(KERN_INFO "%s: Got mutex B. Now trying to acquire mutex A...\n", name);
|
||||
mutex_lock(&mutex_a); // This will block, causing deadlock
|
||||
printk(KERN_INFO "%s: Got mutex A.\n", name);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int trigger_deadlock(void)
|
||||
{
|
||||
thread1 = kthread_run(thread_func, (void *) "Thread1", "thread1");
|
||||
if (IS_ERR(thread1)) {
|
||||
printk(KERN_ERR "Failed to create thread1\n");
|
||||
return PTR_ERR(thread1);
|
||||
}
|
||||
|
||||
thread2 = kthread_run(thread_func, (void *) "Thread2", "thread2");
|
||||
if (IS_ERR(thread2)) {
|
||||
printk(KERN_ERR "Failed to create thread2\n");
|
||||
kthread_stop(thread1);
|
||||
return PTR_ERR(thread2);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int trigger_init(void) {
|
||||
if (test_type)
|
||||
trigger_oom();
|
||||
else
|
||||
if (test_type == 0)
|
||||
trigger_oops();
|
||||
else if (test_type == 1)
|
||||
trigger_oom();
|
||||
else if (test_type == 2)
|
||||
trigger_rcu();
|
||||
else if (test_type == 3)
|
||||
trigger_deadlock();
|
||||
|
||||
return 0; // 加载模块不应该有返回值,但这里返回0避免编译警告。
|
||||
}
|
||||
|
||||
static void __exit trigger_exit(void) {
|
||||
printk(KERN_INFO "oom_trigger: Exiting the oom_trigger LKM\n");
|
||||
if (test_type == 3) {
|
||||
kthread_stop(thread1);
|
||||
kthread_stop(thread2);
|
||||
printk(KERN_INFO "Deadlock trigger exit.\n");
|
||||
}
|
||||
}
|
||||
|
||||
module_init(trigger_init);
|
||||
module_exit(trigger_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
Reference in New Issue
Block a user