slub: fix high order page allocation problem with __GFP_NOFAIL
authorJoonsoo Kim <iamjoonsoo.kim@lge.com>
Wed, 12 Mar 2014 08:26:20 +0000 (17:26 +0900)
committerPekka Enberg <penberg@kernel.org>
Thu, 27 Mar 2014 12:27:34 +0000 (14:27 +0200)
SLUB already try to allocate high order page with clearing __GFP_NOFAIL.
But, when allocating shadow page for kmemcheck, it missed clearing
the flag. This trigger WARN_ON_ONCE() reported by Christian Casteyde.

https://bugzilla.kernel.org/show_bug.cgi?id=65991
https://lkml.org/lkml/2013/12/3/764

This patch fix this situation by using same allocation flag as original
allocation.

Reported-by: Christian Casteyde <casteyde.christian@free.fr>
Acked-by: David Rientjes <rientjes@google.com>
Signed-off-by: Joonsoo Kim <iamjoonsoo.kim@lge.com>
Signed-off-by: Pekka Enberg <penberg@kernel.org>
mm/slub.c

index 7e3e0458bce4180d115469b8ce622afef9b1e367..591bf985aed0a502fc494039aae4c698c212d708 100644 (file)
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -1350,11 +1350,12 @@ static struct page *allocate_slab(struct kmem_cache *s, gfp_t flags, int node)
        page = alloc_slab_page(alloc_gfp, node, oo);
        if (unlikely(!page)) {
                oo = s->min;
+               alloc_gfp = flags;
                /*
                 * Allocation may have failed due to fragmentation.
                 * Try a lower order alloc if possible
                 */
-               page = alloc_slab_page(flags, node, oo);
+               page = alloc_slab_page(alloc_gfp, node, oo);
 
                if (page)
                        stat(s, ORDER_FALLBACK);
@@ -1364,7 +1365,7 @@ static struct page *allocate_slab(struct kmem_cache *s, gfp_t flags, int node)
                && !(s->flags & (SLAB_NOTRACK | DEBUG_DEFAULT_FLAGS))) {
                int pages = 1 << oo_order(oo);
 
-               kmemcheck_alloc_shadow(page, oo_order(oo), flags, node);
+               kmemcheck_alloc_shadow(page, oo_order(oo), alloc_gfp, node);
 
                /*
                 * Objects from caches that have a constructor don't get