Kernel provides mtdoops to dump kmsg to MTD device, but MMC card is not a MTD device.
We can let user-space program to execute the write operation to dump kmsg into block storage.
The sample code is below.
kernel space
--
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/console.h>
#include <linux/vmalloc.h>
#include <linux/seq_file.h>
#include <linux/workqueue.h>
#include <linux/sched.h>
#include <linux/wait.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/kmsg_dump.h>
#include <linux/proc_fs.h>
static struct kmsg_dumper dump;
static struct proc_dir_entry *my_proc;
static int is_panic = 0;
static int my_proc_show(struct seq_file *m, void *v)
{
seq_printf(m, "%d", is_panic);
return 0;
}
static int my_proc_open(struct inode *inode, struct file *file)
{
return single_open(file, my_proc_show, NULL);
}
static const struct file_operations my_proc_ops = {
.open = my_proc_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
static void oops_do_dump(struct kmsg_dumper *dumper,
enum kmsg_dump_reason reason, const char *s1, unsigned long l1,
const char *s2, unsigned long l2)
{
int i;
printk("### [%s:%d] reason = %d\n", __func__, __LINE__, reason);
is_panic = 1;
for (i = 0;i < 10; i++)
msleep(1000);
printk("### [%s:%d] should be done\n", __func__, __LINE__);
}
static int __init my_oops_init(void)
{
int err;
dump.dump = oops_do_dump;
err = kmsg_dump_register(&dump);
if (err) {
printk(KERN_ERR "oops: registering kmsg dumper failed, error %d\n", err);
return -EINVAL;
}
my_proc = proc_create("dump_tester", 0, NULL, &my_proc_ops);
return 0;
}
static void __exit my_oops_exit(void)
{
printk("### [%s:%d]\n", __func__, __LINE__);
if (my_proc)
remove_proc_entry( "dump_tester", NULL);
kmsg_dump_unregister(&dump);
}
module_init(my_oops_init);
module_exit(my_oops_exit);
MODULE_LICENSE("GPL");
User space
--
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <poll.h>
#define BUF_LEN 40960
void main(int argc, char **argv)
{
char tmp = 'X';
char buf[BUF_LEN];
int fd_src, fd_trg;
int fd = open("/proc/dump_tester", O_RDONLY, 0);
while(1) {
lseek(fd, 0, SEEK_SET);
read(fd, &tmp, 1);
//printf("### [%s:%d] ==> '%c'\n", __FUNCTION__, __LINE__, tmp);
if (tmp == '1') {
fd_src = open("/proc/kmsg", O_RDONLY, 0);
fd_trg = open("/dev/block/mmcblk0p6", O_RDWR, 0);
memset(buf, 0, BUF_LEN);
write(fd_trg, buf, BUF_LEN);
lseek(fd_trg, 0, SEEK_SET);
read(fd_src, buf, BUF_LEN);
write(fd_trg, buf, BUF_LEN);
close(fd_src);
close(fd_trg);
sleep(1);
printf("### dump panic log into %s\n", "/dev/block/mmcblk0p6");
break;
}
sleep(1);
}
close(fd);
}
The above source makes several references to "panic". However, if the kernel is actually in panic, the user-space program will not be able to execute and the logs will not be dumped.