Christoph Lameter wrote:
> Ok so the maximum allocation is 11+12=23 which is 8M. KMALLOC_MAX_SIZE
> amd KMALLOC_SHIFT_HIGH are wrong.
> 
> Take the -1 off the constants under #ifdef CONFIG_SLAB in

Current diff is:

---------- patch start ----------
diff --git a/include/linux/slab.h b/include/linux/slab.h
index 0c62175..889d6ef 100644
--- a/include/linux/slab.h
+++ b/include/linux/slab.h
@@ -189,8 +189,8 @@ struct kmem_cache {
  * to do various tricks to work around compiler limitations in order to
  * ensure proper constant folding.
  */
-#define KMALLOC_SHIFT_HIGH     ((MAX_ORDER + PAGE_SHIFT - 1) <= 25 ? \
-                               (MAX_ORDER + PAGE_SHIFT - 1) : 25)
+#define KMALLOC_SHIFT_HIGH     ((MAX_ORDER + PAGE_SHIFT) <= 26 ? \
+                               (MAX_ORDER + PAGE_SHIFT) : 26)
 #define KMALLOC_SHIFT_MAX      KMALLOC_SHIFT_HIGH
 #ifndef KMALLOC_SHIFT_LOW
 #define KMALLOC_SHIFT_LOW      5
