[PATCH] fix potential stack overflow in mm/slab.c
[powerpc.git] / mm / slab.c
index 233e39d..619337a 100644 (file)
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -309,6 +309,13 @@ struct kmem_list3 __initdata initkmem_list3[NUM_INIT_LISTS];
 #define        SIZE_AC 1
 #define        SIZE_L3 (1 + MAX_NUMNODES)
 
+static int drain_freelist(struct kmem_cache *cache,
+                       struct kmem_list3 *l3, int tofree);
+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);
+
 /*
  * This function must be completely optimized away if a constant is passed to
  * it.  Mostly the same as what is in linux/slab.h except it returns an index.
@@ -456,7 +463,7 @@ struct kmem_cache {
 #define        STATS_DEC_ACTIVE(x)     ((x)->num_active--)
 #define        STATS_INC_ALLOCED(x)    ((x)->num_allocations++)
 #define        STATS_INC_GROWN(x)      ((x)->grown++)
-#define        STATS_INC_REAPED(x)     ((x)->reaped++)
+#define        STATS_ADD_REAPED(x,y)   ((x)->reaped += (y))
 #define        STATS_SET_HIGH(x)                                               \
        do {                                                            \
                if ((x)->num_active > (x)->high_mark)                   \
@@ -480,7 +487,7 @@ struct kmem_cache {
 #define        STATS_DEC_ACTIVE(x)     do { } while (0)
 #define        STATS_INC_ALLOCED(x)    do { } while (0)
 #define        STATS_INC_GROWN(x)      do { } while (0)
-#define        STATS_INC_REAPED(x)     do { } while (0)
+#define        STATS_ADD_REAPED(x,y)   do { } while (0)
 #define        STATS_SET_HIGH(x)       do { } while (0)
 #define        STATS_INC_ERR(x)        do { } while (0)
 #define        STATS_INC_NODEALLOCS(x) do { } while (0)
@@ -667,6 +674,63 @@ static struct kmem_cache cache_cache = {
 #endif
 };
 
+#define BAD_ALIEN_MAGIC 0x01020304ul
+
+#ifdef CONFIG_LOCKDEP
+
+/*
+ * Slab sometimes uses the kmalloc slabs to store the slab headers
+ * for other slabs "off slab".
+ * The locking for this is tricky in that it nests within the locks
+ * of all other slabs in a few places; to deal with this special
+ * locking we put on-slab caches into a separate lock-class.
+ *
+ * We set lock class for alien array caches which are up during init.
+ * The lock annotation will be lost if all cpus of a node goes down and
+ * then comes back up during hotplug
+ */
+static struct lock_class_key on_slab_l3_key;
+static struct lock_class_key on_slab_alc_key;
+
+static inline void init_lock_keys(void)
+
+{
+       int q;
+       struct cache_sizes *s = malloc_sizes;
+
+       while (s->cs_size != ULONG_MAX) {
+               for_each_node(q) {
+                       struct array_cache **alc;
+                       int r;
+                       struct kmem_list3 *l3 = s->cs_cachep->nodelists[q];
+                       if (!l3 || OFF_SLAB(s->cs_cachep))
+                               continue;
+                       lockdep_set_class(&l3->list_lock, &on_slab_l3_key);
+                       alc = l3->alien;
+                       /*
+                        * FIXME: This check for BAD_ALIEN_MAGIC
+                        * should go away when common slab code is taught to
+                        * work even without alien caches.
+                        * Currently, non NUMA code returns BAD_ALIEN_MAGIC
+                        * for alloc_alien_cache,
+                        */
+                       if (!alc || (unsigned long)alc == BAD_ALIEN_MAGIC)
+                               continue;
+                       for_each_node(r) {
+                               if (alc[r])
+                                       lockdep_set_class(&alc[r]->lock,
+                                            &on_slab_alc_key);
+                       }
+               }
+               s++;
+       }
+}
+#else
+static inline void init_lock_keys(void)
+{
+}
+#endif
+
 /* Guard access to the cache-chain. */
 static DEFINE_MUTEX(cache_chain_mutex);
 static struct list_head cache_chain;
@@ -700,12 +764,6 @@ int slab_is_available(void)
 
 static DEFINE_PER_CPU(struct work_struct, reap_work);
 
