failslab.c 1.66 KB
Newer Older
Akinobu Mita's avatar
Akinobu Mita committed
1
#include <linux/fault-inject.h>
2
#include <linux/gfp.h>
3
#include <linux/slab.h>
Akinobu Mita's avatar
Akinobu Mita committed
4
5
6
7

static struct {
	struct fault_attr attr;
	u32 ignore_gfp_wait;
8
	int cache_filter;
Akinobu Mita's avatar
Akinobu Mita committed
9
10
#ifdef CONFIG_FAULT_INJECTION_DEBUG_FS
	struct dentry *ignore_gfp_wait_file;
11
	struct dentry *cache_filter_file;
Akinobu Mita's avatar
Akinobu Mita committed
12
13
14
15
#endif
} failslab = {
	.attr = FAULT_ATTR_INITIALIZER,
	.ignore_gfp_wait = 1,
16
	.cache_filter = 0,
Akinobu Mita's avatar
Akinobu Mita committed
17
18
};

19
bool should_failslab(size_t size, gfp_t gfpflags, unsigned long cache_flags)
Akinobu Mita's avatar
Akinobu Mita committed
20
21
22
23
24
25
26
{
	if (gfpflags & __GFP_NOFAIL)
		return false;

        if (failslab.ignore_gfp_wait && (gfpflags & __GFP_WAIT))
		return false;

27
28
29
	if (failslab.cache_filter && !(cache_flags & SLAB_FAILSLAB))
		return false;

Akinobu Mita's avatar
Akinobu Mita committed
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
	return should_fail(&failslab.attr, size);
}

static int __init setup_failslab(char *str)
{
	return setup_fault_attr(&failslab.attr, str);
}
__setup("failslab=", setup_failslab);

#ifdef CONFIG_FAULT_INJECTION_DEBUG_FS
static int __init failslab_debugfs_init(void)
{
	mode_t mode = S_IFREG | S_IRUSR | S_IWUSR;
	struct dentry *dir;
	int err;

	err = init_fault_attr_dentries(&failslab.attr, "failslab");
	if (err)
		return err;
	dir = failslab.attr.dentries.dir;

	failslab.ignore_gfp_wait_file =
		debugfs_create_bool("ignore-gfp-wait", mode, dir,
				      &failslab.ignore_gfp_wait);

55
56
57
58
59
60
	failslab.cache_filter_file =
		debugfs_create_bool("cache-filter", mode, dir,
				      &failslab.cache_filter);

	if (!failslab.ignore_gfp_wait_file ||
	    !failslab.cache_filter_file) {
Akinobu Mita's avatar
Akinobu Mita committed
61
		err = -ENOMEM;
62
		debugfs_remove(failslab.cache_filter_file);
Akinobu Mita's avatar
Akinobu Mita committed
63
64
65
66
67
68
69
70
71
72
		debugfs_remove(failslab.ignore_gfp_wait_file);
		cleanup_fault_attr_dentries(&failslab.attr);
	}

	return err;
}

late_initcall(failslab_debugfs_init);

#endif /* CONFIG_FAULT_INJECTION_DEBUG_FS */