5c56c64
Bugzilla: 1031086
5c56c64
Upstream-status: 3.12
5c56c64
5c56c64
From cd8fa0170867ce6e6e2d7edba1dc1a0b87485854 Mon Sep 17 00:00:00 2001
5c56c64
From: Christoph Lameter <cl@linux.com>
5c56c64
Date: Sat, 21 Sep 2013 21:56:34 +0000
5c56c64
Subject: [PATCH] slab_common: Do not check for duplicate slab names
5c56c64
5c56c64
SLUB can alias multiple slab kmem_create_requests to one slab cache to save
5c56c64
memory and increase the cache hotness. As a result the name of the slab can be
5c56c64
stale. Only check the name for duplicates if we are in debug mode where we do
5c56c64
not merge multiple caches.
5c56c64
5c56c64
This fixes the following problem reported by Jonathan Brassow:
5c56c64
5c56c64
  The problem with kmem_cache* is this:
5c56c64
5c56c64
  *) Assume CONFIG_SLUB is set
5c56c64
  1) kmem_cache_create(name="foo-a")
5c56c64
  - creates new kmem_cache structure
5c56c64
  2) kmem_cache_create(name="foo-b")
5c56c64
  - If identical cache characteristics, it will be merged with the previously
5c56c64
    created cache associated with "foo-a".  The cache's refcount will be
5c56c64
    incremented and an alias will be created via sysfs_slab_alias().
5c56c64
  3) kmem_cache_destroy(<ptr>)
5c56c64
  - Attempting to destroy cache associated with "foo-a", but instead the
5c56c64
    refcount is simply decremented.  I don't even think the sysfs aliases are
5c56c64
    ever removed...
5c56c64
  4) kmem_cache_create(name="foo-a")
5c56c64
  - This FAILS because kmem_cache_sanity_check colides with the existing
5c56c64
    name ("foo-a") associated with the non-removed cache.
5c56c64
5c56c64
  This is a problem for RAID (specifically dm-raid) because the name used
5c56c64
  for the kmem_cache_create is ("raid%d-%p", level, mddev).  If the cache
5c56c64
  persists for long enough, the memory address of an old mddev will be
5c56c64
  reused for a new mddev - causing an identical formulation of the cache
5c56c64
  name.  Even though kmem_cache_destory had long ago been used to delete
5c56c64
  the old cache, the merging of caches has cause the name and cache of that
5c56c64
  old instance to be preserved and causes a colision (and thus failure) in
5c56c64
  kmem_cache_create().  I see this regularly in my testing.
5c56c64
5c56c64
Reported-by: Jonathan Brassow <jbrassow@redhat.com>
5c56c64
Signed-off-by: Christoph Lameter <cl@linux.com>
5c56c64
Signed-off-by: Pekka Enberg <penberg@kernel.org>
5c56c64
---
5c56c64
 mm/slab_common.c | 2 ++
5c56c64
 1 file changed, 2 insertions(+)
5c56c64
5c56c64
diff --git a/mm/slab_common.c b/mm/slab_common.c
5c56c64
index 538bade..d434771 100644
5c56c64
--- a/mm/slab_common.c
5c56c64
+++ b/mm/slab_common.c
5c56c64
@@ -55,6 +55,7 @@ static int kmem_cache_sanity_check(struct mem_cgroup *memcg, const char *name,
5c56c64
 			continue;
5c56c64
 		}
5c56c64
 
5c56c64
+#if !defined(CONFIG_SLUB) || !defined(CONFIG_SLUB_DEBUG_ON)
5c56c64
 		/*
5c56c64
 		 * For simplicity, we won't check this in the list of memcg
5c56c64
 		 * caches. We have control over memcg naming, and if there
5c56c64
@@ -68,6 +69,7 @@ static int kmem_cache_sanity_check(struct mem_cgroup *memcg, const char *name,
5c56c64
 			s = NULL;
5c56c64
 			return -EINVAL;
5c56c64
 		}
5c56c64
+#endif
5c56c64
 	}
5c56c64
 
5c56c64
 	WARN_ON(strchr(name, ' '));	/* It confuses parsers */
5c56c64
-- 
5c56c64
1.8.3.1
5c56c64