/
ec2dump.c
127 lines (96 loc) · 2.57 KB
/
ec2dump.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
/*
* ec2dump - EC2 crash dump tool.
*
* Copyright (C) 2014 Kenta Tada <ktagml@gmail.com>
* This file is released under the GPL.
*/
#include <linux/ioport.h>
#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/highmem.h>
#include <linux/pfn.h>
#include <linux/module.h>
#include <linux/version.h>
#include <linux/string.h>
#include <linux/notifier.h>
#define DUMP_FILE_PATH "/var/dump/ec2dump"
static size_t write_memory_to_fs(void *buf, size_t count);
static int write_memory(struct resource *res);
static int start_ec2dump_on_panic(struct notifier_block *nb, unsigned long e, void *p);
static int setup_for_dump(void);
static struct file *fp = NULL;
static size_t write_memory_to_fs(void *buf, size_t count)
{
mm_segment_t fs;
size_t size;
fs = get_fs();
set_fs(KERNEL_DS);
size = vfs_write(fp, buf, count, &fp->f_pos);
set_fs(fs);
return size;
}
static int write_memory(struct resource *res)
{
resource_size_t i, is;
struct page *pg;
void *vaddr;
int s;
for (i = res->start; i <= res->end; i += is) {
pg = pfn_to_page((i) >> PAGE_SHIFT);
is = min((size_t) PAGE_SIZE, (size_t) (res->end - i + 1));
vaddr = kmap(pg);
s = write_memory_to_fs(vaddr, is);
kunmap(pg);
}
vfs_fsync(fp, 0);
return 0;
}
static int start_ec2dump_on_panic(struct notifier_block *nb, unsigned long e, void *p)
{
struct resource *res;
printk("notified by start_ec2dump_on_panic...\n");
setup_for_dump();
for (res = iomem_resource.child; res; res = res->sibling) {
write_memory(res);
}
printk("dumpcore is created...\n");
return NOTIFY_DONE;
}
static struct notifier_block ec2dump_panic_notifier = {
.notifier_call = start_ec2dump_on_panic,
.priority = 1000000,
};
static int setup_for_dump(void)
{
mm_segment_t fs;
int fs_err;
printk("Currently, filesystem is used for dump...\n");
fs = get_fs();
set_fs(KERNEL_DS);
local_irq_enable();
fp = filp_open(DUMP_FILE_PATH, O_WRONLY | O_CREAT | O_LARGEFILE, 0444);
if (!fp || IS_ERR(fp)) {
printk("error appears when using %ld...\n", PTR_ERR(fp));
set_fs(fs);
fs_err = (fp) ? PTR_ERR(fp) : -EIO;
fp = NULL;
return fs_err;
}
set_fs(fs);
return 0;
}
static int __init ec2dump_init(void)
{
printk("ec2dump is started...\n");
atomic_notifier_chain_register(&panic_notifier_list, &ec2dump_panic_notifier);
printk("registered panic_notifier_list...\n");
return 0;
}
static void __exit ec2dump_exit(void)
{
atomic_notifier_chain_unregister(&panic_notifier_list, &ec2dump_panic_notifier);
printk("exited ec2dump...\n");
}
module_init(ec2dump_init);
module_exit(ec2dump_exit);
MODULE_LICENSE("GPL");