-static void free_block(struct kmem_cache *cachep, void **objpp, int len,
-                       int node);
-static void enable_cpucache(struct kmem_cache *cachep);
-static void cache_reap(void *unused);
-static int __node_shrink(struct kmem_cache *cachep, int node);
-
 static inline struct array_cache *cpu_cache_get(struct kmem_cache *cachep)
 {
        return cachep->array[smp_processor_id()];
@@ -736,11 +794,10 @@ static inline struct kmem_cache *__find_general_cachep(size_t size,
        return csizep->cs_cachep;
 }
 
-struct kmem_cache *kmem_find_general_cachep(size_t size, gfp_t gfpflags)
+static struct kmem_cache *kmem_find_general_cachep(size_t size, gfp_t gfpflags)
 {
        return __find_general_cachep(size, gfpflags);
 }
-EXPORT_SYMBOL(kmem_find_general_cachep);
 
 static size_t slab_mgmt_size(size_t nr_objs, size_t align)
 {
@@ -1060,7 +1117,7 @@ static inline int cache_free_alien(struct kmem_cache *cachep, void *objp)
 
 static inline struct array_cache **alloc_alien_cache(int node, int limit)
 {
-       return (struct array_cache **) 0x01020304ul;
+       return (struct array_cache **)BAD_ALIEN_MAGIC;
 }
 
 static inline void free_alien_cache(struct array_cache **ac_ptr)
@@ -1074,7 +1131,7 @@ static inline int cache_free_alien(struct kmem_cache *cachep, void *objp)
 
 #endif
 
-static int __devinit cpuup_callback(struct notifier_block *nfb,
+static int __cpuinit cpuup_callback(struct notifier_block *nfb,
                                    unsigned long action, void *hcpu)
 {
        long cpu = (long)hcpu;
@@ -1241,10 +1298,7 @@ free_array_cache:
                        l3 = cachep->nodelists[node];
                        if (!l3)
                                continue;
-                       spin_lock_irq(&l3->list_lock);
-                       /* free slabs belonging to this node */
-                       __node_shrink(cachep, node);
-                       spin_unlock_irq(&l3->list_lock);
+                       drain_freelist(cachep, l3, l3->free_objects);
                }
                mutex_unlock(&cache_chain_mutex);
                break;
@@ -1274,6 +1328,11 @@ static void init_list(struct kmem_cache *cachep, struct kmem_list3 *list,
 
        local_irq_disable();
        memcpy(ptr, list, sizeof(struct kmem_list3));
+       /*
+        * Do not assume that spinlocks can be initialized via memcpy:
+        */
+       spin_lock_init(&ptr->list_lock);
+
        MAKE_ALL_LISTS(cachep, ptr, nodeid);
        cachep->nodelists[nodeid] = ptr;
        local_irq_enable();
@@ -1400,7 +1459,7 @@ void __init kmem_cache_init(void)
        }
        /* 4) Replace the bootstrap head arrays */
        {
-               void *ptr;
+               struct array_cache *ptr;
 
                ptr = kmalloc(sizeof(struct arraycache_init), GFP_KERNEL);
 
@@ -1408,6 +1467,11 @@ void __init kmem_cache_init(void)
                BUG_ON(cpu_cache_get(&cache_cache) != &initarray_cache.cache);
                memcpy(ptr, cpu_cache_get(&cache_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;
                local_irq_enable();
 
@@ -1418,6 +1482,11 @@ void __init kmem_cache_init(void)
                       != &initarray_generic.cache);
                memcpy(ptr, cpu_cache_get(malloc_sizes[INDEX_AC].cs_cachep),
                       sizeof(struct arraycache_init));
+               /*
+                * Do not assume that spinlocks can be initialized via memcpy:
+                */
+               spin_lock_init(&ptr->lock);
+
                malloc_sizes[INDEX_AC].cs_cachep->array[smp_processor_id()] =
                    ptr;
                local_irq_enable();
@@ -1446,10 +1515,15 @@ void __init kmem_cache_init(void)
                struct kmem_cache *cachep;
                mutex_lock(&cache_chain_mutex);
                list_for_each_entry(cachep, &cache_chain, next)
-                       enable_cpucache(cachep);
+                       if (enable_cpucache(cachep))
+                               BUG();
                mutex_unlock(&cache_chain_mutex);
        }
 
+       /* Annotate slab for lockdep -- annotate the malloc caches */
+       init_lock_keys();
+
+
        /* Done! */
        g_cpucache_up = FULL;
 
@@ -1507,7 +1581,7 @@ static void *kmem_getpages(struct kmem_cache *cachep, gfp_t flags, int nodeid)
        nr_pages = (1 << cachep->gfporder);
        if (cachep->flags & SLAB_RECLAIM_ACCOUNT)
                atomic_add(nr_pages, &slab_reclaim_pages);
-       add_page_state(nr_slab, nr_pages);
+       add_zone_page_state(page_zone(page), NR_SLAB, nr_pages);
        for (i = 0; i < nr_pages; i++)
                __SetPageSlab(page + i);
        return page_address(page);
@@ -1522,12 +1596,12 @@ static void kmem_freepages(struct kmem_cache *cachep, void *addr)
        struct page *page = virt_to_page(addr);
        const unsigned long nr_freed = i;
 
+       sub_zone_page_state(page_zone(page), NR_SLAB, nr_freed);
        while (i--) {
                BUG_ON(!PageSlab(page));
                __ClearPageSlab(page);
                page++;
        }
-       sub_page_state(nr_slab, nr_freed);
        if (current->reclaim_state)
                current->reclaim_state->reclaimed_slab += nr_freed;
        free_pages((unsigned long)addr, cachep->gfporder);
@@ -1789,6 +1863,27 @@ static void set_up_list3s(struct kmem_cache *cachep, int index)
        }
 }
 
+static 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);
+               }
+       }
+       kmem_cache_free(&cache_cache, cachep);
+}
+
+
 /**
  * calculate_slab_order - calculate size (page order) of slabs
  * @cachep: pointer to the cache that is being created
@@ -1859,12 +1954,11 @@ static size_t calculate_slab_order(struct kmem_cache *cachep,
        return left_over;
 }
 
-static void setup_cpu_cache(struct kmem_cache *cachep)
+static int setup_cpu_cache(struct kmem_cache *cachep)
 {
-       if (g_cpucache_up == FULL) {
-               enable_cpucache(cachep);
-               return;
-       }
+       if (g_cpucache_up == FULL)
+               return enable_cpucache(cachep);
+
        if (g_cpucache_up == NONE) {
                /*
                 * Note: the first kmem_cache_create must create the cache
@@ -1911,6 +2005,7 @@ static void setup_cpu_cache(struct kmem_cache *cachep)
        cpu_cache_get(cachep)->touched = 0;
        cachep->batchcount = 1;
        cachep->limit = BOOT_CPUCACHE_ENTRIES;
+       return 0;
 }
 
 /**
@@ -2052,6 +2147,15 @@ kmem_cache_create (const char *name, size_t size, size_t align,
        } else {
                ralign = BYTES_PER_WORD;
        }
+
+       /*
+        * Redzoning and user store require word alignment. Note this will be
+        * overridden by architecture or caller mandated alignment if either
+        * is greater than BYTES_PER_WORD.
+        */
+       if (flags & SLAB_RED_ZONE || flags & SLAB_STORE_USER)
+               ralign = BYTES_PER_WORD;
+
        /* 2) arch mandated alignment: disables debug if necessary */
        if (ralign < ARCH_SLAB_MINALIGN) {
                ralign = ARCH_SLAB_MINALIGN;
@@ -2065,8 +2169,7 @@ kmem_cache_create (const char *name, size_t size, size_t align,
                        flags &= ~(SLAB_RED_ZONE | SLAB_STORE_USER);
        }
        /*
-        * 4) Store it. Note that the debug code below can reduce
-        *    the alignment to BYTES_PER_WORD.
+        * 4) Store it.
         */
        align = ralign;
 
@@ -2078,20 +2181,19 @@ kmem_cache_create (const char *name, size_t size, size_t align,
 #if DEBUG
        cachep->obj_size = size;
 
+       /*
+        * Both debugging options require word-alignment which is calculated
+        * into align above.
+        */
        if (flags & SLAB_RED_ZONE) {
-               /* redzoning only works with word aligned caches */
-               align = BYTES_PER_WORD;
-
                /* add space for red zone words */
                cachep->obj_offset += BYTES_PER_WORD;
                size += 2 * BYTES_PER_WORD;
        }
        if (flags & SLAB_STORE_USER) {
-               /* user store requires word alignment and
-                * one word storage behind the end of the real
-                * object.
+               /* user store requires one word storage behind the end of
+                * the real object.
                 */
-               align = BYTES_PER_WORD;
                size += BYTES_PER_WORD;
        }
 #if FORCED_DEBUG && defined(CONFIG_DEBUG_PAGEALLOC)
@@ -2155,14 +2257,26 @@ kmem_cache_create (const char *name, size_t size, size_t align,
                cachep->gfpflags |= GFP_DMA;
        cachep->buffer_size = size;
 
-       if (flags & CFLGS_OFF_SLAB)
+       if (flags & CFLGS_OFF_SLAB) {
                cachep->slabp_cache = kmem_find_general_cachep(slab_size, 0u);
+               /*
+                * This is a possibility for one of the malloc_sizes caches.
+                * But since we go off slab only for object size greater than
+                * PAGE_SIZE/8, and malloc_sizes gets created in ascending order,
+                * this should not happen at all.
+                * But leave a BUG_ON for some lucky dude.
+                */
+               BUG_ON(!cachep->slabp_cache);
+       }
        cachep->ctor = ctor;
        cachep->dtor = dtor;
        cachep->name = name;
 
-
-       setup_cpu_cache(cachep);
+       if (setup_cpu_cache(cachep)) {
+               __kmem_cache_destroy(cachep);
+               cachep = NULL;
+               goto oops;
+       }
 
        /* cache setup completed, link it into the list */
        list_add(&cachep->next, &cache_chain);
@@ -2248,32 +2362,45 @@ static void drain_cpu_caches(struct kmem_cache *cachep)
        }
 }
 
-static int __node_shrink(struct kmem_cache *cachep, int node)
+/*
+ * Remove slabs from the list of free slabs.
+ * Specify the number of slabs to drain in tofree.
+ *
+ * Returns the actual number of slabs released.
+ */
+static int drain_freelist(struct kmem_cache *cache,
+                       struct kmem_list3 *l3, int tofree)
 {
+       struct list_head *p;
+       int nr_freed;
        struct slab *slabp;
-       struct kmem_list3 *l3 = cachep->nodelists[node];
-       int ret;
 
-       for (;;) {
-               struct list_head *p;
+       nr_freed = 0;
+       while (nr_freed < tofree && !list_empty(&l3->slabs_free)) {
 
+               spin_lock_irq(&l3->list_lock);
                p = l3->slabs_free.prev;
-               if (p == &l3->slabs_free)
-                       break;
+               if (p == &l3->slabs_free) {
+                       spin_unlock_irq(&l3->list_lock);
+                       goto out;
+               }
 
-               slabp = list_entry(l3->slabs_free.prev, struct slab, list);
+               slabp = list_entry(p, struct slab, list);
 #if DEBUG
                BUG_ON(slabp->inuse);
 #endif
                list_del(&slabp->list);
-
-               l3->free_objects -= cachep->num;
+               /*
+                * Safe to drop the lock. The slab is no longer linked
+                * to the cache.
+                */
+               l3->free_objects -= cache->num;
                spin_unlock_irq(&l3->list_lock);
-               slab_destroy(cachep, slabp);
-               spin_lock_irq(&l3->list_lock);
+               slab_destroy(cache, slabp);
+               nr_freed++;
        }
-       ret = !list_empty(&l3->slabs_full) || !list_empty(&l3->slabs_partial);
-       return ret;
+out:
+       return nr_freed;
 }
 
 static int __cache_shrink(struct kmem_cache *cachep)
@@ -2286,11 +2413,13 @@ static int __cache_shrink(struct kmem_cache *cachep)
        check_irq_on();
        for_each_online_node(i) {
                l3 = cachep->nodelists[i];
-               if (l3) {
-                       spin_lock_irq(&l3->list_lock);
-                       ret += __node_shrink(cachep, i);
-                       spin_unlock_irq(&l3->list_lock);
-               }
+               if (!l3)
+                       continue;
+
+               drain_freelist(cachep, l3, l3->free_objects);
+
+               ret += !list_empty(&l3->slabs_full) ||
+                       !list_empty(&l3->slabs_partial);
        }
        return (ret ? 1 : 0);
 }
@@ -2329,9 +2458,6 @@ EXPORT_SYMBOL(kmem_cache_shrink);
  */
 int kmem_cache_destroy(struct kmem_cache *cachep)
 {
-       int i;
-       struct kmem_list3 *l3;
-
        BUG_ON(!cachep || in_interrupt());
 
        /* Don't let CPUs to come and go */
@@ -2357,25 +2483,23 @@ int kmem_cache_destroy(struct kmem_cache *cachep)
        if (unlikely(cachep->flags & SLAB_DESTROY_BY_RCU))
                synchronize_rcu();
 
-       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);
-               }
-       }
-       kmem_cache_free(&cache_cache, cachep);
+       __kmem_cache_destroy(cachep);
        unlock_cpu_hotplug();
        return 0;
 }
 EXPORT_SYMBOL(kmem_cache_destroy);
 
