diff options
-rw-r--r-- | include/linux/fault-inject.h | 17 | ||||
-rw-r--r-- | lib/fault-inject.c | 21 |
2 files changed, 28 insertions, 10 deletions
diff --git a/include/linux/fault-inject.h b/include/linux/fault-inject.h index c6f996f2abb6..798fad9e420d 100644 --- a/include/linux/fault-inject.h +++ b/include/linux/fault-inject.h | |||
@@ -5,6 +5,7 @@ | |||
5 | 5 | ||
6 | #include <linux/types.h> | 6 | #include <linux/types.h> |
7 | #include <linux/debugfs.h> | 7 | #include <linux/debugfs.h> |
8 | #include <linux/ratelimit.h> | ||
8 | #include <linux/atomic.h> | 9 | #include <linux/atomic.h> |
9 | 10 | ||
10 | /* | 11 | /* |
@@ -25,14 +26,18 @@ struct fault_attr { | |||
25 | unsigned long reject_end; | 26 | unsigned long reject_end; |
26 | 27 | ||
27 | unsigned long count; | 28 | unsigned long count; |
29 | struct ratelimit_state ratelimit_state; | ||
30 | struct dentry *dname; | ||
28 | }; | 31 | }; |
29 | 32 | ||
30 | #define FAULT_ATTR_INITIALIZER { \ | 33 | #define FAULT_ATTR_INITIALIZER { \ |
31 | .interval = 1, \ | 34 | .interval = 1, \ |
32 | .times = ATOMIC_INIT(1), \ | 35 | .times = ATOMIC_INIT(1), \ |
33 | .require_end = ULONG_MAX, \ | 36 | .require_end = ULONG_MAX, \ |
34 | .stacktrace_depth = 32, \ | 37 | .stacktrace_depth = 32, \ |
35 | .verbose = 2, \ | 38 | .ratelimit_state = RATELIMIT_STATE_INIT_DISABLED, \ |
39 | .verbose = 2, \ | ||
40 | .dname = NULL, \ | ||
36 | } | 41 | } |
37 | 42 | ||
38 | #define DECLARE_FAULT_ATTR(name) struct fault_attr name = FAULT_ATTR_INITIALIZER | 43 | #define DECLARE_FAULT_ATTR(name) struct fault_attr name = FAULT_ATTR_INITIALIZER |
diff --git a/lib/fault-inject.c b/lib/fault-inject.c index d7d501ea856d..f1cdeb024d17 100644 --- a/lib/fault-inject.c +++ b/lib/fault-inject.c | |||
@@ -40,10 +40,16 @@ EXPORT_SYMBOL_GPL(setup_fault_attr); | |||
40 | 40 | ||
41 | static void fail_dump(struct fault_attr *attr) | 41 | static void fail_dump(struct fault_attr *attr) |
42 | { | 42 | { |
43 | if (attr->verbose > 0) | 43 | if (attr->verbose > 0 && __ratelimit(&attr->ratelimit_state)) { |
44 | printk(KERN_NOTICE "FAULT_INJECTION: forcing a failure\n"); | 44 | printk(KERN_NOTICE "FAULT_INJECTION: forcing a failure.\n" |
45 | if (attr->verbose > 1) | 45 | "name %pd, interval %lu, probability %lu, " |
46 | dump_stack(); | 46 | "space %d, times %d\n", attr->dname, |
47 | attr->probability, attr->interval, | ||
48 | atomic_read(&attr->space), | ||
49 | atomic_read(&attr->times)); | ||
50 | if (attr->verbose > 1) | ||
51 | dump_stack(); | ||
52 | } | ||
47 | } | 53 | } |
48 | 54 | ||
49 | #define atomic_dec_not_zero(v) atomic_add_unless((v), -1, 0) | 55 | #define atomic_dec_not_zero(v) atomic_add_unless((v), -1, 0) |
@@ -202,6 +208,12 @@ struct dentry *fault_create_debugfs_attr(const char *name, | |||
202 | goto fail; | 208 | goto fail; |
203 | if (!debugfs_create_ul("verbose", mode, dir, &attr->verbose)) | 209 | if (!debugfs_create_ul("verbose", mode, dir, &attr->verbose)) |
204 | goto fail; | 210 | goto fail; |
211 | if (!debugfs_create_u32("verbose_ratelimit_interval_ms", mode, dir, | ||
212 | &attr->ratelimit_state.interval)) | ||
213 | goto fail; | ||
214 | if (!debugfs_create_u32("verbose_ratelimit_burst", mode, dir, | ||
215 | &attr->ratelimit_state.burst)) | ||
216 | goto fail; | ||
205 | if (!debugfs_create_bool("task-filter", mode, dir, &attr->task_filter)) | 217 | if (!debugfs_create_bool("task-filter", mode, dir, &attr->task_filter)) |
206 | goto fail; | 218 | goto fail; |
207 | 219 | ||
@@ -222,6 +234,7 @@ struct dentry *fault_create_debugfs_attr(const char *name, | |||
222 | 234 | ||
223 | #endif /* CONFIG_FAULT_INJECTION_STACKTRACE_FILTER */ | 235 | #endif /* CONFIG_FAULT_INJECTION_STACKTRACE_FILTER */ |
224 | 236 | ||
237 | attr->dname = dget(dir); | ||
225 | return dir; | 238 | return dir; |
226 | fail: | 239 | fail: |
227 | debugfs_remove_recursive(dir); | 240 | debugfs_remove_recursive(dir); |