]> Pileus Git - ~andy/linux/commitdiff
Merge branch 'slab/urgent' into slab/for-linus
authorPekka Enberg <penberg@kernel.org>
Wed, 11 Jan 2012 19:11:29 +0000 (21:11 +0200)
committerPekka Enberg <penberg@kernel.org>
Wed, 11 Jan 2012 19:11:29 +0000 (21:11 +0200)
1  2 
Documentation/kernel-parameters.txt
mm/slab.c
mm/slub.c

index b21093eabef17be6769d1aca0cffd895655c5e7a,81c287fad79d6370d0d697d5ddf33b8af756a036..1aefc79031a4164b147dc363b3cddc5f9bd648d7
@@@ -315,12 -315,12 +315,12 @@@ bytes respectively. Such letter suffixe
                        CPU-intensive style benchmark, and it can vary highly in
                        a microbenchmark depending on workload and compiler.
  
-                       1: only for 32-bit processes
-                       2: only for 64-bit processes
+                       32: only for 32-bit processes
+                       64: only for 64-bit processes
                        on: enable for both 32- and 64-bit processes
                        off: disable for both 32- and 64-bit processes
  
-       amd_iommu=      [HW,X86-84]
+       amd_iommu=      [HW,X86-64]
                        Pass parameters to the AMD IOMMU driver in the system.
                        Possible values are:
                        fullflush - enable flushing of IO/TLB entries when
  
        slram=          [HW,MTD]
  
 +      slab_max_order= [MM, SLAB]
 +                      Determines the maximum allowed order for slabs.
 +                      A high setting may cause OOMs due to memory
 +                      fragmentation.  Defaults to 1 for systems with
 +                      more than 32MB of RAM, 0 otherwise.
 +
        slub_debug[=options[,slabs]]    [MM, SLUB]
                        Enabling slub_debug allows one to determine the
                        culprit if slab objects become corrupted. Enabling
diff --combined mm/slab.c
index a7f9c244aac66908a3d00c9a90047869449553f4,83311c9aaf9de0ad8494f04703c248f155cfc2c1..4ef42baf66f0bb6a6ae73aff3ee2ffed1a276740
+++ b/mm/slab.c
@@@ -479,13 -479,11 +479,13 @@@ EXPORT_SYMBOL(slab_buffer_size)
  #endif
  
  /*
 - * Do not go above this order unless 0 objects fit into the slab.
 + * Do not go above this order unless 0 objects fit into the slab or
 + * overridden on the command line.
   */
 -#define       BREAK_GFP_ORDER_HI      1
 -#define       BREAK_GFP_ORDER_LO      0
 -static int slab_break_gfp_order = BREAK_GFP_ORDER_LO;
 +#define       SLAB_MAX_ORDER_HI       1
 +#define       SLAB_MAX_ORDER_LO       0
 +static int slab_max_order = SLAB_MAX_ORDER_LO;
 +static bool slab_max_order_set __initdata;
  
  /*
   * Functions for storing/retrieving the cachep and or slab from the page
@@@ -597,6 -595,7 +597,7 @@@ static enum 
        PARTIAL_AC,
        PARTIAL_L3,
        EARLY,
+       LATE,
        FULL
  } g_cpucache_up;
  
@@@ -673,7 -672,7 +674,7 @@@ static void init_node_lock_keys(int q
  {
        struct cache_sizes *s = malloc_sizes;
  
-       if (g_cpucache_up != FULL)
+       if (g_cpucache_up < LATE)
                return;
  
        for (s = malloc_sizes; s->cs_size != ULONG_MAX; s++) {
@@@ -853,17 -852,6 +854,17 @@@ static int __init noaliencache_setup(ch
  }
  __setup("noaliencache", noaliencache_setup);
  
 +static int __init slab_max_order_setup(char *str)
 +{
 +      get_option(&str, &slab_max_order);
 +      slab_max_order = slab_max_order < 0 ? 0 :
 +                              min(slab_max_order, MAX_ORDER - 1);
 +      slab_max_order_set = true;
 +
 +      return 1;
 +}
 +__setup("slab_max_order=", slab_max_order_setup);
 +
  #ifdef CONFIG_NUMA
  /*
   * Special reaping functions for NUMA systems called from cache_reap().
@@@ -1512,11 -1500,10 +1513,11 @@@ void __init kmem_cache_init(void
  
        /*
         * Fragmentation resistance on low memory - only use bigger
 -       * page orders on machines with more than 32MB of memory.
 +       * page orders on machines with more than 32MB of memory if
 +       * not overridden on the command line.
         */
 -      if (totalram_pages > (32 << 20) >> PAGE_SHIFT)
 -              slab_break_gfp_order = BREAK_GFP_ORDER_HI;
 +      if (!slab_max_order_set && totalram_pages > (32 << 20) >> PAGE_SHIFT)
 +              slab_max_order = SLAB_MAX_ORDER_HI;
  
        /* Bootstrap is tricky, because several objects are allocated
         * from caches that do not exist yet:
@@@ -1680,6 -1667,8 +1681,8 @@@ void __init kmem_cache_init_late(void
  {
        struct kmem_cache *cachep;
  
+       g_cpucache_up = LATE;
        /* Annotate slab for lockdep -- annotate the malloc caches */
        init_lock_keys();
  
@@@ -1941,8 -1930,8 +1944,8 @@@ static void check_poison_obj(struct kme
                        /* Print header */
                        if (lines == 0) {
                                printk(KERN_ERR
 -                                      "Slab corruption: %s start=%p, len=%d\n",
 -                                      cachep->name, realobj, size);
 +                                      "Slab corruption (%s): %s start=%p, len=%d\n",
 +                                      print_tainted(), cachep->name, realobj, size);
                                print_objinfo(cachep, objp, 0);
                        }
                        /* Hexdump the affected line */
