OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [lib/] [fault-inject.c] - Blame information for rev 81

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
#include <linux/kernel.h>
2
#include <linux/init.h>
3
#include <linux/random.h>
4
#include <linux/stat.h>
5
#include <linux/types.h>
6
#include <linux/fs.h>
7
#include <linux/module.h>
8
#include <linux/interrupt.h>
9
#include <linux/unwind.h>
10
#include <linux/stacktrace.h>
11
#include <linux/kallsyms.h>
12
#include <linux/fault-inject.h>
13
 
14
/*
15
 * setup_fault_attr() is a helper function for various __setup handlers, so it
16
 * returns 0 on error, because that is what __setup handlers do.
17
 */
18
int __init setup_fault_attr(struct fault_attr *attr, char *str)
19
{
20
        unsigned long probability;
21
        unsigned long interval;
22
        int times;
23
        int space;
24
 
25
        /* "<interval>,<probability>,<space>,<times>" */
26
        if (sscanf(str, "%lu,%lu,%d,%d",
27
                        &interval, &probability, &space, &times) < 4) {
28
                printk(KERN_WARNING
29
                        "FAULT_INJECTION: failed to parse arguments\n");
30
                return 0;
31
        }
32
 
33
        attr->probability = probability;
34
        attr->interval = interval;
35
        atomic_set(&attr->times, times);
36
        atomic_set(&attr->space, space);
37
 
38
        return 1;
39
}
40
 
41
static void fail_dump(struct fault_attr *attr)
42
{
43
        if (attr->verbose > 0)
44
                printk(KERN_NOTICE "FAULT_INJECTION: forcing a failure\n");
45
        if (attr->verbose > 1)
46
                dump_stack();
47
}
48
 
49
#define atomic_dec_not_zero(v)          atomic_add_unless((v), -1, 0)
50
 
51
static bool fail_task(struct fault_attr *attr, struct task_struct *task)
52
{
53
        return !in_interrupt() && task->make_it_fail;
54
}
55
 
56
#define MAX_STACK_TRACE_DEPTH 32
57
 
58
#ifdef CONFIG_FAULT_INJECTION_STACKTRACE_FILTER
59
 
60
static bool fail_stacktrace(struct fault_attr *attr)
61
{
62
        struct stack_trace trace;
63
        int depth = attr->stacktrace_depth;
64
        unsigned long entries[MAX_STACK_TRACE_DEPTH];
65
        int n;
66
        bool found = (attr->require_start == 0 && attr->require_end == ULONG_MAX);
67
 
68
        if (depth == 0)
69
                return found;
70
 
71
        trace.nr_entries = 0;
72
        trace.entries = entries;
73
        trace.max_entries = depth;
74
        trace.skip = 1;
75
 
76
        save_stack_trace(&trace);
77
        for (n = 0; n < trace.nr_entries; n++) {
78
                if (attr->reject_start <= entries[n] &&
79
                               entries[n] < attr->reject_end)
80
                        return false;
81
                if (attr->require_start <= entries[n] &&
82
                               entries[n] < attr->require_end)
83
                        found = true;
84
        }
85
        return found;
86
}
87
 
88
#else
89
 
90
static inline bool fail_stacktrace(struct fault_attr *attr)
91
{
92
        return true;
93
}
94
 
95
#endif /* CONFIG_FAULT_INJECTION_STACKTRACE_FILTER */
96
 
97
/*
98
 * This code is stolen from failmalloc-1.0
99
 * http://www.nongnu.org/failmalloc/
100
 */
101
 
102
bool should_fail(struct fault_attr *attr, ssize_t size)
103
{
104
        if (attr->task_filter && !fail_task(attr, current))
105
                return false;
106
 
107
        if (atomic_read(&attr->times) == 0)
108
                return false;
109
 
110
        if (atomic_read(&attr->space) > size) {
111
                atomic_sub(size, &attr->space);
112
                return false;
113
        }
114
 
115
        if (attr->interval > 1) {
116
                attr->count++;
117
                if (attr->count % attr->interval)
118
                        return false;
119
        }
120
 
121
        if (attr->probability <= random32() % 100)
122
                return false;
123
 
124
        if (!fail_stacktrace(attr))
125
                return false;
126
 
127
        fail_dump(attr);
128
 
129
        if (atomic_read(&attr->times) != -1)
130
                atomic_dec_not_zero(&attr->times);
131
 
132
        return true;
133
}
134
 
