aboutsummaryrefslogtreecommitdiffstats
path: root/mm/slab_common.c
diff options
context:
space:
mode:
authorPekka Enberg <penberg@kernel.org>2012-10-03 02:56:37 -0400
committerPekka Enberg <penberg@kernel.org>2012-10-03 02:56:37 -0400
commitf4178cdddd4cb860a17f363fe13264fff03da7f2 (patch)
tree5ca8dc6bb09bcb2c4b959b60712d7a3f60c7a43f /mm/slab_common.c
parent023dc70470502f41b285112d4840f35d9075b767 (diff)
parentf28510d30c7f03daa290019fbc57ad8277347614 (diff)
Merge branch 'slab/common-for-cgroups' into slab/for-linus
Fix up a trivial conflict with NUMA_NO_NODE cleanups. Conflicts: mm/slob.c Signed-off-by: Pekka Enberg <penberg@kernel.org>
Diffstat (limited to 'mm/slab_common.c')
-rw-r--r--mm/slab_common.c80
1 files changed, 76 insertions, 4 deletions
diff --git a/mm/slab_common.c b/mm/slab_common.c
index 8cf8b4962d6c..9c217255ac49 100644
--- a/mm/slab_common.c
+++ b/mm/slab_common.c
@@ -22,6 +22,7 @@
22enum slab_state slab_state; 22enum slab_state slab_state;
23LIST_HEAD(slab_caches); 23LIST_HEAD(slab_caches);
24DEFINE_MUTEX(slab_mutex); 24DEFINE_MUTEX(slab_mutex);
25struct kmem_cache *kmem_cache;
25 26
26#ifdef CONFIG_DEBUG_VM 27#ifdef CONFIG_DEBUG_VM
27static int kmem_cache_sanity_check(const char *name, size_t size) 28static int kmem_cache_sanity_check(const char *name, size_t size)
@@ -98,21 +99,92 @@ struct kmem_cache *kmem_cache_create(const char *name, size_t size, size_t align
98 unsigned long flags, void (*ctor)(void *)) 99 unsigned long flags, void (*ctor)(void *))
99{ 100{
100 struct kmem_cache *s = NULL; 101 struct kmem_cache *s = NULL;
102 int err = 0;
101 103
102 get_online_cpus(); 104 get_online_cpus();
103 mutex_lock(&slab_mutex); 105 mutex_lock(&slab_mutex);
104 if (kmem_cache_sanity_check(name, size) == 0) 106
105 s = __kmem_cache_create(name, size, align, flags, ctor); 107 if (!kmem_cache_sanity_check(name, size) == 0)
108 goto out_locked;
109
110
111 s = __kmem_cache_alias(name, size, align, flags, ctor);
112 if (s)
113 goto out_locked;
114
115 s = kmem_cache_zalloc(kmem_cache, GFP_KERNEL);
116 if (s) {
117 s->object_size = s->size = size;
118 s->align = align;
119 s->ctor = ctor;
120 s->name = kstrdup(name, GFP_KERNEL);
121 if (!s->name) {
122 kmem_cache_free(kmem_cache, s);
123 err = -ENOMEM;
124 goto out_locked;
125 }
126
127 err = __kmem_cache_create(s, flags);
128 if (!err) {
129
130 s->refcount = 1;
131 list_add(&s->list, &slab_caches);
132
133 } else {
134 kfree(s->name);
135 kmem_cache_free(kmem_cache, s);
136 }
137 } else
138 err = -ENOMEM;
139
140out_locked:
106 mutex_unlock(&slab_mutex); 141 mutex_unlock(&slab_mutex);
107 put_online_cpus(); 142 put_online_cpus();
108 143
109 if (!s && (flags & SLAB_PANIC)) 144 if (err) {
110 panic("kmem_cache_create: Failed to create slab '%s'\n", name); 145
146 if (flags & SLAB_PANIC)
147 panic("kmem_cache_create: Failed to create slab '%s'. Error %d\n",
148 name, err);
149 else {
150 printk(KERN_WARNING "kmem_cache_create(%s) failed with error %d",
151 name, err);
152 dump_stack();
153 }
154
155 return NULL;
156 }
111 157
112 return s; 158 return s;
113} 159}
114EXPORT_SYMBOL(kmem_cache_create); 160EXPORT_SYMBOL(kmem_cache_create);
115 161
162void kmem_cache_destroy(struct kmem_cache *s)
163{
164 get_online_cpus();
165 mutex_lock(&slab_mutex);
166 s->refcount--;
167 if (!s->refcount) {
168 list_del(&s->list);
169
170 if (!__kmem_cache_shutdown(s)) {
171 if (s->flags & SLAB_DESTROY_BY_RCU)
172 rcu_barrier();
173
174 kfree(s->name);
175 kmem_cache_free(kmem_cache, s);
176 } else {
177 list_add(&s->list, &slab_caches);
178 printk(KERN_ERR "kmem_cache_destroy %s: Slab cache still has objects\n",
179 s->name);
180 dump_stack();
181 }
182 }
183 mutex_unlock(&slab_mutex);
184 put_online_cpus();
185}
186EXPORT_SYMBOL(kmem_cache_destroy);
187
116int slab_is_available(void) 188int slab_is_available(void)
117{ 189{
118 return slab_state >= UP; 190 return slab_state >= UP;