All of lore.kernel.org
 help / color / mirror / Atom feed
* C13 [05/14] Extract a common function for kmem_cache_destroy
       [not found] <20120824160903.168122683@linux.com>
@ 2012-08-24 16:10 ` Christoph Lameter
  2012-09-03 14:41   ` Glauber Costa
  2012-09-03 15:26   ` Glauber Costa
  2012-08-24 16:12 ` C13 [08/14] Get rid of __kmem_cache_destroy Christoph Lameter
                   ` (12 subsequent siblings)
  13 siblings, 2 replies; 32+ messages in thread
From: Christoph Lameter @ 2012-08-24 16:10 UTC (permalink / raw)
  To: Pekka Enberg; +Cc: Joonsoo Kim, Glauber Costa, linux-mm, David Rientjes

kmem_cache_destroy does basically the same in all allocators.

Extract common code which is easy since we already have common mutex handling.

V1-V2:
	- Move percpu freeing to later so that we fail cleaner if
		objects are left in the cache [JoonSoo Kim]

Signed-off-by: Christoph Lameter <cl@linux.com>
---
 mm/slab.c        |   55 +++---------------------------------------------------
 mm/slab.h        |    3 +++
 mm/slab_common.c |   25 +++++++++++++++++++++++++
 mm/slob.c        |   15 +++++++--------
 mm/slub.c        |   36 +++++++++++------------------------
 5 files changed, 49 insertions(+), 85 deletions(-)

diff --git a/mm/slab.c b/mm/slab.c
index a699031..6826d93 100644
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -803,16 +803,6 @@ static void cache_estimate(unsigned long gfporder, size_t buffer_size,
 	*left_over = slab_size - nr_objs*buffer_size - mgmt_size;
 }
 
-#define slab_error(cachep, msg) __slab_error(__func__, cachep, msg)
-
-static void __slab_error(const char *function, struct kmem_cache *cachep,
-			char *msg)
-{
-	printk(KERN_ERR "slab error in %s(): cache `%s': %s\n",
-	       function, cachep->name, msg);
-	dump_stack();
-}
-
 /*
  * By default on NUMA we use alien caches to stage the freeing of
  * objects allocated from other nodes. This causes massive memory
@@ -2206,7 +2196,7 @@ static void slab_destroy(struct kmem_cache *cachep, struct slab *slabp)
 	}
 }
 
-static void __kmem_cache_destroy(struct kmem_cache *cachep)
+void __kmem_cache_destroy(struct kmem_cache *cachep)
 {
 	int i;
 	struct kmem_list3 *l3;
@@ -2763,49 +2753,10 @@ int kmem_cache_shrink(struct kmem_cache *cachep)
 }
 EXPORT_SYMBOL(kmem_cache_shrink);
 
-/**
- * kmem_cache_destroy - delete a cache
- * @cachep: the cache to destroy
- *
- * Remove a &struct kmem_cache object from the slab cache.
- *
- * It is expected this function will be called by a module when it is
- * unloaded.  This will remove the cache completely, and avoid a duplicate
- * cache being allocated each time a module is loaded and unloaded, if the
- * module doesn't have persistent in-kernel storage across loads and unloads.
- *
- * The cache must be empty before calling this function.
- *
- * The caller must guarantee that no one will allocate memory from the cache
- * during the kmem_cache_destroy().
- */
-void kmem_cache_destroy(struct kmem_cache *cachep)
+int __kmem_cache_shutdown(struct kmem_cache *cachep)
 {
-	BUG_ON(!cachep || in_interrupt());
-
-	/* Find the cache in the chain of caches. */
-	get_online_cpus();
-	mutex_lock(&slab_mutex);
-	/*
-	 * the chain is never empty, cache_cache is never destroyed
-	 */
-	list_del(&cachep->list);
-	if (__cache_shrink(cachep)) {
-		slab_error(cachep, "Can't free all objects");
-		list_add(&cachep->list, &slab_caches);
-		mutex_unlock(&slab_mutex);
-		put_online_cpus();
-		return;
-	}
-
-	if (unlikely(cachep->flags & SLAB_DESTROY_BY_RCU))
-		rcu_barrier();
-
-	__kmem_cache_destroy(cachep);
-	mutex_unlock(&slab_mutex);
-	put_online_cpus();
+	return __cache_shrink(cachep);
 }
-EXPORT_SYMBOL(kmem_cache_destroy);
 
 /*
  * Get the memory for a slab management obj.
diff --git a/mm/slab.h b/mm/slab.h
index db7848c..07a537e 100644
--- a/mm/slab.h
+++ b/mm/slab.h
@@ -30,4 +30,7 @@ extern struct list_head slab_caches;
 struct kmem_cache *__kmem_cache_create(const char *name, size_t size,
 	size_t align, unsigned long flags, void (*ctor)(void *));
 
+int __kmem_cache_shutdown(struct kmem_cache *);
+void __kmem_cache_destroy(struct kmem_cache *);
+
 #endif
diff --git a/mm/slab_common.c b/mm/slab_common.c
index d419a3e..5cc1371 100644
--- a/mm/slab_common.c
+++ b/mm/slab_common.c
@@ -140,6 +140,31 @@ out_locked:
 }
 EXPORT_SYMBOL(kmem_cache_create);
 
+void kmem_cache_destroy(struct kmem_cache *s)
+{
+	get_online_cpus();
+	mutex_lock(&slab_mutex);
+	s->refcount--;
+	if (!s->refcount) {
+		list_del(&s->list);
+
+		if (!__kmem_cache_shutdown(s)) {
+			if (s->flags & SLAB_DESTROY_BY_RCU)
+				rcu_barrier();
+
+			__kmem_cache_destroy(s);
+		} else {
+			list_add(&s->list, &slab_caches);
+			printk(KERN_ERR "kmem_cache_destroy %s: Slab cache still has objects\n",
+				s->name);
+			dump_stack();
+		}
+	}
+	mutex_unlock(&slab_mutex);
+	put_online_cpus();
+}
+EXPORT_SYMBOL(kmem_cache_destroy);
+
 int slab_is_available(void)
 {
 	return slab_state >= UP;
diff --git a/mm/slob.c b/mm/slob.c
index 5225d28..289be4f 100644
--- a/mm/slob.c
+++ b/mm/slob.c
@@ -538,18 +538,11 @@ struct kmem_cache *__kmem_cache_create(const char *name, size_t size,
 	return c;
 }
 
-void kmem_cache_destroy(struct kmem_cache *c)
+void __kmem_cache_destroy(struct kmem_cache *c)
 {
-	mutex_lock(&slab_mutex);
-	list_del(&c->list);
-	mutex_unlock(&slab_mutex);
-
 	kmemleak_free(c);
-	if (c->flags & SLAB_DESTROY_BY_RCU)
-		rcu_barrier();
 	slob_free(c, sizeof(struct kmem_cache));
 }
-EXPORT_SYMBOL(kmem_cache_destroy);
 
 void *kmem_cache_alloc_node(struct kmem_cache *c, gfp_t flags, int node)
 {
@@ -617,6 +610,12 @@ unsigned int kmem_cache_size(struct kmem_cache *c)
 }
 EXPORT_SYMBOL(kmem_cache_size);
 
+int __kmem_cache_shutdown(struct kmem_cache *c)
+{
+	/* No way to check for remaining objects */
+	return 0;
+}
+
 int kmem_cache_shrink(struct kmem_cache *d)
 {
 	return 0;
diff --git a/mm/slub.c b/mm/slub.c
index 37d5177..c99c0af 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -624,7 +624,7 @@ static void object_err(struct kmem_cache *s, struct page *page,
 	print_trailer(s, page, object);
 }
 
-static void slab_err(struct kmem_cache *s, struct page *page, char *fmt, ...)
+static void slab_err(struct kmem_cache *s, struct page *page, const char *fmt, ...)
 {
 	va_list args;
 	char buf[100];
@@ -3146,7 +3146,7 @@ static void list_slab_objects(struct kmem_cache *s, struct page *page,
 				     sizeof(long), GFP_ATOMIC);
 	if (!map)
 		return;
-	slab_err(s, page, "%s", text);
+	slab_err(s, page, text, s->name);
 	slab_lock(page);
 
 	get_map(s, page, map);
@@ -3178,7 +3178,7 @@ static void free_partial(struct kmem_cache *s, struct kmem_cache_node *n)
 			discard_slab(s, page);
 		} else {
 			list_slab_objects(s, page,
-				"Objects remaining on kmem_cache_close()");
+			"Objects remaining in %s on kmem_cache_close()");
 		}
 	}
 }
@@ -3191,7 +3191,6 @@ static inline int kmem_cache_close(struct kmem_cache *s)
 	int node;
 
 	flush_all(s);
-	free_percpu(s->cpu_slab);
 	/* Attempt to free all objects */
 	for_each_node_state(node, N_NORMAL_MEMORY) {
 		struct kmem_cache_node *n = get_node(s, node);
@@ -3200,33 +3199,20 @@ static inline int kmem_cache_close(struct kmem_cache *s)
 		if (n->nr_partial || slabs_node(s, node))
 			return 1;
 	}
+	free_percpu(s->cpu_slab);
 	free_kmem_cache_nodes(s);
 	return 0;
 }
 
-/*
- * Close a cache and release the kmem_cache structure
- * (must be used for caches created using kmem_cache_create)
- */
-void kmem_cache_destroy(struct kmem_cache *s)
+int __kmem_cache_shutdown(struct kmem_cache *s)
 {
-	mutex_lock(&slab_mutex);
-	s->refcount--;
-	if (!s->refcount) {
-		list_del(&s->list);
-		mutex_unlock(&slab_mutex);
-		if (kmem_cache_close(s)) {
-			printk(KERN_ERR "SLUB %s: %s called for cache that "
-				"still has objects.\n", s->name, __func__);
-			dump_stack();
-		}
-		if (s->flags & SLAB_DESTROY_BY_RCU)
-			rcu_barrier();
-		sysfs_slab_remove(s);
-	} else
-		mutex_unlock(&slab_mutex);
+	return kmem_cache_close(s);
+}
+
+void __kmem_cache_destroy(struct kmem_cache *s)
+{
+	sysfs_slab_remove(s);
 }
-EXPORT_SYMBOL(kmem_cache_destroy);
 
 /********************************************************************
  *		Kmalloc subsystem
-- 
1.7.9.5


--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply related	[flat|nested] 32+ messages in thread

* C13 [07/14] Move freeing of kmem_cache structure to common code
       [not found] <20120824160903.168122683@linux.com>
  2012-08-24 16:10 ` C13 [05/14] Extract a common function for kmem_cache_destroy Christoph Lameter
  2012-08-24 16:12 ` C13 [08/14] Get rid of __kmem_cache_destroy Christoph Lameter
@ 2012-08-24 16:12 ` Christoph Lameter
  2012-09-03 14:51   ` Glauber Costa
  2012-08-24 16:17 ` C13 [03/14] Improve error handling in kmem_cache_create Christoph Lameter
                   ` (10 subsequent siblings)
  13 siblings, 1 reply; 32+ messages in thread
From: Christoph Lameter @ 2012-08-24 16:12 UTC (permalink / raw)
  To: Pekka Enberg; +Cc: Joonsoo Kim, Glauber Costa, linux-mm, David Rientjes

The freeing action is basically the same in all slab allocators.
Move to the common kmem_cache_destroy() function.

Reviewed-by: Joonsoo Kim <js1304@gmail.com>
Signed-off-by: Christoph Lameter <cl@linux.com>
---
 mm/slab.c        |    1 -
 mm/slab_common.c |    1 +
 mm/slob.c        |    2 --
 mm/slub.c        |    2 --
 4 files changed, 1 insertion(+), 5 deletions(-)

diff --git a/mm/slab.c b/mm/slab.c
index 6365632..814cfc9 100644
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -2215,7 +2215,6 @@ void __kmem_cache_destroy(struct kmem_cache *cachep)
 			kfree(l3);
 		}
 	}
-	kmem_cache_free(kmem_cache, cachep);
 }
 
 
diff --git a/mm/slab_common.c b/mm/slab_common.c
index 850c497..3e3c403 100644
--- a/mm/slab_common.c
+++ b/mm/slab_common.c
@@ -154,6 +154,7 @@ void kmem_cache_destroy(struct kmem_cache *s)
 				rcu_barrier();
 
 			__kmem_cache_destroy(s);
+			kmem_cache_free(kmem_cache, s);
 		} else {
 			list_add(&s->list, &slab_caches);
 			printk(KERN_ERR "kmem_cache_destroy %s: Slab cache still has objects\n",
diff --git a/mm/slob.c b/mm/slob.c
index 7d272c3..cb4ab96 100644
--- a/mm/slob.c
+++ b/mm/slob.c
@@ -540,8 +540,6 @@ struct kmem_cache *__kmem_cache_create(const char *name, size_t size,
 
 void __kmem_cache_destroy(struct kmem_cache *c)
 {
-	kmemleak_free(c);
-	slob_free(c, sizeof(struct kmem_cache));
 }
 
 void *kmem_cache_alloc_node(struct kmem_cache *c, gfp_t flags, int node)
diff --git a/mm/slub.c b/mm/slub.c
index 607fee5..8da785a 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -213,7 +213,6 @@ static inline int sysfs_slab_alias(struct kmem_cache *s, const char *p)
 static inline void sysfs_slab_remove(struct kmem_cache *s)
 {
 	kfree(s->name);
-	kmem_cache_free(kmem_cache, s);
 }
 
 #endif
@@ -5206,7 +5205,6 @@ static void kmem_cache_release(struct kobject *kobj)
 	struct kmem_cache *s = to_slab(kobj);
 
 	kfree(s->name);
-	kmem_cache_free(kmem_cache, s);
 }
 
 static const struct sysfs_ops slab_sysfs_ops = {
-- 
1.7.9.5


--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply related	[flat|nested] 32+ messages in thread

* C13 [08/14] Get rid of __kmem_cache_destroy
       [not found] <20120824160903.168122683@linux.com>
  2012-08-24 16:10 ` C13 [05/14] Extract a common function for kmem_cache_destroy Christoph Lameter
@ 2012-08-24 16:12 ` Christoph Lameter
  2012-09-03 14:58   ` Glauber Costa
  2012-08-24 16:12 ` C13 [07/14] Move freeing of kmem_cache structure to common code Christoph Lameter
                   ` (11 subsequent siblings)
  13 siblings, 1 reply; 32+ messages in thread
From: Christoph Lameter @ 2012-08-24 16:12 UTC (permalink / raw)
  To: Pekka Enberg; +Cc: Joonsoo Kim, Glauber Costa, linux-mm, David Rientjes

What is done there can be done in __kmem_cache_shutdown.

This affects RCU handling somewhat. On rcu free all slab allocators
do not refer to other management structures than the kmem_cache structure.
Therefore these other structures can be freed before the rcu deferred
free to the page allocator occurs.

Reviewed-by: Joonsoo Kim <js1304@gmail.com>
Signed-off-by: Christoph Lameter <cl@linux.com>
---
 mm/slab.c        |   46 +++++++++++++++++++++-------------------------
 mm/slab.h        |    1 -
 mm/slab_common.c |    1 -
 mm/slob.c        |    4 ----
 mm/slub.c        |   10 +++++-----
 5 files changed, 26 insertions(+), 36 deletions(-)

diff --git a/mm/slab.c b/mm/slab.c
index 814cfc9..9449e7e 100644
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -2198,26 +2198,6 @@ static void slab_destroy(struct kmem_cache *cachep, struct slab *slabp)
 	}
 }
 
-void __kmem_cache_destroy(struct kmem_cache *cachep)
-{
-	int i;
-	struct kmem_list3 *l3;
-
-	for_each_online_cpu(i)
-	    kfree(cachep->array[i]);
-
-	/* NUMA: free the list3 structures */
-	for_each_online_node(i) {
-		l3 = cachep->nodelists[i];
-		if (l3) {
-			kfree(l3->shared);
-			free_alien_cache(l3->alien);
-			kfree(l3);
-		}
-	}
-}
-
-
 /**
  * calculate_slab_order - calculate size (page order) of slabs
  * @cachep: pointer to the cache that is being created
@@ -2354,9 +2334,6 @@ static int __init_refok setup_cpu_cache(struct kmem_cache *cachep, gfp_t gfp)
  * Cannot be called within a int, but can be interrupted.
  * The @ctor is run when new pages are allocated by the cache.
  *
- * @name must be valid until the cache is destroyed. This implies that
- * the module calling this has to destroy the cache before getting unloaded.
- *
  * The flags are
  *
  * %SLAB_POISON - Poison the slab with a known test pattern (a5a5a5a5)
@@ -2581,7 +2558,7 @@ __kmem_cache_create (const char *name, size_t size, size_t align,
 	cachep->refcount = 1;
 
 	if (setup_cpu_cache(cachep, gfp)) {
-		__kmem_cache_destroy(cachep);
+		__kmem_cache_shutdown(cachep);
 		return NULL;
 	}
 
@@ -2756,7 +2733,26 @@ EXPORT_SYMBOL(kmem_cache_shrink);
 
 int __kmem_cache_shutdown(struct kmem_cache *cachep)
 {
-	return __cache_shrink(cachep);
+	int i;
+	struct kmem_list3 *l3;
+	int rc = __cache_shrink(cachep);
+
+	if (rc)
+		return rc;
+
+	for_each_online_cpu(i)
+	    kfree(cachep->array[i]);
+
+	/* NUMA: free the list3 structures */
+	for_each_online_node(i) {
+		l3 = cachep->nodelists[i];
+		if (l3) {
+			kfree(l3->shared);
+			free_alien_cache(l3->alien);
+			kfree(l3);
+		}
+	}
+	return 0;
 }
 
 /*
diff --git a/mm/slab.h b/mm/slab.h
index 6724aa6..c4f9a36 100644
--- a/mm/slab.h
+++ b/mm/slab.h
@@ -37,6 +37,5 @@ struct kmem_cache *__kmem_cache_create(const char *name, size_t size,
 	size_t align, unsigned long flags, void (*ctor)(void *));
 
 int __kmem_cache_shutdown(struct kmem_cache *);
-void __kmem_cache_destroy(struct kmem_cache *);
 
 #endif
diff --git a/mm/slab_common.c b/mm/slab_common.c
index 3e3c403..777cae0 100644
--- a/mm/slab_common.c
+++ b/mm/slab_common.c
@@ -153,7 +153,6 @@ void kmem_cache_destroy(struct kmem_cache *s)
 			if (s->flags & SLAB_DESTROY_BY_RCU)
 				rcu_barrier();
 
-			__kmem_cache_destroy(s);
 			kmem_cache_free(kmem_cache, s);
 		} else {
 			list_add(&s->list, &slab_caches);
diff --git a/mm/slob.c b/mm/slob.c
index cb4ab96..50f6053 100644
--- a/mm/slob.c
+++ b/mm/slob.c
@@ -538,10 +538,6 @@ struct kmem_cache *__kmem_cache_create(const char *name, size_t size,
 	return c;
 }
 
-void __kmem_cache_destroy(struct kmem_cache *c)
-{
-}
-
 void *kmem_cache_alloc_node(struct kmem_cache *c, gfp_t flags, int node)
 {
 	void *b;
diff --git a/mm/slub.c b/mm/slub.c
index 8da785a..bb02589 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -3205,12 +3205,12 @@ static inline int kmem_cache_close(struct kmem_cache *s)
 
 int __kmem_cache_shutdown(struct kmem_cache *s)
 {
-	return kmem_cache_close(s);
-}
+	int rc = kmem_cache_close(s);
 
-void __kmem_cache_destroy(struct kmem_cache *s)
-{
-	sysfs_slab_remove(s);
+	if (!rc)
+		sysfs_slab_remove(s);
+
+	return rc;
 }
 
 /********************************************************************
-- 
1.7.9.5


--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply related	[flat|nested] 32+ messages in thread

* C13 [12/14] Move kmem_cache allocations into common code.
       [not found] <20120824160903.168122683@linux.com>
                   ` (3 preceding siblings ...)
  2012-08-24 16:17 ` C13 [03/14] Improve error handling in kmem_cache_create Christoph Lameter
@ 2012-08-24 16:17 ` Christoph Lameter
  2012-09-03 15:24   ` Glauber Costa
  2012-08-24 16:17 ` C13 [11/14] Move sysfs_slab_add to common Christoph Lameter
                   ` (8 subsequent siblings)
  13 siblings, 1 reply; 32+ messages in thread
From: Christoph Lameter @ 2012-08-24 16:17 UTC (permalink / raw)
  To: Pekka Enberg; +Cc: Joonsoo Kim, Glauber Costa, linux-mm, David Rientjes

Shift the allocations to common code. That way the allocation
and freeing of the kmem_cache structures is handled by common code.

V2->V3: Use GFP_KERNEL instead of GFP_NOWAIT (JoonSoo Kim).
V1->V2: Use the return code from setup_cpucache() in slab instead of returning -ENOSPC


Signed-off-by: Christoph Lameter <cl@linux.com>
---
 mm/slab.c        |   34 ++++++++++++++++------------------
 mm/slab.h        |    4 ++--
 mm/slab_common.c |   18 ++++++++++--------
 mm/slob.c        |   43 ++++++++++++++++++-------------------------
 mm/slub.c        |   22 ++++++----------------
 5 files changed, 52 insertions(+), 69 deletions(-)

Index: linux/mm/slab.c
===================================================================
--- linux.orig/mm/slab.c	2012-08-24 10:50:34.437400135 -0500
+++ linux/mm/slab.c	2012-08-24 10:50:41.621511827 -0500
@@ -1666,7 +1666,8 @@ void __init kmem_cache_init(void)
 	 * bug.
 	 */
 