135
#ifdef CONFIG_FAULT_INJECTION_DEBUG_FS
136
 
137
static void debugfs_ul_set(void *data, u64 val)
138
{
139
        *(unsigned long *)data = val;
140
}
141
 
142
#ifdef CONFIG_FAULT_INJECTION_STACKTRACE_FILTER
143
static void debugfs_ul_set_MAX_STACK_TRACE_DEPTH(void *data, u64 val)
144
{
145
        *(unsigned long *)data =
146
                val < MAX_STACK_TRACE_DEPTH ?
147
                val : MAX_STACK_TRACE_DEPTH;
148
}
149
#endif /* CONFIG_FAULT_INJECTION_STACKTRACE_FILTER */
150
 
151
static u64 debugfs_ul_get(void *data)
152
{
153
        return *(unsigned long *)data;
154
}
155
 
156
DEFINE_SIMPLE_ATTRIBUTE(fops_ul, debugfs_ul_get, debugfs_ul_set, "%llu\n");
157
 
158
static struct dentry *debugfs_create_ul(const char *name, mode_t mode,
159
                                struct dentry *parent, unsigned long *value)
160
{
161
        return debugfs_create_file(name, mode, parent, value, &fops_ul);
162
}
163
 
164
#ifdef CONFIG_FAULT_INJECTION_STACKTRACE_FILTER
165
DEFINE_SIMPLE_ATTRIBUTE(fops_ul_MAX_STACK_TRACE_DEPTH, debugfs_ul_get,
166
                        debugfs_ul_set_MAX_STACK_TRACE_DEPTH, "%llu\n");
167
 
168
static struct dentry *debugfs_create_ul_MAX_STACK_TRACE_DEPTH(
169
        const char *name, mode_t mode,
170
        struct dentry *parent, unsigned long *value)
171
{
172
        return debugfs_create_file(name, mode, parent, value,
173
                                   &fops_ul_MAX_STACK_TRACE_DEPTH);
174
}
175
#endif /* CONFIG_FAULT_INJECTION_STACKTRACE_FILTER */
176
 
177
static void debugfs_atomic_t_set(void *data, u64 val)
178
{
179
        atomic_set((atomic_t *)data, val);
180
}
181
 
182
static u64 debugfs_atomic_t_get(void *data)
183
{
184
        return atomic_read((atomic_t *)data);
185
}
186
 
187
DEFINE_SIMPLE_ATTRIBUTE(fops_atomic_t, debugfs_atomic_t_get,
188
                        debugfs_atomic_t_set, "%lld\n");
189
 
190
static struct dentry *debugfs_create_atomic_t(const char *name, mode_t mode,
191
                                struct dentry *parent, atomic_t *value)
192
{
193
        return debugfs_create_file(name, mode, parent, value, &fops_atomic_t);
194
}
195
 
