summaryrefslogtreecommitdiff
path: root/mm/slub.c
diff options
context:
space:
mode:
authorChristoph Lameter <clameter@sgi.com>2007-05-31 00:40:51 -0700
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-05-31 07:58:14 -0700
commit8ffa68755a0eddf3baeecd0e7612a5106cf2db23 (patch)
tree8c0fa3d0adda180687e7e35d49f978eae3284ddd /mm/slub.c
parentfbe9c9612930e0604dc99ef2da7e063fa3278817 (diff)
downloadlwn-8ffa68755a0eddf3baeecd0e7612a5106cf2db23.tar.gz
lwn-8ffa68755a0eddf3baeecd0e7612a5106cf2db23.zip
SLUB: Fix NUMA / SYSFS bootstrap issue
We need this patch in ASAP. Patch fixes the mysterious hang that remained on some particular configurations with lockdep on after the first fix that moved the #idef CONFIG_SLUB_DEBUG to the right location. See http://marc.info/?t=117963072300001&r=1&w=2 The kmem_cache_node cache is very special because it is needed for NUMA bootstrap. Under certain conditions (like for example if lockdep is enabled and significantly increases the size of spinlock_t) the structure may become exactly the size as one of the larger caches in the kmalloc array. That early during bootstrap we cannot perform merging properly. The unique id for the kmem_cache_node cache will match one of the kmalloc array. Sysfs will complain about a duplicate directory entry. All of this occurs while the console is not yet fully operational. Thus boot may appear to be silently failing. The kmem_cache_node cache is very special. During early boostrap the main allocation function is not operational yet and so we have to run our own small special alloc function during early boot. It is also special in that it is never freed. We really do not want any merging on that cache. Set the refcount -1 and forbid merging of slabs that have a negative refcount. Signed-off-by: Christoph Lameter <clameter@sgi.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/slub.c')
-rw-r--r--mm/slub.c7
1 files changed, 7 insertions, 0 deletions
diff --git a/mm/slub.c b/mm/slub.c
index 3e5aefcb4075..238c5a6ee896 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -2435,6 +2435,7 @@ void __init kmem_cache_init(void)
*/
create_kmalloc_cache(&kmalloc_caches[0], "kmem_cache_node",
sizeof(struct kmem_cache_node), GFP_KERNEL);
+ kmalloc_caches[0].refcount = -1;
#endif
/* Able to allocate the per node structures */
@@ -2482,6 +2483,12 @@ static int slab_unmergeable(struct kmem_cache *s)
if (s->ctor)
return 1;
+ /*
+ * We may have set a slab to be unmergeable during bootstrap.
+ */
+ if (s->refcount < 0)
+ return 1;
+
return 0;
}