-	sizes[INDEX_AC].cs_cachep = __kmem_cache_create(names[INDEX_AC].name,
+	sizes[INDEX_AC].cs_cachep = kmem_cache_zalloc(kmem_cache, GFP_NOWAIT);
+	__kmem_cache_create(sizes[INDEX_AC].cs_cachep, names[INDEX_AC].name,
 					sizes[INDEX_AC].cs_size,
 					ARCH_KMALLOC_MINALIGN,
 					ARCH_KMALLOC_FLAGS|SLAB_PANIC,
@@ -1674,8 +1675,8 @@ void __init kmem_cache_init(void)
 
 	list_add(&sizes[INDEX_AC].cs_cachep->list, &slab_caches);
 	if (INDEX_AC != INDEX_L3) {
-		sizes[INDEX_L3].cs_cachep =
-			__kmem_cache_create(names[INDEX_L3].name,
+		sizes[INDEX_L3].cs_cachep = kmem_cache_zalloc(kmem_cache, GFP_NOWAIT);
+		__kmem_cache_create(sizes[INDEX_L3].cs_cachep, names[INDEX_L3].name,
 				sizes[INDEX_L3].cs_size,
 				ARCH_KMALLOC_MINALIGN,
 				ARCH_KMALLOC_FLAGS|SLAB_PANIC,
@@ -1694,7 +1695,8 @@ void __init kmem_cache_init(void)
 		 * allow tighter packing of the smaller caches.
 		 */
 		if (!sizes->cs_cachep) {
-			sizes->cs_cachep = __kmem_cache_create(names->name,
+			sizes->cs_cachep = kmem_cache_zalloc(kmem_cache, GFP_NOWAIT);
+			__kmem_cache_create(sizes->cs_cachep, names->name,
 					sizes->cs_size,
 					ARCH_KMALLOC_MINALIGN,
 					ARCH_KMALLOC_FLAGS|SLAB_PANIC,
@@ -1702,7 +1704,8 @@ void __init kmem_cache_init(void)
 			list_add(&sizes->cs_cachep->list, &slab_caches);
 		}
 #ifdef CONFIG_ZONE_DMA
-		sizes->cs_dmacachep = __kmem_cache_create(
+		sizes->cs_dmacachep = kmem_cache_zalloc(kmem_cache, GFP_NOWAIT);
+		__kmem_cache_create(sizes->cs_dmacachep,
 					names->name_dma,
 					sizes->cs_size,
 					ARCH_KMALLOC_MINALIGN,
@@ -2346,13 +2349,13 @@ static int __init_refok setup_cpu_cache(
  * cacheline.  This can be beneficial if you're counting cycles as closely
  * as davem.
  */
-struct kmem_cache *
-__kmem_cache_create (const char *name, size_t size, size_t align,
+int
+__kmem_cache_create (struct kmem_cache *cachep, const char *name, size_t size, size_t align,
 	unsigned long flags, void (*ctor)(void *))
 {
 	size_t left_over, slab_size, ralign;
-	struct kmem_cache *cachep = NULL;
 	gfp_t gfp;
+	int err;
 
 #if DEBUG
 #if FORCED_DEBUG
@@ -2440,11 +2443,6 @@ __kmem_cache_create (const char *name, s
 	else
 		gfp = GFP_NOWAIT;
 
-	/* Get cache's description obj. */
-	cachep = kmem_cache_zalloc(kmem_cache, gfp);
-	if (!cachep)
-		return NULL;
-
 	cachep->nodelists = (struct kmem_list3 **)&cachep->array[nr_cpu_ids];
 	cachep->object_size = size;
 	cachep->align = align;
@@ -2499,8 +2497,7 @@ __kmem_cache_create (const char *name, s
 	if (!cachep->num) {
 		printk(KERN_ERR
 		       "kmem_cache_create: couldn't create cache %s.\n", name);
-		kmem_cache_free(kmem_cache, cachep);
-		return NULL;
+		return -E2BIG;
 	}
 	slab_size = ALIGN(cachep->num * sizeof(kmem_bufctl_t)
 			  + sizeof(struct slab), align);
@@ -2557,9 +2554,10 @@ __kmem_cache_create (const char *name, s
 	cachep->name = name;
 	cachep->refcount = 1;
 
-	if (setup_cpu_cache(cachep, gfp)) {
+	err = setup_cpu_cache(cachep, gfp);
+	if (err) {
 		__kmem_cache_shutdown(cachep);
-		return NULL;
+		return err;
 	}
 
 	if (flags & SLAB_DEBUG_OBJECTS) {
@@ -2572,7 +2570,7 @@ __kmem_cache_create (const char *name, s
 		slab_set_debugobj_lock_classes(cachep);
 	}
 
-	return cachep;
+	return 0;
 }
 
 #if DEBUG
Index: linux/mm/slab.h
===================================================================
--- linux.orig/mm/slab.h	2012-08-24 10:50:39.981486341 -0500
+++ linux/mm/slab.h	2012-08-24 10:50:41.621511827 -0500
@@ -33,8 +33,8 @@ extern struct list_head slab_caches;
 extern struct kmem_cache *kmem_cache;
 
 /* Functions provided by the slab allocators */
-struct kmem_cache *__kmem_cache_create(const char *name, size_t size,
-	size_t align, unsigned long flags, void (*ctor)(void *));
+extern int __kmem_cache_create(struct kmem_cache *, const char *name,
+	size_t size, size_t align, unsigned long flags, void (*ctor)(void *));
 
 #ifdef CONFIG_SLUB
 struct kmem_cache *__kmem_cache_alias(const char *name, size_t size,
Index: linux/mm/slab_common.c
===================================================================
--- linux.orig/mm/slab_common.c	2012-08-24 10:50:39.981486341 -0500
+++ linux/mm/slab_common.c	2012-08-24 10:50:41.621511827 -0500
@@ -119,19 +119,21 @@ struct kmem_cache *kmem_cache_create(con
 	if (s)
 		goto out_locked;
 
-	s = __kmem_cache_create(n, size, align, flags, ctor);
-
+	s = kmem_cache_zalloc(kmem_cache, GFP_KERNEL);
 	if (s) {
-		/*
-		 * Check if the slab has actually been created and if it was a
-		 * real instatiation. Aliases do not belong on the list
-		 */
-		if (s->refcount == 1)
+		err = __kmem_cache_create(s, n, size, align, flags, ctor);
+		if (!err)
+
 			list_add(&s->list, &slab_caches);
 
+		else {
+			kfree(n);
+			kmem_cache_free(kmem_cache, s);
+		}
+
 	} else {
 		kfree(n);
-		err = -ENOSYS; /* Until __kmem_cache_create returns code */
+		err = -ENOMEM;
 	}
 
 out_locked:
Index: linux/mm/slob.c
===================================================================
--- linux.orig/mm/slob.c	2012-08-24 10:50:34.437400135 -0500
+++ linux/mm/slob.c	2012-08-24 10:50:41.621511827 -0500
@@ -508,34 +508,27 @@ size_t ksize(const void *block)
 }
 EXPORT_SYMBOL(ksize);
 
-struct kmem_cache *__kmem_cache_create(const char *name, size_t size,
+int __kmem_cache_create(struct kmem_cache *c, const char *name, size_t size,
 	size_t align, unsigned long flags, void (*ctor)(void *))
 {
-	struct kmem_cache *c;
-
-	c = slob_alloc(sizeof(struct kmem_cache),
-		GFP_KERNEL, ARCH_KMALLOC_MINALIGN, -1);
-
-	if (c) {
-		c->name = name;
-		c->size = size;
-		if (flags & SLAB_DESTROY_BY_RCU) {
-			/* leave room for rcu footer at the end of object */
-			c->size += sizeof(struct slob_rcu);
-		}
-		c->flags = flags;
-		c->ctor = ctor;
-		/* ignore alignment unless it's forced */
-		c->align = (flags & SLAB_HWCACHE_ALIGN) ? SLOB_ALIGN : 0;
-		if (c->align < ARCH_SLAB_MINALIGN)
-			c->align = ARCH_SLAB_MINALIGN;
-		if (c->align < align)
-			c->align = align;
-
-		kmemleak_alloc(c, sizeof(struct kmem_cache), 1, GFP_KERNEL);
-		c->refcount = 1;
+	c->name = name;
+	c->size = size;
+	if (flags & SLAB_DESTROY_BY_RCU) {
+		/* leave room for rcu footer at the end of object */
+		c->size += sizeof(struct slob_rcu);
 	}
-	return c;
+	c->flags = flags;
+	c->ctor = ctor;
+	/* ignore alignment unless it's forced */
+	c->align = (flags & SLAB_HWCACHE_ALIGN) ? SLOB_ALIGN : 0;
+	if (c->align < ARCH_SLAB_MINALIGN)
+		c->align = ARCH_SLAB_MINALIGN;
+	if (c->align < align)
+		c->align = align;
+
+	kmemleak_alloc(c, sizeof(struct kmem_cache), 1, GFP_KERNEL);
+	c->refcount = 1;
+	return 0;
 }
 
 void *kmem_cache_alloc_node(struct kmem_cache *c, gfp_t flags, int node)
Index: linux/mm/slub.c
===================================================================
--- linux.orig/mm/slub.c	2012-08-24 10:50:39.981486341 -0500
+++ linux/mm/slub.c	2012-08-24 10:50:56.857748597 -0500
@@ -3034,7 +3034,6 @@ static int kmem_cache_open(struct kmem_c
 		size_t align, unsigned long flags,
 		void (*ctor)(void *))
 {
-	memset(s, 0, kmem_size);
 	s->name = name;
 	s->ctor = ctor;
 	s->object_size = size;
@@ -3109,7 +3108,7 @@ static int kmem_cache_open(struct kmem_c
 		goto error;
 
 	if (alloc_kmem_cache_cpus(s))
-		return 1;
+		return 0;
 
 	free_kmem_cache_nodes(s);
 error:
@@ -3118,7 +3117,7 @@ error:
 			"order=%u offset=%u flags=%lx\n",
 			s->name, (unsigned long)size, s->size, oo_order(s->oo),
 			s->offset, flags);
-	return 0;
+	return -EINVAL;
 }
 
 /*
@@ -3260,13 +3259,13 @@ static struct kmem_cache *__init create_
 {
 	struct kmem_cache *s;
 
-	s = kmem_cache_alloc(kmem_cache, GFP_NOWAIT);
+	s = kmem_cache_zalloc(kmem_cache, GFP_NOWAIT);
 
 	/*
 	 * This function is called with IRQs disabled during early-boot on
 	 * single CPU so there's no need to take slab_mutex here.
 	 */
-	if (!kmem_cache_open(s, name, size, ARCH_KMALLOC_MINALIGN,
+	if (kmem_cache_open(s, name, size, ARCH_KMALLOC_MINALIGN,
 								flags, NULL))
 		goto panic;
 
@@ -3944,20 +3943,11 @@ struct kmem_cache *__kmem_cache_alias(co
 	return s;
 }
 
-struct kmem_cache *__kmem_cache_create(const char *name, size_t size,
+int __kmem_cache_create(struct kmem_cache *s,
+		const char *name, size_t size,
 		size_t align, unsigned long flags, void (*ctor)(void *))
 {
-	struct kmem_cache *s;
-
-	s = kmem_cache_alloc(kmem_cache, GFP_KERNEL);
-	if (s) {
-		if (kmem_cache_open(s, name,
-				size, align, flags, ctor)) {
-			return s;
-		}
-		kmem_cache_free(kmem_cache, s);
-	}
-	return NULL;
+	return kmem_cache_open(s, name, size, align, flags, ctor);
 }
 
 #ifdef CONFIG_SMP

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 32+ messages in thread

* C13 [03/14] Improve error handling in kmem_cache_create
       [not found] <20120824160903.168122683@linux.com>
                   ` (2 preceding siblings ...)
  2012-08-24 16:12 ` C13 [07/14] Move freeing of kmem_cache structure to common code Christoph Lameter
@ 2012-08-24 16:17 ` Christoph Lameter
  2012-09-03 14:30   ` Glauber Costa
  2012-08-24 16:17 ` C13 [12/14] Move kmem_cache allocations into common code Christoph Lameter
                   ` (9 subsequent siblings)
  13 siblings, 1 reply; 32+ messages in thread
From: Christoph Lameter @ 2012-08-24 16:17 UTC (permalink / raw)
  To: Pekka Enberg; +Cc: Joonsoo Kim, David Rientjes, Glauber Costa, linux-mm

Instead of using s == NULL use an errorcode. This allows much more
detailed diagnostics as to what went wrong. As we add more functionality
from the slab allocators to the common kmem_cache_create() function we will
also add more error conditions.

Print the error code during the panic as well as in a warning if the module
can handle failure. The API for kmem_cache_create() currently does not allow
the returning of an error code. Return NULL but log the cause of the problem
in the syslog.

Acked-by: David Rientjes <rientjes@google.com>
Signed-off-by: Christoph Lameter <cl@linux.com>
---
 mm/slab_common.c |   30 +++++++++++++++++++++++++-----
 1 file changed, 25 insertions(+), 5 deletions(-)

Index: linux/mm/slab_common.c
===================================================================
--- linux.orig/mm/slab_common.c	2012-08-24 10:49:41.632579621 -0500
+++ linux/mm/slab_common.c	2012-08-24 10:49:59.352854993 -0500
@@ -98,16 +98,36 @@ struct kmem_cache *kmem_cache_create(con
 		unsigned long flags, void (*ctor)(void *))
 {
 	struct kmem_cache *s = NULL;
+	int err = 0;
 
 	get_online_cpus();
 	mutex_lock(&slab_mutex);
-	if (kmem_cache_sanity_check(name, size) == 0)
-		s = __kmem_cache_create(name, size, align, flags, ctor);
+
+	if (!kmem_cache_sanity_check(name, size) == 0)
+		goto out_locked;
+
+
+	s = __kmem_cache_create(name, size, align, flags, ctor);
+	if (!s)
+		err = -ENOSYS; /* Until __kmem_cache_create returns code */
+
+out_locked:
 	mutex_unlock(&slab_mutex);
 	put_online_cpus();
 
-	if (!s && (flags & SLAB_PANIC))
-		panic("kmem_cache_create: Failed to create slab '%s'\n", name);
+	if (err) {
+
+		if (flags & SLAB_PANIC)
+			panic("kmem_cache_create: Failed to create slab '%s'. Error %d\n",
+				name, err);
+		else {
+			printk(KERN_WARNING "kmem_cache_create(%s) failed with error %d",
+				name, err);
+			dump_stack();
+		}
+
+		return NULL;
+	}
 
 	return s;
 }

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 32+ messages in thread

* C13 [11/14] Move sysfs_slab_add to common
       [not found] <20120824160903.168122683@linux.com>
                   ` (4 preceding siblings ...)
  2012-08-24 16:17 ` C13 [12/14] Move kmem_cache allocations into common code Christoph Lameter
@ 2012-08-24 16:17 ` Christoph Lameter
  2012-09-03 15:09   ` Glauber Costa
  2012-08-24 16:17 ` C13 [04/14] Move list_add() to slab_common.c Christoph Lameter
                   ` (7 subsequent siblings)
  13 siblings, 1 reply; 32+ messages in thread
From: Christoph Lameter @ 2012-08-24 16:17 UTC (permalink / raw)
  To: Pekka Enberg; +Cc: Joonsoo Kim, Glauber Costa, linux-mm, David Rientjes

Simplify locking by moving the slab_add_sysfs after all locks
have been dropped. Eases the upcoming move to provide sysfs
support for all allocators.

Signed-off-by: Christoph Lameter <cl@linux.com>
---
 mm/slab.h        |    3 +++
 mm/slab_common.c |    8 ++++++++
 mm/slub.c        |   15 ++-------------
 3 files changed, 13 insertions(+), 13 deletions(-)

diff --git a/mm/slab.h b/mm/slab.h
index 84c28f4..ec7b944 100644
--- a/mm/slab.h
+++ b/mm/slab.h
@@ -39,10 +39,13 @@ struct kmem_cache *__kmem_cache_create(const char *name, size_t size,
 #ifdef CONFIG_SLUB
 struct kmem_cache *__kmem_cache_alias(const char *name, size_t size,
 	size_t align, unsigned long flags, void (*ctor)(void *));
+extern int sysfs_slab_add(struct kmem_cache *s);
 #else
 static inline struct kmem_cache *__kmem_cache_alias(const char *name, size_t size,
 	size_t align, unsigned long flags, void (*ctor)(void *))
 { return NULL; }
+static inline int sysfs_slab_add(struct kmem_cache *s) { return 0; }
+
 #endif
 
 
diff --git a/mm/slab_common.c b/mm/slab_common.c
index e5cd47f..ec93056 100644
--- a/mm/slab_common.c
+++ b/mm/slab_common.c
@@ -152,6 +152,14 @@ out_locked:
 		return NULL;
 	}
 
+	if (s->refcount == 1) {
+		err = sysfs_slab_add(s);
+		if (err)
+			printk(KERN_WARNING "kmem_cache_create(%s) failed to"
+				" create sysfs entry. Error %d\n",
+					name, err);
+	}
+
 	return s;
 }
 EXPORT_SYMBOL(kmem_cache_create);
diff --git a/mm/slub.c b/mm/slub.c
index 5751f30..5e37c89 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -202,12 +202,10 @@ struct track {
 enum track_item { TRACK_ALLOC, TRACK_FREE };
 
 #ifdef CONFIG_SYSFS
-static int sysfs_slab_add(struct kmem_cache *);
 static int sysfs_slab_alias(struct kmem_cache *, const char *);
 static void sysfs_slab_remove(struct kmem_cache *);
 
 #else
-static inline int sysfs_slab_add(struct kmem_cache *s) { return 0; }
 static inline int sysfs_slab_alias(struct kmem_cache *s, const char *p)
 							{ return 0; }
 static inline void sysfs_slab_remove(struct kmem_cache *s) { }
@@ -3955,16 +3953,7 @@ struct kmem_cache *__kmem_cache_create(const char *name, size_t size,
 	if (s) {
 		if (kmem_cache_open(s, name,
 				size, align, flags, ctor)) {
-			int r;
-
-			mutex_unlock(&slab_mutex);
-			r = sysfs_slab_add(s);
-			mutex_lock(&slab_mutex);
-
-			if (!r)
-				return s;
-
-			kmem_cache_close(s);
+			return s;
 		}
 		kmem_cache_free(kmem_cache, s);
 	}
@@ -5258,7 +5247,7 @@ static char *create_unique_id(struct kmem_cache *s)
 	return name;
 }
 
-static int sysfs_slab_add(struct kmem_cache *s)
+int sysfs_slab_add(struct kmem_cache *s)
 {
 	int err;
 	const char *name;
-- 
1.7.9.5


--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply related	[flat|nested] 32+ messages in thread

* C13 [06/14] Always use the name "kmem_cache" for the slab cache with the kmem_cache structure.
       [not found] <20120824160903.168122683@linux.com>
                   ` (6 preceding siblings ...)
  2012-08-24 16:17 ` C13 [04/14] Move list_add() to slab_common.c Christoph Lameter
@ 2012-08-24 16:17 ` Christoph Lameter
  2012-08-24 16:17 ` C13 [10/14] Do slab aliasing call from common code Christoph Lameter
                   ` (5 subsequent siblings)
  13 siblings, 0 replies; 32+ messages in thread
From: Christoph Lameter @ 2012-08-24 16:17 UTC (permalink / raw)
  To: Pekka Enberg; +Cc: Joonsoo Kim, Glauber Costa, linux-mm, David Rientjes

Make all allocators use the "kmem_cache" slabname for the "kmem_cache" structure.

Reviewed-by: Glauber Costa <glommer@parallels.com>
Reviewed-by: Joonsoo Kim <js1304@gmail.com>
Signed-off-by: Christoph Lameter <cl@linux.com>
---
 mm/slab.c        |   72 ++++++++++++++++++++++++++++--------------------------
 mm/slab.h        |    6 +++++
 mm/slab_common.c |    1 +
 mm/slob.c        |    8 ++++++
 mm/slub.c        |    2 --
 5 files changed, 52 insertions(+), 37 deletions(-)

diff --git a/mm/slab.c b/mm/slab.c
index 6826d93..6365632 100644
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -578,9 +578,9 @@ static struct arraycache_init initarray_generic =
     { {0, BOOT_CPUCACHE_ENTRIES, 1, 0} };
 
 /* internal cache of cache description objs */
-static struct kmem_list3 *cache_cache_nodelists[MAX_NUMNODES];
-static struct kmem_cache cache_cache = {
-	.nodelists = cache_cache_nodelists,
+static struct kmem_list3 *kmem_cache_nodelists[MAX_NUMNODES];
+static struct kmem_cache kmem_cache_boot = {
+	.nodelists = kmem_cache_nodelists,
 	.batchcount = 1,
 	.limit = BOOT_CPUCACHE_ENTRIES,
 	.shared = 1,
@@ -1584,15 +1584,17 @@ void __init kmem_cache_init(void)
 	int order;
 	int node;
 
+	kmem_cache = &kmem_cache_boot;
+
 	if (num_possible_nodes() == 1)
 		use_alien_caches = 0;
 
 	for (i = 0; i < NUM_INIT_LISTS; i++) {
 		kmem_list3_init(&initkmem_list3[i]);
 		if (i < MAX_NUMNODES)
-			cache_cache.nodelists[i] = NULL;
+			kmem_cache->nodelists[i] = NULL;
 	}
-	set_up_list3s(&cache_cache, CACHE_CACHE);
+	set_up_list3s(kmem_cache, CACHE_CACHE);
 
 	/*
 	 * Fragmentation resistance on low memory - only use bigger
@@ -1604,9 +1606,9 @@ void __init kmem_cache_init(void)
 
 	/* Bootstrap is tricky, because several objects are allocated
 	 * from caches that do not exist yet:
-	 * 1) initialize the cache_cache cache: it contains the struct
-	 *    kmem_cache structures of all caches, except cache_cache itself:
-	 *    cache_cache is statically allocated.
+	 * 1) initialize the kmem_cache cache: it contains the struct
+	 *    kmem_cache structures of all caches, except kmem_cache itself:
+	 *    kmem_cache is statically allocated.
 	 *    Initially an __init data area is used for the head array and the
 	 *    kmem_list3 structures, it's replaced with a kmalloc allocated
 	 *    array at the end of the bootstrap.
@@ -1615,43 +1617,43 @@ void __init kmem_cache_init(void)
 	 *    An __init data area is used for the head array.
 	 * 3) Create the remaining kmalloc caches, with minimally sized
 	 *    head arrays.
-	 * 4) Replace the __init data head arrays for cache_cache and the first
+	 * 4) Replace the __init data head arrays for kmem_cache and the first
 	 *    kmalloc cache with kmalloc allocated arrays.
-	 * 5) Replace the __init data for kmem_list3 for cache_cache and
+	 * 5) Replace the __init data for kmem_list3 for kmem_cache and
 	 *    the other cache's with kmalloc allocated memory.
 	 * 6) Resize the head arrays of the kmalloc caches to their final sizes.
 	 */
 
 	node = numa_mem_id();
 
-	/* 1) create the cache_cache */
+	/* 1) create the kmem_cache */
 	INIT_LIST_HEAD(&slab_caches);
-	list_add(&cache_cache.list, &slab_caches);
-	cache_cache.colour_off = cache_line_size();
-	cache_cache.array[smp_processor_id()] = &initarray_cache.cache;
-	cache_cache.nodelists[node] = &initkmem_list3[CACHE_CACHE + node];
+	list_add(&kmem_cache->list, &slab_caches);
+	kmem_cache->colour_off = cache_line_size();
+	kmem_cache->array[smp_processor_id()] = &initarray_cache.cache;
+	kmem_cache->nodelists[node] = &initkmem_list3[CACHE_CACHE + node];
 
 	/*
 	 * struct kmem_cache size depends on nr_node_ids & nr_cpu_ids
 	 */
-	cache_cache.size = offsetof(struct kmem_cache, array[nr_cpu_ids]) +
+	kmem_cache->size = offsetof(struct kmem_cache, array[nr_cpu_ids]) +
 				  nr_node_ids * sizeof(struct kmem_list3 *);
-	cache_cache.object_size = cache_cache.size;
-	cache_cache.size = ALIGN(cache_cache.size,
+	kmem_cache->object_size = kmem_cache->size;
+	kmem_cache->size = ALIGN(kmem_cache->object_size,
 					cache_line_size());
-	cache_cache.reciprocal_buffer_size =
-		reciprocal_value(cache_cache.size);
+	kmem_cache->reciprocal_buffer_size =
+		reciprocal_value(kmem_cache->size);
 
 	for (order = 0; order < MAX_ORDER; order++) {
-		cache_estimate(order, cache_cache.size,
-			cache_line_size(), 0, &left_over, &cache_cache.num);
-		if (cache_cache.num)
+		cache_estimate(order, kmem_cache->size,
+			cache_line_size(), 0, &left_over, &kmem_cache->num);
+		if (kmem_cache->num)
 			break;
 	}
-	BUG_ON(!cache_cache.num);
-	cache_cache.gfporder = order;
-	cache_cache.colour = left_over / cache_cache.colour_off;
-	cache_cache.slab_size = ALIGN(cache_cache.num * sizeof(kmem_bufctl_t) +
+	BUG_ON(!kmem_cache->num);
+	kmem_cache->gfporder = order;
+	kmem_cache->colour = left_over / kmem_cache->colour_off;
+	kmem_cache->slab_size = ALIGN(kmem_cache->num * sizeof(kmem_bufctl_t) +
 				      sizeof(struct slab), cache_line_size());
 
 	/* 2+3) create the kmalloc caches */
@@ -1718,15 +1720,15 @@ void __init kmem_cache_init(void)
 
 		ptr = kmalloc(sizeof(struct arraycache_init), GFP_NOWAIT);
 
-		BUG_ON(cpu_cache_get(&cache_cache) != &initarray_cache.cache);
-		memcpy(ptr, cpu_cache_get(&cache_cache),
+		BUG_ON(cpu_cache_get(kmem_cache) != &initarray_cache.cache);
+		memcpy(ptr, cpu_cache_get(kmem_cache),
 		       sizeof(struct arraycache_init));
 		/*
 		 * Do not assume that spinlocks can be initialized via memcpy:
 		 */
 		spin_lock_init(&ptr->lock);
 
-		cache_cache.array[smp_processor_id()] = ptr;
+		kmem_cache->array[smp_processor_id()] = ptr;
 
 		ptr = kmalloc(sizeof(struct arraycache_init), GFP_NOWAIT);
 
@@ -1747,7 +1749,7 @@ void __init kmem_cache_init(void)
 		int nid;
 
 		for_each_online_node(nid) {
-			init_list(&cache_cache, &initkmem_list3[CACHE_CACHE + nid], nid);
+			init_list(kmem_cache, &initkmem_list3[CACHE_CACHE + nid], nid);
 
 			init_list(malloc_sizes[INDEX_AC].cs_cachep,
 				  &initkmem_list3[SIZE_AC + nid], nid);
@@ -2213,7 +2215,7 @@ void __kmem_cache_destroy(struct kmem_cache *cachep)
 			kfree(l3);
 		}
 	}
-	kmem_cache_free(&cache_cache, cachep);
+	kmem_cache_free(kmem_cache, cachep);
 }
 
 
@@ -2463,7 +2465,7 @@ __kmem_cache_create (const char *name, size_t size, size_t align,
 		gfp = GFP_NOWAIT;
 
 	/* Get cache's description obj. */
-	cachep = kmem_cache_zalloc(&cache_cache, gfp);
+	cachep = kmem_cache_zalloc(kmem_cache, gfp);
 	if (!cachep)
 		return NULL;
 
@@ -2521,7 +2523,7 @@ __kmem_cache_create (const char *name, size_t size, size_t align,
 	if (!cachep->num) {
 		printk(KERN_ERR
 		       "kmem_cache_create: couldn't create cache %s.\n", name);
-		kmem_cache_free(&cache_cache, cachep);
+		kmem_cache_free(kmem_cache, cachep);
 		return NULL;
 	}
 	slab_size = ALIGN(cachep->num * sizeof(kmem_bufctl_t)
@@ -3289,7 +3291,7 @@ static void *cache_alloc_debugcheck_after(struct kmem_cache *cachep,
 
 static bool slab_should_failslab(struct kmem_cache *cachep, gfp_t flags)
 {
-	if (cachep == &cache_cache)
+	if (cachep == kmem_cache)
 		return false;
 
 	return should_failslab(cachep->object_size, flags, cachep->flags);
diff --git a/mm/slab.h b/mm/slab.h
index 07a537e..6724aa6 100644
--- a/mm/slab.h
+++ b/mm/slab.h
@@ -25,8 +25,14 @@ extern enum slab_state slab_state;
 
 /* The slab cache mutex protects the management structures during changes */
 extern struct mutex slab_mutex;
+
+/* The list of all slab caches on the system */
 extern struct list_head slab_caches;
 
+/* The slab cache that manages slab cache information */
+extern struct kmem_cache *kmem_cache;
+
+/* Functions provided by the slab allocators */
 struct kmem_cache *__kmem_cache_create(const char *name, size_t size,
 	size_t align, unsigned long flags, void (*ctor)(void *));
 
diff --git a/mm/slab_common.c b/mm/slab_common.c
index 5cc1371..850c497 100644
--- a/mm/slab_common.c
+++ b/mm/slab_common.c
@@ -22,6 +22,7 @@
 enum slab_state slab_state;
 LIST_HEAD(slab_caches);
 DEFINE_MUTEX(slab_mutex);
+struct kmem_cache *kmem_cache;
 
 #ifdef CONFIG_DEBUG_VM
 static int kmem_cache_sanity_check(const char *name, size_t size)
diff --git a/mm/slob.c b/mm/slob.c
index 289be4f..7d272c3 100644
--- a/mm/slob.c
+++ b/mm/slob.c
@@ -622,8 +622,16 @@ int kmem_cache_shrink(struct kmem_cache *d)
 }
 EXPORT_SYMBOL(kmem_cache_shrink);
 
+struct kmem_cache kmem_cache_boot = {
+	.name = "kmem_cache",
+	.size = sizeof(struct kmem_cache),
+	.flags = SLAB_PANIC,
+	.align = ARCH_KMALLOC_MINALIGN,
+};
+
 void __init kmem_cache_init(void)
 {
+	kmem_cache = &kmem_cache_boot;
 	slab_state = UP;
 }
 
diff --git a/mm/slub.c b/mm/slub.c
index c99c0af..607fee5 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -3221,8 +3221,6 @@ void __kmem_cache_destroy(struct kmem_cache *s)
 struct kmem_cache *kmalloc_caches[SLUB_PAGE_SHIFT];
 EXPORT_SYMBOL(kmalloc_caches);
 
-static struct kmem_cache *kmem_cache;
-
 #ifdef CONFIG_ZONE_DMA
 static struct kmem_cache *kmalloc_dma_caches[SLUB_PAGE_SHIFT];
 #endif
-- 
1.7.9.5


--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply related	[flat|nested] 32+ messages in thread

* C13 [10/14] Do slab aliasing call from common code
       [not found] <20120824160903.168122683@linux.com>
                   ` (7 preceding siblings ...)
  2012-08-24 16:17 ` C13 [06/14] Always use the name "kmem_cache" for the slab cache with the kmem_cache structure Christoph Lameter
@ 2012-08-24 16:17 ` Christoph Lameter
  2012-08-24 16:17 ` C13 [01/14] slub: Add debugging to verify correct cache use on kmem_cache_free() Christoph Lameter
                   ` (4 subsequent siblings)
  13 siblings, 0 replies; 32+ messages in thread
From: Christoph Lameter @ 2012-08-24 16:17 UTC (permalink / raw)
  To: Pekka Enberg; +Cc: Joonsoo Kim, Glauber Costa, linux-mm, David Rientjes

The slab aliasing logic causes some strange contortions in
slub. So add a call to deal with aliases to slab_common.c
but disable it for other slab allocators by providng stubs
that fail to create aliases.

Full general support for aliases will require additional
cleanup passes and more standardization of fields in
kmem_cache.

V1->V2:
	- Move kstrdup before kmem_cache_alias invocation.
	(JoonSoo Kim)

Signed-off-by: Christoph Lameter <cl@linux.com>
---
 mm/slab.h        |   10 ++++++++++
 mm/slab_common.c |    4 ++++
 mm/slub.c        |   15 +++++++++++----
 3 files changed, 25 insertions(+), 4 deletions(-)

diff --git a/mm/slab.h b/mm/slab.h
index c4f9a36..84c28f4 100644
--- a/mm/slab.h
+++ b/mm/slab.h
@@ -36,6 +36,16 @@ extern struct kmem_cache *kmem_cache;
 struct kmem_cache *__kmem_cache_create(const char *name, size_t size,
 	size_t align, unsigned long flags, void (*ctor)(void *));
 
+#ifdef CONFIG_SLUB
+struct kmem_cache *__kmem_cache_alias(const char *name, size_t size,
+	size_t align, unsigned long flags, void (*ctor)(void *));
+#else
+static inline struct kmem_cache *__kmem_cache_alias(const char *name, size_t size,
+	size_t align, unsigned long flags, void (*ctor)(void *))
+{ return NULL; }
+#endif
+
+
 int __kmem_cache_shutdown(struct kmem_cache *);
 
 #endif
diff --git a/mm/slab_common.c b/mm/slab_common.c
index cb3b2c1..e5cd47f 100644
--- a/mm/slab_common.c
+++ b/mm/slab_common.c
@@ -115,6 +115,10 @@ struct kmem_cache *kmem_cache_create(const char *name, size_t size, size_t align
 		goto out_locked;
 	}
 
+	s = __kmem_cache_alias(name, size, align, flags, ctor);
+	if (s)
+		goto out_locked;
+
 	s = __kmem_cache_create(n, size, align, flags, ctor);
 
 	if (s) {
diff --git a/mm/slub.c b/mm/slub.c
index 09ea157..5751f30 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -3708,7 +3708,7 @@ void __init kmem_cache_init(void)
 		slub_max_order = 0;
 
 	kmem_size = offsetof(struct kmem_cache, node) +
-				nr_node_ids * sizeof(struct kmem_cache_node *);
+			nr_node_ids * sizeof(struct kmem_cache_node *);
 
 	/* Allocate two kmem_caches from the page allocator */
 	kmalloc_size = ALIGN(kmem_size, cache_line_size());
@@ -3922,7 +3922,7 @@ static struct kmem_cache *find_mergeable(size_t size,
 	return NULL;
 }
 
-struct kmem_cache *__kmem_cache_create(const char *name, size_t size,
+struct kmem_cache *__kmem_cache_alias(const char *name, size_t size,
 		size_t align, unsigned long flags, void (*ctor)(void *))
 {
 	struct kmem_cache *s;
@@ -3939,11 +3939,18 @@ struct kmem_cache *__kmem_cache_create(const char *name, size_t size,
 
 		if (sysfs_slab_alias(s, name)) {
 			s->refcount--;
-			return NULL;
+			s = NULL;
 		}
-		return s;
 	}
 
+	return s;
+}
+
+struct kmem_cache *__kmem_cache_create(const char *name, size_t size,
+		size_t align, unsigned long flags, void (*ctor)(void *))
+{
+	struct kmem_cache *s;
+
 	s = kmem_cache_alloc(kmem_cache, GFP_KERNEL);
 	if (s) {
 		if (kmem_cache_open(s, name,
-- 
1.7.9.5


--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply related	[flat|nested] 32+ messages in thread

* C13 [04/14] Move list_add() to slab_common.c
       [not found] <20120824160903.168122683@linux.com>
                   ` (5 preceding siblings ...)
  2012-08-24 16:17 ` C13 [11/14] Move sysfs_slab_add to common Christoph Lameter
@ 2012-08-24 16:17 ` Christoph Lameter
  2012-08-24 16:17 ` C13 [06/14] Always use the name "kmem_cache" for the slab cache with the kmem_cache structure Christoph Lameter
                   ` (6 subsequent siblings)
  13 siblings, 0 replies; 32+ messages in thread
From: Christoph Lameter @ 2012-08-24 16:17 UTC (permalink / raw)
  To: Pekka Enberg; +Cc: Joonsoo Kim, David Rientjes, Glauber Costa, linux-mm

Move the code to append the new kmem_cache to the list of slab caches to
the kmem_cache_create code in the shared code.

This is possible now since the acquisition of the mutex was moved into
kmem_cache_create().

V1->V2:
	- SLOB: Add code to remove the slab from list
	 (will be removed a couple of patches down when we also move the
	 list_del to common code).

Acked-by: David Rientjes <rientjes@google.com>
Reviewed-by: Glauber Costa <glommer@parallels.com>
Reviewed-by: Joonsoo Kim <js1304@gmail.com>
Signed-off-by: Christoph Lameter <cl@linux.com>
---
 mm/slab.c        |    7 +++++--
 mm/slab_common.c |    7 +++++++
 mm/slob.c        |    4 ++++
 mm/slub.c        |    2 --
 4 files changed, 16 insertions(+), 4 deletions(-)

diff --git a/mm/slab.c b/mm/slab.c
index 3b4587b..a699031 100644
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -1680,6 +1680,7 @@ void __init kmem_cache_init(void)
 					ARCH_KMALLOC_FLAGS|SLAB_PANIC,
 					NULL);
 
+	list_add(&sizes[INDEX_AC].cs_cachep->list, &slab_caches);
 	if (INDEX_AC != INDEX_L3) {
 		sizes[INDEX_L3].cs_cachep =
 			__kmem_cache_create(names[INDEX_L3].name,
@@ -1687,6 +1688,7 @@ void __init kmem_cache_init(void)
 				ARCH_KMALLOC_MINALIGN,
 				ARCH_KMALLOC_FLAGS|SLAB_PANIC,
 				NULL);
+		list_add(&sizes[INDEX_L3].cs_cachep->list, &slab_caches);
 	}
 
 	slab_early_init = 0;
@@ -1705,6 +1707,7 @@ void __init kmem_cache_init(void)
 					ARCH_KMALLOC_MINALIGN,
 					ARCH_KMALLOC_FLAGS|SLAB_PANIC,
 					NULL);
+			list_add(&sizes->cs_cachep->list, &slab_caches);
 		}
 #ifdef CONFIG_ZONE_DMA
 		sizes->cs_dmacachep = __kmem_cache_create(
@@ -1714,6 +1717,7 @@ void __init kmem_cache_init(void)
 					ARCH_KMALLOC_FLAGS|SLAB_CACHE_DMA|
 						SLAB_PANIC,
 					NULL);
+		list_add(&sizes->cs_dmacachep->list, &slab_caches);
 #endif
 		sizes++;
 		names++;
@@ -2583,6 +2587,7 @@ __kmem_cache_create (const char *name, size_t size, size_t align,
 	}
 	cachep->ctor = ctor;
 	cachep->name = name;
+	cachep->refcount = 1;
 
 	if (setup_cpu_cache(cachep, gfp)) {
 		__kmem_cache_destroy(cachep);
@@ -2599,8 +2604,6 @@ __kmem_cache_create (const char *name, size_t size, size_t align,
 		slab_set_debugobj_lock_classes(cachep);
 	}
 
-	/* cache setup completed, link it into the list */
-	list_add(&cachep->list, &slab_caches);
 	return cachep;
 }
 
diff --git a/mm/slab_common.c b/mm/slab_common.c
index b61c9ae..d419a3e 100644
--- a/mm/slab_common.c
+++ b/mm/slab_common.c
@@ -111,6 +111,13 @@ struct kmem_cache *kmem_cache_create(const char *name, size_t size, size_t align
 	if (!s)
 		err = -ENOSYS; /* Until __kmem_cache_create returns code */
 
+	/*
+	 * Check if the slab has actually been created and if it was a
+	 * real instatiation. Aliases do not belong on the list
+	 */
+	if (s && s->refcount == 1)
+		list_add(&s->list, &slab_caches);
+
 out_locked:
 	mutex_unlock(&slab_mutex);
 	put_online_cpus();
diff --git a/mm/slob.c b/mm/slob.c
index 45d4ca7..5225d28 100644
--- a/mm/slob.c
+++ b/mm/slob.c
@@ -540,6 +540,10 @@ struct kmem_cache *__kmem_cache_create(const char *name, size_t size,
 
 void kmem_cache_destroy(struct kmem_cache *c)
 {
+	mutex_lock(&slab_mutex);
+	list_del(&c->list);
+	mutex_unlock(&slab_mutex);
+
 	kmemleak_free(c);
 	if (c->flags & SLAB_DESTROY_BY_RCU)
 		rcu_barrier();
diff --git a/mm/slub.c b/mm/slub.c
index e0b9403..37d5177 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -3975,7 +3975,6 @@ struct kmem_cache *__kmem_cache_create(const char *name, size_t size,
 				size, align, flags, ctor)) {
 			int r;
 
-			list_add(&s->list, &slab_caches);
 			mutex_unlock(&slab_mutex);
 			r = sysfs_slab_add(s);
 			mutex_lock(&slab_mutex);
@@ -3983,7 +3982,6 @@ struct kmem_cache *__kmem_cache_create(const char *name, size_t size,
 			if (!r)
 				return s;
 
-			list_del(&s->list);
 			kmem_cache_close(s);
 		}
 		kmem_cache_free(kmem_cache, s);
-- 
1.7.9.5


--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply related	[flat|nested] 32+ messages in thread

* C13 [01/14] slub: Add debugging to verify correct cache use on kmem_cache_free()
       [not found] <20120824160903.168122683@linux.com>
                   ` (8 preceding siblings ...)
  2012-08-24 16:17 ` C13 [10/14] Do slab aliasing call from common code Christoph Lameter
@ 2012-08-24 16:17 ` Christoph Lameter
  2012-09-03 14:26   ` Glauber Costa
  2012-08-24 16:17 ` C13 [09/14] Move duping of slab name to slab_common.c Christoph Lameter
                   ` (3 subsequent siblings)
  13 siblings, 1 reply; 32+ messages in thread
From: Christoph Lameter @ 2012-08-24 16:17 UTC (permalink / raw)
  To: Pekka Enberg; +Cc: Joonsoo Kim, Glauber Costa, linux-mm, David Rientjes

Add additional debugging to check that the objects is actually from the cache
the caller claims. Doing so currently trips up some other debugging code. It
takes a lot to infer from that what was happening.

V2: Only warn once.

Signed-off-by: Christoph Lameter <cl@linux.com>
---
 mm/slub.c |    7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/mm/slub.c b/mm/slub.c
index c67bd0a..00f8557 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -2614,6 +2614,13 @@ void kmem_cache_free(struct kmem_cache *s, void *x)
 
 	page = virt_to_head_page(x);
 
+	if (kmem_cache_debug(s) && page->slab != s) {
+		printk("kmem_cache_free: Wrong slab cache. %s but object"
+			" is from  %s\n", page->slab->name, s->name);
+		WARN_ON_ONCE(1);
+		return;
+	}
+
 	slab_free(s, page, x, _RET_IP_);
 
 	trace_kmem_cache_free(_RET_IP_, x);
-- 
1.7.9.5


--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply related	[flat|nested] 32+ messages in thread

* C13 [09/14] Move duping of slab name to slab_common.c
       [not found] <20120824160903.168122683@linux.com>
                   ` (9 preceding siblings ...)
  2012-08-24 16:17 ` C13 [01/14] slub: Add debugging to verify correct cache use on kmem_cache_free() Christoph Lameter
@ 2012-08-24 16:17 ` Christoph Lameter
  2012-09-03 15:02   ` Glauber Costa
  2012-08-24 16:17 ` C13 [02/14] slub: Use kmem_cache for the kmem_cache structure Christoph Lameter
                   ` (2 subsequent siblings)
  13 siblings, 1 reply; 32+ messages in thread
From: Christoph Lameter @ 2012-08-24 16:17 UTC (permalink / raw)
  To: Pekka Enberg; +Cc: Joonsoo Kim, Glauber Costa, linux-mm, David Rientjes

Duping of the slabname has to be done by each slab. Moving this code
to slab_common avoids duplicate implementations.

With this patch we have common string handling for all slab allocators.
Strings passed to kmem_cache_create() are copied internally. Subsystems
can create temporary strings to create slab caches.

Slabs allocated in early states of bootstrap will never be freed (and those
can never be freed since they are essential to slab allocator operations).
During bootstrap we therefore do not have to worry about duping names.

Signed-off-by: Christoph Lameter <cl@linux.com>
---
 mm/slab_common.c |   30 +++++++++++++++++++++---------
 mm/slub.c        |   21 ++-------------------
 2 files changed, 23 insertions(+), 28 deletions(-)

diff --git a/mm/slab_common.c b/mm/slab_common.c
index 777cae0..cb3b2c1 100644
--- a/mm/slab_common.c
+++ b/mm/slab_common.c
@@ -100,6 +100,7 @@ struct kmem_cache *kmem_cache_create(const char *name, size_t size, size_t align
 {
 	struct kmem_cache *s;
 	int err = 0;
+	char *n;
 
 	get_online_cpus();
 	mutex_lock(&slab_mutex);
@@ -108,16 +109,26 @@ struct kmem_cache *kmem_cache_create(const char *name, size_t size, size_t align
 		goto out_locked;
 
 
-	s = __kmem_cache_create(name, size, align, flags, ctor);
-	if (!s)
-		err = -ENOSYS; /* Until __kmem_cache_create returns code */
+	n = kstrdup(name, GFP_KERNEL);
+	if (!n) {
+		err = -ENOMEM;
+		goto out_locked;
+	}
+
+	s = __kmem_cache_create(n, size, align, flags, ctor);
+
+	if (s) {
+		/*
+		 * Check if the slab has actually been created and if it was a
+		 * real instatiation. Aliases do not belong on the list
+		 */
+		if (s->refcount == 1)
+			list_add(&s->list, &slab_caches);
 
-	/*
-	 * Check if the slab has actually been created and if it was a
-	 * real instatiation. Aliases do not belong on the list
-	 */
-	if (s && s->refcount == 1)
-		list_add(&s->list, &slab_caches);
+	} else {
+		kfree(n);
+		err = -ENOSYS; /* Until __kmem_cache_create returns code */
+	}
 
 out_locked:
 	mutex_unlock(&slab_mutex);
@@ -153,6 +164,7 @@ void kmem_cache_destroy(struct kmem_cache *s)
 			if (s->flags & SLAB_DESTROY_BY_RCU)
 				rcu_barrier();
 
+			kfree(s->name);
 			kmem_cache_free(kmem_cache, s);
 		} else {
 			list_add(&s->list, &slab_caches);
diff --git a/mm/slub.c b/mm/slub.c
index bb02589..09ea157 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -210,10 +210,7 @@ static void sysfs_slab_remove(struct kmem_cache *);
 static inline int sysfs_slab_add(struct kmem_cache *s) { return 0; }
 static inline int sysfs_slab_alias(struct kmem_cache *s, const char *p)
 							{ return 0; }
-static inline void sysfs_slab_remove(struct kmem_cache *s)
-{
-	kfree(s->name);
-}
+static inline void sysfs_slab_remove(struct kmem_cache *s) { }
 
 #endif
 
@@ -3929,7 +3926,6 @@ struct kmem_cache *__kmem_cache_create(const char *name, size_t size,
 		size_t align, unsigned long flags, void (*ctor)(void *))
 {
 	struct kmem_cache *s;
-	char *n;
 
 	s = find_mergeable(size, align, flags, name, ctor);
 	if (s) {
@@ -3948,13 +3944,9 @@ struct kmem_cache *__kmem_cache_create(const char *name, size_t size,
 		return s;
 	}
 
-	n = kstrdup(name, GFP_KERNEL);
-	if (!n)
-		return NULL;
-
 	s = kmem_cache_alloc(kmem_cache, GFP_KERNEL);
 	if (s) {
-		if (kmem_cache_open(s, n,
+		if (kmem_cache_open(s, name,
 				size, align, flags, ctor)) {
 			int r;
 
@@ -3969,7 +3961,6 @@ struct kmem_cache *__kmem_cache_create(const char *name, size_t size,
 		}
 		kmem_cache_free(kmem_cache, s);
 	}
-	kfree(n);
 	return NULL;
 }
 
@@ -5200,13 +5191,6 @@ static ssize_t slab_attr_store(struct kobject *kobj,
 	return err;
 }
 
-static void kmem_cache_release(struct kobject *kobj)
-{
-	struct kmem_cache *s = to_slab(kobj);
-
-	kfree(s->name);
-}
-
 static const struct sysfs_ops slab_sysfs_ops = {
 	.show = slab_attr_show,
 	.store = slab_attr_store,
@@ -5214,7 +5198,6 @@ static const struct sysfs_ops slab_sysfs_ops = {
 
 static struct kobj_type slab_ktype = {
 	.sysfs_ops = &slab_sysfs_ops,
-	.release = kmem_cache_release
 };
 
 static int uevent_filter(struct kset *kset, struct kobject *kobj)
-- 
1.7.9.5


--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply related	[flat|nested] 32+ messages in thread

* C13 [02/14] slub: Use kmem_cache for the kmem_cache structure
       [not found] <20120824160903.168122683@linux.com>
                   ` (10 preceding siblings ...)
  2012-08-24 16:17 ` C13 [09/14] Move duping of slab name to slab_common.c Christoph Lameter
@ 2012-08-24 16:17 ` Christoph Lameter
  2012-09-03 14:27   ` Glauber Costa
  2012-08-24 16:17 ` C13 [13/14] Shrink __kmem_cache_create() parameter lists Christoph Lameter
  2012-08-24 16:17 ` C13 [14/14] Move kmem_cache refcounting to common code Christoph Lameter
  13 siblings, 1 reply; 32+ messages in thread
From: Christoph Lameter @ 2012-08-24 16:17 UTC (permalink / raw)
  To: Pekka Enberg; +Cc: Joonsoo Kim, David Rientjes, Glauber Costa, linux-mm

Do not use kmalloc() but kmem_cache_alloc() for the allocation
of the kmem_cache structures in slub.

Acked-by: David Rientjes <rientjes@google.com>
Signed-off-by: Christoph Lameter <cl@linux.com>
---
 mm/slub.c |    8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/mm/slub.c b/mm/slub.c
index 00f8557..e0b9403 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -213,7 +213,7 @@ static inline int sysfs_slab_alias(struct kmem_cache *s, const char *p)
 static inline void sysfs_slab_remove(struct kmem_cache *s)
 {
 	kfree(s->name);
-	kfree(s);
+	kmem_cache_free(kmem_cache, s);
 }
 
 #endif
@@ -3969,7 +3969,7 @@ struct kmem_cache *__kmem_cache_create(const char *name, size_t size,
 	if (!n)
 		return NULL;
 
-	s = kmalloc(kmem_size, GFP_KERNEL);
+	s = kmem_cache_alloc(kmem_cache, GFP_KERNEL);
 	if (s) {
 		if (kmem_cache_open(s, n,
 				size, align, flags, ctor)) {
@@ -3986,7 +3986,7 @@ struct kmem_cache *__kmem_cache_create(const char *name, size_t size,
 			list_del(&s->list);
 			kmem_cache_close(s);
 		}
-		kfree(s);
+		kmem_cache_free(kmem_cache, s);
 	}
 	kfree(n);
 	return NULL;
@@ -5224,7 +5224,7 @@ static void kmem_cache_release(struct kobject *kobj)
 	struct kmem_cache *s = to_slab(kobj);
 
 	kfree(s->name);
-	kfree(s);
+	kmem_cache_free(kmem_cache, s);
 }
 
 static const struct sysfs_ops slab_sysfs_ops = {
-- 
1.7.9.5


--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply related	[flat|nested] 32+ messages in thread

* C13 [14/14] Move kmem_cache refcounting to common code
       [not found] <20120824160903.168122683@linux.com>
                   ` (12 preceding siblings ...)
  2012-08-24 16:17 ` C13 [13/14] Shrink __kmem_cache_create() parameter lists Christoph Lameter
@ 2012-08-24 16:17 ` Christoph Lameter
  2012-09-03 15:12   ` Glauber Costa
  13 siblings, 1 reply; 32+ messages in thread
From: Christoph Lameter @ 2012-08-24 16:17 UTC (permalink / raw)
  To: Pekka Enberg; +Cc: Joonsoo Kim, Glauber Costa, linux-mm, David Rientjes

Get rid of the refcount stuff in the allocators and do that
part of kmem_cache management in the common code.

Signed-off-by: Christoph Lameter <cl@linux.com>
---
 mm/slab.c        |    1 -
 mm/slab_common.c |    5 +++--
 mm/slob.c        |    2 --
 mm/slub.c        |    1 -
 4 files changed, 3 insertions(+), 6 deletions(-)

Index: linux/mm/slab.c
===================================================================
--- linux.orig/mm/slab.c	2012-08-22 10:27:54.838388363 -0500
+++ linux/mm/slab.c	2012-08-22 10:28:31.658969127 -0500
@@ -2543,7 +2543,6 @@ __kmem_cache_create (struct kmem_cache *
 		 */
 		BUG_ON(ZERO_OR_NULL_PTR(cachep->slabp_cache));
 	}
-	cachep->refcount = 1;
 
 	err = setup_cpu_cache(cachep, gfp);
 	if (err) {
Index: linux/mm/slab_common.c
===================================================================
--- linux.orig/mm/slab_common.c	2012-08-22 10:27:54.858388583 -0500
+++ linux/mm/slab_common.c	2012-08-22 10:28:31.658969127 -0500
@@ -125,11 +125,12 @@ struct kmem_cache *kmem_cache_create(con
 		}
 
 		err = __kmem_cache_create(s, flags);
-		if (!err)
+		if (!err) {
 
+			s->refcount = 1;
 			list_add(&s->list, &slab_caches);
 
-		else {
+		} else {
 			kfree(s->name);
 			kmem_cache_free(kmem_cache, s);
 		}
Index: linux/mm/slob.c
===================================================================
--- linux.orig/mm/slob.c	2012-08-22 10:27:54.846388442 -0500
+++ linux/mm/slob.c	2012-08-22 10:28:31.658969127 -0500
@@ -524,8 +524,6 @@ int __kmem_cache_create(struct kmem_cach
 	if (c->align < align)
 		c->align = align;
 
-	kmemleak_alloc(c, sizeof(struct kmem_cache), 1, GFP_KERNEL);
-	c->refcount = 1;
 	return 0;
 }
 
Index: linux/mm/slub.c
===================================================================
--- linux.orig/mm/slub.c	2012-08-22 10:27:54.870388814 -0500
+++ linux/mm/slub.c	2012-08-22 10:28:31.662969186 -0500
@@ -3093,7 +3093,6 @@ static int kmem_cache_open(struct kmem_c
 	else
 		s->cpu_partial = 30;
 
-	s->refcount = 1;
 #ifdef CONFIG_NUMA
 	s->remote_node_defrag_ratio = 1000;
 #endif

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 32+ messages in thread

* C13 [13/14] Shrink __kmem_cache_create() parameter lists
       [not found] <20120824160903.168122683@linux.com>
                   ` (11 preceding siblings ...)
  2012-08-24 16:17 ` C13 [02/14] slub: Use kmem_cache for the kmem_cache structure Christoph Lameter
@ 2012-08-24 16:17 ` Christoph Lameter
  2012-09-03 15:33   ` Glauber Costa
  2012-08-24 16:17 ` C13 [14/14] Move kmem_cache refcounting to common code Christoph Lameter
  13 siblings, 1 reply; 32+ messages in thread
From: Christoph Lameter @ 2012-08-24 16:17 UTC (permalink / raw)
  To: Pekka Enberg; +Cc: Joonsoo Kim, Glauber Costa, linux-mm, David Rientjes

Do the initial settings of the fields in common code. This will allow
us to push more processing into common code later and improve readability.

Signed-off-by: Christoph Lameter <cl@linux.com>
---
 mm/slab.c        |   91 ++++++++++++++++++++++++------------------------------
 mm/slab.h        |    3 +-
 mm/slab_common.c |   26 ++++++++--------
 mm/slob.c        |    8 ++---
 mm/slub.c        |   39 +++++++++++------------
 5 files changed, 76 insertions(+), 91 deletions(-)

Index: linux/mm/slab.c
===================================================================
--- linux.orig/mm/slab.c	2012-08-22 16:00:44.201655179 -0500
+++ linux/mm/slab.c	2012-08-22 16:00:45.705677849 -0500
@@ -1667,20 +1667,20 @@ void __init kmem_cache_init(void)
 	 */
 
 	sizes[INDEX_AC].cs_cachep = kmem_cache_zalloc(kmem_cache, GFP_NOWAIT);
-	__kmem_cache_create(sizes[INDEX_AC].cs_cachep, names[INDEX_AC].name,
-					sizes[INDEX_AC].cs_size,
-					ARCH_KMALLOC_MINALIGN,
-					ARCH_KMALLOC_FLAGS|SLAB_PANIC,
-					NULL);
-
+	sizes[INDEX_AC].cs_cachep->name = names[INDEX_AC].name;
+	sizes[INDEX_AC].cs_cachep->size = sizes[INDEX_AC].cs_size;
+	sizes[INDEX_AC].cs_cachep->object_size = sizes[INDEX_AC].cs_size;
+	sizes[INDEX_AC].cs_cachep->align = ARCH_KMALLOC_MINALIGN;
+	__kmem_cache_create(sizes[INDEX_AC].cs_cachep, ARCH_KMALLOC_FLAGS|SLAB_PANIC);
 	list_add(&sizes[INDEX_AC].cs_cachep->list, &slab_caches);
+
 	if (INDEX_AC != INDEX_L3) {
 		sizes[INDEX_L3].cs_cachep = kmem_cache_zalloc(kmem_cache, GFP_NOWAIT);
-		__kmem_cache_create(sizes[INDEX_L3].cs_cachep, names[INDEX_L3].name,
-				sizes[INDEX_L3].cs_size,
-				ARCH_KMALLOC_MINALIGN,
-				ARCH_KMALLOC_FLAGS|SLAB_PANIC,
-				NULL);
+		sizes[INDEX_L3].cs_cachep->name = names[INDEX_L3].name;
+		sizes[INDEX_L3].cs_cachep->size = sizes[INDEX_L3].cs_size;
+		sizes[INDEX_L3].cs_cachep->object_size = sizes[INDEX_L3].cs_size;
+		sizes[INDEX_L3].cs_cachep->align = ARCH_KMALLOC_MINALIGN;
+		__kmem_cache_create(sizes[INDEX_L3].cs_cachep, ARCH_KMALLOC_FLAGS|SLAB_PANIC);
 		list_add(&sizes[INDEX_L3].cs_cachep->list, &slab_caches);
 	}
 
@@ -1696,22 +1696,21 @@ void __init kmem_cache_init(void)
 		 */
 		if (!sizes->cs_cachep) {
 			sizes->cs_cachep = kmem_cache_zalloc(kmem_cache, GFP_NOWAIT);
-			__kmem_cache_create(sizes->cs_cachep, names->name,
-					sizes->cs_size,
-					ARCH_KMALLOC_MINALIGN,
-					ARCH_KMALLOC_FLAGS|SLAB_PANIC,
-					NULL);
+			sizes->cs_cachep->name = names->name;
+			sizes->cs_cachep->size = sizes->cs_size;
+			sizes->cs_cachep->object_size = sizes->cs_size;
+			sizes->cs_cachep->align = ARCH_KMALLOC_MINALIGN;
+			__kmem_cache_create(sizes->cs_cachep, ARCH_KMALLOC_FLAGS|SLAB_PANIC);
 			list_add(&sizes->cs_cachep->list, &slab_caches);
 		}
 #ifdef CONFIG_ZONE_DMA
 		sizes->cs_dmacachep = kmem_cache_zalloc(kmem_cache, GFP_NOWAIT);
+		sizes->cs_dmacachep->name = names->name_dma;
+		sizes->cs_dmacachep->size = sizes->cs_size;
+		sizes->cs_dmacachep->object_size = sizes->cs_size;
+		sizes->cs_dmacachep->align = ARCH_KMALLOC_MINALIGN;
 		__kmem_cache_create(sizes->cs_dmacachep,
-					names->name_dma,
-					sizes->cs_size,
-					ARCH_KMALLOC_MINALIGN,
-					ARCH_KMALLOC_FLAGS|SLAB_CACHE_DMA|
-						SLAB_PANIC,
-					NULL);
+			       ARCH_KMALLOC_FLAGS|SLAB_CACHE_DMA| SLAB_PANIC);
 		list_add(&sizes->cs_dmacachep->list, &slab_caches);
 #endif
 		sizes++;
@@ -2350,8 +2349,7 @@ static int __init_refok setup_cpu_cache(
  * as davem.
  */
 int
-__kmem_cache_create (struct kmem_cache *cachep, const char *name, size_t size, size_t align,
-	unsigned long flags, void (*ctor)(void *))
+__kmem_cache_create (struct kmem_cache *cachep, unsigned long flags)
 {
 	size_t left_over, slab_size, ralign;
 	gfp_t gfp;
@@ -2385,9 +2383,9 @@ __kmem_cache_create (struct kmem_cache *
 	 * unaligned accesses for some archs when redzoning is used, and makes
 	 * sure any on-slab bufctl's are also correctly aligned.
 	 */
-	if (size & (BYTES_PER_WORD - 1)) {
-		size += (BYTES_PER_WORD - 1);
-		size &= ~(BYTES_PER_WORD - 1);
+	if (cachep->size & (BYTES_PER_WORD - 1)) {
+		cachep->size += (BYTES_PER_WORD - 1);
+		cachep->size &= ~(BYTES_PER_WORD - 1);
 	}
 
 	/* calculate the final buffer alignment: */
@@ -2400,7 +2398,7 @@ __kmem_cache_create (struct kmem_cache *
 		 * one cacheline.
 		 */
 		ralign = cache_line_size();
-		while (size <= ralign / 2)
+		while (cachep->size <= ralign / 2)
 			ralign /= 2;
 	} else {
 		ralign = BYTES_PER_WORD;
@@ -2418,8 +2416,8 @@ __kmem_cache_create (struct kmem_cache *
 		ralign = REDZONE_ALIGN;
 		/* If redzoning, ensure that the second redzone is suitably
 		 * aligned, by adjusting the object size accordingly. */
-		size += REDZONE_ALIGN - 1;
-		size &= ~(REDZONE_ALIGN - 1);
+		cachep->size += REDZONE_ALIGN - 1;
+		cachep->size &= ~(REDZONE_ALIGN - 1);
 	}
 
 	/* 2) arch mandated alignment */
@@ -2427,8 +2425,8 @@ __kmem_cache_create (struct kmem_cache *
 		ralign = ARCH_SLAB_MINALIGN;
 	}
 	/* 3) caller mandated alignment */
-	if (ralign < align) {
-		ralign = align;
+	if (ralign < cachep->align) {
+		ralign = cachep->align;
 	}
 	/* disable debug if necessary */
 	if (ralign > __alignof__(unsigned long long))
@@ -2436,7 +2434,7 @@ __kmem_cache_create (struct kmem_cache *
 	/*
 	 * 4) Store it.
 	 */
-	align = ralign;
+	cachep->align = ralign;
 
 	if (slab_is_available())
 		gfp = GFP_KERNEL;
@@ -2444,8 +2442,6 @@ __kmem_cache_create (struct kmem_cache *
 		gfp = GFP_NOWAIT;
 
 	cachep->nodelists = (struct kmem_list3 **)&cachep->array[nr_cpu_ids];
-	cachep->object_size = size;
-	cachep->align = align;
 #if DEBUG
 
 	/*
@@ -2482,7 +2478,7 @@ __kmem_cache_create (struct kmem_cache *
 	 * it too early on. Always use on-slab management when
 	 * SLAB_NOLEAKTRACE to avoid recursive calls into kmemleak)
 	 */
-	if ((size >= (PAGE_SIZE >> 3)) && !slab_early_init &&
+	if ((cachep->size >= (PAGE_SIZE >> 3)) && !slab_early_init &&
 	    !(flags & SLAB_NOLEAKTRACE))
 		/*
 		 * Size is large, assume best to place the slab management obj
@@ -2490,17 +2486,15 @@ __kmem_cache_create (struct kmem_cache *
 		 */
 		flags |= CFLGS_OFF_SLAB;
 
-	size = ALIGN(size, align);
+	cachep->size = ALIGN(cachep->size, cachep->align);
 
-	left_over = calculate_slab_order(cachep, size, align, flags);
+	left_over = calculate_slab_order(cachep, cachep->size, cachep->align, flags);
 
-	if (!cachep->num) {
-		printk(KERN_ERR
-		       "kmem_cache_create: couldn't create cache %s.\n", name);
+	if (!cachep->num)
 		return -E2BIG;
-	}
+
 	slab_size = ALIGN(cachep->num * sizeof(kmem_bufctl_t)
-			  + sizeof(struct slab), align);
+			  + sizeof(struct slab), cachep->align);
 
 	/*
 	 * If the slab has been placed off-slab, and we have enough space then
@@ -2521,23 +2515,22 @@ __kmem_cache_create (struct kmem_cache *
 		 * poisoning, then it's going to smash the contents of
 		 * the redzone and userword anyhow, so switch them off.
 		 */
-		if (size % PAGE_SIZE == 0 && flags & SLAB_POISON)
+		if (cachep->size % PAGE_SIZE == 0 && flags & SLAB_POISON)
 			flags &= ~(SLAB_RED_ZONE | SLAB_STORE_USER);
 #endif
 	}
 
 	cachep->colour_off = cache_line_size();
 	/* Offset must be a multiple of the alignment. */
-	if (cachep->colour_off < align)
-		cachep->colour_off = align;
+	if (cachep->colour_off < cachep->align)
+		cachep->colour_off = cachep->align;
 	cachep->colour = left_over / cachep->colour_off;
 	cachep->slab_size = slab_size;
 	cachep->flags = flags;
 	cachep->allocflags = 0;
 	if (CONFIG_ZONE_DMA_FLAG && (flags & SLAB_CACHE_DMA))
 		cachep->allocflags |= GFP_DMA;
-	cachep->size = size;
-	cachep->reciprocal_buffer_size = reciprocal_value(size);
+	cachep->reciprocal_buffer_size = reciprocal_value(cachep->size);
 
 	if (flags & CFLGS_OFF_SLAB) {
 		cachep->slabp_cache = kmem_find_general_cachep(slab_size, 0u);
@@ -2550,8 +2543,6 @@ __kmem_cache_create (struct kmem_cache *
 		 */
 		BUG_ON(ZERO_OR_NULL_PTR(cachep->slabp_cache));
 	}
-	cachep->ctor = ctor;
-	cachep->name = name;
 	cachep->refcount = 1;
 
 	err = setup_cpu_cache(cachep, gfp);
Index: linux/mm/slab.h
===================================================================
--- linux.orig/mm/slab.h	2012-08-22 16:00:44.205655239 -0500
+++ linux/mm/slab.h	2012-08-22 16:00:45.705677849 -0500
@@ -33,8 +33,7 @@ extern struct list_head slab_caches;
 extern struct kmem_cache *kmem_cache;
 
 /* Functions provided by the slab allocators */
-extern int __kmem_cache_create(struct kmem_cache *, const char *name,
-	size_t size, size_t align, unsigned long flags, void (*ctor)(void *));
+extern int __kmem_cache_create(struct kmem_cache *, unsigned long flags);
 
 #ifdef CONFIG_SLUB
 struct kmem_cache *__kmem_cache_alias(const char *name, size_t size,
Index: linux/mm/slab_common.c
===================================================================
--- linux.orig/mm/slab_common.c	2012-08-22 16:00:44.205655239 -0500
+++ linux/mm/slab_common.c	2012-08-22 16:00:45.705677849 -0500
@@ -100,7 +100,6 @@ struct kmem_cache *kmem_cache_create(con
 {
 	struct kmem_cache *s = NULL;
 	int err = 0;
-	char *n;
 
 	get_online_cpus();
 	mutex_lock(&slab_mutex);
@@ -109,32 +108,33 @@ struct kmem_cache *kmem_cache_create(con
 		goto out_locked;
 
 
-	n = kstrdup(name, GFP_KERNEL);
-	if (!n) {
-		err = -ENOMEM;
-		goto out_locked;
-	}
-
 	s = __kmem_cache_alias(name, size, align, flags, ctor);
 	if (s)
 		goto out_locked;
 
 	s = kmem_cache_zalloc(kmem_cache, GFP_KERNEL);
 	if (s) {
-		err = __kmem_cache_create(s, n, size, align, flags, ctor);
+		s->object_size = s->size = size;
+		s->align = align;
+		s->ctor = ctor;
+		s->name = kstrdup(name, GFP_KERNEL);
+		if (!s->name) {
+			kmem_cache_free(kmem_cache, s);
+			err = -ENOMEM;
+			goto out_locked;
+		}
+
+		err = __kmem_cache_create(s, flags);
 		if (!err)
 
 			list_add(&s->list, &slab_caches);
 
 		else {
-			kfree(n);
+			kfree(s->name);
 			kmem_cache_free(kmem_cache, s);
 		}
-
-	} else {
-		kfree(n);
+	} else
 		err = -ENOMEM;
-	}
 
 out_locked:
 	mutex_unlock(&slab_mutex);
Index: linux/mm/slob.c
===================================================================
--- linux.orig/mm/slob.c	2012-08-22 16:00:44.205655239 -0500
+++ linux/mm/slob.c	2012-08-22 16:00:45.705677849 -0500
@@ -508,17 +508,15 @@ size_t ksize(const void *block)
 }
 EXPORT_SYMBOL(ksize);
 
-int __kmem_cache_create(struct kmem_cache *c, const char *name, size_t size,
-	size_t align, unsigned long flags, void (*ctor)(void *))
+int __kmem_cache_create(struct kmem_cache *c, unsigned long flags)
 {
-	c->name = name;
-	c->size = size;
+	size_t align = c->size;
+
 	if (flags & SLAB_DESTROY_BY_RCU) {
 		/* leave room for rcu footer at the end of object */
 		c->size += sizeof(struct slob_rcu);
 	}
 	c->flags = flags;
-	c->ctor = ctor;
 	/* ignore alignment unless it's forced */
 	c->align = (flags & SLAB_HWCACHE_ALIGN) ? SLOB_ALIGN : 0;
 	if (c->align < ARCH_SLAB_MINALIGN)
Index: linux/mm/slub.c
===================================================================
--- linux.orig/mm/slub.c	2012-08-22 16:00:44.737663265 -0500
+++ linux/mm/slub.c	2012-08-22 16:00:45.709677909 -0500
@@ -3029,16 +3029,9 @@ static int calculate_sizes(struct kmem_c
 
 }
 
-static int kmem_cache_open(struct kmem_cache *s,
-		const char *name, size_t size,
-		size_t align, unsigned long flags,
-		void (*ctor)(void *))
+static int kmem_cache_open(struct kmem_cache *s, unsigned long flags)
 {
-	s->name = name;
-	s->ctor = ctor;
-	s->object_size = size;
-	s->align = align;
-	s->flags = kmem_cache_flags(size, flags, name, ctor);
+	s->flags = kmem_cache_flags(s->size, flags, s->name, s->ctor);
 	s->reserved = 0;
 
 	if (need_reserve_slab_rcu && (s->flags & SLAB_DESTROY_BY_RCU))
@@ -3115,7 +3108,7 @@ error:
 	if (flags & SLAB_PANIC)
 		panic("Cannot create slab %s size=%lu realsize=%u "
 			"order=%u offset=%u flags=%lx\n",
-			s->name, (unsigned long)size, s->size, oo_order(s->oo),
+			s->name, (unsigned long)s->size, s->size, oo_order(s->oo),
 			s->offset, flags);
 	return -EINVAL;
 }
@@ -3261,12 +3254,15 @@ static struct kmem_cache *__init create_
 
 	s = kmem_cache_zalloc(kmem_cache, GFP_NOWAIT);
 
+	s->name = name;
+	s->size = s->object_size = size;
+	s->align = ARCH_KMALLOC_MINALIGN;
+
 	/*
 	 * This function is called with IRQs disabled during early-boot on
 	 * single CPU so there's no need to take slab_mutex here.
 	 */
-	if (kmem_cache_open(s, name, size, ARCH_KMALLOC_MINALIGN,
-								flags, NULL))
+	if (kmem_cache_open(s, flags))
 		goto panic;
 
 	list_add(&s->list, &slab_caches);
@@ -3719,9 +3715,10 @@ void __init kmem_cache_init(void)
 	 */
 	kmem_cache_node = (void *)kmem_cache + kmalloc_size;
 
-	kmem_cache_open(kmem_cache_node, "kmem_cache_node",
-		sizeof(struct kmem_cache_node),
-		0, SLAB_HWCACHE_ALIGN | SLAB_PANIC, NULL);
+	kmem_cache_node->name = "kmem_cache_node";
+	kmem_cache_node->size = kmem_cache_node->object_size =
+		sizeof(struct kmem_cache_node);
+	kmem_cache_open(kmem_cache_node, SLAB_HWCACHE_ALIGN | SLAB_PANIC);
 
 	hotplug_memory_notifier(slab_memory_callback, SLAB_CALLBACK_PRI);
 
@@ -3729,8 +3726,10 @@ void __init kmem_cache_init(void)
 	slab_state = PARTIAL;
 
 	temp_kmem_cache = kmem_cache;
-	kmem_cache_open(kmem_cache, "kmem_cache", kmem_size,
-		0, SLAB_HWCACHE_ALIGN | SLAB_PANIC, NULL);
+	kmem_cache->name = "kmem_cache";
+	kmem_cache->size = kmem_cache->object_size = kmem_size;
+	kmem_cache_open(kmem_cache, SLAB_HWCACHE_ALIGN | SLAB_PANIC);
+
 	kmem_cache = kmem_cache_alloc(kmem_cache, GFP_NOWAIT);
 	memcpy(kmem_cache, temp_kmem_cache, kmem_size);
 
@@ -3943,11 +3942,9 @@ struct kmem_cache *__kmem_cache_alias(co
 	return s;
 }
 
-int __kmem_cache_create(struct kmem_cache *s,
-		const char *name, size_t size,
-		size_t align, unsigned long flags, void (*ctor)(void *))
+int __kmem_cache_create(struct kmem_cache *s, unsigned long flags)
 {
-	return kmem_cache_open(s, name, size, align, flags, ctor);
+	return kmem_cache_open(s, flags);
 }
 
 #ifdef CONFIG_SMP

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: C13 [01/14] slub: Add debugging to verify correct cache use on kmem_cache_free()
  2012-08-24 16:17 ` C13 [01/14] slub: Add debugging to verify correct cache use on kmem_cache_free() Christoph Lameter
@ 2012-09-03 14:26   ` Glauber Costa
  0 siblings, 0 replies; 32+ messages in thread
From: Glauber Costa @ 2012-09-03 14:26 UTC (permalink / raw)
  To: Christoph Lameter; +Cc: Pekka Enberg, Joonsoo Kim, linux-mm, David Rientjes

On 08/24/2012 08:17 PM, Christoph Lameter wrote:
> Add additional debugging to check that the objects is actually from the cache
> the caller claims. Doing so currently trips up some other debugging code. It
> takes a lot to infer from that what was happening.
> 
> V2: Only warn once.
> 
> Signed-off-by: Christoph Lameter <cl@linux.com>

I am fine with it.

Reviewed-by: Glauber Costa <glommer@parallels.com>
> ---
>  mm/slub.c |    7 +++++++
>  1 file changed, 7 insertions(+)
> 
> diff --git a/mm/slub.c b/mm/slub.c
> index c67bd0a..00f8557 100644
> --- a/mm/slub.c
> +++ b/mm/slub.c
> @@ -2614,6 +2614,13 @@ void kmem_cache_free(struct kmem_cache *s, void *x)
>  
>  	page = virt_to_head_page(x);
>  
> +	if (kmem_cache_debug(s) && page->slab != s) {
> +		printk("kmem_cache_free: Wrong slab cache. %s but object"
> +			" is from  %s\n", page->slab->name, s->name);
> +		WARN_ON_ONCE(1);
> +		return;
> +	}
> +
>  	slab_free(s, page, x, _RET_IP_);
>  
>  	trace_kmem_cache_free(_RET_IP_, x);
> 

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: C13 [02/14] slub: Use kmem_cache for the kmem_cache structure
  2012-08-24 16:17 ` C13 [02/14] slub: Use kmem_cache for the kmem_cache structure Christoph Lameter
@ 2012-09-03 14:27   ` Glauber Costa
  0 siblings, 0 replies; 32+ messages in thread
From: Glauber Costa @ 2012-09-03 14:27 UTC (permalink / raw)
  To: Christoph Lameter; +Cc: Pekka Enberg, Joonsoo Kim, David Rientjes, linux-mm

On 08/24/2012 08:17 PM, Christoph Lameter wrote:
> Do not use kmalloc() but kmem_cache_alloc() for the allocation
> of the kmem_cache structures in slub.
> 
> Acked-by: David Rientjes <rientjes@google.com>
> Signed-off-by: Christoph Lameter <cl@linux.com>

Reviewed-by: Glauber Costa <glommer@parallels.com>

> ---
>  mm/slub.c |    8 ++++----
>  1 file changed, 4 insertions(+), 4 deletions(-)
> 
> diff --git a/mm/slub.c b/mm/slub.c
> index 00f8557..e0b9403 100644
> --- a/mm/slub.c
> +++ b/mm/slub.c
> @@ -213,7 +213,7 @@ static inline int sysfs_slab_alias(struct kmem_cache *s, const char *p)
>  static inline void sysfs_slab_remove(struct kmem_cache *s)
>  {
>  	kfree(s->name);
> -	kfree(s);
> +	kmem_cache_free(kmem_cache, s);
>  }
>  
>  #endif
> @@ -3969,7 +3969,7 @@ struct kmem_cache *__kmem_cache_create(const char *name, size_t size,
>  	if (!n)
>  		return NULL;
>  
> -	s = kmalloc(kmem_size, GFP_KERNEL);
> +	s = kmem_cache_alloc(kmem_cache, GFP_KERNEL);
>  	if (s) {
>  		if (kmem_cache_open(s, n,
>  				size, align, flags, ctor)) {
> @@ -3986,7 +3986,7 @@ struct kmem_cache *__kmem_cache_create(const char *name, size_t size,
>  			list_del(&s->list);
>  			kmem_cache_close(s);
>  		}
> -		kfree(s);
> +		kmem_cache_free(kmem_cache, s);
>  	}
>  	kfree(n);
>  	return NULL;
> @@ -5224,7 +5224,7 @@ static void kmem_cache_release(struct kobject *kobj)
>  	struct kmem_cache *s = to_slab(kobj);
>  
>  	kfree(s->name);
> -	kfree(s);
> +	kmem_cache_free(kmem_cache, s);
>  }
>  
>  static const struct sysfs_ops slab_sysfs_ops = {
> 

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: C13 [03/14] Improve error handling in kmem_cache_create
  2012-08-24 16:17 ` C13 [03/14] Improve error handling in kmem_cache_create Christoph Lameter
@ 2012-09-03 14:30   ` Glauber Costa
  0 siblings, 0 replies; 32+ messages in thread
From: Glauber Costa @ 2012-09-03 14:30 UTC (permalink / raw)
  To: Christoph Lameter; +Cc: Pekka Enberg, Joonsoo Kim, David Rientjes, linux-mm

On 08/24/2012 08:17 PM, Christoph Lameter wrote:
> Instead of using s == NULL use an errorcode. This allows much more
> detailed diagnostics as to what went wrong. As we add more functionality
> from the slab allocators to the common kmem_cache_create() function we will
> also add more error conditions.
> 
> Print the error code during the panic as well as in a warning if the module
> can handle failure. The API for kmem_cache_create() currently does not allow
> the returning of an error code. Return NULL but log the cause of the problem
> in the syslog.
> 
> Acked-by: David Rientjes <rientjes@google.com>
> Signed-off-by: Christoph Lameter <cl@linux.com>

Reviewed-by: Glauber Costa <glommer@parallels.com>

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: C13 [05/14] Extract a common function for kmem_cache_destroy
  2012-08-24 16:10 ` C13 [05/14] Extract a common function for kmem_cache_destroy Christoph Lameter
@ 2012-09-03 14:41   ` Glauber Costa
  2012-09-03 15:26   ` Glauber Costa
  1 sibling, 0 replies; 32+ messages in thread
From: Glauber Costa @ 2012-09-03 14:41 UTC (permalink / raw)
  To: Christoph Lameter; +Cc: Pekka Enberg, Joonsoo Kim, linux-mm, David Rientjes

On 08/24/2012 08:10 PM, Christoph Lameter wrote:
> kmem_cache_destroy does basically the same in all allocators.
> 
> Extract common code which is easy since we already have common mutex handling.
> 
> V1-V2:
> 	- Move percpu freeing to later so that we fail cleaner if
> 		objects are left in the cache [JoonSoo Kim]
> 
> Signed-off-by: Christoph Lameter <cl@linux.com>

This code is subtle and could benefit from other reviewers. From my
side, I reviewed it, tested it, and couldn't find any obvious problems.

Reviewed-by: Glauber Costa <glommer@parallels.com>

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: C13 [07/14] Move freeing of kmem_cache structure to common code
  2012-08-24 16:12 ` C13 [07/14] Move freeing of kmem_cache structure to common code Christoph Lameter
@ 2012-09-03 14:51   ` Glauber Costa
  0 siblings, 0 replies; 32+ messages in thread
From: Glauber Costa @ 2012-09-03 14:51 UTC (permalink / raw)
  To: Christoph Lameter; +Cc: Pekka Enberg, Joonsoo Kim, linux-mm, David Rientjes

On 08/24/2012 08:12 PM, Christoph Lameter wrote:
> The freeing action is basically the same in all slab allocators.
> Move to the common kmem_cache_destroy() function.
> 
> Reviewed-by: Joonsoo Kim <js1304@gmail.com>
> Signed-off-by: Christoph Lameter <cl@linux.com>

For slab & slub, it seems trivial. Then:

Reviewed-by: Glauber Costa <glommer@parallels.com>

I should point out that the code movement in the slob is not equivalent.
First, we'll not be always calling kmemleak_free(). We'll only do it
when SLAB_NOLEAKTRACE is not set. This actually seem even safer than
before, but it is worth mentioning.

Also, we'll be freeing here under a rcu call, which didn't happen
before. To my eyes, this seems that it will only potentially take more
time to complete, without any context problems. But slob reviewers are
appreciated.

> ---
>  mm/slab.c        |    1 -
>  mm/slab_common.c |    1 +
>  mm/slob.c        |    2 --
>  mm/slub.c        |    2 --
>  4 files changed, 1 insertion(+), 5 deletions(-)
> 
> diff --git a/mm/slab.c b/mm/slab.c
> index 6365632..814cfc9 100644
> --- a/mm/slab.c
> +++ b/mm/slab.c
> @@ -2215,7 +2215,6 @@ void __kmem_cache_destroy(struct kmem_cache *cachep)
>  			kfree(l3);
>  		}
>  	}
> -	kmem_cache_free(kmem_cache, cachep);
>  }
>  
>  
> diff --git a/mm/slab_common.c b/mm/slab_common.c
> index 850c497..3e3c403 100644
> --- a/mm/slab_common.c
> +++ b/mm/slab_common.c
> @@ -154,6 +154,7 @@ void kmem_cache_destroy(struct kmem_cache *s)
>  				rcu_barrier();
>  
>  			__kmem_cache_destroy(s);
> +			kmem_cache_free(kmem_cache, s);
>  		} else {
>  			list_add(&s->list, &slab_caches);
>  			printk(KERN_ERR "kmem_cache_destroy %s: Slab cache still has objects\n",
> diff --git a/mm/slob.c b/mm/slob.c
> index 7d272c3..cb4ab96 100644
> --- a/mm/slob.c
> +++ b/mm/slob.c
> @@ -540,8 +540,6 @@ struct kmem_cache *__kmem_cache_create(const char *name, size_t size,
>  
>  void __kmem_cache_destroy(struct kmem_cache *c)
>  {
> -	kmemleak_free(c);
> -	slob_free(c, sizeof(struct kmem_cache));
>  }
>  
>  void *kmem_cache_alloc_node(struct kmem_cache *c, gfp_t flags, int node)
> diff --git a/mm/slub.c b/mm/slub.c
> index 607fee5..8da785a 100644
> --- a/mm/slub.c
> +++ b/mm/slub.c
> @@ -213,7 +213,6 @@ static inline int sysfs_slab_alias(struct kmem_cache *s, const char *p)
>  static inline void sysfs_slab_remove(struct kmem_cache *s)
>  {
>  	kfree(s->name);
> -	kmem_cache_free(kmem_cache, s);
>  }
>  
>  #endif
> @@ -5206,7 +5205,6 @@ static void kmem_cache_release(struct kobject *kobj)
>  	struct kmem_cache *s = to_slab(kobj);
>  
>  	kfree(s->name);
> -	kmem_cache_free(kmem_cache, s);
>  }
>  
>  static const struct sysfs_ops slab_sysfs_ops = {
> 

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: C13 [08/14] Get rid of __kmem_cache_destroy
  2012-08-24 16:12 ` C13 [08/14] Get rid of __kmem_cache_destroy Christoph Lameter
@ 2012-09-03 14:58   ` Glauber Costa
  2012-09-04 22:39     ` Christoph Lameter
  0 siblings, 1 reply; 32+ messages in thread
From: Glauber Costa @ 2012-09-03 14:58 UTC (permalink / raw)
  To: Christoph Lameter; +Cc: Pekka Enberg, Joonsoo Kim, linux-mm, David Rientjes

On 08/24/2012 08:12 PM, Christoph Lameter wrote:
> What is done there can be done in __kmem_cache_shutdown.
> 
> This affects RCU handling somewhat. On rcu free all slab allocators
> do not refer to other management structures than the kmem_cache structure.
> Therefore these other structures can be freed before the rcu deferred
> free to the page allocator occurs.
> 
> Reviewed-by: Joonsoo Kim <js1304@gmail.com>
> Signed-off-by: Christoph Lameter <cl@linux.com>

Here is the code for that in slab_common.c:

    if (!__kmem_cache_shutdown(s)) {
        if (s->flags & SLAB_DESTROY_BY_RCU)
            rcu_barrier();

        __kmem_cache_destroy(s);
    } ...

All that code that used to belong in __kmem_cache_destroy(), will not be
executed in kmem_cache_shutdown() without an rcu_barrier.

You need at least Paul's ack here to guarantee it is safe, but I believe
it is not. Take a look for instance at 7ed9f7e5db5, which describes a
subtle bug arising from such a situation.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: C13 [09/14] Move duping of slab name to slab_common.c
  2012-08-24 16:17 ` C13 [09/14] Move duping of slab name to slab_common.c Christoph Lameter
@ 2012-09-03 15:02   ` Glauber Costa
  0 siblings, 0 replies; 32+ messages in thread
From: Glauber Costa @ 2012-09-03 15:02 UTC (permalink / raw)
  To: Christoph Lameter; +Cc: Pekka Enberg, Joonsoo Kim, linux-mm, David Rientjes

On 08/24/2012 08:17 PM, Christoph Lameter wrote:
> Duping of the slabname has to be done by each slab. Moving this code
> to slab_common avoids duplicate implementations.
> 
> With this patch we have common string handling for all slab allocators.
> Strings passed to kmem_cache_create() are copied internally. Subsystems
> can create temporary strings to create slab caches.
> 
> Slabs allocated in early states of bootstrap will never be freed (and those
> can never be freed since they are essential to slab allocator operations).
> During bootstrap we therefore do not have to worry about duping names.
> 
> Signed-off-by: Christoph Lameter <cl@linux.com>

This version fixes all the problems I've raised before.

I've also boot-tested and applied my previous repeated
kmem_cache_destroy() test and it seems to survive well.

Reviewed-by: Glauber Costa <glommer@parallels.com>

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: C13 [11/14] Move sysfs_slab_add to common
  2012-08-24 16:17 ` C13 [11/14] Move sysfs_slab_add to common Christoph Lameter
@ 2012-09-03 15:09   ` Glauber Costa
  0 siblings, 0 replies; 32+ messages in thread
From: Glauber Costa @ 2012-09-03 15:09 UTC (permalink / raw)
  To: Christoph Lameter; +Cc: Pekka Enberg, Joonsoo Kim, linux-mm, David Rientjes

On 08/24/2012 08:17 PM, Christoph Lameter wrote:
> Simplify locking by moving the slab_add_sysfs after all locks
> have been dropped. Eases the upcoming move to provide sysfs
> support for all allocators.
> 
> Signed-off-by: Christoph Lameter <cl@linux.com>

Makes sense.

Reviewed-by: Glauber Costa <glommer@parallels.com>

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: C13 [14/14] Move kmem_cache refcounting to common code
  2012-08-24 16:17 ` C13 [14/14] Move kmem_cache refcounting to common code Christoph Lameter
@ 2012-09-03 15:12   ` Glauber Costa
  2012-09-04 19:10     ` Christoph Lameter
  0 siblings, 1 reply; 32+ messages in thread
From: Glauber Costa @ 2012-09-03 15:12 UTC (permalink / raw)
  To: Christoph Lameter; +Cc: Pekka Enberg, Joonsoo Kim, linux-mm, David Rientjes

On 08/24/2012 08:17 PM, Christoph Lameter wrote:
> Index: linux/mm/slob.c
> ===================================================================
> --- linux.orig/mm/slob.c	2012-08-22 10:27:54.846388442 -0500
> +++ linux/mm/slob.c	2012-08-22 10:28:31.658969127 -0500
> @@ -524,8 +524,6 @@ int __kmem_cache_create(struct kmem_cach
>  	if (c->align < align)
>  		c->align = align;
>  
> -	kmemleak_alloc(c, sizeof(struct kmem_cache), 1, GFP_KERNEL);
> -	c->refcount = 1;
>  	return 0;
>  }
>  
Is the removal of kmemleak_alloc intended ?
Nothing about that is mentioned in the changelog.


--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: C13 [12/14] Move kmem_cache allocations into common code.
  2012-08-24 16:17 ` C13 [12/14] Move kmem_cache allocations into common code Christoph Lameter
@ 2012-09-03 15:24   ` Glauber Costa
  0 siblings, 0 replies; 32+ messages in thread
From: Glauber Costa @ 2012-09-03 15:24 UTC (permalink / raw)
  To: Christoph Lameter; +Cc: Pekka Enberg, Joonsoo Kim, linux-mm, David Rientjes

On 08/24/2012 08:17 PM, Christoph Lameter wrote:
> Shift the allocations to common code. That way the allocation
> and freeing of the kmem_cache structures is handled by common code.
> 
> V2->V3: Use GFP_KERNEL instead of GFP_NOWAIT (JoonSoo Kim).
> V1->V2: Use the return code from setup_cpucache() in slab instead of returning -ENOSPC
> 
> 
> Signed-off-by: Christoph Lameter <cl@linux.com>

Reviewed-by: Glauber Costa <glommer@parallels.com>


--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: C13 [05/14] Extract a common function for kmem_cache_destroy
  2012-08-24 16:10 ` C13 [05/14] Extract a common function for kmem_cache_destroy Christoph Lameter
  2012-09-03 14:41   ` Glauber Costa
@ 2012-09-03 15:26   ` Glauber Costa
  2012-09-04 22:58     ` Christoph Lameter
  1 sibling, 1 reply; 32+ messages in thread
From: Glauber Costa @ 2012-09-03 15:26 UTC (permalink / raw)
  To: Christoph Lameter; +Cc: Pekka Enberg, Joonsoo Kim, linux-mm, David Rientjes

On 08/24/2012 08:10 PM, Christoph Lameter wrote:
> kmem_cache_destroy does basically the same in all allocators.
> 
> Extract common code which is easy since we already have common mutex handling.
> 
> V1-V2:
> 	- Move percpu freeing to later so that we fail cleaner if
> 		objects are left in the cache [JoonSoo Kim]
> 
> Signed-off-by: Christoph Lameter <cl@linux.com>

Fails to build for the slab. Error is pretty much self-explanatory:

  CC      mm/slab.o
mm/slab.c: In function ‘slab_destroy_debugcheck’:
mm/slab.c:2157:5: error: implicit declaration of function ‘slab_error’
[-Werror=implicit-function-declaration]

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: C13 [13/14] Shrink __kmem_cache_create() parameter lists
  2012-08-24 16:17 ` C13 [13/14] Shrink __kmem_cache_create() parameter lists Christoph Lameter
@ 2012-09-03 15:33   ` Glauber Costa
  2012-09-03 15:35     ` Glauber Costa
  0 siblings, 1 reply; 32+ messages in thread
From: Glauber Costa @ 2012-09-03 15:33 UTC (permalink / raw)
  To: Christoph Lameter; +Cc: Pekka Enberg, Joonsoo Kim, linux-mm, David Rientjes

On 08/24/2012 08:17 PM, Christoph Lameter wrote:
> -__kmem_cache_create (struct kmem_cache *cachep, const char *name, size_t size, size_t align,
> -	unsigned long flags, void (*ctor)(void *))
> +__kmem_cache_create (struct kmem_cache *cachep, unsigned long flags)
>  {
>  	size_t left_over, slab_size, ralign;
>  	gfp_t gfp;
> @@ -2385,9 +2383,9 @@ __kmem_cache_create (struct kmem_cache *
>  	 * unaligned accesses for some archs when redzoning is used, and makes
>  	 * sure any on-slab bufctl's are also correctly aligned.
>  	 */
> -	if (size & (BYTES_PER_WORD - 1)) {
> -		size += (BYTES_PER_WORD - 1);
> -		size &= ~(BYTES_PER_WORD - 1);
> +	if (cachep->size & (BYTES_PER_WORD - 1)) {
> +		cachep->size += (BYTES_PER_WORD - 1);
> +		cachep->size &= ~(BYTES_PER_WORD - 1);
>  	}

There are still one reference to "size" inside this function that will
break the build. This reference is enclosed inside CONFIG_DEBUG.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: C13 [13/14] Shrink __kmem_cache_create() parameter lists
  2012-09-03 15:33   ` Glauber Costa
@ 2012-09-03 15:35     ` Glauber Costa
  2012-09-04 22:48       ` Christoph Lameter
  0 siblings, 1 reply; 32+ messages in thread
From: Glauber Costa @ 2012-09-03 15:35 UTC (permalink / raw)
  To: Christoph Lameter; +Cc: Pekka Enberg, Joonsoo Kim, linux-mm, David Rientjes

On 09/03/2012 07:33 PM, Glauber Costa wrote:
> On 08/24/2012 08:17 PM, Christoph Lameter wrote:
>> -__kmem_cache_create (struct kmem_cache *cachep, const char *name, size_t size, size_t align,
>> -	unsigned long flags, void (*ctor)(void *))
>> +__kmem_cache_create (struct kmem_cache *cachep, unsigned long flags)
>>  {
>>  	size_t left_over, slab_size, ralign;
>>  	gfp_t gfp;
>> @@ -2385,9 +2383,9 @@ __kmem_cache_create (struct kmem_cache *
>>  	 * unaligned accesses for some archs when redzoning is used, and makes
>>  	 * sure any on-slab bufctl's are also correctly aligned.
>>  	 */
>> -	if (size & (BYTES_PER_WORD - 1)) {
>> -		size += (BYTES_PER_WORD - 1);
>> -		size &= ~(BYTES_PER_WORD - 1);
>> +	if (cachep->size & (BYTES_PER_WORD - 1)) {
>> +		cachep->size += (BYTES_PER_WORD - 1);
>> +		cachep->size &= ~(BYTES_PER_WORD - 1);
>>  	}
> 
> There are still one reference to "size" inside this function that will
> break the build. This reference is enclosed inside CONFIG_DEBUG.
> 

Actually, Christoph, it would be a lot cleaner if you would just do

   size_t size = cachep->size;

in the beginning of this function. The resulting patch size would be a
lot smaller since you don't need to patch the references, and would
avoid mistakes like that altogether.


--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: C13 [14/14] Move kmem_cache refcounting to common code
  2012-09-03 15:12   ` Glauber Costa
@ 2012-09-04 19:10     ` Christoph Lameter
  0 siblings, 0 replies; 32+ messages in thread
From: Christoph Lameter @ 2012-09-04 19:10 UTC (permalink / raw)
  To: Glauber Costa; +Cc: Pekka Enberg, Joonsoo Kim, linux-mm, David Rientjes


On Mon, 3 Sep 2012, Glauber Costa wrote:

> On 08/24/2012 08:17 PM, Christoph Lameter wrote:
> > Index: linux/mm/slob.c
> > ===================================================================
> > --- linux.orig/mm/slob.c	2012-08-22 10:27:54.846388442 -0500
> > +++ linux/mm/slob.c	2012-08-22 10:28:31.658969127 -0500
> > @@ -524,8 +524,6 @@ int __kmem_cache_create(struct kmem_cach
> >  	if (c->align < align)
> >  		c->align = align;
> >
> > -	kmemleak_alloc(c, sizeof(struct kmem_cache), 1, GFP_KERNEL);
> > -	c->refcount = 1;
> >  	return 0;
> >  }
> >
> Is the removal of kmemleak_alloc intended ?
> Nothing about that is mentioned in the changelog.

The statement should have been removed earlier. Checking is done when
allocating the object.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: C13 [08/14] Get rid of __kmem_cache_destroy
  2012-09-03 14:58   ` Glauber Costa
@ 2012-09-04 22:39     ` Christoph Lameter
  2012-09-05  8:25       ` Glauber Costa
  0 siblings, 1 reply; 32+ messages in thread
From: Christoph Lameter @ 2012-09-04 22:39 UTC (permalink / raw)
  To: Glauber Costa
  Cc: Pekka Enberg, Joonsoo Kim, Paul E. McKenney, linux-mm, David Rientjes

On Mon, 3 Sep 2012, Glauber Costa wrote:

> Here is the code for that in slab_common.c:
>
>     if (!__kmem_cache_shutdown(s)) {
>         if (s->flags & SLAB_DESTROY_BY_RCU)
>             rcu_barrier();
>
>         __kmem_cache_destroy(s);
>     } ...
>
> All that code that used to belong in __kmem_cache_destroy(), will not be
> executed in kmem_cache_shutdown() without an rcu_barrier.

But that allocator specific code in __kmem_cache_destroy will not free the
kmem_cache structure. That is the only important thing to be aware of.
Only deferred frees of slab pages may still be in progress at this time
until the close of the RCU period. These deferred freeing actions do not
refer to anything but the kmem_cache structure. Therefore the rest can be
freed before the period is over. And we check that the rest can be freed.
Should there be a leftover at that point then f.e.
free_partial() will issue a warning.

kmem_cache_destroy() can only be called after all objects have been freed
and it checks that this actually was done. "Have been freed" means in the
context of an SLAB_DESTROY_BY_RCU slab that the rcu delayed frees for the
individual objects are complete. During kmem_cache_destroy() only slab
pages that contain no objects are freed back to the page allocator. Those
will be also freed in a deferred way at kmem_cache_destroy. Hmmm.... we
could simply delete the SLAB_DESTROY_BY_RCU flag and free the objects
without obeying the rcu period since no objects should be allocated at
that point.

> You need at least Paul's ack here to guarantee it is safe, but I believe
> it is not. Take a look for instance at 7ed9f7e5db5, which describes a
> subtle bug arising from such a situation.

The commit that you referred to ensures that kmem_cache is not freed
before the rcu period is over. This patch does not change that guarantee.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: C13 [13/14] Shrink __kmem_cache_create() parameter lists
  2012-09-03 15:35     ` Glauber Costa
@ 2012-09-04 22:48       ` Christoph Lameter
  0 siblings, 0 replies; 32+ messages in thread
From: Christoph Lameter @ 2012-09-04 22:48 UTC (permalink / raw)
  To: Glauber Costa; +Cc: Pekka Enberg, Joonsoo Kim, linux-mm, David Rientjes

On Mon, 3 Sep 2012, Glauber Costa wrote:

> Actually, Christoph, it would be a lot cleaner if you would just do
>
>    size_t size = cachep->size;
>
> in the beginning of this function. The resulting patch size would be a
> lot smaller since you don't need to patch the references, and would
> avoid mistakes like that altogether.

Ok. Done.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: C13 [05/14] Extract a common function for kmem_cache_destroy
  2012-09-03 15:26   ` Glauber Costa
@ 2012-09-04 22:58     ` Christoph Lameter
  0 siblings, 0 replies; 32+ messages in thread
From: Christoph Lameter @ 2012-09-04 22:58 UTC (permalink / raw)
  To: Glauber Costa; +Cc: Pekka Enberg, Joonsoo Kim, linux-mm, David Rientjes

[-- Attachment #1: Type: TEXT/PLAIN, Size: 771 bytes --]

On Mon, 3 Sep 2012, Glauber Costa wrote:

> On 08/24/2012 08:10 PM, Christoph Lameter wrote:
> > kmem_cache_destroy does basically the same in all allocators.
> >
> > Extract common code which is easy since we already have common mutex handling.
> >
> > V1-V2:
> > 	- Move percpu freeing to later so that we fail cleaner if
> > 		objects are left in the cache [JoonSoo Kim]
> >
> > Signed-off-by: Christoph Lameter <cl@linux.com>
>
> Fails to build for the slab. Error is pretty much self-explanatory:
>
>   CC      mm/slab.o
> mm/slab.c: In function i? 1/2 slab_destroy_debugchecki? 1/2 :
> mm/slab.c:2157:5: error: implicit declaration of function i? 1/2 slab_errori? 1/2 
> [-Werror=implicit-function-declaration]

Ok. We need to keep the slab_error function for now.

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: C13 [08/14] Get rid of __kmem_cache_destroy
  2012-09-04 22:39     ` Christoph Lameter
@ 2012-09-05  8:25       ` Glauber Costa
  0 siblings, 0 replies; 32+ messages in thread
From: Glauber Costa @ 2012-09-05  8:25 UTC (permalink / raw)
  To: Christoph Lameter
  Cc: Pekka Enberg, Joonsoo Kim, Paul E. McKenney, linux-mm, David Rientjes

On 09/05/2012 02:39 AM, Christoph Lameter wrote:
> On Mon, 3 Sep 2012, Glauber Costa wrote:
> 
>> Here is the code for that in slab_common.c:
>>
>>     if (!__kmem_cache_shutdown(s)) {
>>         if (s->flags & SLAB_DESTROY_BY_RCU)
>>             rcu_barrier();
>>
>>         __kmem_cache_destroy(s);
>>     } ...
>>
>> All that code that used to belong in __kmem_cache_destroy(), will not be
>> executed in kmem_cache_shutdown() without an rcu_barrier.
> 
> But that allocator specific code in __kmem_cache_destroy will not free the
> kmem_cache structure. That is the only important thing to be aware of.
> Only deferred frees of slab pages may still be in progress at this time
> until the close of the RCU period. These deferred freeing actions do not
> refer to anything but the kmem_cache structure. Therefore the rest can be
> freed before the period is over. And we check that the rest can be freed.
> Should there be a leftover at that point then f.e.
> free_partial() will issue a warning.
> 

Ok. That sounds reasonable.
(not sure if correct, but reasonable)

> kmem_cache_destroy() can only be called after all objects have been freed
> and it checks that this actually was done. "Have been freed" means in the
> context of an SLAB_DESTROY_BY_RCU slab that the rcu delayed frees for the
> individual objects are complete. During kmem_cache_destroy() only slab
> pages that contain no objects are freed back to the page allocator. Those
> will be also freed in a deferred way at kmem_cache_destroy. Hmmm.... we
> could simply delete the SLAB_DESTROY_BY_RCU flag and free the objects
> without obeying the rcu period since no objects should be allocated at
> that point.
> 
>> You need at least Paul's ack here to guarantee it is safe, but I believe
>> it is not. Take a look for instance at 7ed9f7e5db5, which describes a
>> subtle bug arising from such a situation.
> 
> The commit that you referred to ensures that kmem_cache is not freed
> before the rcu period is over. This patch does not change that guarantee.
> 
> --
> To unsubscribe, send a message with 'unsubscribe linux-mm' in
> the body to majordomo@kvack.org.  For more info on Linux MM,
> see: http://www.linux-mm.org/ .
> Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
> 

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 32+ messages in thread

end of thread, other threads:[~2012-09-05  8:28 UTC | newest]

Thread overview: 32+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <20120824160903.168122683@linux.com>
2012-08-24 16:10 ` C13 [05/14] Extract a common function for kmem_cache_destroy Christoph Lameter
2012-09-03 14:41   ` Glauber Costa
2012-09-03 15:26   ` Glauber Costa
2012-09-04 22:58     ` Christoph Lameter
2012-08-24 16:12 ` C13 [08/14] Get rid of __kmem_cache_destroy Christoph Lameter
2012-09-03 14:58   ` Glauber Costa
2012-09-04 22:39     ` Christoph Lameter
2012-09-05  8:25       ` Glauber Costa
2012-08-24 16:12 ` C13 [07/14] Move freeing of kmem_cache structure to common code Christoph Lameter
2012-09-03 14:51   ` Glauber Costa
2012-08-24 16:17 ` C13 [03/14] Improve error handling in kmem_cache_create Christoph Lameter
2012-09-03 14:30   ` Glauber Costa
2012-08-24 16:17 ` C13 [12/14] Move kmem_cache allocations into common code Christoph Lameter
2012-09-03 15:24   ` Glauber Costa
2012-08-24 16:17 ` C13 [11/14] Move sysfs_slab_add to common Christoph Lameter
2012-09-03 15:09   ` Glauber Costa
2012-08-24 16:17 ` C13 [04/14] Move list_add() to slab_common.c Christoph Lameter
2012-08-24 16:17 ` C13 [06/14] Always use the name "kmem_cache" for the slab cache with the kmem_cache structure Christoph Lameter
2012-08-24 16:17 ` C13 [10/14] Do slab aliasing call from common code Christoph Lameter
2012-08-24 16:17 ` C13 [01/14] slub: Add debugging to verify correct cache use on kmem_cache_free() Christoph Lameter
2012-09-03 14:26   ` Glauber Costa
2012-08-24 16:17 ` C13 [09/14] Move duping of slab name to slab_common.c Christoph Lameter
2012-09-03 15:02   ` Glauber Costa
2012-08-24 16:17 ` C13 [02/14] slub: Use kmem_cache for the kmem_cache structure Christoph Lameter
2012-09-03 14:27   ` Glauber Costa
2012-08-24 16:17 ` C13 [13/14] Shrink __kmem_cache_create() parameter lists Christoph Lameter
2012-09-03 15:33   ` Glauber Costa
2012-09-03 15:35     ` Glauber Costa
2012-09-04 22:48       ` Christoph Lameter
2012-08-24 16:17 ` C13 [14/14] Move kmem_cache refcounting to common code Christoph Lameter
2012-09-03 15:12   ` Glauber Costa
2012-09-04 19:10     ` Christoph Lameter

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.