1#include <linux/fault-inject.h>
2#include <linux/slab.h>
3
4static struct {
5	struct fault_attr attr;
6	u32 ignore_gfp_wait;
7	int cache_filter;
8#ifdef CONFIG_FAULT_INJECTION_DEBUG_FS
9	struct dentry *ignore_gfp_wait_file;
10	struct dentry *cache_filter_file;
11#endif
12} failslab = {
13	.attr = FAULT_ATTR_INITIALIZER,
14	.ignore_gfp_wait = 1,
15	.cache_filter = 0,
16};
17
18bool should_failslab(size_t size, gfp_t gfpflags, unsigned long cache_flags)
19{
20	if (gfpflags & __GFP_NOFAIL)
21		return false;
22
23        if (failslab.ignore_gfp_wait && (gfpflags & __GFP_WAIT))
24		return false;
25
26	if (failslab.cache_filter && !(cache_flags & SLAB_FAILSLAB))
27		return false;
28
29	return should_fail(&failslab.attr, size);
30}
31
32static int __init setup_failslab(char *str)
33{
34	return setup_fault_attr(&failslab.attr, str);
35}
36__setup("failslab=", setup_failslab);
37
38#ifdef CONFIG_FAULT_INJECTION_DEBUG_FS
39static int __init failslab_debugfs_init(void)
40{
41	mode_t mode = S_IFREG | S_IRUSR | S_IWUSR;
42	struct dentry *dir;
43	int err;
44
45	err = init_fault_attr_dentries(&failslab.attr, "failslab");
46	if (err)
47		return err;
48	dir = failslab.attr.dentries.dir;
49
50	failslab.ignore_gfp_wait_file =
51		debugfs_create_bool("ignore-gfp-wait", mode, dir,
52				      &failslab.ignore_gfp_wait);
53
54	failslab.cache_filter_file =
55		debugfs_create_bool("cache-filter", mode, dir,
56				      &failslab.cache_filter);
57
58	if (!failslab.ignore_gfp_wait_file ||
59	    !failslab.cache_filter_file) {
60		err = -ENOMEM;
61		debugfs_remove(failslab.cache_filter_file);
62		debugfs_remove(failslab.ignore_gfp_wait_file);
63		cleanup_fault_attr_dentries(&failslab.attr);
64	}
65
66	return err;
67}
68
69late_initcall(failslab_debugfs_init);
70
71#endif /* CONFIG_FAULT_INJECTION_DEBUG_FS */
72