diff options
Diffstat (limited to 'lib/error-inject.c')
-rw-r--r-- | lib/error-inject.c | 43 |
1 files changed, 36 insertions, 7 deletions
diff --git a/lib/error-inject.c b/lib/error-inject.c index bccadcf3c981..c0d4600f4896 100644 --- a/lib/error-inject.c +++ b/lib/error-inject.c | |||
@@ -16,6 +16,7 @@ struct ei_entry { | |||
16 | struct list_head list; | 16 | struct list_head list; |
17 | unsigned long start_addr; | 17 | unsigned long start_addr; |
18 | unsigned long end_addr; | 18 | unsigned long end_addr; |
19 | int etype; | ||
19 | void *priv; | 20 | void *priv; |
20 | }; | 21 | }; |
21 | 22 | ||
@@ -35,6 +36,17 @@ bool within_error_injection_list(unsigned long addr) | |||
35 | return ret; | 36 | return ret; |
36 | } | 37 | } |
37 | 38 | ||
39 | int get_injectable_error_type(unsigned long addr) | ||
40 | { | ||
41 | struct ei_entry *ent; | ||
42 | |||
43 | list_for_each_entry(ent, &error_injection_list, list) { | ||
44 | if (addr >= ent->start_addr && addr < ent->end_addr) | ||
45 | return ent->etype; | ||
46 | } | ||
47 | return EI_ETYPE_NONE; | ||
48 | } | ||
49 | |||
38 | /* | 50 | /* |
39 | * Lookup and populate the error_injection_list. | 51 | * Lookup and populate the error_injection_list. |
40 | * | 52 | * |
@@ -42,16 +54,17 @@ bool within_error_injection_list(unsigned long addr) | |||
42 | * bpf_error_injection, so we need to populate the list of the symbols that have | 54 | * bpf_error_injection, so we need to populate the list of the symbols that have |
43 | * been marked as safe for overriding. | 55 | * been marked as safe for overriding. |
44 | */ | 56 | */ |
45 | static void populate_error_injection_list(unsigned long *start, | 57 | static void populate_error_injection_list(struct error_injection_entry *start, |
46 | unsigned long *end, void *priv) | 58 | struct error_injection_entry *end, |
59 | void *priv) | ||
47 | { | 60 | { |
48 | unsigned long *iter; | 61 | struct error_injection_entry *iter; |
49 | struct ei_entry *ent; | 62 | struct ei_entry *ent; |
50 | unsigned long entry, offset = 0, size = 0; | 63 | unsigned long entry, offset = 0, size = 0; |
51 | 64 | ||
52 | mutex_lock(&ei_mutex); | 65 | mutex_lock(&ei_mutex); |
53 | for (iter = start; iter < end; iter++) { | 66 | for (iter = start; iter < end; iter++) { |
54 | entry = arch_deref_entry_point((void *)*iter); | 67 | entry = arch_deref_entry_point((void *)iter->addr); |
55 | 68 | ||
56 | if (!kernel_text_address(entry) || | 69 | if (!kernel_text_address(entry) || |
57 | !kallsyms_lookup_size_offset(entry, &size, &offset)) { | 70 | !kallsyms_lookup_size_offset(entry, &size, &offset)) { |
@@ -65,6 +78,7 @@ static void populate_error_injection_list(unsigned long *start, | |||
65 | break; | 78 | break; |
66 | ent->start_addr = entry; | 79 | ent->start_addr = entry; |
67 | ent->end_addr = entry + size; | 80 | ent->end_addr = entry + size; |
81 | ent->etype = iter->etype; | ||
68 | ent->priv = priv; | 82 | ent->priv = priv; |
69 | INIT_LIST_HEAD(&ent->list); | 83 | INIT_LIST_HEAD(&ent->list); |
70 | list_add_tail(&ent->list, &error_injection_list); | 84 | list_add_tail(&ent->list, &error_injection_list); |
@@ -73,8 +87,8 @@ static void populate_error_injection_list(unsigned long *start, | |||
73 | } | 87 | } |
74 | 88 | ||
75 | /* Markers of the _error_inject_whitelist section */ | 89 | /* Markers of the _error_inject_whitelist section */ |
76 | extern unsigned long __start_error_injection_whitelist[]; | 90 | extern struct error_injection_entry __start_error_injection_whitelist[]; |
77 | extern unsigned long __stop_error_injection_whitelist[]; | 91 | extern struct error_injection_entry __stop_error_injection_whitelist[]; |
78 | 92 | ||
79 | static void __init populate_kernel_ei_list(void) | 93 | static void __init populate_kernel_ei_list(void) |
80 | { | 94 | { |
@@ -157,11 +171,26 @@ static void *ei_seq_next(struct seq_file *m, void *v, loff_t *pos) | |||
157 | return seq_list_next(v, &error_injection_list, pos); | 171 | return seq_list_next(v, &error_injection_list, pos); |
158 | } | 172 | } |
159 | 173 | ||
174 | static const char *error_type_string(int etype) | ||
175 | { | ||
176 | switch (etype) { | ||
177 | case EI_ETYPE_NULL: | ||
178 | return "NULL"; | ||
179 | case EI_ETYPE_ERRNO: | ||
180 | return "ERRNO"; | ||
181 | case EI_ETYPE_ERRNO_NULL: | ||
182 | return "ERRNO_NULL"; | ||
183 | default: | ||
184 | return "(unknown)"; | ||
185 | } | ||
186 | } | ||
187 | |||
160 | static int ei_seq_show(struct seq_file *m, void *v) | 188 | static int ei_seq_show(struct seq_file *m, void *v) |
161 | { | 189 | { |
162 | struct ei_entry *ent = list_entry(v, struct ei_entry, list); | 190 | struct ei_entry *ent = list_entry(v, struct ei_entry, list); |
163 | 191 | ||
164 | seq_printf(m, "%pf\n", (void *)ent->start_addr); | 192 | seq_printf(m, "%pf\t%s\n", (void *)ent->start_addr, |
193 | error_type_string(ent->etype)); | ||
165 | return 0; | 194 | return 0; |
166 | } | 195 | } |
167 | 196 | ||