[PATCH] slab debug and ARCH_SLAB_MINALIGN don't get along
[pandora-kernel.git] / mm / slab.c
index 3dbd6f4..ff60a94 100644 (file)
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -86,7 +86,6 @@
  *     All object allocations for a node occur from node specific slab lists.
  */
 
-#include       <linux/config.h>
 #include       <linux/slab.h>
 #include       <linux/mm.h>
 #include       <linux/poison.h>
@@ -314,7 +313,7 @@ static int drain_freelist(struct kmem_cache *cache,
 static void free_block(struct kmem_cache *cachep, void **objpp, int len,
                        int node);
 static int enable_cpucache(struct kmem_cache *cachep);
-static void cache_reap(void *unused);
+static void cache_reap(struct work_struct *unused);
 
 /*
  * This function must be completely optimized away if a constant is passed to
@@ -754,7 +753,7 @@ int slab_is_available(void)
        return g_cpucache_up == FULL;
 }
 
-static DEFINE_PER_CPU(struct work_struct, reap_work);
+static DEFINE_PER_CPU(struct delayed_work, reap_work);
 
 static inline struct array_cache *cpu_cache_get(struct kmem_cache *cachep)
 {
@@ -884,7 +883,7 @@ static void init_reap_node(int cpu)
        if (node == MAX_NUMNODES)
                node = first_node(node_online_map);
 
-       __get_cpu_var(reap_node) = node;
+       per_cpu(reap_node, cpu) = node;
 }
 
 static void next_reap_node(void)
@@ -917,16 +916,16 @@ static void next_reap_node(void)
  */
 static void __devinit start_cpu_timer(int cpu)
 {
-       struct work_struct *reap_work = &per_cpu(reap_work, cpu);
+       struct delayed_work *reap_work = &per_cpu(reap_work, cpu);
 
        /*
         * When this gets called from do_initcalls via cpucache_init(),
         * init_workqueues() has already run, so keventd will be setup
         * at that time.
         */
-       if (keventd_up() && reap_work->func == NULL) {
+       if (keventd_up() && reap_work->work.func == NULL) {
                init_reap_node(cpu);
-               INIT_WORK(reap_work, cache_reap, NULL);
+               INIT_DELAYED_WORK(reap_work, cache_reap);
                schedule_delayed_work_on(cpu, reap_work, HZ + 3 * cpu);
        }
 }
@@ -1107,15 +1106,18 @@ static inline int cache_free_alien(struct kmem_cache *cachep, void *objp)
        int nodeid = slabp->nodeid;
        struct kmem_list3 *l3;
        struct array_cache *alien = NULL;
+       int node;
+
+       node = numa_node_id();
 
        /*
         * Make sure we are not freeing a object from another node to the array
         * cache on this cpu.
         */
-       if (likely(slabp->nodeid == numa_node_id()))
+       if (likely(slabp->nodeid == node))
                return 0;
 
-       l3 = cachep->nodelists[numa_node_id()];
+       l3 = cachep->nodelists[node];
        STATS_INC_NODEFREES(cachep);
        if (l3->alien && l3->alien[nodeid]) {
                alien = l3->alien[nodeid];
@@ -1326,7 +1328,6 @@ static void init_list(struct kmem_cache *cachep, struct kmem_list3 *list,
 {
        struct kmem_list3 *ptr;
 
-       BUG_ON(cachep->nodelists[nodeid] != list);
        ptr = kmalloc_node(sizeof(struct kmem_list3), GFP_KERNEL, nodeid);
        BUG_ON(!ptr);
 
@@ -1353,6 +1354,7 @@ void __init kmem_cache_init(void)
        struct cache_names *names;
        int i;
        int order;
+       int node;
 
        for (i = 0; i < NUM_INIT_LISTS; i++) {
                kmem_list3_init(&initkmem_list3[i]);
@@ -1387,12 +1389,14 @@ void __init kmem_cache_init(void)
         * 6) Resize the head arrays of the kmalloc caches to their final sizes.
         */
 
+       node = numa_node_id();
+
        /* 1) create the cache_cache */
        INIT_LIST_HEAD(&cache_chain);
        list_add(&cache_cache.next, &cache_chain);
        cache_cache.colour_off = cache_line_size();
        cache_cache.array[smp_processor_id()] = &initarray_cache.cache;
-       cache_cache.nodelists[numa_node_id()] = &initkmem_list3[CACHE_CACHE];
+       cache_cache.nodelists[node] = &initkmem_list3[CACHE_CACHE];
 
        cache_cache.buffer_size = ALIGN(cache_cache.buffer_size,
                                        cache_line_size());
@@ -1497,19 +1501,18 @@ void __init kmem_cache_init(void)
        }
        /* 5) Replace the bootstrap kmem_list3's */
        {
-               int node;
+               int nid;
+
                /* Replace the static kmem_list3 structures for the boot cpu */
-               init_list(&cache_cache, &initkmem_list3[CACHE_CACHE],
-                         numa_node_id());
+               init_list(&cache_cache, &initkmem_list3[CACHE_CACHE], node);
 
-               for_each_online_node(node) {
+               for_each_online_node(nid) {
                        init_list(malloc_sizes[INDEX_AC].cs_cachep,
-                                 &initkmem_list3[SIZE_AC + node], node);
+                                 &initkmem_list3[SIZE_AC + nid], nid);
 
                        if (INDEX_AC != INDEX_L3) {
                                init_list(malloc_sizes[INDEX_L3].cs_cachep,
-                                         &initkmem_list3[SIZE_L3 + node],
-                                         node);
+                                         &initkmem_list3[SIZE_L3 + nid], nid);
                        }
                }
        }
@@ -2194,18 +2197,17 @@ kmem_cache_create (const char *name, size_t size, size_t align,
        if (flags & SLAB_RED_ZONE || flags & SLAB_STORE_USER)
                ralign = BYTES_PER_WORD;
 
-       /* 2) arch mandated alignment: disables debug if necessary */
+       /* 2) arch mandated alignment */
        if (ralign < ARCH_SLAB_MINALIGN) {
                ralign = ARCH_SLAB_MINALIGN;
-               if (ralign > BYTES_PER_WORD)
-                       flags &= ~(SLAB_RED_ZONE | SLAB_STORE_USER);
        }
-       /* 3) caller mandated alignment: disables debug if necessary */
+       /* 3) caller mandated alignment */
        if (ralign < align) {
                ralign = align;
-               if (ralign > BYTES_PER_WORD)
-                       flags &= ~(SLAB_RED_ZONE | SLAB_STORE_USER);
        }
+       /* disable debug if necessary */
+       if (ralign > BYTES_PER_WORD)
+               flags &= ~(SLAB_RED_ZONE | SLAB_STORE_USER);
        /*
         * 4) Store it.
         */
@@ -2919,6 +2921,9 @@ static void *cache_alloc_refill(struct kmem_cache *cachep, gfp_t flags)
        int batchcount;
        struct kmem_list3 *l3;
        struct array_cache *ac;
+       int node;
+
+       node = numa_node_id();
 
        check_irq_off();
        ac = cpu_cache_get(cachep);
@@ -2932,7 +2937,7 @@ retry:
                 */
                batchcount = BATCHREFILL_LIMIT;
        }
-       l3 = cachep->nodelists[numa_node_id()];
+       l3 = cachep->nodelists[node];
 
        BUG_ON(ac->avail > 0 || !l3);
        spin_lock(&l3->list_lock);
@@ -2962,7 +2967,7 @@ retry:
                        STATS_SET_HIGH(cachep);
 
                        ac->entry[ac->avail++] = slab_get_obj(cachep, slabp,
-                                                           numa_node_id());
+                                                           node);
                }
                check_slabp(cachep, slabp);
 
@@ -2981,7 +2986,7 @@ alloc_done:
 
        if (unlikely(!ac->avail)) {
                int x;
-               x = cache_grow(cachep, flags, numa_node_id());
+               x = cache_grow(cachep, flags, node);
 
                /* cache_grow can reenable interrupts, then ac could change. */
                ac = cpu_cache_get(cachep);
@@ -3057,6 +3062,12 @@ static void *cache_alloc_debugcheck_after(struct kmem_cache *cachep,
 
                cachep->ctor(objp, cachep, ctor_flags);
        }
+#if ARCH_SLAB_MINALIGN
+       if ((u32)objp & (ARCH_SLAB_MINALIGN-1)) {
+               printk(KERN_ERR "0x%p: not aligned to ARCH_SLAB_MINALIGN=%d\n",
+                      objp, ARCH_SLAB_MINALIGN);
+       }
+#endif
        return objp;
 }
 #else
@@ -3146,12 +3157,15 @@ void *fallback_alloc(struct kmem_cache *cache, gfp_t flags)
        struct zone **z;
        void *obj = NULL;
 
-       for (z = zonelist->zones; *z && !obj; z++)
+       for (z = zonelist->zones; *z && !obj; z++) {
+               int nid = zone_to_nid(*z);
+
                if (zone_idx(*z) <= ZONE_NORMAL &&
-                               cpuset_zone_allowed(*z, flags))
+                               cpuset_zone_allowed(*z, flags) &&
+                               cache->nodelists[nid])
                        obj = __cache_alloc_node(cache,
-                                       flags | __GFP_THISNODE,
-                                       zone_to_nid(*z));
+                                       flags | __GFP_THISNODE, nid);
+       }
        return obj;
 }
 
