[Mod] Support the automatic mounting of pstore/ram.

This commit is contained in:
gaoyang3513
2024-05-02 17:10:08 +08:00
parent 40ff13d05f
commit b9741f3cc7
4 changed files with 146 additions and 13 deletions

View File

@ -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

View File

@ -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

View File

@ -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,

View File

@ -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");