lkml.org 
[lkml]   [2017]   [Sep]   [17]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH for 4.9 30/39] mm/cgroup: avoid panic when init with low memory
    Date
    From: Laurent Dufour <ldufour@linux.vnet.ibm.com>

    [ Upstream commit bfc7228b9a9647e1c353e50b40297a2929801759 ]

    The system may panic when initialisation is done when almost all the
    memory is assigned to the huge pages using the kernel command line
    parameter hugepage=xxxx. Panic may occur like this:

    Unable to handle kernel paging request for data at address 0x00000000
    Faulting instruction address: 0xc000000000302b88
    Oops: Kernel access of bad area, sig: 11 [#1]
    SMP NR_CPUS=2048 [ 0.082424] NUMA
    pSeries
    Modules linked in:
    CPU: 0 PID: 1 Comm: swapper/0 Not tainted 4.9.0-15-generic #16-Ubuntu
    task: c00000021ed01600 task.stack: c00000010d108000
    NIP: c000000000302b88 LR: c000000000270e04 CTR: c00000000016cfd0
    REGS: c00000010d10b2c0 TRAP: 0300 Not tainted (4.9.0-15-generic)
    MSR: 8000000002009033 <SF,VEC,EE,ME,IR,DR,RI,LE>[ 0.082770] CR: 28424422 XER: 00000000
    CFAR: c0000000003d28b8 DAR: 0000000000000000 DSISR: 40000000 SOFTE: 1
    GPR00: c000000000270e04 c00000010d10b540 c00000000141a300 c00000010fff6300
    GPR04: 0000000000000000 00000000026012c0 c00000010d10b630 0000000487ab0000
    GPR08: 000000010ee90000 c000000001454fd8 0000000000000000 0000000000000000
    GPR12: 0000000000004400 c00000000fb80000 00000000026012c0 00000000026012c0
    GPR16: 00000000026012c0 0000000000000000 0000000000000000 0000000000000002
    GPR20: 000000000000000c 0000000000000000 0000000000000000 00000000024200c0
    GPR24: c0000000016eef48 0000000000000000 c00000010fff7d00 00000000026012c0
    GPR28: 0000000000000000 c00000010fff7d00 c00000010fff6300 c00000010d10b6d0
    NIP mem_cgroup_soft_limit_reclaim+0xf8/0x4f0
    LR do_try_to_free_pages+0x1b4/0x450
    Call Trace:
    do_try_to_free_pages+0x1b4/0x450
    try_to_free_pages+0xf8/0x270
    __alloc_pages_nodemask+0x7a8/0xff0
    new_slab+0x104/0x8e0
    ___slab_alloc+0x620/0x700
    __slab_alloc+0x34/0x60
    kmem_cache_alloc_node_trace+0xdc/0x310
    mem_cgroup_init+0x158/0x1c8
    do_one_initcall+0x68/0x1d0
    kernel_init_freeable+0x278/0x360
    kernel_init+0x24/0x170
    ret_from_kernel_thread+0x5c/0x74
    Instruction dump:
    eb81ffe0 eba1ffe8 ebc1fff0 ebe1fff8 4e800020 3d230001 e9499a42 3d220004
    3929acd8 794a1f24 7d295214 eac90100 <e9360000> 2fa90000 419eff74 3b200000
    ---[ end trace 342f5208b00d01b6 ]---

    This is a chicken and egg issue where the kernel try to get free memory
    when allocating per node data in mem_cgroup_init(), but in that path
    mem_cgroup_soft_limit_reclaim() is called which assumes that these data
    are allocated.

    As mem_cgroup_soft_limit_reclaim() is best effort, it should return when
    these data are not yet allocated.

    This patch also fixes potential null pointer access in
    mem_cgroup_remove_from_trees() and mem_cgroup_update_tree().

    Link: http://lkml.kernel.org/r/1487856999-16581-2-git-send-email-ldufour@linux.vnet.ibm.com
    Signed-off-by: Laurent Dufour <ldufour@linux.vnet.ibm.com>
    Acked-by: Michal Hocko <mhocko@suse.com>
    Acked-by: Johannes Weiner <hannes@cmpxchg.org>
    Acked-by: Balbir Singh <bsingharora@gmail.com>
    Cc: Vladimir Davydov <vdavydov.dev@gmail.com>
    Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
    Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
    Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
    ---
    mm/memcontrol.c | 7 +++++--
    1 file changed, 5 insertions(+), 2 deletions(-)

    diff --git a/mm/memcontrol.c b/mm/memcontrol.c
    index 47559cc0cdcc..2a800c4a39bd 100644
    --- a/mm/memcontrol.c
    +++ b/mm/memcontrol.c
    @@ -462,6 +462,8 @@ static void mem_cgroup_update_tree(struct mem_cgroup *memcg, struct page *page)
    struct mem_cgroup_tree_per_node *mctz;

    mctz = soft_limit_tree_from_page(page);
    + if (!mctz)
    + return;
    /*
    * Necessary to update all ancestors when hierarchy is used.
    * because their event counter is not touched.
    @@ -499,7 +501,8 @@ static void mem_cgroup_remove_from_trees(struct mem_cgroup *memcg)
    for_each_node(nid) {
    mz = mem_cgroup_nodeinfo(memcg, nid);
    mctz = soft_limit_tree_node(nid);
    - mem_cgroup_remove_exceeded(mz, mctz);
    + if (mctz)
    + mem_cgroup_remove_exceeded(mz, mctz);
    }
    }

    @@ -2565,7 +2568,7 @@ unsigned long mem_cgroup_soft_limit_reclaim(pg_data_t *pgdat, int order,
    * is empty. Do it lockless to prevent lock bouncing. Races
    * are acceptable as soft limit is best effort anyway.
    */
    - if (RB_EMPTY_ROOT(&mctz->rb_root))
    + if (!mctz || RB_EMPTY_ROOT(&mctz->rb_root))
    return 0;

    /*
    --
    2.11.0
    \
     
     \ /
      Last update: 2017-09-18 02:43    [W:6.537 / U:0.060 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site