196
void cleanup_fault_attr_dentries(struct fault_attr *attr)
197
{
198
        debugfs_remove(attr->dentries.probability_file);
199
        attr->dentries.probability_file = NULL;
200
 
201
        debugfs_remove(attr->dentries.interval_file);
202
        attr->dentries.interval_file = NULL;
203
 
204
        debugfs_remove(attr->dentries.times_file);
205
        attr->dentries.times_file = NULL;
206
 
207
        debugfs_remove(attr->dentries.space_file);
208
        attr->dentries.space_file = NULL;
209
 
210
        debugfs_remove(attr->dentries.verbose_file);
211
        attr->dentries.verbose_file = NULL;
212
 
213
        debugfs_remove(attr->dentries.task_filter_file);
214
        attr->dentries.task_filter_file = NULL;
215
 
216
#ifdef CONFIG_FAULT_INJECTION_STACKTRACE_FILTER
217
 
218
        debugfs_remove(attr->dentries.stacktrace_depth_file);
219
        attr->dentries.stacktrace_depth_file = NULL;
220
 
221
        debugfs_remove(attr->dentries.require_start_file);
222
        attr->dentries.require_start_file = NULL;
223
 
224
        debugfs_remove(attr->dentries.require_end_file);
225
        attr->dentries.require_end_file = NULL;
226
 
227
        debugfs_remove(attr->dentries.reject_start_file);
228
        attr->dentries.reject_start_file = NULL;
229
 
230
        debugfs_remove(attr->dentries.reject_end_file);
231
        attr->dentries.reject_end_file = NULL;
232
 
233
#endif /* CONFIG_FAULT_INJECTION_STACKTRACE_FILTER */
234
 
235
        if (attr->dentries.dir)
236
                WARN_ON(!simple_empty(attr->dentries.dir));
237
 
238
        debugfs_remove(attr->dentries.dir);
239
        attr->dentries.dir = NULL;
240
}
241
 
242
int init_fault_attr_dentries(struct fault_attr *attr, const char *name)
243
{
244
        mode_t mode = S_IFREG | S_IRUSR | S_IWUSR;
245
        struct dentry *dir;
246
 
247
        memset(&attr->dentries, 0, sizeof(attr->dentries));
248
 
249
        dir = debugfs_create_dir(name, NULL);
250
        if (!dir)
251
                goto fail;
252
        attr->dentries.dir = dir;
253
 
254
        attr->dentries.probability_file =
255
                debugfs_create_ul("probability", mode, dir, &attr->probability);
256
 
257
        attr->dentries.interval_file =
258
                debugfs_create_ul("interval", mode, dir, &attr->interval);
259
 
260
        attr->dentries.times_file =
261
                debugfs_create_atomic_t("times", mode, dir, &attr->times);
262
 
263
        attr->dentries.space_file =
264
                debugfs_create_atomic_t("space", mode, dir, &attr->space);
265
 
266
        attr->dentries.verbose_file =
267
                debugfs_create_ul("verbose", mode, dir, &attr->verbose);
268
 
269
        attr->dentries.task_filter_file = debugfs_create_bool("task-filter",
270
                                                mode, dir, &attr->task_filter);
271
 
272
        if (!attr->dentries.probability_file || !attr->dentries.interval_file ||
273
            !attr->dentries.times_file || !attr->dentries.space_file ||
274
            !attr->dentries.verbose_file || !attr->dentries.task_filter_file)
275
                goto fail;
276
 
277
#ifdef CONFIG_FAULT_INJECTION_STACKTRACE_FILTER
278
 
279
        attr->dentries.stacktrace_depth_file =
280
                debugfs_create_ul_MAX_STACK_TRACE_DEPTH(
281
                        "stacktrace-depth", mode, dir, &attr->stacktrace_depth);
282
 
283
        attr->dentries.require_start_file =
284
                debugfs_create_ul("require-start", mode, dir, &attr->require_start);
285
 
286
        attr->dentries.require_end_file =
287
                debugfs_create_ul("require-end", mode, dir, &attr->require_end);
288
 
289
        attr->dentries.reject_start_file =
290
                debugfs_create_ul("reject-start", mode, dir, &attr->reject_start);
291
 
292
        attr->dentries.reject_end_file =
293
                debugfs_create_ul("reject-end", mode, dir, &attr->reject_end);
294
 
295
        if (!attr->dentries.stacktrace_depth_file ||
296
            !attr->dentries.require_start_file ||
297
            !attr->dentries.require_end_file ||
298
            !attr->dentries.reject_start_file ||
299
            !attr->dentries.reject_end_file)
300
                goto fail;
301
 
302
#endif /* CONFIG_FAULT_INJECTION_STACKTRACE_FILTER */
303
 
304
        return 0;
305
fail:
306
        cleanup_fault_attr_dentries(attr);
307
        return -ENOMEM;
308
}
309
 
310
#endif /* CONFIG_FAULT_INJECTION_DEBUG_FS */

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.