[PPC] MCC2 missing in MPC826x device_list
[safe/jmp/linux-2.6] / mm / slub.c
index b9e0536..5e3e8bc 100644 (file)
--- a/mm/slub.c
+++ b/mm/slub.c
  * PageActive          The slab is used as a cpu cache. Allocations
  *                     may be performed from the slab. The slab is not
  *                     on any slab list and cannot be moved onto one.
+ *                     The cpu slab may be equipped with an additioanl
+ *                     lockless_freelist that allows lockless access to
+ *                     free objects in addition to the regular freelist
+ *                     that requires the slab lock.
  *
  * PageError           Slab requires special handling due to debug
  *                     options set. This moves slab handling out of
- *                     the fast path.
+ *                     the fast path and disables lockless freelists.
  */
 
 static inline int SlabDebug(struct page *page)
 {
+#ifdef CONFIG_SLUB_DEBUG
        return PageError(page);
+#else
+       return 0;
+#endif
 }
 
 static inline void SetSlabDebug(struct page *page)
 {
+#ifdef CONFIG_SLUB_DEBUG
        SetPageError(page);
+#endif
 }
 
 static inline void ClearSlabDebug(struct page *page)
 {
+#ifdef CONFIG_SLUB_DEBUG
        ClearPageError(page);
+#endif
 }
 
 /*
@@ -207,7 +219,7 @@ struct track {
 
 enum track_item { TRACK_ALLOC, TRACK_FREE };
 
-#ifdef CONFIG_SYSFS
+#if defined(CONFIG_SYSFS) && defined(CONFIG_SLUB_DEBUG)
 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 *);
@@ -284,6 +296,14 @@ static inline int slab_index(void *p, struct kmem_cache *s, void *addr)
        return (p - addr) / s->size;
 }
 
+#ifdef CONFIG_SLUB_DEBUG
+/*
+ * Debug settings:
+ */
+static int slub_debug;
+
+static char *slub_debug_slabs;
+
 /*
  * Object debugging
  */
@@ -821,6 +841,97 @@ static void trace(struct kmem_cache *s, struct page *page, void *object, int all
        }
 }
 
+static int __init setup_slub_debug(char *str)
+{
+       if (!str || *str != '=')
+               slub_debug = DEBUG_DEFAULT_FLAGS;
+       else {
+               str++;
+               if (*str == 0 || *str == ',')
+                       slub_debug = DEBUG_DEFAULT_FLAGS;
+               else
+               for( ;*str && *str != ','; str++)
+                       switch (*str) {
+                       case 'f' : case 'F' :
+                               slub_debug |= SLAB_DEBUG_FREE;
+                               break;
+                       case 'z' : case 'Z' :
+                               slub_debug |= SLAB_RED_ZONE;
+                               break;
+                       case 'p' : case 'P' :
+                               slub_debug |= SLAB_POISON;
+                               break;
+                       case 'u' : case 'U' :
+                               slub_debug |= SLAB_STORE_USER;
+                               break;
+                       case 't' : case 'T' :
+                               slub_debug |= SLAB_TRACE;
+                               break;
+                       default:
+                               printk(KERN_ERR "slub_debug option '%c' "
+                                       "unknown. skipped\n",*str);
+                       }
+       }
+
+       if (*str == ',')
+               slub_debug_slabs = str + 1;
+       return 1;
+}
+
+__setup("slub_debug", setup_slub_debug);
+
+static void kmem_cache_open_debug_check(struct kmem_cache *s)
+{
+       /*
+        * The page->offset field is only 16 bit wide. This is an offset
+        * in units of words from the beginning of an object. If the slab
+        * size is bigger then we cannot move the free pointer behind the
+        * object anymore.
+        *
+        * On 32 bit platforms the limit is 256k. On 64bit platforms
+        * the limit is 512k.
+        *
+        * Debugging or ctor/dtors may create a need to move the free
+        * pointer. Fail if this happens.
+        */
+       if (s->size >= 65535 * sizeof(void *)) {
+               BUG_ON(s->flags & (SLAB_RED_ZONE | SLAB_POISON |
+                               SLAB_STORE_USER | SLAB_DESTROY_BY_RCU));
+               BUG_ON(s->ctor || s->dtor);
+       }
+       else
+               /*
+                * Enable debugging if selected on the kernel commandline.
+                */
+               if (slub_debug && (!slub_debug_slabs ||
+                   strncmp(slub_debug_slabs, s->name,
+                       strlen(slub_debug_slabs)) == 0))
+                               s->flags |= slub_debug;
+}
+#else
+
+static inline int alloc_object_checks(struct kmem_cache *s,
+               struct page *page, void *object) { return 0; }
+
+static inline int free_object_checks(struct kmem_cache *s,
+               struct page *page, void *object) { return 0; }
+
+static inline void add_full(struct kmem_cache_node *n, struct page *page) {}
+static inline void remove_full(struct kmem_cache *s, struct page *page) {}
+static inline void trace(struct kmem_cache *s, struct page *page,
+                       void *object, int alloc) {}
+static inline void init_object(struct kmem_cache *s,
+                       void *object, int active) {}
+static inline void init_tracking(struct kmem_cache *s, void *object) {}
+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; }
+static inline void set_track(struct kmem_cache *s, void *object,
+                       enum track_item alloc, void *addr) {}
+static inline void kmem_cache_open_debug_check(struct kmem_cache *s) {}
+#define slub_debug 0
+#endif
 /*
  * Slab allocation and freeing
  */