@@ -221,9 +221,9 @@ struct kmem_cache {
 #define KMALLOC_MIN_SIZE (1 << KMALLOC_SHIFT_LOW)
 #endif
 
-extern struct kmem_cache *kmalloc_caches[KMALLOC_SHIFT_HIGH + 1];
+extern struct kmem_cache *kmalloc_caches[KMALLOC_SHIFT_HIGH];
 #ifdef CONFIG_ZONE_DMA
-extern struct kmem_cache *kmalloc_dma_caches[KMALLOC_SHIFT_HIGH + 1];
+extern struct kmem_cache *kmalloc_dma_caches[KMALLOC_SHIFT_HIGH];
 #endif
 
 /*
diff --git a/include/linux/slab_def.h b/include/linux/slab_def.h
index 113ec08..be1446a 100644
--- a/include/linux/slab_def.h
+++ b/include/linux/slab_def.h
@@ -126,6 +126,9 @@ static __always_inline void *kmalloc(size_t size, gfp_t 
flags)
                if (!size)
                        return ZERO_SIZE_PTR;
 
+               if (size > KMALLOC_MAX_SIZE)
+                       goto not_found;
+
                i = kmalloc_index(size);
 
 #ifdef CONFIG_ZONE_DMA
@@ -139,6 +142,7 @@ static __always_inline void *kmalloc(size_t size, gfp_t 
flags)
 
                return ret;
        }
+not_found:
        return __kmalloc(size, flags);
 }
 
@@ -172,8 +176,10 @@ static __always_inline void *kmalloc_node(size_t size, 
gfp_t flags, int node)
                if (!size)
                        return ZERO_SIZE_PTR;
 
-               i = kmalloc_index(size);
+               if (size > KMALLOC_MAX_SIZE)
+                       goto not_found;
 
+               i = kmalloc_index(size);
 #ifdef CONFIG_ZONE_DMA
                if (flags & GFP_DMA)
                        cachep = kmalloc_dma_caches[i];
@@ -183,6 +189,7 @@ static __always_inline void *kmalloc_node(size_t size, 
gfp_t flags, int node)
 
                return kmem_cache_alloc_node_trace(cachep, flags, node, size);
        }
+not_found:
        return __kmalloc_node(size, flags, node);
 }
 
diff --git a/mm/slab_common.c b/mm/slab_common.c
index 2f0e7d5..083e7c7 100644
--- a/mm/slab_common.c
+++ b/mm/slab_common.c
@@ -319,11 +319,11 @@ struct kmem_cache *__init create_kmalloc_cache(const char 
*name, size_t size,
        return s;
 }
 
-struct kmem_cache *kmalloc_caches[KMALLOC_SHIFT_HIGH + 1];
+struct kmem_cache *kmalloc_caches[KMALLOC_SHIFT_HIGH];
 EXPORT_SYMBOL(kmalloc_caches);
 
 #ifdef CONFIG_ZONE_DMA
-struct kmem_cache *kmalloc_dma_caches[KMALLOC_SHIFT_HIGH + 1];
+struct kmem_cache *kmalloc_dma_caches[KMALLOC_SHIFT_HIGH];
 EXPORT_SYMBOL(kmalloc_dma_caches);
 #endif
 
---------- patch end ----------

Current testcases are:

---------- testcases start ----------
        volatile unsigned int size;
        void *ptr;
        ptr = kmalloc(0, GFP_KERNEL);
        printk("kmalloc(%u)=%p\n", 0, ptr);
        kfree(ptr);
        ptr = kmalloc(1, GFP_KERNEL);
        printk("kmalloc(%u)=%p\n", 1, ptr);
        kfree(ptr);
        ptr = kmalloc(2, GFP_KERNEL);
        printk("kmalloc(%u)=%p\n", 2, ptr);
        kfree(ptr);
        ptr = kmalloc(4, GFP_KERNEL);
        printk("kmalloc(%u)=%p\n", 4, ptr);
        kfree(ptr);
        ptr = kmalloc(8, GFP_KERNEL);
        printk("kmalloc(%u)=%p\n", 8, ptr);
        kfree(ptr);
        ptr = kmalloc(16, GFP_KERNEL);
        printk("kmalloc(%u)=%p\n", 16, ptr);
        kfree(ptr);
        ptr = kmalloc(32, GFP_KERNEL);
        printk("kmalloc(%u)=%p\n", 32, ptr);
        kfree(ptr);
        ptr = kmalloc(64, GFP_KERNEL);
        printk("kmalloc(%u)=%p\n", 64, ptr);
        kfree(ptr);
        ptr = kmalloc(128, GFP_KERNEL);
        printk("kmalloc(%u)=%p\n", 128, ptr);
        kfree(ptr);
        ptr = kmalloc(256, GFP_KERNEL);
        printk("kmalloc(%u)=%p\n", 256, ptr);
        kfree(ptr);
        ptr = kmalloc(512, GFP_KERNEL);
        printk("kmalloc(%u)=%p\n", 512, ptr);
        kfree(ptr);
        ptr = kmalloc(1024, GFP_KERNEL);
        printk("kmalloc(%u)=%p\n", 1024, ptr);
        kfree(ptr);
        ptr = kmalloc(2 * 1024, GFP_KERNEL);
        printk("kmalloc(%u)=%p\n", 2 * 1024, ptr);
        kfree(ptr);
        ptr = kmalloc(4 * 1024, GFP_KERNEL);
        printk("kmalloc(%u)=%p\n", 4 * 1024, ptr);
        kfree(ptr);
        ptr = kmalloc(8 * 1024, GFP_KERNEL);
        printk("kmalloc(%u)=%p\n", 8 * 1024, ptr);
        kfree(ptr);
        ptr = kmalloc(16 * 1024, GFP_KERNEL);
        printk("kmalloc(%u)=%p\n", 16 * 1024, ptr);
        kfree(ptr);
        ptr = kmalloc(32 * 1024, GFP_KERNEL);
        printk("kmalloc(%u)=%p\n", 32 * 1024, ptr);
        kfree(ptr);
        ptr = kmalloc(64 * 1024, GFP_KERNEL);
        printk("kmalloc(%u)=%p\n", 64 * 1024, ptr);
        kfree(ptr);
        ptr = kmalloc(128 * 1024, GFP_KERNEL);
        printk("kmalloc(%u)=%p\n", 128 * 1024, ptr);
        kfree(ptr);
        ptr = kmalloc(256 * 1024, GFP_KERNEL);
        printk("kmalloc(%u)=%p\n", 256 * 1024, ptr);
        kfree(ptr);
        ptr = kmalloc(512 * 1024, GFP_KERNEL);
        printk("kmalloc(%u)=%p\n", 512 * 1024, ptr);
        kfree(ptr);
        ptr = kmalloc(1024 * 1024, GFP_KERNEL);
        printk("kmalloc(%u)=%p\n", 1024 * 1024, ptr);
        kfree(ptr);
        ptr = kmalloc(2 * 1024 * 1024, GFP_KERNEL);
        printk("kmalloc(%u)=%p\n", 2 * 1024 * 1024, ptr);
        kfree(ptr);
        ptr = kmalloc(4 * 1024 * 1024, GFP_KERNEL);
        printk("kmalloc(%u)=%p\n", 4 * 1024 * 1024, ptr);
        kfree(ptr);
        ptr = kmalloc(8 * 1024 * 1024, GFP_KERNEL);
        printk("kmalloc(%u)=%p\n", 8 * 1024 * 1024, ptr);
        kfree(ptr);
        ptr = kmalloc(16 * 1024 * 1024, GFP_KERNEL);
        printk("kmalloc(%u)=%p\n", 16 * 1024 * 1024, ptr);
        kfree(ptr);
        ptr = kmalloc(32 * 1024 * 1024, GFP_KERNEL);
        printk("kmalloc(%u)=%p\n", 32 * 1024 * 1024, ptr);
        kfree(ptr);
        ptr = kmalloc(64 * 1024 * 1024, GFP_KERNEL);
        printk("kmalloc(%u)=%p\n", 64 * 1024 * 1024, ptr);
        kfree(ptr);
        ptr = kmalloc(128 * 1024 * 1024, GFP_KERNEL);
        printk("kmalloc(%u)=%p\n", 128 * 1024 * 1024, ptr);
        kfree(ptr);
        ptr = kmalloc(256 * 1024 * 1024, GFP_KERNEL);
        printk("kmalloc(%u)=%p\n", 256 * 1024 * 1024, ptr);
        kfree(ptr);
        ptr = kmalloc(512 * 1024 * 1024, GFP_KERNEL);
        printk("kmalloc(%u)=%p\n", 512 * 1024 * 1024, ptr);
        kfree(ptr);
        ptr = kmalloc(1024 * 1024 * 1024, GFP_KERNEL);
        printk("kmalloc(%u)=%p\n", 1024 * 1024 * 1024, ptr);
        kfree(ptr);
        ptr = kmalloc(2 * 1024 * 1024 * 1024, GFP_KERNEL);
        printk("kmalloc(%u)=%p\n", 2 * 1024 * 1024 * 1024, ptr);
        kfree(ptr);
        ptr = kmalloc(2 * 1024 * 1024 * 1024 + 1, GFP_KERNEL);
        printk("kmalloc(%u)=%p\n", 2 * 1024 * 1024 * 1024 + 1, ptr);
        kfree(ptr);
        for (size = 0; size; size <<= 1) {
                ptr = kmalloc(size, GFP_KERNEL);
                printk("kmalloc(%u)=%p\n", size, ptr);
                kfree(ptr);
                if (!size)
                        size = 1;
        }
        for (size = 1; size; size <<= 1) {
                ptr = kmalloc(size + 1, GFP_KERNEL);
                printk("kmalloc(%u)=%p\n", size + 1, ptr);
                kfree(ptr);
        }
---------- testcases end ----------

The testcases still trigger BUG() at 32M:

---------- dmesg start ----------
(...snipped...)
kmalloc(2097152)=dde00000
kmalloc(4194304)=d9c00000
------------[ cut here ]------------
WARNING: at mm/page_alloc.c:2410 __alloc_pages_nodemask+0x179/0x650()
(...snipped...)
---[ end trace c08f36179e2d8ff2 ]---
SLAB: Unable to allocate memory on node 0 (gfp=0xd0)
  cache: kmalloc-8388608, object size: 8388608, order: 11
  node 0: slabs: 0/0, objs: 0/0, free: 0
kmalloc(8388608)=  (null)
kmalloc(16777216)=  (null)
------------[ cut here ]------------
Kernel BUG at c10b9c9b [verbose debug info unavailable]
invalid opcode: 0000 [#1] SMP
(...snipped...)
---------- dmesg end ----------

This means that redirecting to !__builtin_constant_p(size) case does not help.
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to