-/* Get the memory for a slab management obj. */
+/*
+ * Get the memory for a slab management obj.
+ * For a slab cache when the slab descriptor is off-slab, slab descriptors
+ * always come from malloc_sizes caches.  The slab descriptor cannot
+ * come from the same cache which is getting created because,
+ * when we are searching for an appropriate cache for these
+ * descriptors in kmem_cache_create, we search through the malloc_sizes array.
+ * If we are creating a malloc_sizes cache here it would not be visible to
+ * kmem_find_general_cachep till the initialization is complete.
+ * Hence we cannot have slabp_cache same as the original cache.
+ */
 static struct slab *alloc_slabmgmt(struct kmem_cache *cachep, void *objp,
                                   int colour_off, gfp_t local_flags,
                                   int nodeid)
@@ -3059,6 +3183,12 @@ static void free_block(struct kmem_cache *cachep, void **objpp, int nr_objects,
                if (slabp->inuse == 0) {
                        if (l3->free_objects > l3->free_limit) {
                                l3->free_objects -= cachep->num;
+                               /* No need to drop any previously held
+                                * lock here, even if we have a off-slab slab
+                                * descriptor it is guaranteed to come from
+                                * a different cache, refer to comments before
+                                * alloc_slabmgmt.
+                                */
                                slab_destroy(cachep, slabp);
                        } else {
                                list_add(&slabp->list, &l3->slabs_free);
@@ -3164,7 +3294,7 @@ void *kmem_cache_alloc(struct kmem_cache *cachep, gfp_t flags)
 EXPORT_SYMBOL(kmem_cache_alloc);
 
 /**
- * kmem_cache_alloc - Allocate an object. The memory is set to zero.
+ * kmem_cache_zalloc - Allocate an object. The memory is set to zero.
  * @cache: The cache to allocate from.
  * @flags: See kmalloc().
  *
@@ -3257,7 +3387,7 @@ void *kmem_cache_alloc_node(struct kmem_cache *cachep, gfp_t flags, int nodeid)
 }
 EXPORT_SYMBOL(kmem_cache_alloc_node);
 
-void *kmalloc_node(size_t size, gfp_t flags, int node)
+void *__kmalloc_node(size_t size, gfp_t flags, int node)
 {
        struct kmem_cache *cachep;
 
@@ -3266,7 +3396,7 @@ void *kmalloc_node(size_t size, gfp_t flags, int node)
                return NULL;
        return kmem_cache_alloc_node(cachep, flags, node);
 }
-EXPORT_SYMBOL(kmalloc_node);
+EXPORT_SYMBOL(__kmalloc_node);
 #endif
 
 /**
@@ -3312,52 +3442,127 @@ EXPORT_SYMBOL(__kmalloc_track_caller);
 
 #ifdef CONFIG_SMP
 /**
- * __alloc_percpu - allocate one copy of the object for every present
- * cpu in the system, zeroing them.
- * Objects should be dereferenced using the per_cpu_ptr macro only.
+ * percpu_depopulate - depopulate per-cpu data for given cpu
+ * @__pdata: per-cpu data to depopulate
+ * @cpu: depopulate per-cpu data for this cpu
  *
- * @size: how many bytes of memory are required.
+ * Depopulating per-cpu data for a cpu going offline would be a typical
+ * use case. You need to register a cpu hotplug handler for that purpose.
  */
-void *__alloc_percpu(size_t size)
+void percpu_depopulate(void *__pdata, int cpu)
 {
-       int i;
-       struct percpu_data *pdata = kmalloc(sizeof(*pdata), GFP_KERNEL);
+       struct percpu_data *pdata = __percpu_disguise(__pdata);
+       if (pdata->ptrs[cpu]) {
+               kfree(pdata->ptrs[cpu]);
+               pdata->ptrs[cpu] = NULL;
+       }
+}
+EXPORT_SYMBOL_GPL(percpu_depopulate);
 
-       if (!pdata)
-               return NULL;
+/**
+ * percpu_depopulate_mask - depopulate per-cpu data for some cpu's
+ * @__pdata: per-cpu data to depopulate
+ * @mask: depopulate per-cpu data for cpu's selected through mask bits
+ */
+void __percpu_depopulate_mask(void *__pdata, cpumask_t *mask)
+{
+       int cpu;
+       for_each_cpu_mask(cpu, *mask)
+               percpu_depopulate(__pdata, cpu);
+}
+EXPORT_SYMBOL_GPL(__percpu_depopulate_mask);
 
-       /*
-        * Cannot use for_each_online_cpu since a cpu may come online
-        * and we have no way of figuring out how to fix the array
-        * that we have allocated then....
-        */
-       for_each_possible_cpu(i) {
-               int node = cpu_to_node(i);
+/**
+ * percpu_populate - populate per-cpu data for given cpu
+ * @__pdata: per-cpu data to populate further
+ * @size: size of per-cpu object
+ * @gfp: may sleep or not etc.
+ * @cpu: populate per-data for this cpu
+ *
+ * Populating per-cpu data for a cpu coming online would be a typical
+ * use case. You need to register a cpu hotplug handler for that purpose.
+ * Per-cpu object is populated with zeroed buffer.
+ */
+void *percpu_populate(void *__pdata, size_t size, gfp_t gfp, int cpu)
+{
+       struct percpu_data *pdata = __percpu_disguise(__pdata);
+       int node = cpu_to_node(cpu);
 
-               if (node_online(node))
-                       pdata->ptrs[i] = kmalloc_node(size, GFP_KERNEL, node);
-               else
-                       pdata->ptrs[i] = kmalloc(size, GFP_KERNEL);
+       BUG_ON(pdata->ptrs[cpu]);
+       if (node_online(node)) {
+               /* FIXME: kzalloc_node(size, gfp, node) */
+               pdata->ptrs[cpu] = kmalloc_node(size, gfp, node);
+               if (pdata->ptrs[cpu])
+                       memset(pdata->ptrs[cpu], 0, size);
+       } else
+               pdata->ptrs[cpu] = kzalloc(size, gfp);
+       return pdata->ptrs[cpu];
+}
+EXPORT_SYMBOL_GPL(percpu_populate);
 
-               if (!pdata->ptrs[i])
-                       goto unwind_oom;
-               memset(pdata->ptrs[i], 0, size);
-       }
+/**
+ * percpu_populate_mask - populate per-cpu data for more cpu's
+ * @__pdata: per-cpu data to populate further
+ * @size: size of per-cpu object
+ * @gfp: may sleep or not etc.
+ * @mask: populate per-cpu data for cpu's selected through mask bits
+ *
+ * Per-cpu objects are populated with zeroed buffers.
+ */
+int __percpu_populate_mask(void *__pdata, size_t size, gfp_t gfp,
+                          cpumask_t *mask)
+{
+       cpumask_t populated = CPU_MASK_NONE;
+       int cpu;
 
-       /* Catch derefs w/o wrappers */
-       return (void *)(~(unsigned long)pdata);
+       for_each_cpu_mask(cpu, *mask)
+               if (unlikely(!percpu_populate(__pdata, size, gfp, cpu))) {
+                       __percpu_depopulate_mask(__pdata, &populated);
+                       return -ENOMEM;
+               } else
+                       cpu_set(cpu, populated);
+       return 0;
+}
+EXPORT_SYMBOL_GPL(__percpu_populate_mask);
 
-unwind_oom:
-       while (--i >= 0) {
-               if (!cpu_possible(i))
-                       continue;
-               kfree(pdata->ptrs[i]);
-       }
+/**
+ * percpu_alloc_mask - initial setup of per-cpu data
+ * @size: size of per-cpu object
+ * @gfp: may sleep or not etc.
+ * @mask: populate per-data for cpu's selected through mask bits
+ *
+ * Populating per-cpu data for all online cpu's would be a typical use case,
+ * which is simplified by the percpu_alloc() wrapper.
+ * Per-cpu objects are populated with zeroed buffers.
+ */
+void *__percpu_alloc_mask(size_t size, gfp_t gfp, cpumask_t *mask)
+{
+       void *pdata = kzalloc(sizeof(struct percpu_data), gfp);
+       void *__pdata = __percpu_disguise(pdata);
+
+       if (unlikely(!pdata))
+               return NULL;
+       if (likely(!__percpu_populate_mask(__pdata, size, gfp, mask)))
+               return __pdata;
        kfree(pdata);
        return NULL;
 }
-EXPORT_SYMBOL(__alloc_percpu);
-#endif
+EXPORT_SYMBOL_GPL(__percpu_alloc_mask);
+
+/**
+ * percpu_free - final cleanup of per-cpu data
+ * @__pdata: object to clean up
+ *
+ * We simply clean up any per-cpu object left. No need for the client to
+ * track and specify through a bis mask which per-cpu objects are to free.
+ */
+void percpu_free(void *__pdata)
+{
+       __percpu_depopulate_mask(__pdata, &cpu_possible_map);
+       kfree(__percpu_disguise(__pdata));
+}
+EXPORT_SYMBOL_GPL(percpu_free);
+#endif /* CONFIG_SMP */
 
 /**
  * kmem_cache_free - Deallocate an object
@@ -3404,29 +3609,6 @@ void kfree(const void *objp)
 }
 EXPORT_SYMBOL(kfree);
 
-#ifdef CONFIG_SMP
-/**
- * free_percpu - free previously allocated percpu memory
- * @objp: pointer returned by alloc_percpu.
- *
- * Don't free memory not originally allocated by alloc_percpu()
- * The complemented objp is to check for that.
- */
-void free_percpu(const void *objp)
-{
-       int i;
-       struct percpu_data *p = (struct percpu_data *)(~(unsigned long)objp);
-
-       /*
-        * We allocate for all cpus so we cannot use for online cpu here.
-        */
-       for_each_possible_cpu(i)
-           kfree(p->ptrs[i]);
-       kfree(p);
-}
-EXPORT_SYMBOL(free_percpu);
-#endif
-
 unsigned int kmem_cache_size(struct kmem_cache *cachep)
 {
        return obj_size(cachep);
@@ -3543,22 +3725,26 @@ static void do_ccupdate_local(void *info)
 static int do_tune_cpucache(struct kmem_cache *cachep, int limit,
                                int batchcount, int shared)
 {
-       struct ccupdate_struct new;
-       int i, err;
+       struct ccupdate_struct *new;
+       int i;
+
+       new = kzalloc(sizeof(*new), GFP_KERNEL);
+       if (!new)
+               return -ENOMEM;
 
-       memset(&new.new, 0, sizeof(new.new));
        for_each_online_cpu(i) {
-               new.new[i] = alloc_arraycache(cpu_to_node(i), limit,
+               new->new[i] = alloc_arraycache(cpu_to_node(i), limit,
                                                batchcount);
-               if (!new.new[i]) {
+               if (!new->new[i]) {
                        for (i--; i >= 0; i--)
-                               kfree(new.new[i]);
+                               kfree(new->new[i]);
+                       kfree(new);
                        return -ENOMEM;
                }
        }
-       new.cachep = cachep;
+       new->cachep = cachep;
 
-       on_each_cpu(do_ccupdate_local, (void *)&new, 1, 1);
+       on_each_cpu(do_ccupdate_local, (void *)new, 1, 1);
 
        check_irq_on();
        cachep->batchcount = batchcount;
@@ -3566,7 +3752,7 @@ static int do_tune_cpucache(struct kmem_cache *cachep, int limit,
        cachep->shared = shared;
 
        for_each_online_cpu(i) {
-               struct array_cache *ccold = new.new[i];
+               struct array_cache *ccold = new->new[i];
                if (!ccold)
                        continue;
                spin_lock_irq(&cachep->nodelists[cpu_to_node(i)]->list_lock);
@@ -3574,18 +3760,12 @@ static int do_tune_cpucache(struct kmem_cache *cachep, int limit,
                spin_unlock_irq(&cachep->nodelists[cpu_to_node(i)]->list_lock);
                kfree(ccold);
        }
-
-       err = alloc_kmemlist(cachep);
-       if (err) {
-               printk(KERN_ERR "alloc_kmemlist failed for %s, error %d.\n",
-                      cachep->name, -err);
-               BUG();
-       }
-       return 0;
+       kfree(new);
+       return alloc_kmemlist(cachep);
 }
 
 /* Called with cache_chain_mutex held always */
-static void enable_cpucache(struct kmem_cache *cachep)
+static int enable_cpucache(struct kmem_cache *cachep)
 {
        int err;
        int limit, shared;
@@ -3637,6 +3817,7 @@ static void enable_cpucache(struct kmem_cache *cachep)
        if (err)
                printk(KERN_ERR "enable_cpucache failed for %s, error %d.\n",
                       cachep->name, -err);
+       return err;
 }
 
 /*
@@ -3694,10 +3875,6 @@ static void cache_reap(void *unused)
        }
 
        list_for_each_entry(searchp, &cache_chain, next) {
-               struct list_head *p;
-               int tofree;
-               struct slab *slabp;
-
                check_irq_on();
 
                /*
@@ -3722,47 +3899,22 @@ static void cache_reap(void *unused)
 
                drain_array(searchp, l3, l3->shared, 0, node);
 
-               if (l3->free_touched) {
+               if (l3->free_touched)
                        l3->free_touched = 0;
-                       goto next;
-               }
-
-               tofree = (l3->free_limit + 5 * searchp->num - 1) /
-                               (5 * searchp->num);
-               do {
-                       /*
-                        * Do not lock if there are no free blocks.
-                        */
-                       if (list_empty(&l3->slabs_free))
-                               break;
+               else {
+                       int freed;
 
-                       spin_lock_irq(&l3->list_lock);
-                       p = l3->slabs_free.next;
-                       if (p == &(l3->slabs_free)) {
-                               spin_unlock_irq(&l3->list_lock);
-                               break;
-                       }
-
-                       slabp = list_entry(p, struct slab, list);
-                       BUG_ON(slabp->inuse);
-                       list_del(&slabp->list);
-                       STATS_INC_REAPED(searchp);
-
-                       /*
-                        * Safe to drop the lock. The slab is no longer linked
-                        * to the cache. searchp cannot disappear, we hold
-                        * cache_chain_lock
-                        */
-                       l3->free_objects -= searchp->num;
-                       spin_unlock_irq(&l3->list_lock);
-                       slab_destroy(searchp, slabp);
-               } while (--tofree > 0);
+                       freed = drain_freelist(searchp, l3, (l3->free_limit +
+                               5 * searchp->num - 1) / (5 * searchp->num));
+                       STATS_ADD_REAPED(searchp, freed);
+               }
 next:
                cond_resched();
        }
        check_irq_on();
        mutex_unlock(&cache_chain_mutex);
        next_reap_node();
+       refresh_cpu_vm_stats(smp_processor_id());
        /* Set up the next iteration */
        schedule_delayed_work(&__get_cpu_var(reap_work), REAPTIMEOUT_CPUC);
 }
@@ -4126,6 +4278,7 @@ static int leaks_show(struct seq_file *m, void *p)
                show_symbol(m, n[2*i+2]);
                seq_putc(m, '\n');
        }
+
        return 0;
 }