首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

[linux][kernel]dump kmsg到文件系统中

前言:

有的时候,看到panic了,但是最后一次访问的backtrace有点长,一个屏幕内的log非常短,刚好错过了关键的backtrace。。。

分析:

1,patch

作者写了一个patch,方便把kmsg信息保存到文件中,下次启动可以查看:

修改linux-4.4/kernel/panic.c文件,增加函数:

#ifdef CONFIG_PRINTK
void dump_kmsg_to_file(void)
{
    struct file *fkmsg = NULL;
    struct file *ffile = NULL;
    loff_t pos_kmsg = 0;
    loff_t pos_file = 0;
    int open_fflag = O_CREAT | O_RDWR | O_NOFOLLOW | O_SYNC;
    char *buf = NULL;
    size_t size = PAGE_SIZE;
    size_t ret = 0;
    const char __user *p;
    mm_segment_t old_fs;

    pr_emerg("trigger dump kmsg\n");
    fkmsg = filp_open("/dev/kmsg", O_RDONLY, 0600);
    if (fkmsg == NULL) {
        pr_emerg("open /dev/ksmg fail\n");
        goto out;
    }

    //(void) sys_unlink((const char __user *)"/var/KDUMPMSG");
    ffile = filp_open("/var/KDUMPMSG", open_fflag, 0600);
    if (ffile == NULL) {
        pr_emerg("open /dev/ksmg fail\n");
        goto close_fkmsg;
    }

    buf = vmalloc(size);
    if (buf == NULL) {
        pr_emerg("vmalloc fail\n");
        goto close_ffile;
    }

    pr_emerg("start dump kmsg\n");
    old_fs = get_fs();
    set_fs(get_ds());
    p = (__force const char __user *)buf;
    fkmsg->f_pos = 0;
    ffile->f_pos = 0;
    while ((ret = __vfs_read(fkmsg, p, size, &pos_kmsg)) > 0) {
        int n = 0;
        fkmsg->f_pos = pos_kmsg;

        while (ret) {
            n = __vfs_write(ffile, p, ret, &pos_file);
            if (n <= 0) {
                pr_emerg("write log fail\n");
                goto free_buf;
            }
            ffile->f_pos = pos_file;
            ret -= n;
        }
    }

free_buf:
    set_fs(old_fs);
    if (buf)
        kvfree(buf);

close_ffile:
    if (ffile)
        filp_close(ffile, NULL);

close_fkmsg:
    if (fkmsg)
        filp_close(fkmsg, NULL);

out:
    return;
}
#endif    /*#ifdef CONFIG_PRINTK*/

在pr_emerg("Kernel panic - not syncing: %s\n", buf);函数后面调用dump_kmsg_to_file();即可。
下一篇
举报
领券