]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - mm/slub.c
ptrace: cleanup arch_ptrace() on score
[net-next-2.6.git] / mm / slub.c
index c1add106c4317f15743e10ab26bc340cdd5f0c27..8fd5401bb0717f3cfc73141bdad1c901e92764a7 100644 (file)
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -198,7 +198,7 @@ struct track {
 
 enum track_item { TRACK_ALLOC, TRACK_FREE };
 
-#ifdef CONFIG_SLUB_DEBUG
+#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 *);
@@ -209,6 +209,7 @@ 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);
        kfree(s);
 }
 
@@ -232,11 +233,7 @@ int slab_is_available(void)
 
 static inline struct kmem_cache_node *get_node(struct kmem_cache *s, int node)
 {
-#ifdef CONFIG_NUMA
        return s->node[node];
-#else
-       return &s->local_node;
-#endif
 }
 
 /* Verify that a pointer has an address that is valid within a slab page */
@@ -493,7 +490,7 @@ static void slab_err(struct kmem_cache *s, struct page *page, char *fmt, ...)
        dump_stack();
 }
 
-static void init_object(struct kmem_cache *s, void *object, int active)
+static void init_object(struct kmem_cache *s, void *object, u8 val)
 {
        u8 *p = object;
 
@@ -503,9 +500,7 @@ static void init_object(struct kmem_cache *s, void *object, int active)
        }
 
        if (s->flags & SLAB_RED_ZONE)
-               memset(p + s->objsize,
-                       active ? SLUB_RED_ACTIVE : SLUB_RED_INACTIVE,
-                       s->inuse - s->objsize);
+               memset(p + s->objsize, val, s->inuse - s->objsize);
 }
 
 static u8 *check_bytes(u8 *start, unsigned int value, unsigned int bytes)
