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); }
記事全体を表示