mm: failslab: Add support to force slab alloc failures based on size.
[linux-2.6.git] / mm / failslab.c
1 #include <linux/fault-inject.h>
2 #include <linux/slab.h>
3
4 static struct {
5         struct fault_attr attr;
6         u32 ignore_gfp_wait;
7         int cache_filter;
8         u32 size;
9 } failslab = {
10         .attr = FAULT_ATTR_INITIALIZER,
11         .ignore_gfp_wait = 1,
12         .cache_filter = 0,
13         .size = 0,
14 };
15
16 static void fail_dump(struct fault_attr *attr)
17 {
18         if (attr->verbose > 0)
19                 printk(KERN_NOTICE "FAULT_INJECTION: forcing a failure\n");
20         if (attr->verbose > 1)
21                 dump_stack();
22 }
23
24 bool should_failslab(size_t size, gfp_t gfpflags, unsigned long cache_flags)
25 {
26         if (failslab.size && size > failslab.size) {
27                 fail_dump(&failslab.attr);
28                 return true;
29         }
30
31         if (gfpflags & __GFP_NOFAIL)
32                 return false;
33
34         if (failslab.ignore_gfp_wait && (gfpflags & __GFP_WAIT))
35                 return false;
36
37         if (failslab.cache_filter && !(cache_flags & SLAB_FAILSLAB))
38                 return false;
39
40         return should_fail(&failslab.attr, size);
41 }
42
43 static int __init setup_failslab(char *str)
44 {
45         return setup_fault_attr(&failslab.attr, str);
46 }
47 __setup("failslab=", setup_failslab);
48
49 #ifdef CONFIG_FAULT_INJECTION_DEBUG_FS
50 static int __init failslab_debugfs_init(void)
51 {
52         struct dentry *dir;
53         mode_t mode = S_IFREG | S_IRUSR | S_IWUSR;
54
55         dir = fault_create_debugfs_attr("failslab", NULL, &failslab.attr);
56         if (IS_ERR(dir))
57                 return PTR_ERR(dir);
58
59         if (!debugfs_create_bool("ignore-gfp-wait", mode, dir,
60                                 &failslab.ignore_gfp_wait))
61                 goto fail;
62         if (!debugfs_create_bool("cache-filter", mode, dir,
63                                 &failslab.cache_filter))
64                 goto fail;
65
66         if (!debugfs_create_u32("size", mode, dir,
67                                 &failslab.size))
68                 goto fail;
69
70         return 0;
71 fail:
72         debugfs_remove_recursive(dir);
73
74         return -ENOMEM;
75 }
76
77 late_initcall(failslab_debugfs_init);
78
79 #endif /* CONFIG_FAULT_INJECTION_DEBUG_FS */