Commit 3c506efd7e0f615bd9603ce8c06bc4a896952599
Exists in
master
and in
4 other branches
Merge branch 'topic/failslab' into for-linus
Conflicts: mm/slub.c Signed-off-by: Pekka Enberg <penberg@cs.helsinki.fi>
Showing 6 changed files Side-by-side Diff
include/linux/fault-inject.h
... | ... | @@ -81,5 +81,14 @@ |
81 | 81 | |
82 | 82 | #endif /* CONFIG_FAULT_INJECTION */ |
83 | 83 | |
84 | +#ifdef CONFIG_FAILSLAB | |
85 | +extern bool should_failslab(size_t size, gfp_t gfpflags); | |
86 | +#else | |
87 | +static inline bool should_failslab(size_t size, gfp_t gfpflags) | |
88 | +{ | |
89 | + return false; | |
90 | +} | |
91 | +#endif /* CONFIG_FAILSLAB */ | |
92 | + | |
84 | 93 | #endif /* _LINUX_FAULT_INJECT_H */ |
lib/Kconfig.debug
mm/Makefile
... | ... | @@ -28,6 +28,7 @@ |
28 | 28 | obj-$(CONFIG_MMU_NOTIFIER) += mmu_notifier.o |
29 | 29 | obj-$(CONFIG_SLAB) += slab.o |
30 | 30 | obj-$(CONFIG_SLUB) += slub.o |
31 | +obj-$(CONFIG_FAILSLAB) += failslab.o | |
31 | 32 | obj-$(CONFIG_MEMORY_HOTPLUG) += memory_hotplug.o |
32 | 33 | obj-$(CONFIG_FS_XIP) += filemap_xip.o |
33 | 34 | obj-$(CONFIG_MIGRATION) += migrate.o |
mm/failslab.c
1 | +#include <linux/fault-inject.h> | |
2 | + | |
3 | +static struct { | |
4 | + struct fault_attr attr; | |
5 | + u32 ignore_gfp_wait; | |
6 | +#ifdef CONFIG_FAULT_INJECTION_DEBUG_FS | |
7 | + struct dentry *ignore_gfp_wait_file; | |
8 | +#endif | |
9 | +} failslab = { | |
10 | + .attr = FAULT_ATTR_INITIALIZER, | |
11 | + .ignore_gfp_wait = 1, | |
12 | +}; | |
13 | + | |
14 | +bool should_failslab(size_t size, gfp_t gfpflags) | |
15 | +{ | |
16 | + if (gfpflags & __GFP_NOFAIL) | |
17 | + return false; | |
18 | + | |
19 | + if (failslab.ignore_gfp_wait && (gfpflags & __GFP_WAIT)) | |
20 | + return false; | |
21 | + | |
22 | + return should_fail(&failslab.attr, size); | |
23 | +} | |
24 | + | |
25 | +static int __init setup_failslab(char *str) | |
26 | +{ | |
27 | + return setup_fault_attr(&failslab.attr, str); | |
28 | +} | |
29 | +__setup("failslab=", setup_failslab); | |
30 | + | |
31 | +#ifdef CONFIG_FAULT_INJECTION_DEBUG_FS | |
32 | + | |
33 | +static int __init failslab_debugfs_init(void) | |
34 | +{ | |
35 | + mode_t mode = S_IFREG | S_IRUSR | S_IWUSR; | |
36 | + struct dentry *dir; | |
37 | + int err; | |
38 | + | |
39 | + err = init_fault_attr_dentries(&failslab.attr, "failslab"); | |
40 | + if (err) | |
41 | + return err; | |
42 | + dir = failslab.attr.dentries.dir; | |
43 | + | |
44 | + failslab.ignore_gfp_wait_file = | |
45 | + debugfs_create_bool("ignore-gfp-wait", mode, dir, | |
46 | + &failslab.ignore_gfp_wait); | |
47 | + | |
48 | + if (!failslab.ignore_gfp_wait_file) { | |
49 | + err = -ENOMEM; | |
50 | + debugfs_remove(failslab.ignore_gfp_wait_file); | |
51 | + cleanup_fault_attr_dentries(&failslab.attr); | |
52 | + } | |
53 | + | |
54 | + return err; | |
55 | +} | |
56 | + | |
57 | +late_initcall(failslab_debugfs_init); | |
58 | + | |
59 | +#endif /* CONFIG_FAULT_INJECTION_DEBUG_FS */ |
mm/slab.c
... | ... | @@ -3108,79 +3108,14 @@ |
3108 | 3108 | #define cache_alloc_debugcheck_after(a,b,objp,d) (objp) |
3109 | 3109 | #endif |
3110 | 3110 | |
3111 | -#ifdef CONFIG_FAILSLAB | |
3112 | - | |
3113 | -static struct failslab_attr { | |
3114 | - | |
3115 | - struct fault_attr attr; | |
3116 | - | |
3117 | - u32 ignore_gfp_wait; | |
3118 | -#ifdef CONFIG_FAULT_INJECTION_DEBUG_FS | |
3119 | - struct dentry *ignore_gfp_wait_file; | |
3120 | -#endif | |
3121 | - | |
3122 | -} failslab = { | |
3123 | - .attr = FAULT_ATTR_INITIALIZER, | |
3124 | - .ignore_gfp_wait = 1, | |
3125 | -}; | |
3126 | - | |
3127 | -static int __init setup_failslab(char *str) | |
3111 | +static bool slab_should_failslab(struct kmem_cache *cachep, gfp_t flags) | |
3128 | 3112 | { |
3129 | - return setup_fault_attr(&failslab.attr, str); | |
3130 | -} | |
3131 | -__setup("failslab=", setup_failslab); | |
3132 | - | |
3133 | -static int should_failslab(struct kmem_cache *cachep, gfp_t flags) | |
3134 | -{ | |
3135 | 3113 | if (cachep == &cache_cache) |
3136 | - return 0; | |
3137 | - if (flags & __GFP_NOFAIL) | |
3138 | - return 0; | |
3139 | - if (failslab.ignore_gfp_wait && (flags & __GFP_WAIT)) | |
3140 | - return 0; | |
3114 | + return false; | |
3141 | 3115 | |
3142 | - return should_fail(&failslab.attr, obj_size(cachep)); | |
3116 | + return should_failslab(obj_size(cachep), flags); | |
3143 | 3117 | } |
3144 | 3118 | |
3145 | -#ifdef CONFIG_FAULT_INJECTION_DEBUG_FS | |
3146 | - | |
3147 | -static int __init failslab_debugfs(void) | |
3148 | -{ | |
3149 | - mode_t mode = S_IFREG | S_IRUSR | S_IWUSR; | |
3150 | - struct dentry *dir; | |
3151 | - int err; | |
3152 | - | |
3153 | - err = init_fault_attr_dentries(&failslab.attr, "failslab"); | |
3154 | - if (err) | |
3155 | - return err; | |
3156 | - dir = failslab.attr.dentries.dir; | |
3157 | - | |
3158 | - failslab.ignore_gfp_wait_file = | |
3159 | - debugfs_create_bool("ignore-gfp-wait", mode, dir, | |
3160 | - &failslab.ignore_gfp_wait); | |
3161 | - | |
3162 | - if (!failslab.ignore_gfp_wait_file) { | |
3163 | - err = -ENOMEM; | |
3164 | - debugfs_remove(failslab.ignore_gfp_wait_file); | |
3165 | - cleanup_fault_attr_dentries(&failslab.attr); | |
3166 | - } | |
3167 | - | |
3168 | - return err; | |
3169 | -} | |
3170 | - | |
3171 | -late_initcall(failslab_debugfs); | |
3172 | - | |
3173 | -#endif /* CONFIG_FAULT_INJECTION_DEBUG_FS */ | |
3174 | - | |
3175 | -#else /* CONFIG_FAILSLAB */ | |
3176 | - | |
3177 | -static inline int should_failslab(struct kmem_cache *cachep, gfp_t flags) | |
3178 | -{ | |
3179 | - return 0; | |
3180 | -} | |
3181 | - | |
3182 | -#endif /* CONFIG_FAILSLAB */ | |
3183 | - | |
3184 | 3119 | static inline void *____cache_alloc(struct kmem_cache *cachep, gfp_t flags) |
3185 | 3120 | { |
3186 | 3121 | void *objp; |
... | ... | @@ -3383,7 +3318,7 @@ |
3383 | 3318 | unsigned long save_flags; |
3384 | 3319 | void *ptr; |
3385 | 3320 | |
3386 | - if (should_failslab(cachep, flags)) | |
3321 | + if (slab_should_failslab(cachep, flags)) | |
3387 | 3322 | return NULL; |
3388 | 3323 | |
3389 | 3324 | cache_alloc_debugcheck_before(cachep, flags); |
... | ... | @@ -3459,7 +3394,7 @@ |
3459 | 3394 | unsigned long save_flags; |
3460 | 3395 | void *objp; |
3461 | 3396 | |
3462 | - if (should_failslab(cachep, flags)) | |
3397 | + if (slab_should_failslab(cachep, flags)) | |
3463 | 3398 | return NULL; |
3464 | 3399 | |
3465 | 3400 | cache_alloc_debugcheck_before(cachep, flags); |
mm/slub.c
... | ... | @@ -24,6 +24,7 @@ |
24 | 24 | #include <linux/kallsyms.h> |
25 | 25 | #include <linux/memory.h> |
26 | 26 | #include <linux/math64.h> |
27 | +#include <linux/fault-inject.h> | |
27 | 28 | |
28 | 29 | /* |
29 | 30 | * Lock order: |
... | ... | @@ -1596,6 +1597,10 @@ |
1596 | 1597 | unsigned int objsize; |
1597 | 1598 | |
1598 | 1599 | might_sleep_if(gfpflags & __GFP_WAIT); |
1600 | + | |
1601 | + if (should_failslab(s->objsize, gfpflags)) | |
1602 | + return NULL; | |
1603 | + | |
1599 | 1604 | local_irq_save(flags); |
1600 | 1605 | c = get_cpu_slab(s, smp_processor_id()); |
1601 | 1606 | objsize = c->objsize; |