slab: do not panic on invalid gfp_mask
authorMichal Hocko <mhocko@suse.com>
Tue, 26 Jul 2016 22:22:05 +0000 (15:22 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 26 Jul 2016 23:19:19 +0000 (16:19 -0700)
Both SLAB and SLUB BUG() when a caller provides an invalid gfp_mask.
This is a rather harsh way to announce a non-critical issue.  Allocator
is free to ignore invalid flags.  Let's simply replace BUG() by
dump_stack to tell the offender and fixup the mask to move on with the
allocation request.

This is an example for kmalloc(GFP_KERNEL|__GFP_HIGHMEM) from a test
module:

  Unexpected gfp: 0x2 (__GFP_HIGHMEM). Fixing up to gfp: 0x24000c0 (GFP_KERNEL). Fix your code!
  CPU: 0 PID: 2916 Comm: insmod Tainted: G           O    4.6.0-slabgfp2-00002-g4cdfc2ef4892-dirty #936
  Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Debian-1.8.2-1 04/01/2014
  Call Trace:
    dump_stack+0x67/0x90
    cache_alloc_refill+0x201/0x617
    kmem_cache_alloc_trace+0xa7/0x24a
    ? 0xffffffffa0005000
    mymodule_init+0x20/0x1000 [test_slab]
    do_one_initcall+0xe7/0x16c
    ? rcu_read_lock_sched_held+0x61/0x69
    ? kmem_cache_alloc_trace+0x197/0x24a
    do_init_module+0x5f/0x1d9
    load_module+0x1a3d/0x1f21
    ? retint_kernel+0x2d/0x2d
    SyS_init_module+0xe8/0x10e
    ? SyS_init_module+0xe8/0x10e
    do_syscall_64+0x68/0x13f
    entry_SYSCALL64_slow_path+0x25/0x25

Link: http://lkml.kernel.org/r/1465548200-11384-2-git-send-email-mhocko@kernel.org
Signed-off-by: Michal Hocko <mhocko@suse.com>
Cc: Sergey Senozhatsky <sergey.senozhatsky.work@gmail.com>
Cc: Christoph Lameter <cl@linux.com>
Cc: Pekka Enberg <penberg@kernel.org>
Cc: David Rientjes <rientjes@google.com>
Cc: Joonsoo Kim <iamjoonsoo.kim@lge.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
mm/slab.c
mm/slub.c

index 03fb724d6e48f405afe76e025a2b208184c0af7c..fc9496bdd038061db8fd8ce92b4c7b6ec3e2911a 100644 (file)
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -2687,8 +2687,10 @@ static struct page *cache_grow_begin(struct kmem_cache *cachep,
         */
        if (unlikely(flags & GFP_SLAB_BUG_MASK)) {
                gfp_t invalid_mask = flags & GFP_SLAB_BUG_MASK;
-               pr_emerg("Unexpected gfp: %#x (%pGg)\n", invalid_mask, &invalid_mask);
-               BUG();
+               flags &= ~GFP_SLAB_BUG_MASK;
+               pr_warn("Unexpected gfp: %#x (%pGg). Fixing up to gfp: %#x (%pGg). Fix your code!\n",
+                               invalid_mask, &invalid_mask, flags, &flags);
+               dump_stack();
        }
        local_flags = flags & (GFP_CONSTRAINT_MASK|GFP_RECLAIM_MASK);
 
index a2fe4edc3599d9e54581bcbca3655de6db49ebe2..c0cfa272253972b54f4e62cda46014c9ef6c8112 100644 (file)
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -1613,8 +1613,9 @@ static struct page *new_slab(struct kmem_cache *s, gfp_t flags, int node)
 {
        if (unlikely(flags & GFP_SLAB_BUG_MASK)) {
                gfp_t invalid_mask = flags & GFP_SLAB_BUG_MASK;
-               pr_emerg("Unexpected gfp: %#x (%pGg)\n", invalid_mask, &invalid_mask);
-               BUG();
+               flags &= ~GFP_SLAB_BUG_MASK;
+               pr_warn("Unexpected gfp: %#x (%pGg). Fixing up to gfp: %#x (%pGg). Fix your code!\n",
+                               invalid_mask, &invalid_mask, flags, &flags);
        }
 
        return allocate_slab(s,