@@ -640,17 +635,14 @@ static int slab_pad_check(struct kmem_cache *s, struct page *page)
 }
 
 static int check_object(struct kmem_cache *s, struct page *page,
-                                       void *object, int active)
+                                       void *object, u8 val)
 {
        u8 *p = object;
        u8 *endobject = object + s->objsize;
 
        if (s->flags & SLAB_RED_ZONE) {
-               unsigned int red =
-                       active ? SLUB_RED_ACTIVE : SLUB_RED_INACTIVE;
-
                if (!check_bytes_and_report(s, page, object, "Redzone",
-                       endobject, red, s->inuse - s->objsize))
+                       endobject, val, s->inuse - s->objsize))
                        return 0;
        } else {
                if ((s->flags & SLAB_POISON) && s->objsize < s->inuse) {
@@ -660,7 +652,7 @@ static int check_object(struct kmem_cache *s, struct page *page,
        }
 
        if (s->flags & SLAB_POISON) {
-               if (!active && (s->flags & __OBJECT_POISON) &&
+               if (val != SLUB_RED_ACTIVE && (s->flags & __OBJECT_POISON) &&
                        (!check_bytes_and_report(s, page, p, "Poison", p,
                                        POISON_FREE, s->objsize - 1) ||
                         !check_bytes_and_report(s, page, p, "Poison",
@@ -672,7 +664,7 @@ static int check_object(struct kmem_cache *s, struct page *page,
                check_pad_bytes(s, page, p);
        }
 
-       if (!s->offset && active)
+       if (!s->offset && val == SLUB_RED_ACTIVE)
                /*
                 * Object and freepointer overlap. Cannot check
                 * freepointer while object is allocated.
@@ -870,7 +862,7 @@ static inline void inc_slabs_node(struct kmem_cache *s, int node, int objects)
         * dilemma by deferring the increment of the count during
         * bootstrap (see early_kmem_cache_node_alloc).
         */
-       if (!NUMA_BUILD || n) {
+       if (n) {
                atomic_long_inc(&n->nr_slabs);
                atomic_long_add(objects, &n->total_objects);
        }
@@ -890,7 +882,7 @@ static void setup_object_debug(struct kmem_cache *s, struct page *page,
        if (!(s->flags & (SLAB_STORE_USER|SLAB_RED_ZONE|__OBJECT_POISON)))
                return;
 
-       init_object(s, object, 0);
+       init_object(s, object, SLUB_RED_INACTIVE);
        init_tracking(s, object);
 }
 
@@ -910,14 +902,14 @@ static noinline int alloc_debug_processing(struct kmem_cache *s, struct page *pa
                goto bad;
        }
 
-       if (!check_object(s, page, object, 0))
+       if (!check_object(s, page, object, SLUB_RED_INACTIVE))
                goto bad;
 
        /* Success perform special debug activities for allocs */
        if (s->flags & SLAB_STORE_USER)
                set_track(s, object, TRACK_ALLOC, addr);
        trace(s, page, object, 1);
-       init_object(s, object, 1);
+       init_object(s, object, SLUB_RED_ACTIVE);
        return 1;
 
 bad:
@@ -950,7 +942,7 @@ static noinline int free_debug_processing(struct kmem_cache *s,
                goto fail;
        }
 
-       if (!check_object(s, page, object, 1))
+       if (!check_object(s, page, object, SLUB_RED_ACTIVE))
                return 0;
 
        if (unlikely(s != page->slab)) {
@@ -974,7 +966,7 @@ static noinline int free_debug_processing(struct kmem_cache *s,
        if (s->flags & SLAB_STORE_USER)
                set_track(s, object, TRACK_FREE, addr);
        trace(s, page, object, 0);
-       init_object(s, object, 0);
+       init_object(s, object, SLUB_RED_INACTIVE);
        return 1;
 
 fail:
@@ -1078,7 +1070,7 @@ static inline int free_debug_processing(struct kmem_cache *s,
 static inline int slab_pad_check(struct kmem_cache *s, struct page *page)
                        { return 1; }
 static inline int check_object(struct kmem_cache *s, struct page *page,
-                       void *object, int active) { return 1; }
+                       void *object, u8 val) { return 1; }
 static inline void add_full(struct kmem_cache_node *n, struct page *page) {}
 static inline unsigned long kmem_cache_flags(unsigned long objsize,
        unsigned long flags, const char *name,
@@ -1110,7 +1102,7 @@ static inline void slab_free_hook(struct kmem_cache *s, void *x) {}
 static inline void slab_free_hook_irq(struct kmem_cache *s,
                void *object) {}
 
-#endif
+#endif /* CONFIG_SLUB_DEBUG */
 
 /*
  * Slab allocation and freeing
@@ -1238,7 +1230,7 @@ static void __free_slab(struct kmem_cache *s, struct page *page)
                slab_pad_check(s, page);
                for_each_object(p, s, page_address(page),
                                                page->objects)
-                       check_object(s, page, p, 0);
+                       check_object(s, page, p, SLUB_RED_INACTIVE);
        }
 
        kmemcheck_free_shadow(page, compound_order(page));
@@ -1318,13 +1310,19 @@ static void add_partial(struct kmem_cache_node *n,
        spin_unlock(&n->list_lock);
 }
 
+static inline void __remove_partial(struct kmem_cache_node *n,
+                                       struct page *page)
+{
+       list_del(&page->lru);
+       n->nr_partial--;
+}
+
 static void remove_partial(struct kmem_cache *s, struct page *page)
 {
        struct kmem_cache_node *n = get_node(s, page_to_nid(page));
 
        spin_lock(&n->list_lock);
-       list_del(&page->lru);
-       n->nr_partial--;
+       __remove_partial(n, page);
        spin_unlock(&n->list_lock);
 }
 
@@ -1337,8 +1335,7 @@ static inline int lock_and_freeze_slab(struct kmem_cache_node *n,
                                                        struct page *page)
 {
        if (slab_trylock(page)) {
-               list_del(&page->lru);
-               n->nr_partial--;
+               __remove_partial(n, page);
                __SetPageSlubFrozen(page);
                return 1;
        }
@@ -1449,6 +1446,7 @@ static struct page *get_partial(struct kmem_cache *s, gfp_t flags, int node)
  * On exit the slab lock will have been dropped.
  */
 static void unfreeze_slab(struct kmem_cache *s, struct page *page, int tail)
+       __releases(bitlock)
 {
        struct kmem_cache_node *n = get_node(s, page_to_nid(page));
 
@@ -1491,6 +1489,7 @@ static void unfreeze_slab(struct kmem_cache *s, struct page *page, int tail)
  * Remove the cpu slab
  */
 static void deactivate_slab(struct kmem_cache *s, struct kmem_cache_cpu *c)
+       __releases(bitlock)
 {
        struct page *page = c->page;
        int tail = 1;
@@ -1719,7 +1718,7 @@ debug:
 
        c->page->inuse++;
        c->page->freelist = get_freepointer(s, object);
-       c->node = -1;
+       c->node = NUMA_NO_NODE;
        goto unlock_out;
 }
 
@@ -1793,7 +1792,6 @@ void *kmem_cache_alloc_node(struct kmem_cache *s, gfp_t gfpflags, int node)
        return ret;
 }
 EXPORT_SYMBOL(kmem_cache_alloc_node);
-#endif
 
 #ifdef CONFIG_TRACING
 void *kmem_cache_alloc_node_notrace(struct kmem_cache *s,
@@ -1804,6 +1802,7 @@ void *kmem_cache_alloc_node_notrace(struct kmem_cache *s,
 }
 EXPORT_SYMBOL(kmem_cache_alloc_node_notrace);
 #endif
+#endif
 
 /*
  * Slow patch handling. This may still be called frequently since objects
@@ -1896,7 +1895,7 @@ static __always_inline void slab_free(struct kmem_cache *s,
 
        slab_free_hook_irq(s, x);
 
-       if (likely(page == c->page && c->node >= 0)) {
+       if (likely(page == c->page && c->node != NUMA_NO_NODE)) {
                set_freepointer(s, object, c->freelist);
                c->freelist = object;
                stat(s, FREE_FASTPATH);
@@ -2111,7 +2110,6 @@ static inline int alloc_kmem_cache_cpus(struct kmem_cache *s)
        return s->cpu_slab != NULL;
 }
 
-#ifdef CONFIG_NUMA
 static struct kmem_cache *kmem_cache_node;
 
 /*
@@ -2147,7 +2145,7 @@ static void early_kmem_cache_node_alloc(int node)
        page->inuse++;
        kmem_cache_node->node[node] = n;
 #ifdef CONFIG_SLUB_DEBUG
-       init_object(kmem_cache_node, n, 1);
+       init_object(kmem_cache_node, n, SLUB_RED_ACTIVE);
        init_tracking(kmem_cache_node, n);
 #endif
        init_kmem_cache_node(n, kmem_cache_node);
@@ -2201,17 +2199,6 @@ static int init_kmem_cache_nodes(struct kmem_cache *s)
        }
        return 1;
 }
-#else
-static void free_kmem_cache_nodes(struct kmem_cache *s)
-{
-}
-
-static int init_kmem_cache_nodes(struct kmem_cache *s)
-{
-       init_kmem_cache_node(&s->local_node, s);
-       return 1;
-}
-#endif
 
 static void set_min_partial(struct kmem_cache *s, unsigned long min)
 {
@@ -2448,9 +2435,8 @@ static void list_slab_objects(struct kmem_cache *s, struct page *page,
 #ifdef CONFIG_SLUB_DEBUG
        void *addr = page_address(page);
        void *p;
-       long *map = kzalloc(BITS_TO_LONGS(page->objects) * sizeof(long),
-                           GFP_ATOMIC);
-
+       unsigned long *map = kzalloc(BITS_TO_LONGS(page->objects) *
+                                    sizeof(long), GFP_ATOMIC);
        if (!map)
                return;
        slab_err(s, page, "%s", text);
@@ -2482,9 +2468,8 @@ static void free_partial(struct kmem_cache *s, struct kmem_cache_node *n)
        spin_lock_irqsave(&n->list_lock, flags);
        list_for_each_entry_safe(page, h, &n->partial, lru) {
                if (!page->inuse) {
-                       list_del(&page->lru);
+                       __remove_partial(n, page);
                        discard_slab(s, page);
-                       n->nr_partial--;
                } else {
                        list_slab_objects(s, page,
                                "Objects remaining on kmem_cache_close()");
@@ -2688,6 +2673,7 @@ void *__kmalloc(size_t size, gfp_t flags)
 }
 EXPORT_SYMBOL(__kmalloc);
 
+#ifdef CONFIG_NUMA
 static void *kmalloc_large_node(size_t size, gfp_t flags, int node)
 {
        struct page *page;
@@ -2702,7 +2688,6 @@ static void *kmalloc_large_node(size_t size, gfp_t flags, int node)
        return ptr;
 }
 
-#ifdef CONFIG_NUMA
 void *__kmalloc_node(size_t size, gfp_t flags, int node)
 {
        struct kmem_cache *s;
@@ -2842,8 +2827,7 @@ int kmem_cache_shrink(struct kmem_cache *s)
                                 * may have freed the last object and be
                                 * waiting to release the slab.
                                 */
-                               list_del(&page->lru);
-                               n->nr_partial--;
+                               __remove_partial(n, page);
                                slab_unlock(page);
                                discard_slab(s, page);
                        } else {
@@ -2867,7 +2851,7 @@ int kmem_cache_shrink(struct kmem_cache *s)
 }
 EXPORT_SYMBOL(kmem_cache_shrink);
 
-#if defined(CONFIG_NUMA) && defined(CONFIG_MEMORY_HOTPLUG)
+#if defined(CONFIG_MEMORY_HOTPLUG)
 static int slab_mem_going_offline_callback(void *arg)
 {
        struct kmem_cache *s;
@@ -2909,7 +2893,7 @@ static void slab_mem_offline_callback(void *arg)
                        BUG_ON(slabs_node(s, offline_node));
 
                        s->node[offline_node] = NULL;
-                       kmem_cache_free(kmalloc_caches, n);
+                       kmem_cache_free(kmem_cache_node, n);
                }
        }
        up_read(&slub_lock);
@@ -2942,7 +2926,7 @@ static int slab_mem_going_online_callback(void *arg)
                 *      since memory is not yet available from the node that
                 *      is brought up.
                 */
-               n = kmem_cache_alloc(kmalloc_caches, GFP_KERNEL);
+               n = kmem_cache_alloc(kmem_cache_node, GFP_KERNEL);
                if (!n) {
                        ret = -ENOMEM;
                        goto out;
@@ -3022,8 +3006,6 @@ void __init kmem_cache_init(void)
        int caches = 0;
        struct kmem_cache *temp_kmem_cache;
        int order;
-
-#ifdef CONFIG_NUMA
        struct kmem_cache *temp_kmem_cache_node;
        unsigned long kmalloc_size;
 
@@ -3047,12 +3029,6 @@ void __init kmem_cache_init(void)
                0, SLAB_HWCACHE_ALIGN | SLAB_PANIC, NULL);
 
        hotplug_memory_notifier(slab_memory_callback, SLAB_CALLBACK_PRI);
-#else
-       /* Allocate a single kmem_cache from the page allocator */
-       kmem_size = sizeof(struct kmem_cache);
-       order = get_order(kmem_size);
-       kmem_cache = (void *)__get_free_pages(GFP_NOWAIT, order);
-#endif
 
        /* Able to allocate the per node structures */
        slab_state = PARTIAL;
@@ -3063,7 +3039,6 @@ void __init kmem_cache_init(void)
        kmem_cache = kmem_cache_alloc(kmem_cache, GFP_NOWAIT);
        memcpy(kmem_cache, temp_kmem_cache, kmem_size);
 
-#ifdef CONFIG_NUMA
        /*
         * Allocate kmem_cache_node properly from the kmem_cache slab.
         * kmem_cache_node is separately allocated so no need to
@@ -3077,18 +3052,6 @@ void __init kmem_cache_init(void)
        kmem_cache_bootstrap_fixup(kmem_cache_node);
 
        caches++;
-#else
-       /*
-        * kmem_cache has kmem_cache_node embedded and we moved it!
-        * Update the list heads
-        */
-       INIT_LIST_HEAD(&kmem_cache->local_node.partial);
-       list_splice(&temp_kmem_cache->local_node.partial, &kmem_cache->local_node.partial);
-#ifdef CONFIG_SLUB_DEBUG
-       INIT_LIST_HEAD(&kmem_cache->local_node.full);
-       list_splice(&temp_kmem_cache->local_node.full, &kmem_cache->local_node.full);
-#endif
-#endif
        kmem_cache_bootstrap_fixup(kmem_cache);
        caches++;
        /* Free temporary boot structure */
@@ -3153,6 +3116,16 @@ void __init kmem_cache_init(void)
        slab_state = UP;
 
        /* Provide the correct kmalloc names now that the caches are up */
+       if (KMALLOC_MIN_SIZE <= 32) {
+               kmalloc_caches[1]->name = kstrdup(kmalloc_caches[1]->name, GFP_NOWAIT);
+               BUG_ON(!kmalloc_caches[1]->name);
+       }
+
+       if (KMALLOC_MIN_SIZE <= 64) {
+               kmalloc_caches[2]->name = kstrdup(kmalloc_caches[2]->name, GFP_NOWAIT);
+               BUG_ON(!kmalloc_caches[2]->name);
+       }
+
        for (i = KMALLOC_SHIFT_LOW; i < SLUB_PAGE_SHIFT; i++) {
                char *s = kasprintf(GFP_NOWAIT, "kmalloc-%d", 1 << i);
 
@@ -3255,6 +3228,7 @@ 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;
 
        if (WARN_ON(!name))
                return NULL;
@@ -3278,19 +3252,25 @@ struct kmem_cache *kmem_cache_create(const char *name, size_t size,
                return s;
        }
 
+       n = kstrdup(name, GFP_KERNEL);
+       if (!n)
+               goto err;
+
        s = kmalloc(kmem_size, GFP_KERNEL);
        if (s) {
-               if (kmem_cache_open(s, name,
+               if (kmem_cache_open(s, n,
                                size, align, flags, ctor)) {
                        list_add(&s->list, &slab_caches);
                        if (sysfs_slab_add(s)) {
                                list_del(&s->list);
+                               kfree(n);
                                kfree(s);
                                goto err;
                        }
                        up_write(&slub_lock);
                        return s;
                }
+               kfree(n);
                kfree(s);
        }
        up_write(&slub_lock);
@@ -3362,6 +3342,7 @@ void *__kmalloc_track_caller(size_t size, gfp_t gfpflags, unsigned long caller)
        return ret;
 }
 
+#ifdef CONFIG_NUMA
 void *__kmalloc_node_track_caller(size_t size, gfp_t gfpflags,
                                        int node, unsigned long caller)
 {
@@ -3390,8 +3371,9 @@ void *__kmalloc_node_track_caller(size_t size, gfp_t gfpflags,
 
        return ret;
 }
+#endif
 
-#ifdef CONFIG_SLUB_DEBUG
+#ifdef CONFIG_SYSFS
 static int count_inuse(struct page *page)
 {
        return page->inuse;
@@ -3401,7 +3383,9 @@ static int count_total(struct page *page)
 {
        return page->objects;
 }
+#endif
 
+#ifdef CONFIG_SLUB_DEBUG
 static int validate_slab(struct kmem_cache *s, struct page *page,
                                                unsigned long *map)
 {
@@ -3492,65 +3476,6 @@ static long validate_slab_cache(struct kmem_cache *s)
        kfree(map);
        return count;
 }
-
-#ifdef SLUB_RESILIENCY_TEST
-static void resiliency_test(void)
-{
-       u8 *p;
-
-       printk(KERN_ERR "SLUB resiliency testing\n");
-       printk(KERN_ERR "-----------------------\n");
-       printk(KERN_ERR "A. Corruption after allocation\n");
-
-       p = kzalloc(16, GFP_KERNEL);
-       p[16] = 0x12;
-       printk(KERN_ERR "\n1. kmalloc-16: Clobber Redzone/next pointer"
-                       " 0x12->0x%p\n\n", p + 16);
-
-       validate_slab_cache(kmalloc_caches + 4);
-
-       /* Hmmm... The next two are dangerous */
-       p = kzalloc(32, GFP_KERNEL);
-       p[32 + sizeof(void *)] = 0x34;
-       printk(KERN_ERR "\n2. kmalloc-32: Clobber next pointer/next slab"
-                       " 0x34 -> -0x%p\n", p);
-       printk(KERN_ERR
-               "If allocated object is overwritten then not detectable\n\n");
-
-       validate_slab_cache(kmalloc_caches + 5);
-       p = kzalloc(64, GFP_KERNEL);
-       p += 64 + (get_cycles() & 0xff) * sizeof(void *);
-       *p = 0x56;
-       printk(KERN_ERR "\n3. kmalloc-64: corrupting random byte 0x56->0x%p\n",
-                                                                       p);
-       printk(KERN_ERR
-               "If allocated object is overwritten then not detectable\n\n");
-       validate_slab_cache(kmalloc_caches + 6);
-
-       printk(KERN_ERR "\nB. Corruption after free\n");
-       p = kzalloc(128, GFP_KERNEL);
-       kfree(p);
-       *p = 0x78;
-       printk(KERN_ERR "1. kmalloc-128: Clobber first word 0x78->0x%p\n\n", p);
-       validate_slab_cache(kmalloc_caches + 7);
-
-       p = kzalloc(256, GFP_KERNEL);
-       kfree(p);
-       p[50] = 0x9a;
-       printk(KERN_ERR "\n2. kmalloc-256: Clobber 50th byte 0x9a->0x%p\n\n",
-                       p);
-       validate_slab_cache(kmalloc_caches + 8);
-
-       p = kzalloc(512, GFP_KERNEL);
-       kfree(p);
-       p[512] = 0xab;
-       printk(KERN_ERR "\n3. kmalloc-512: Clobber redzone 0xab->0x%p\n\n", p);
-       validate_slab_cache(kmalloc_caches + 9);
-}
-#else
-static void resiliency_test(void) {};
-#endif
-
 /*
  * Generate lists of code addresses where slabcache objects are allocated
  * and freed.
@@ -3679,7 +3604,7 @@ static int add_location(struct loc_track *t, struct kmem_cache *s,
 
 static void process_slab(struct loc_track *t, struct kmem_cache *s,
                struct page *page, enum track_item alloc,
-               long *map)
+               unsigned long *map)
 {
        void *addr = page_address(page);
        void *p;
@@ -3779,7 +3704,71 @@ static int list_locations(struct kmem_cache *s, char *buf,
                len += sprintf(buf, "No data\n");
        return len;
 }
+#endif
+
+#ifdef SLUB_RESILIENCY_TEST
+static void resiliency_test(void)
+{
+       u8 *p;
+
+       BUILD_BUG_ON(KMALLOC_MIN_SIZE > 16 || SLUB_PAGE_SHIFT < 10);
+
+       printk(KERN_ERR "SLUB resiliency testing\n");
+       printk(KERN_ERR "-----------------------\n");
+       printk(KERN_ERR "A. Corruption after allocation\n");
+
+       p = kzalloc(16, GFP_KERNEL);
+       p[16] = 0x12;
+       printk(KERN_ERR "\n1. kmalloc-16: Clobber Redzone/next pointer"
+                       " 0x12->0x%p\n\n", p + 16);
 
+       validate_slab_cache(kmalloc_caches[4]);
+
+       /* Hmmm... The next two are dangerous */
+       p = kzalloc(32, GFP_KERNEL);
+       p[32 + sizeof(void *)] = 0x34;
+       printk(KERN_ERR "\n2. kmalloc-32: Clobber next pointer/next slab"
+                       " 0x34 -> -0x%p\n", p);
+       printk(KERN_ERR
+               "If allocated object is overwritten then not detectable\n\n");
+
+       validate_slab_cache(kmalloc_caches[5]);
+       p = kzalloc(64, GFP_KERNEL);
+       p += 64 + (get_cycles() & 0xff) * sizeof(void *);
+       *p = 0x56;
+       printk(KERN_ERR "\n3. kmalloc-64: corrupting random byte 0x56->0x%p\n",
+                                                                       p);
+       printk(KERN_ERR
+               "If allocated object is overwritten then not detectable\n\n");
+       validate_slab_cache(kmalloc_caches[6]);
+
+       printk(KERN_ERR "\nB. Corruption after free\n");
+       p = kzalloc(128, GFP_KERNEL);
+       kfree(p);
+       *p = 0x78;
+       printk(KERN_ERR "1. kmalloc-128: Clobber first word 0x78->0x%p\n\n", p);
+       validate_slab_cache(kmalloc_caches[7]);
+
+       p = kzalloc(256, GFP_KERNEL);
+       kfree(p);
+       p[50] = 0x9a;
+       printk(KERN_ERR "\n2. kmalloc-256: Clobber 50th byte 0x9a->0x%p\n\n",
+                       p);
+       validate_slab_cache(kmalloc_caches[8]);
+
+       p = kzalloc(512, GFP_KERNEL);
+       kfree(p);
+       p[512] = 0xab;
+       printk(KERN_ERR "\n3. kmalloc-512: Clobber redzone 0xab->0x%p\n\n", p);
+       validate_slab_cache(kmalloc_caches[9]);
+}
+#else
+#ifdef CONFIG_SYSFS
+static void resiliency_test(void) {};
+#endif
+#endif
+
+#ifdef CONFIG_SYSFS
 enum slab_stat_type {
        SL_ALL,                 /* All slabs */
        SL_PARTIAL,             /* Only partially allocated slabs */
@@ -3832,6 +3821,8 @@ static ssize_t show_slab_objects(struct kmem_cache *s,
                }
        }
 
+       down_read(&slub_lock);
+#ifdef CONFIG_SLUB_DEBUG
        if (flags & SO_ALL) {
                for_each_node_state(node, N_NORMAL_MEMORY) {
                        struct kmem_cache_node *n = get_node(s, node);
@@ -3848,7 +3839,9 @@ static ssize_t show_slab_objects(struct kmem_cache *s,
                        nodes[node] += x;
                }
 
-       } else if (flags & SO_PARTIAL) {
+       } else
+#endif
+       if (flags & SO_PARTIAL) {
                for_each_node_state(node, N_NORMAL_MEMORY) {
                        struct kmem_cache_node *n = get_node(s, node);
 
@@ -3873,6 +3866,7 @@ static ssize_t show_slab_objects(struct kmem_cache *s,
        return x + sprintf(buf + x, "\n");
 }
 
+#ifdef CONFIG_SLUB_DEBUG
 static int any_slab_objects(struct kmem_cache *s)
 {
        int node;
@@ -3888,6 +3882,7 @@ static int any_slab_objects(struct kmem_cache *s)
        }
        return 0;
 }
+#endif
 
 #define to_slab_attr(n) container_of(n, struct slab_attribute, attr)
 #define to_slab(n) container_of(n, struct kmem_cache, kobj);
@@ -3989,12 +3984,6 @@ static ssize_t aliases_show(struct kmem_cache *s, char *buf)
 }
 SLAB_ATTR_RO(aliases);
 
-static ssize_t slabs_show(struct kmem_cache *s, char *buf)
-{
-       return show_slab_objects(s, buf, SO_ALL);
-}
-SLAB_ATTR_RO(slabs);
-
 static ssize_t partial_show(struct kmem_cache *s, char *buf)
 {
        return show_slab_objects(s, buf, SO_PARTIAL);
@@ -4019,93 +4008,83 @@ static ssize_t objects_partial_show(struct kmem_cache *s, char *buf)
 }
 SLAB_ATTR_RO(objects_partial);
 
-static ssize_t total_objects_show(struct kmem_cache *s, char *buf)
-{
-       return show_slab_objects(s, buf, SO_ALL|SO_TOTAL);
-}
-SLAB_ATTR_RO(total_objects);
-
-static ssize_t sanity_checks_show(struct kmem_cache *s, char *buf)
+static ssize_t reclaim_account_show(struct kmem_cache *s, char *buf)
 {
-       return sprintf(buf, "%d\n", !!(s->flags & SLAB_DEBUG_FREE));
+       return sprintf(buf, "%d\n", !!(s->flags & SLAB_RECLAIM_ACCOUNT));
 }
 
-static ssize_t sanity_checks_store(struct kmem_cache *s,
+static ssize_t reclaim_account_store(struct kmem_cache *s,
                                const char *buf, size_t length)
 {
-       s->flags &= ~SLAB_DEBUG_FREE;
+       s->flags &= ~SLAB_RECLAIM_ACCOUNT;
        if (buf[0] == '1')
-               s->flags |= SLAB_DEBUG_FREE;
+               s->flags |= SLAB_RECLAIM_ACCOUNT;
        return length;
 }
-SLAB_ATTR(sanity_checks);
+SLAB_ATTR(reclaim_account);
 
-static ssize_t trace_show(struct kmem_cache *s, char *buf)
+static ssize_t hwcache_align_show(struct kmem_cache *s, char *buf)
 {
-       return sprintf(buf, "%d\n", !!(s->flags & SLAB_TRACE));
+       return sprintf(buf, "%d\n", !!(s->flags & SLAB_HWCACHE_ALIGN));
 }
+SLAB_ATTR_RO(hwcache_align);
 
-static ssize_t trace_store(struct kmem_cache *s, const char *buf,
-                                                       size_t length)
+#ifdef CONFIG_ZONE_DMA
+static ssize_t cache_dma_show(struct kmem_cache *s, char *buf)
 {
-       s->flags &= ~SLAB_TRACE;
-       if (buf[0] == '1')
-               s->flags |= SLAB_TRACE;
-       return length;
+       return sprintf(buf, "%d\n", !!(s->flags & SLAB_CACHE_DMA));
 }
-SLAB_ATTR(trace);
+SLAB_ATTR_RO(cache_dma);
+#endif
 
-#ifdef CONFIG_FAILSLAB
-static ssize_t failslab_show(struct kmem_cache *s, char *buf)
+static ssize_t destroy_by_rcu_show(struct kmem_cache *s, char *buf)
 {
-       return sprintf(buf, "%d\n", !!(s->flags & SLAB_FAILSLAB));
+       return sprintf(buf, "%d\n", !!(s->flags & SLAB_DESTROY_BY_RCU));
 }
+SLAB_ATTR_RO(destroy_by_rcu);
 
-static ssize_t failslab_store(struct kmem_cache *s, const char *buf,
-                                                       size_t length)
+#ifdef CONFIG_SLUB_DEBUG
+static ssize_t slabs_show(struct kmem_cache *s, char *buf)
 {
-       s->flags &= ~SLAB_FAILSLAB;
-       if (buf[0] == '1')
-               s->flags |= SLAB_FAILSLAB;
-       return length;
+       return show_slab_objects(s, buf, SO_ALL);
 }
-SLAB_ATTR(failslab);
-#endif
+SLAB_ATTR_RO(slabs);
 
-static ssize_t reclaim_account_show(struct kmem_cache *s, char *buf)
+static ssize_t total_objects_show(struct kmem_cache *s, char *buf)
 {
-       return sprintf(buf, "%d\n", !!(s->flags & SLAB_RECLAIM_ACCOUNT));
+       return show_slab_objects(s, buf, SO_ALL|SO_TOTAL);
 }
+SLAB_ATTR_RO(total_objects);
 
-static ssize_t reclaim_account_store(struct kmem_cache *s,
-                               const char *buf, size_t length)
+static ssize_t sanity_checks_show(struct kmem_cache *s, char *buf)
 {
-       s->flags &= ~SLAB_RECLAIM_ACCOUNT;
-       if (buf[0] == '1')
-               s->flags |= SLAB_RECLAIM_ACCOUNT;
-       return length;
+       return sprintf(buf, "%d\n", !!(s->flags & SLAB_DEBUG_FREE));
 }
-SLAB_ATTR(reclaim_account);
 
-static ssize_t hwcache_align_show(struct kmem_cache *s, char *buf)
+static ssize_t sanity_checks_store(struct kmem_cache *s,
+                               const char *buf, size_t length)
 {
-       return sprintf(buf, "%d\n", !!(s->flags & SLAB_HWCACHE_ALIGN));
+       s->flags &= ~SLAB_DEBUG_FREE;
+       if (buf[0] == '1')
+               s->flags |= SLAB_DEBUG_FREE;
+       return length;
 }
-SLAB_ATTR_RO(hwcache_align);
+SLAB_ATTR(sanity_checks);
 
-#ifdef CONFIG_ZONE_DMA
-static ssize_t cache_dma_show(struct kmem_cache *s, char *buf)
+static ssize_t trace_show(struct kmem_cache *s, char *buf)
 {
-       return sprintf(buf, "%d\n", !!(s->flags & SLAB_CACHE_DMA));
+       return sprintf(buf, "%d\n", !!(s->flags & SLAB_TRACE));
 }
-SLAB_ATTR_RO(cache_dma);
-#endif
 
-static ssize_t destroy_by_rcu_show(struct kmem_cache *s, char *buf)
+static ssize_t trace_store(struct kmem_cache *s, const char *buf,
+                                                       size_t length)
 {
-       return sprintf(buf, "%d\n", !!(s->flags & SLAB_DESTROY_BY_RCU));
+       s->flags &= ~SLAB_TRACE;
+       if (buf[0] == '1')
+               s->flags |= SLAB_TRACE;
+       return length;
 }
-SLAB_ATTR_RO(destroy_by_rcu);
+SLAB_ATTR(trace);
 
 static ssize_t red_zone_show(struct kmem_cache *s, char *buf)
 {
@@ -4183,6 +4162,40 @@ static ssize_t validate_store(struct kmem_cache *s,
 }
 SLAB_ATTR(validate);
 
+static ssize_t alloc_calls_show(struct kmem_cache *s, char *buf)
+{
+       if (!(s->flags & SLAB_STORE_USER))
+               return -ENOSYS;
+       return list_locations(s, buf, TRACK_ALLOC);
+}
+SLAB_ATTR_RO(alloc_calls);
+
+static ssize_t free_calls_show(struct kmem_cache *s, char *buf)
+{
+       if (!(s->flags & SLAB_STORE_USER))
+               return -ENOSYS;
+       return list_locations(s, buf, TRACK_FREE);
+}
+SLAB_ATTR_RO(free_calls);
+#endif /* CONFIG_SLUB_DEBUG */
+
+#ifdef CONFIG_FAILSLAB
+static ssize_t failslab_show(struct kmem_cache *s, char *buf)
+{
+       return sprintf(buf, "%d\n", !!(s->flags & SLAB_FAILSLAB));
+}
+
+static ssize_t failslab_store(struct kmem_cache *s, const char *buf,
+                                                       size_t length)
+{
+       s->flags &= ~SLAB_FAILSLAB;
+       if (buf[0] == '1')
+               s->flags |= SLAB_FAILSLAB;
+       return length;
+}
+SLAB_ATTR(failslab);
+#endif
+
 static ssize_t shrink_show(struct kmem_cache *s, char *buf)
 {
        return 0;
@@ -4202,22 +4215,6 @@ static ssize_t shrink_store(struct kmem_cache *s,
 }
 SLAB_ATTR(shrink);
 
-static ssize_t alloc_calls_show(struct kmem_cache *s, char *buf)
-{
-       if (!(s->flags & SLAB_STORE_USER))
-               return -ENOSYS;
-       return list_locations(s, buf, TRACK_ALLOC);
-}
-SLAB_ATTR_RO(alloc_calls);
-
-static ssize_t free_calls_show(struct kmem_cache *s, char *buf)
-{
-       if (!(s->flags & SLAB_STORE_USER))
-               return -ENOSYS;
-       return list_locations(s, buf, TRACK_FREE);
-}
-SLAB_ATTR_RO(free_calls);
-
 #ifdef CONFIG_NUMA
 static ssize_t remote_node_defrag_ratio_show(struct kmem_cache *s, char *buf)
 {
@@ -4323,25 +4320,27 @@ static struct attribute *slab_attrs[] = {
        &min_partial_attr.attr,
        &objects_attr.attr,
        &objects_partial_attr.attr,
-       &total_objects_attr.attr,
-       &slabs_attr.attr,
        &partial_attr.attr,
        &cpu_slabs_attr.attr,
        &ctor_attr.attr,
        &aliases_attr.attr,
        &align_attr.attr,
-       &sanity_checks_attr.attr,
-       &trace_attr.attr,
        &hwcache_align_attr.attr,
        &reclaim_account_attr.attr,
        &destroy_by_rcu_attr.attr,
+       &shrink_attr.attr,
+#ifdef CONFIG_SLUB_DEBUG
+       &total_objects_attr.attr,
+       &slabs_attr.attr,
+       &sanity_checks_attr.attr,
+       &trace_attr.attr,
        &red_zone_attr.attr,
        &poison_attr.attr,
        &store_user_attr.attr,
        &validate_attr.attr,
-       &shrink_attr.attr,
        &alloc_calls_attr.attr,
        &free_calls_attr.attr,
+#endif
 #ifdef CONFIG_ZONE_DMA
        &cache_dma_attr.attr,
 #endif
@@ -4421,6 +4420,7 @@ static void kmem_cache_release(struct kobject *kobj)
 {
        struct kmem_cache *s = to_slab(kobj);
 
+       kfree(s->name);
        kfree(s);
 }
 
@@ -4623,7 +4623,7 @@ static int __init slab_sysfs_init(void)
 }
 
 __initcall(slab_sysfs_init);
-#endif
+#endif /* CONFIG_SYSFS */
 
 /*
  * The /proc/slabinfo ABI