@@@ -2126,7 -2115,7 +2129,7 @@@ static size_t calculate_slab_order(stru
                 * Large number of objects is good, but very large slabs are
                 * currently bad for the gfp()s.
                 */
 -              if (gfporder >= slab_break_gfp_order)
 +              if (gfporder >= slab_max_order)
                        break;
  
                /*
@@@ -3051,9 -3040,8 +3054,9 @@@ static void check_slabp(struct kmem_cac
        if (entries != cachep->num - slabp->inuse) {
  bad:
                printk(KERN_ERR "slab: Internal list corruption detected in "
 -                              "cache '%s'(%d), slabp %p(%d). Hexdump:\n",
 -                      cachep->name, cachep->num, slabp, slabp->inuse);
 +                      "cache '%s'(%d), slabp %p(%d). Tainted(%s). Hexdump:\n",
 +                      cachep->name, cachep->num, slabp, slabp->inuse,
 +                      print_tainted());
                print_hex_dump(KERN_ERR, "", DUMP_PREFIX_OFFSET, 16, 1, slabp,
                        sizeof(*slabp) + cachep->num * sizeof(kmem_bufctl_t),
                        1);
diff --combined mm/slub.c
index a47df0aa5d367c637de854de285c99ad9c96cfdd,8284a206f48d2da3a712adb726ec4319c91c632f..19436f53876079b6de95e13270d1ef5b22a169c6
+++ b/mm/slub.c
@@@ -570,7 -570,7 +570,7 @@@ static void slab_bug(struct kmem_cache 
        va_end(args);
        printk(KERN_ERR "========================================"
                        "=====================================\n");
 -      printk(KERN_ERR "BUG %s: %s\n", s->name, buf);
 +      printk(KERN_ERR "BUG %s (%s): %s\n", s->name, print_tainted(), buf);
        printk(KERN_ERR "----------------------------------------"
                        "-------------------------------------\n\n");
  }
@@@ -2126,37 -2126,6 +2126,37 @@@ static inline void *new_slab_objects(st
        return object;
  }
  
 +/*
 + * Check the page->freelist of a page and either transfer the freelist to the per cpu freelist
 + * or deactivate the page.
 + *
 + * The page is still frozen if the return value is not NULL.
 + *
 + * If this function returns NULL then the page has been unfrozen.
 + */
 +static inline void *get_freelist(struct kmem_cache *s, struct page *page)
 +{
 +      struct page new;
 +      unsigned long counters;
 +      void *freelist;
 +
 +      do {
 +              freelist = page->freelist;
 +              counters = page->counters;
 +              new.counters = counters;
 +              VM_BUG_ON(!new.frozen);
 +
 +              new.inuse = page->objects;
 +              new.frozen = freelist != NULL;
 +
 +      } while (!cmpxchg_double_slab(s, page,
 +              freelist, counters,
 +              NULL, new.counters,
 +              "get_freelist"));
 +
 +      return freelist;
 +}
 +
  /*
   * Slow path. The lockless freelist is empty or we need to perform
   * debugging duties.
@@@ -2178,6 -2147,8 +2178,6 @@@ static void *__slab_alloc(struct kmem_c
  {
        void **object;
        unsigned long flags;
 -      struct page new;
 -      unsigned long counters;
  
        local_irq_save(flags);
  #ifdef CONFIG_PREEMPT
@@@ -2198,14 -2169,31 +2198,14 @@@ redo
                goto new_slab;
        }
  
 -      stat(s, ALLOC_SLOWPATH);
 -
 -      do {
 -              object = c->page->freelist;
 -              counters = c->page->counters;
 -              new.counters = counters;
 -              VM_BUG_ON(!new.frozen);
 -
 -              /*
 -               * If there is no object left then we use this loop to
 -               * deactivate the slab which is simple since no objects
 -               * are left in the slab and therefore we do not need to
 -               * put the page back onto the partial list.
 -               *
 -               * If there are objects left then we retrieve them
 -               * and use them to refill the per cpu queue.
 -               */
 +      /* must check again c->freelist in case of cpu migration or IRQ */
 +      object = c->freelist;
 +      if (object)
 +              goto load_freelist;
  
 -              new.inuse = c->page->objects;
 -              new.frozen = object != NULL;
 +      stat(s, ALLOC_SLOWPATH);
  
 -      } while (!__cmpxchg_double_slab(s, c->page,
 -                      object, counters,
 -                      NULL, new.counters,
 -                      "__slab_alloc"));
 +      object = get_freelist(s, c->page);
  
        if (!object) {
                c->page = NULL;
@@@ -3043,7 -3031,9 +3043,9 @@@ static int kmem_cache_open(struct kmem_
         *    per node list when we run out of per cpu objects. We only fetch 50%
         *    to keep some capacity around for frees.
         */
-       if (s->size >= PAGE_SIZE)
+       if (kmem_cache_debug(s))
+               s->cpu_partial = 0;
+       else if (s->size >= PAGE_SIZE)
                s->cpu_partial = 2;
        else if (s->size >= 1024)
                s->cpu_partial = 6;
@@@ -4649,8 -4639,6 +4651,8 @@@ static ssize_t cpu_partial_store(struc
        err = strict_strtoul(buf, 10, &objects);
        if (err)
                return err;
 +      if (objects && kmem_cache_debug(s))
 +              return -EINVAL;
  
        s->cpu_partial = objects;
        flush_all(s);