@@ -907,6 +1018,7 @@ static struct page *new_slab(struct kmem_cache *s, gfp_t flags, int node)
        set_freepointer(s, last, NULL);
 
        page->freelist = start;
+       page->lockless_freelist = NULL;
        page->inuse = 0;
 out:
        if (flags & __GFP_WAIT)
@@ -1169,6 +1281,23 @@ static void putback_slab(struct kmem_cache *s, struct page *page)
  */
 static void deactivate_slab(struct kmem_cache *s, struct page *page, int cpu)
 {
+       /*
+        * Merge cpu freelist into freelist. Typically we get here
+        * because both freelists are empty. So this is unlikely
+        * to occur.
+        */
+       while (unlikely(page->lockless_freelist)) {
+               void **object;
+
+               /* Retrieve object from cpu_freelist */
+               object = page->lockless_freelist;
+               page->lockless_freelist = page->lockless_freelist[page->offset];
+
+               /* And put onto the regular freelist */
+               object[page->offset] = page->freelist;
+               page->freelist = object;
+               page->inuse--;
+       }
        s->cpu_slab[cpu] = NULL;
        ClearPageActive(page);
 
@@ -1215,47 +1344,46 @@ static void flush_all(struct kmem_cache *s)
 }
 
 /*
- * slab_alloc is optimized to only modify two cachelines on the fast path
- * (aside from the stack):
+ * Slow path. The lockless freelist is empty or we need to perform
+ * debugging duties.
+ *
+ * Interrupts are disabled.
  *
- * 1. The page struct
- * 2. The first cacheline of the object to be allocated.
+ * Processing is still very fast if new objects have been freed to the
+ * regular freelist. In that case we simply take over the regular freelist
+ * as the lockless freelist and zap the regular freelist.
  *
- * The only other cache lines that are read (apart from code) is the
- * per cpu array in the kmem_cache struct.
+ * If that is not working then we fall back to the partial lists. We take the
+ * first element of the freelist as the object to allocate now and move the
+ * rest of the freelist to the lockless freelist.
  *
- * Fastpath is not possible if we need to get a new slab or have
- * debugging enabled (which means all slabs are marked with SlabDebug)
+ * And if we were unable to get a new slab from the partial slab lists then
+ * we need to allocate a new slab. This is slowest path since we may sleep.
  */
