lkml.org 
[lkml]   [2014]   [Jul]   [18]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 3.12 119/170] mm: page_alloc: fix CMA area initialisation when pageblock > MAX_ORDER
    Date
    From: Michal Nazarewicz <mina86@mina86.com>

    3.12-stable review patch. If anyone has any objections, please let me know.

    ===============

    commit dc78327c0ea7da5186d8cbc1647bd6088c5c9fa5 upstream.

    With a kernel configured with ARM64_64K_PAGES && !TRANSPARENT_HUGEPAGE,
    the following is triggered at early boot:

    SMP: Total of 8 processors activated.
    devtmpfs: initialized
    Unable to handle kernel NULL pointer dereference at virtual address 00000008
    pgd = fffffe0000050000
    [00000008] *pgd=00000043fba00003, *pmd=00000043fba00003, *pte=00e0000078010407
    Internal error: Oops: 96000006 [#1] SMP
    Modules linked in:
    CPU: 0 PID: 1 Comm: swapper/0 Not tainted 3.15.0-rc864k+ #44
    task: fffffe03bc040000 ti: fffffe03bc080000 task.ti: fffffe03bc080000
    PC is at __list_add+0x10/0xd4
    LR is at free_one_page+0x270/0x638
    ...
    Call trace:
    __list_add+0x10/0xd4
    free_one_page+0x26c/0x638
    __free_pages_ok.part.52+0x84/0xbc
    __free_pages+0x74/0xbc
    init_cma_reserved_pageblock+0xe8/0x104
    cma_init_reserved_areas+0x190/0x1e4
    do_one_initcall+0xc4/0x154
    kernel_init_freeable+0x204/0x2a8
    kernel_init+0xc/0xd4

    This happens because init_cma_reserved_pageblock() calls
    __free_one_page() with pageblock_order as page order but it is bigger
    than MAX_ORDER. This in turn causes accesses past zone->free_list[].

    Fix the problem by changing init_cma_reserved_pageblock() such that it
    splits pageblock into individual MAX_ORDER pages if pageblock is bigger
    than a MAX_ORDER page.

    In cases where !CONFIG_HUGETLB_PAGE_SIZE_VARIABLE, which is all
    architectures expect for ia64, powerpc and tile at the moment, the
    “pageblock_order > MAX_ORDER” condition will be optimised out since both
    sides of the operator are constants. In cases where pageblock size is
    variable, the performance degradation should not be significant anyway
    since init_cma_reserved_pageblock() is called only at boot time at most
    MAX_CMA_AREAS times which by default is eight.

    Signed-off-by: Michal Nazarewicz <mina86@mina86.com>
    Reported-by: Mark Salter <msalter@redhat.com>
    Tested-by: Mark Salter <msalter@redhat.com>
    Tested-by: Christopher Covington <cov@codeaurora.org>
    Cc: Mel Gorman <mgorman@suse.de>
    Cc: David Rientjes <rientjes@google.com>
    Cc: Marek Szyprowski <m.szyprowski@samsung.com>
    Cc: Catalin Marinas <catalin.marinas@arm.com>
    Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
    Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
    Signed-off-by: Jiri Slaby <jslaby@suse.cz>
    ---
    mm/page_alloc.c | 16 ++++++++++++++--
    1 file changed, 14 insertions(+), 2 deletions(-)

    diff --git a/mm/page_alloc.c b/mm/page_alloc.c
    index 83aaa49bcba7..6e0a9cf8d02a 100644
    --- a/mm/page_alloc.c
    +++ b/mm/page_alloc.c
    @@ -785,9 +785,21 @@ void __init init_cma_reserved_pageblock(struct page *page)
    set_page_count(p, 0);
    } while (++p, --i);

    - set_page_refcounted(page);
    set_pageblock_migratetype(page, MIGRATE_CMA);
    - __free_pages(page, pageblock_order);
    +
    + if (pageblock_order >= MAX_ORDER) {
    + i = pageblock_nr_pages;
    + p = page;
    + do {
    + set_page_refcounted(p);
    + __free_pages(p, MAX_ORDER - 1);
    + p += MAX_ORDER_NR_PAGES;
    + } while (i -= MAX_ORDER_NR_PAGES);
    + } else {
    + set_page_refcounted(page);
    + __free_pages(page, pageblock_order);
    + }
    +
    adjust_managed_page_count(page, pageblock_nr_pages);
    }
    #endif
    --
    2.0.0
    --
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

    \
     
     \ /
      Last update: 2014-07-18 17:21    [W:4.125 / U:0.088 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site