Skip to content
  • Joonsoo Kim's avatar
    mm/slab: fix unexpected index mapping result of kmalloc_size(INDEX_NODE+1) · 03a2d2a3
    Joonsoo Kim authored
    Commit description is copied from the original post of this bug:
    
      http://comments.gmane.org/gmane.linux.kernel.mm/135349
    
    Kernels after v3.9 use kmalloc_size(INDEX_NODE + 1) to get the next
    larger cache size than the size index INDEX_NODE mapping.  In kernels
    3.9 and earlier we used malloc_sizes[INDEX_L3 + 1].cs_size.
    
    However, sometimes we can't get the right output we expected via
    kmalloc_size(INDEX_NODE + 1), causing a BUG().
    
    The mapping table in the latest kernel is like:
        index = {0,   1,  2 ,  3,  4,   5,   6,   n}
         size = {0,   96, 192, 8, 16,  32,  64,   2^n}
    The mapping table before 3.10 is like this:
        index = {0 , 1 , 2,   3,  4 ,  5 ,  6,   n}
        size  = {32, 64, 96, 128, 192, 256, 512, 2^(n+3)}
    
    The problem on my mips64 machine is as follows:
    
    (1) When configured DEBUG_SLAB && DEBUG_PAGEALLOC && DEBUG_LOCK_ALLOC
        && DEBUG_SPINLOCK, the sizeof(struct kmem_cache_node) will be "150",
        and the macro INDEX_NODE turns out to be "2": #define INDEX_NODE
        kmalloc_index(sizeof(struct kmem_cache_node))
    
    (2) Then the result of kmalloc_size(INDEX_NODE + 1) is 8.
    
    (3) Then "if(size >= kmalloc_size(INDEX_NODE + 1)" will lead to "size
        = PAGE_SIZE".
    
    (4) Then "if ((size >= (PAGE_SIZE >> 3))" test will be satisfied and
        "flags |= CFLGS_OFF_SLAB" will be covered.
    
    (5) if (flags & CFLGS_OFF_SLAB)" test will be satisfied and will go to
        "cachep->slabp_cache = kmalloc_slab(slab_size, 0u)", and the result
        here may be NULL while kernel bootup.
    
    (6) Finally,"BUG_ON(ZERO_OR_NULL_PTR(cachep->slabp_cache));" causes the
        BUG info as the following shows (may be only mips64 has this problem):
    
    This patch fixes the problem of kmalloc_size(INDEX_NODE + 1) and removes
    the BUG by adding 'size >= 256' check to guarantee that all necessary
    small sized slabs are initialized regardless sequence of slab size in
    mapping table.
    
    Fixes: e3366016
    
     ("slab: Use common kmalloc_index/kmalloc_size...")
    Signed-off-by: default avatarJoonsoo Kim <iamjoonsoo.kim@lge.com>
    Reported-by: default avatarLiuhailong <liu.hailong6@zte.com.cn>
    Acked-by: default avatarChristoph Lameter <cl@linux.com>
    Cc: Pekka Enberg <penberg@kernel.org>
    Cc: David Rientjes <rientjes@google.com>
    Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
    Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
    03a2d2a3