-static void *slab_alloc(struct kmem_cache *s,
-                               gfp_t gfpflags, int node, void *addr)
+static void *__slab_alloc(struct kmem_cache *s,
+               gfp_t gfpflags, int node, void *addr, struct page *page)
 {
-       struct page *page;
        void **object;
-       unsigned long flags;
-       int cpu;
+       int cpu = smp_processor_id();
 
-       local_irq_save(flags);
-       cpu = smp_processor_id();
-       page = s->cpu_slab[cpu];
        if (!page)
                goto new_slab;
 
        slab_lock(page);
        if (unlikely(node != -1 && page_to_nid(page) != node))
                goto another_slab;
-redo:
+load_freelist:
        object = page->freelist;
        if (unlikely(!object))
                goto another_slab;
        if (unlikely(SlabDebug(page)))
                goto debug;
 
-have_object:
-       page->inuse++;
-       page->freelist = object[page->offset];
+       object = page->freelist;
+       page->lockless_freelist = object[page->offset];
+       page->inuse = s->objects;
+       page->freelist = NULL;
        slab_unlock(page);
-       local_irq_restore(flags);
        return object;
 
 another_slab:
@@ -1263,11 +1391,11 @@ another_slab:
 
 new_slab:
        page = get_partial(s, gfpflags, node);
-       if (likely(page)) {
+       if (page) {
 have_slab:
                s->cpu_slab[cpu] = page;
                SetPageActive(page);
-               goto redo;
+               goto load_freelist;
        }
 
        page = new_slab(s, gfpflags, node);
@@ -1290,7 +1418,7 @@ have_slab:
                                discard_slab(s, page);
                                page = s->cpu_slab[cpu];
                                slab_lock(page);
-                               goto redo;
+                               goto load_freelist;
                        }
                        /* New slab does not fit our expectations */
                        flush_slab(s, s->cpu_slab[cpu], cpu);
@@ -1298,16 +1426,52 @@ have_slab:
                slab_lock(page);
                goto have_slab;
        }
-       local_irq_restore(flags);
        return NULL;
 debug:
+       object = page->freelist;
        if (!alloc_object_checks(s, page, object))
                goto another_slab;
        if (s->flags & SLAB_STORE_USER)
                set_track(s, object, TRACK_ALLOC, addr);
        trace(s, page, object, 1);
        init_object(s, object, 1);
-       goto have_object;
+
+       page->inuse++;
+       page->freelist = object[page->offset];
+       slab_unlock(page);
+       return object;
+}
+
+/*
+ * Inlined fastpath so that allocation functions (kmalloc, kmem_cache_alloc)
+ * have the fastpath folded into their functions. So no function call
+ * overhead for requests that can be satisfied on the fastpath.
+ *
+ * The fastpath works by first checking if the lockless freelist can be used.
+ * If not then __slab_alloc is called for slow processing.
+ *
+ * Otherwise we can simply pick the next object from the lockless free list.
+ */
+static void __always_inline *slab_alloc(struct kmem_cache *s,
+                               gfp_t gfpflags, int node, void *addr)
+{
+       struct page *page;
+       void **object;
+       unsigned long flags;
+
+       local_irq_save(flags);
+       page = s->cpu_slab[smp_processor_id()];
+       if (unlikely(!page || !page->lockless_freelist ||
+                       (node != -1 && page_to_nid(page) != node)))
+
+               object = __slab_alloc(s, gfpflags, node, addr, page);
+
+       else {
+               object = page->lockless_freelist;
+               page->lockless_freelist = object[page->offset];
+       }
+       local_irq_restore(flags);
+       return object;
 }
 
 void *kmem_cache_alloc(struct kmem_cache *s, gfp_t gfpflags)
