aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAkinobu Mita <akinobu.mita@gmail.com>2008-12-23 05:37:01 -0500
committerPekka Enberg <penberg@cs.helsinki.fi>2008-12-29 04:27:46 -0500
commit773ff60e841461cb1f9374a713ffcda029b8c317 (patch)
treec3691b5a82261a3d2c1861f2913774faac63fa96
parent3c92ec8ae91ecf59d88c798301833d7cf83f2179 (diff)
SLUB: failslab support
Currently fault-injection capability for SLAB allocator is only available to SLAB. This patch makes it available to SLUB, too. [penberg@cs.helsinki.fi: unify slab and slub implementations] Cc: Christoph Lameter <cl@linux-foundation.org> Cc: Matt Mackall <mpm@selenic.com> Signed-off-by: Akinobu Mita <akinobu.mita@gmail.com> Signed-off-by: Pekka Enberg <penberg@cs.helsinki.fi>
-rw-r--r--include/linux/fault-inject.h9
-rw-r--r--lib/Kconfig.debug1
-rw-r--r--mm/Makefile1
-rw-r--r--mm/failslab.c59
-rw-r--r--mm/slab.c75
-rw-r--r--mm/slub.c4
6 files changed, 79 insertions, 70 deletions
diff --git a/include/linux/fault-inject.h b/include/linux/fault-inject.h
index 32368c4f0326..06ca9b21dad2 100644
--- a/include/linux/fault-inject.h
+++ b/include/linux/fault-inject.h
@@ -81,4 +81,13 @@ static inline void cleanup_fault_attr_dentries(struct fault_attr *attr)
81 81
82#endif /* CONFIG_FAULT_INJECTION */ 82#endif /* CONFIG_FAULT_INJECTION */
83 83
84#ifdef CONFIG_FAILSLAB
85extern bool should_failslab(size_t size, gfp_t gfpflags);
86#else
87static inline bool should_failslab(size_t size, gfp_t gfpflags)
88{
89 return false;
90}
91#endif /* CONFIG_FAILSLAB */
92
84#endif /* _LINUX_FAULT_INJECT_H */ 93#endif /* _LINUX_FAULT_INJECT_H */
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index b0f239e443bc..af65ae7f0549 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -699,6 +699,7 @@ config FAULT_INJECTION
699config FAILSLAB 699config FAILSLAB
700 bool "Fault-injection capability for kmalloc" 700 bool "Fault-injection capability for kmalloc"
701 depends on FAULT_INJECTION 701 depends on FAULT_INJECTION
702 depends on SLAB || SLUB
702 help 703 help
703 Provide fault-injection capability for kmalloc. 704 Provide fault-injection capability for kmalloc.
704 705
diff --git a/mm/Makefile b/mm/Makefile
index c06b45a1ff5f..51c27709cc7c 100644
--- a/mm/Makefile
+++ b/mm/Makefile
@@ -28,6 +28,7 @@ obj-$(CONFIG_SLOB) += slob.o
28obj-$(CONFIG_MMU_NOTIFIER) += mmu_notifier.o 28obj-$(CONFIG_MMU_NOTIFIER) += mmu_notifier.o
29obj-$(CONFIG_SLAB) += slab.o 29obj-$(CONFIG_SLAB) += slab.o
30obj-$(CONFIG_SLUB) += slub.o 30obj-$(CONFIG_SLUB) += slub.o
31obj-$(CONFIG_FAILSLAB) += failslab.o
31obj-$(CONFIG_MEMORY_HOTPLUG) += memory_hotplug.o 32obj-$(CONFIG_MEMORY_HOTPLUG) += memory_hotplug.o
32obj-$(CONFIG_FS_XIP) += filemap_xip.o 33obj-$(CONFIG_FS_XIP) += filemap_xip.o
33obj-$(CONFIG_MIGRATION) += migrate.o 34obj-$(CONFIG_MIGRATION) += migrate.o
diff --git a/mm/failslab.c b/mm/failslab.c
new file mode 100644
index 000000000000..7c6ea6493f80
--- /dev/null
+++ b/mm/failslab.c
@@ -0,0 +1,59 @@
1#include <linux/fault-inject.h>
2
3static 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
14bool 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
25static 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
33static 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
57late_initcall(failslab_debugfs_init);
58
59#endif /* CONFIG_FAULT_INJECTION_DEBUG_FS */
diff --git a/mm/slab.c b/mm/slab.c
index 09187517f9dc..c347dd8480cc 100644
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -3106,79 +3106,14 @@ static void *cache_alloc_debugcheck_after(struct kmem_cache *cachep,
3106#define cache_alloc_debugcheck_after(a,b,objp,d) (objp) 3106#define cache_alloc_debugcheck_after(a,b,objp,d) (objp)
3107#endif 3107#endif
3108 3108
3109#ifdef CONFIG_FAILSLAB 3109static bool slab_should_failslab(struct kmem_cache *cachep, gfp_t flags)
3110
3111static struct failslab_attr {
3112
3113 struct fault_attr attr;
3114
3115 u32 ignore_gfp_wait;
3116#ifdef CONFIG_FAULT_INJECTION_DEBUG_FS
3117 struct dentry *ignore_gfp_wait_file;
3118#endif
3119
3120} failslab = {
3121 .attr = FAULT_ATTR_INITIALIZER,
3122 .ignore_gfp_wait = 1,
3123};
3124
3125static int __init setup_failslab(char *str)
3126{
3127 return setup_fault_attr(&failslab.attr, str);
3128}
3129__setup("failslab=", setup_failslab);
3130
3131static int should_failslab(struct kmem_cache *cachep, gfp_t flags)
3132{ 3110{
3133 if (cachep == &cache_cache) 3111 if (cachep == &cache_cache)
3134 return 0; 3112 return false;
3135 if (flags & __GFP_NOFAIL)
3136 return 0;
3137 if (failslab.ignore_gfp_wait && (flags & __GFP_WAIT))
3138 return 0;
3139 3113
3140 return should_fail(&failslab.attr, obj_size(cachep)); 3114 return should_failslab(obj_size(cachep), flags);
3141} 3115}
3142 3116
3143#ifdef CONFIG_FAULT_INJECTION_DEBUG_FS
3144
3145static int __init failslab_debugfs(void)
3146{
3147 mode_t mode = S_IFREG | S_IRUSR | S_IWUSR;
3148 struct dentry *dir;
3149 int err;
3150
3151 err = init_fault_attr_dentries(&failslab.attr, "failslab");
3152 if (err)
3153 return err;
3154 dir = failslab.attr.dentries.dir;
3155
3156 failslab.ignore_gfp_wait_file =
3157 debugfs_create_bool("ignore-gfp-wait", mode, dir,
3158 &failslab.ignore_gfp_wait);
3159
3160 if (!failslab.ignore_gfp_wait_file) {
3161 err = -ENOMEM;
3162 debugfs_remove(failslab.ignore_gfp_wait_file);
3163 cleanup_fault_attr_dentries(&failslab.attr);
3164 }
3165
3166 return err;
3167}
3168
3169late_initcall(failslab_debugfs);
3170
3171#endif /* CONFIG_FAULT_INJECTION_DEBUG_FS */
3172
3173#else /* CONFIG_FAILSLAB */
3174
3175static inline int should_failslab(struct kmem_cache *cachep, gfp_t flags)
3176{
3177 return 0;
3178}
3179
3180#endif /* CONFIG_FAILSLAB */
3181
3182static inline void *____cache_alloc(struct kmem_cache *cachep, gfp_t flags) 3117static inline void *____cache_alloc(struct kmem_cache *cachep, gfp_t flags)
3183{ 3118{
3184 void *objp; 3119 void *objp;
@@ -3381,7 +3316,7 @@ __cache_alloc_node(struct kmem_cache *cachep, gfp_t flags, int nodeid,
3381 unsigned long save_flags; 3316 unsigned long save_flags;
3382 void *ptr; 3317 void *ptr;
3383 3318
3384 if (should_failslab(cachep, flags)) 3319 if (slab_should_failslab(cachep, flags))
3385 return NULL; 3320 return NULL;
3386 3321
3387 cache_alloc_debugcheck_before(cachep, flags); 3322 cache_alloc_debugcheck_before(cachep, flags);
@@ -3457,7 +3392,7 @@ __cache_alloc(struct kmem_cache *cachep, gfp_t flags, void *caller)
3457 unsigned long save_flags; 3392 unsigned long save_flags;
3458 void *objp; 3393 void *objp;
3459 3394
3460 if (should_failslab(cachep, flags)) 3395 if (slab_should_failslab(cachep, flags))
3461 return NULL; 3396 return NULL;
3462 3397
3463 cache_alloc_debugcheck_before(cachep, flags); 3398 cache_alloc_debugcheck_before(cachep, flags);
diff --git a/mm/slub.c b/mm/slub.c
index a2cd47d89e0a..640fde7e354c 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -24,6 +24,7 @@
24#include <linux/kallsyms.h> 24#include <linux/kallsyms.h>
25#include <linux/memory.h> 25#include <linux/memory.h>
26#include <linux/math64.h> 26#include <linux/math64.h>
27#include <linux/fault-inject.h>
27 28
28/* 29/*
29 * Lock order: 30 * Lock order:
@@ -1591,6 +1592,9 @@ static __always_inline void *slab_alloc(struct kmem_cache *s,
1591 unsigned long flags; 1592 unsigned long flags;
1592 unsigned int objsize; 1593 unsigned int objsize;
1593 1594
1595 if (should_failslab(s->objsize, gfpflags))
1596 return NULL;
1597
1594 local_irq_save(flags); 1598 local_irq_save(flags);
1595 c = get_cpu_slab(s, smp_processor_id()); 1599 c = get_cpu_slab(s, smp_processor_id());
1596 objsize = c->objsize; 1600 objsize = c->objsize;