@@ -3488,22 +3502,25 @@ static __always_inline void *__do_kmalloc(size_t size, gfp_t flags,
 }
 
 
+#ifdef CONFIG_DEBUG_SLAB
 void *__kmalloc(size_t size, gfp_t flags)
 {
-#ifndef CONFIG_DEBUG_SLAB
-       return __do_kmalloc(size, flags, NULL);
-#else
        return __do_kmalloc(size, flags, __builtin_return_address(0));
-#endif
 }
 EXPORT_SYMBOL(__kmalloc);
 
-#ifdef CONFIG_DEBUG_SLAB
 void *__kmalloc_track_caller(size_t size, gfp_t flags, void *caller)
 {
        return __do_kmalloc(size, flags, caller);
 }
 EXPORT_SYMBOL(__kmalloc_track_caller);
+
+#else
+void *__kmalloc(size_t size, gfp_t flags)
+{
+       return __do_kmalloc(size, flags, NULL);
+}
+EXPORT_SYMBOL(__kmalloc);
 #endif
 
 /**
@@ -3803,7 +3820,7 @@ void drain_array(struct kmem_cache *cachep, struct kmem_list3 *l3,
  * If we cannot acquire the cache chain mutex then just give up - we'll try
  * again on the next iteration.
  */
-static void cache_reap(void *unused)
+static void cache_reap(struct work_struct *unused)
 {
        struct kmem_cache *searchp;
        struct kmem_list3 *l3;