@@ -1325,20 +1489,19 @@ EXPORT_SYMBOL(kmem_cache_alloc_node);
 #endif
 
 /*
- * The fastpath only writes the cacheline of the page struct and the first
- * cacheline of the object.
+ * Slow patch handling. This may still be called frequently since objects
+ * have a longer lifetime than the cpu slabs in most processing loads.
  *
- * We read the cpu_slab cacheline to check if the slab is the per cpu
- * slab for this processor.
+ * So we still attempt to reduce cache line usage. Just take the slab
+ * lock and free the item. If there is no additional partial page
+ * handling required then we can return immediately.
  */
-static void slab_free(struct kmem_cache *s, struct page *page,
+static void __slab_free(struct kmem_cache *s, struct page *page,
                                        void *x, void *addr)
 {
        void *prior;
        void **object = (void *)x;
-       unsigned long flags;
 
-       local_irq_save(flags);
        slab_lock(page);
 
        if (unlikely(SlabDebug(page)))
@@ -1368,7 +1531,6 @@ checks_ok:
 
 out_unlock:
        slab_unlock(page);
-       local_irq_restore(flags);
        return;
 
 slab_empty:
@@ -1380,7 +1542,6 @@ slab_empty:
 
        slab_unlock(page);
        discard_slab(s, page);
-       local_irq_restore(flags);
        return;
 
 debug:
@@ -1395,6 +1556,34 @@ debug:
        goto checks_ok;
 }
 
+/*
+ * Fastpath with forced inlining to produce a kfree and kmem_cache_free that
+ * can perform fastpath freeing without additional function calls.
+ *
+ * The fastpath is only possible if we are freeing to the current cpu slab
+ * of this processor. This typically the case if we have just allocated
+ * the item before.
+ *
+ * If fastpath is not possible then fall back to __slab_free where we deal
+ * with all sorts of special processing.
+ */
+static void __always_inline slab_free(struct kmem_cache *s,
+                       struct page *page, void *x, void *addr)
+{
+       void **object = (void *)x;
+       unsigned long flags;
+
+       local_irq_save(flags);
+       if (likely(page == s->cpu_slab[smp_processor_id()] &&
+                                               !SlabDebug(page))) {
+               object[page->offset] = page->lockless_freelist;
+               page->lockless_freelist = object;
+       } else
+               __slab_free(s, page, x, addr);
+
+       local_irq_restore(flags);
+}
+
 void kmem_cache_free(struct kmem_cache *s, void *x)
 {
        struct page *page;
@@ -1446,13 +1635,6 @@ static int slub_min_objects = DEFAULT_MIN_OBJECTS;
 static int slub_nomerge;
 
 /*
- * Debug settings:
- */
-static int slub_debug;
-
-static char *slub_debug_slabs;
-
-/*
  * Calculate the order of allocation given an slab object size.
  *
  * The order of allocation has significant impact on performance and other
@@ -1477,34 +1659,75 @@ static char *slub_debug_slabs;
  * requested a higher mininum order then we start with that one instead of
  * the smallest order which will fit the object.
  */
-static int calculate_order(int size)
+static inline int slab_order(int size, int min_objects,
+                               int max_order, int fract_leftover)
 {
        int order;
        int rem;
 
-       for (order = max(slub_min_order, fls(size - 1) - PAGE_SHIFT);
-                       order < MAX_ORDER; order++) {
-               unsigned long slab_size = PAGE_SIZE << order;
+       for (order = max(slub_min_order,
+                               fls(min_objects * size - 1) - PAGE_SHIFT);
+                       order <= max_order; order++) {
 
-               if (slub_max_order > order &&
-                               slab_size < slub_min_objects * size)
-                       continue;
+               unsigned long slab_size = PAGE_SIZE << order;
 
-               if (slab_size < size)
+               if (slab_size < min_objects * size)
                        continue;
 
                rem = slab_size % size;
 
-               if (rem <= slab_size / 8)
+               if (rem <= slab_size / fract_leftover)
                        break;
 
        }
-       if (order >= MAX_ORDER)
-               return -E2BIG;
 
        return order;
 }
 
+static inline int calculate_order(int size)
+{
+       int order;
+       int min_objects;
+       int fraction;
+
+       /*
+        * Attempt to find best configuration for a slab. This
+        * works by first attempting to generate a layout with
+        * the best configuration and backing off gradually.
+        *
+        * First we reduce the acceptable waste in a slab. Then
+        * we reduce the minimum objects required in a slab.
+        */
+       min_objects = slub_min_objects;
+       while (min_objects > 1) {
+               fraction = 8;
+               while (fraction >= 4) {
+                       order = slab_order(size, min_objects,
+                                               slub_max_order, fraction);
+                       if (order <= slub_max_order)
+                               return order;
+                       fraction /= 2;
+               }
+               min_objects /= 2;
+       }
+
+       /*
+        * We were unable to place multiple objects in a slab. Now
+        * lets see if we can place a single object there.
+        */
+       order = slab_order(size, 1, slub_max_order, 1);
+       if (order <= slub_max_order)
+               return order;
+
+       /*
+        * Doh this slab cannot be placed using slub_max_order.
+        */
+       order = slab_order(size, 1, MAX_ORDER, 1);
+       if (order <= MAX_ORDER)
+               return order;
+       return -ENOSYS;
+}
+
 /*
  * Figure out what the alignment of the objects will be.
  */
@@ -1660,6 +1883,7 @@ static int calculate_sizes(struct kmem_cache *s)
         */
        size = ALIGN(size, sizeof(void *));
 
+#ifdef CONFIG_SLUB_DEBUG
        /*
         * If we are Redzoning then check if there is some space between the
         * end of the object and the free pointer. If not then add an
@@ -1667,6 +1891,7 @@ static int calculate_sizes(struct kmem_cache *s)
         */
        if ((flags & SLAB_RED_ZONE) && size == s->objsize)
                size += sizeof(void *);
+#endif
 
        /*
         * With that we have determined the number of bytes in actual use
@@ -1674,6 +1899,7 @@ static int calculate_sizes(struct kmem_cache *s)
         */
        s->inuse = size;
 
+#ifdef CONFIG_SLUB_DEBUG
        if (((flags & (SLAB_DESTROY_BY_RCU | SLAB_POISON)) ||
                s->ctor || s->dtor)) {
                /*
@@ -1704,6 +1930,7 @@ static int calculate_sizes(struct kmem_cache *s)
                 * of the object.
                 */
                size += sizeof(void *);
+#endif
 
        /*
         * Determine the alignment based on various parameters that the
@@ -1753,32 +1980,7 @@ static int kmem_cache_open(struct kmem_cache *s, gfp_t gfpflags,
        s->objsize = size;
        s->flags = flags;
        s->align = align;
-
-       /*
-        * The page->offset field is only 16 bit wide. This is an offset
-        * in units of words from the beginning of an object. If the slab
-        * size is bigger then we cannot move the free pointer behind the
-        * object anymore.
-        *
-        * On 32 bit platforms the limit is 256k. On 64bit platforms
-        * the limit is 512k.
-        *
-        * Debugging or ctor/dtors may create a need to move the free
-        * pointer. Fail if this happens.
-        */
-       if (s->size >= 65535 * sizeof(void *)) {
-               BUG_ON(flags & (SLAB_RED_ZONE | SLAB_POISON |
-                               SLAB_STORE_USER | SLAB_DESTROY_BY_RCU));
-               BUG_ON(ctor || dtor);
-       }
-       else
-               /*
-                * Enable debugging if selected on the kernel commandline.
-                */
-               if (slub_debug && (!slub_debug_slabs ||
-                   strncmp(slub_debug_slabs, name,
-                       strlen(slub_debug_slabs)) == 0))
-                               s->flags |= slub_debug;
+       kmem_cache_open_debug_check(s);
 
        if (!calculate_sizes(s))
                goto error;
@@ -1949,45 +2151,6 @@ static int __init setup_slub_nomerge(char *str)
 
 __setup("slub_nomerge", setup_slub_nomerge);
 
-static int __init setup_slub_debug(char *str)
-{
-       if (!str || *str != '=')
-               slub_debug = DEBUG_DEFAULT_FLAGS;
-       else {
-               str++;
-               if (*str == 0 || *str == ',')
-                       slub_debug = DEBUG_DEFAULT_FLAGS;
-               else
-               for( ;*str && *str != ','; str++)
-                       switch (*str) {
-                       case 'f' : case 'F' :
-                               slub_debug |= SLAB_DEBUG_FREE;
-                               break;
-                       case 'z' : case 'Z' :
-                               slub_debug |= SLAB_RED_ZONE;
-                               break;
-                       case 'p' : case 'P' :
-                               slub_debug |= SLAB_POISON;
-                               break;
-                       case 'u' : case 'U' :
-                               slub_debug |= SLAB_STORE_USER;
-                               break;
-                       case 't' : case 'T' :
-                               slub_debug |= SLAB_TRACE;
-                               break;
-                       default:
-                               printk(KERN_ERR "slub_debug option '%c' "
-                                       "unknown. skipped\n",*str);
-                       }
-       }
-
-       if (*str == ',')
-               slub_debug_slabs = str + 1;
-       return 1;
-}
-
-__setup("slub_debug", setup_slub_debug);
-
 static struct kmem_cache *create_kmalloc_cache(struct kmem_cache *s,
                const char *name, int size, gfp_t gfp_flags)
 {
@@ -2205,7 +2368,6 @@ EXPORT_SYMBOL(kmem_cache_shrink);
 
 /**
  * krealloc - reallocate memory. The contents will remain unchanged.
- *
  * @p: object to reallocate memory for.
  * @new_size: how many bytes of memory are required.
  * @flags: the type of memory to allocate.
@@ -2283,9 +2445,8 @@ void __init kmem_cache_init(void)
        register_cpu_notifier(&slab_notifier);
 #endif
 
-       if (nr_cpu_ids) /* Remove when nr_cpu_ids is fixed upstream ! */
-               kmem_size = offsetof(struct kmem_cache, cpu_slab)
-                        + nr_cpu_ids * sizeof(struct page *);
+       kmem_size = offsetof(struct kmem_cache, cpu_slab) +
+                               nr_cpu_ids * sizeof(struct page *);
 
        printk(KERN_INFO "SLUB: Genslabs=%d, HWalign=%d, Order=%d-%d, MinObjects=%d,"
                " Processors=%d, Nodes=%d\n",
@@ -2361,7 +2522,7 @@ struct kmem_cache *kmem_cache_create(const char *name, size_t size,
        struct kmem_cache *s;
 
        down_write(&slub_lock);
-       s = find_mergeable(size, align, flags, dtor, ctor);
+       s = find_mergeable(size, align, flags, ctor, dtor);
        if (s) {
                s->refcount++;
                /*
@@ -2434,7 +2595,9 @@ static int __cpuinit slab_cpuup_callback(struct notifier_block *nfb,
 
        switch (action) {
        case CPU_UP_CANCELED:
+       case CPU_UP_CANCELED_FROZEN:
        case CPU_DEAD:
+       case CPU_DEAD_FROZEN:
                for_all_slabs(__flush_cpu_slab, cpu);
                break;
        default:
@@ -2448,91 +2611,6 @@ static struct notifier_block __cpuinitdata slab_notifier =
 
 #endif
 
-#ifdef CONFIG_NUMA
-
-/*****************************************************************
- * Generic reaper used to support the page allocator
- * (the cpu slabs are reaped by a per slab workqueue).
- *
- * Maybe move this to the page allocator?
- ****************************************************************/
-
-static DEFINE_PER_CPU(unsigned long, reap_node);
-
-static void init_reap_node(int cpu)
-{
-       int node;
-
-       node = next_node(cpu_to_node(cpu), node_online_map);
-       if (node == MAX_NUMNODES)
-               node = first_node(node_online_map);
-
-       __get_cpu_var(reap_node) = node;
-}
-
-static void next_reap_node(void)
-{
-       int node = __get_cpu_var(reap_node);
-
-       /*
-        * Also drain per cpu pages on remote zones
-        */
-       if (node != numa_node_id())
-               drain_node_pages(node);
-
-       node = next_node(node, node_online_map);
-       if (unlikely(node >= MAX_NUMNODES))
-               node = first_node(node_online_map);
-       __get_cpu_var(reap_node) = node;
-}
-#else
-#define init_reap_node(cpu) do { } while (0)
-#define next_reap_node(void) do { } while (0)
-#endif
-
-#define REAPTIMEOUT_CPUC       (2*HZ)
-
-#ifdef CONFIG_SMP
-static DEFINE_PER_CPU(struct delayed_work, reap_work);
-
-static void cache_reap(struct work_struct *unused)
-{
-       next_reap_node();
-       refresh_cpu_vm_stats(smp_processor_id());
-       schedule_delayed_work(&__get_cpu_var(reap_work),
-                                     REAPTIMEOUT_CPUC);
-}
-
-static void __devinit start_cpu_timer(int 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->work.func == NULL) {
-               init_reap_node(cpu);
-               INIT_DELAYED_WORK(reap_work, cache_reap);
-               schedule_delayed_work_on(cpu, reap_work, HZ + 3 * cpu);
-       }
-}
-
-static int __init cpucache_init(void)
-{
-       int cpu;
-
-       /*
-        * Register the timers that drain pcp pages and update vm statistics
-        */
-       for_each_online_cpu(cpu)
-               start_cpu_timer(cpu);
-       return 0;
-}
-__initcall(cpucache_init);
-#endif
-
 void *__kmalloc_track_caller(size_t size, gfp_t gfpflags, void *caller)
 {
        struct kmem_cache *s = get_slab(size, gfpflags);
@@ -2554,8 +2632,7 @@ void *__kmalloc_node_track_caller(size_t size, gfp_t gfpflags,
        return slab_alloc(s, gfpflags, node, caller);
 }
 
-#ifdef CONFIG_SYSFS
-
+#if defined(CONFIG_SYSFS) && defined(CONFIG_SLUB_DEBUG)
 static int validate_slab(struct kmem_cache *s, struct page *page)
 {
        void *p;
@@ -2712,6 +2789,13 @@ static void resiliency_test(void) {};
 struct location {
        unsigned long count;
        void *addr;
+       long long sum_time;
+       long min_time;
+       long max_time;
+       long min_pid;
+       long max_pid;
+       cpumask_t cpus;
+       nodemask_t nodes;
 };
 
 struct loc_track {
@@ -2752,11 +2836,12 @@ static int alloc_loc_track(struct loc_track *t, unsigned long max)
 }
 
 static int add_location(struct loc_track *t, struct kmem_cache *s,
-                                               void *addr)
+                               const struct track *track)
 {
        long start, end, pos;
        struct location *l;
        void *caddr;
+       unsigned long age = jiffies - track->when;
 
        start = -1;
        end = t->count;
@@ -2772,12 +2857,29 @@ static int add_location(struct loc_track *t, struct kmem_cache *s,
                        break;
 
                caddr = t->loc[pos].addr;
-               if (addr == caddr) {
-                       t->loc[pos].count++;
+               if (track->addr == caddr) {
+
+                       l = &t->loc[pos];
+                       l->count++;
+                       if (track->when) {
+                               l->sum_time += age;
+                               if (age < l->min_time)
+                                       l->min_time = age;
+                               if (age > l->max_time)
+                                       l->max_time = age;
+
+                               if (track->pid < l->min_pid)
+                                       l->min_pid = track->pid;
+                               if (track->pid > l->max_pid)
+                                       l->max_pid = track->pid;
+
+                               cpu_set(track->cpu, l->cpus);
+                       }
+                       node_set(page_to_nid(virt_to_page(track)), l->nodes);
                        return 1;
                }
 
-               if (addr < caddr)
+               if (track->addr < caddr)
                        end = pos;
                else
                        start = pos;
@@ -2795,7 +2897,16 @@ static int add_location(struct loc_track *t, struct kmem_cache *s,
                        (t->count - pos) * sizeof(struct location));
        t->count++;
        l->count = 1;
-       l->addr = addr;
+       l->addr = track->addr;
+       l->sum_time = age;
+       l->min_time = age;
+       l->max_time = age;
+       l->min_pid = track->pid;
+       l->max_pid = track->pid;
+       cpus_clear(l->cpus);
+       cpu_set(track->cpu, l->cpus);
+       nodes_clear(l->nodes);
+       node_set(page_to_nid(virt_to_page(track)), l->nodes);
        return 1;
 }
 
@@ -2811,11 +2922,8 @@ static void process_slab(struct loc_track *t, struct kmem_cache *s,
                set_bit(slab_index(p, s, addr), map);
 
        for_each_object(p, s, addr)
-               if (!test_bit(slab_index(p, s, addr), map)) {
-                       void *addr = get_track(s, p, alloc)->addr;
-
-                       add_location(t, s, addr);
-               }
+               if (!test_bit(slab_index(p, s, addr), map))
+                       add_location(t, s, get_track(s, p, alloc));
 }
 
 static int list_locations(struct kmem_cache *s, char *buf,
@@ -2849,15 +2957,47 @@ static int list_locations(struct kmem_cache *s, char *buf,
        }
 
        for (i = 0; i < t.count; i++) {
-               void *addr = t.loc[i].addr;
+               struct location *l = &t.loc[i];
 
                if (n > PAGE_SIZE - 100)
                        break;
-               n += sprintf(buf + n, "%7ld ", t.loc[i].count);
-               if (addr)
-                       n += sprint_symbol(buf + n, (unsigned long)t.loc[i].addr);
+               n += sprintf(buf + n, "%7ld ", l->count);
+
+               if (l->addr)
+                       n += sprint_symbol(buf + n, (unsigned long)l->addr);
                else
                        n += sprintf(buf + n, "<not-available>");
+
+               if (l->sum_time != l->min_time) {
+                       unsigned long remainder;
+
+                       n += sprintf(buf + n, " age=%ld/%ld/%ld",
+                       l->min_time,
+                       div_long_long_rem(l->sum_time, l->count, &remainder),
+                       l->max_time);
+               } else
+                       n += sprintf(buf + n, " age=%ld",
+                               l->min_time);
+
+               if (l->min_pid != l->max_pid)
+                       n += sprintf(buf + n, " pid=%ld-%ld",
+                               l->min_pid, l->max_pid);
+               else
+                       n += sprintf(buf + n, " pid=%ld",
+                               l->min_pid);
+
+               if (num_online_cpus() > 1 && !cpus_empty(l->cpus)) {
+                       n += sprintf(buf + n, " cpus=");
+                       n += cpulist_scnprintf(buf + n, PAGE_SIZE - n - 50,
+                                       l->cpus);
+               }
+
+               if (num_online_nodes() > 1 && !nodes_empty(l->nodes)) {
+                       n += sprintf(buf + n, " nodes=");
+                       n += nodelist_scnprintf(buf + n, PAGE_SIZE - n - 50,
+                                       l->nodes);
+               }
+
                n += sprintf(buf + n, "\n");
        }