• Hugh Dickins's avatar
    memcg: fix oops on NULL lru list · fb59e9f1
    Hugh Dickins authored
    While testing force_empty, during an exit_mmap, __mem_cgroup_remove_list
    called from mem_cgroup_uncharge_page oopsed on a NULL pointer in the lru list.
     I couldn't see what racing tasks on other cpus were doing, but surmise that
    another must have been in mem_cgroup_charge_common on the same page, between
    its unlock_page_cgroup and spin_lock_irqsave near done (thanks to that kzalloc
    which I'd almost changed to a kmalloc).
    
    Normally such a race cannot happen, the ref_cnt prevents it, the final
    uncharge cannot race with the initial charge.  But force_empty buggers the
    ref_cnt, that's what it's all about; and thereafter forced pages are
    vulnerable to races such as this (just think of a shared page also mapped into
    an mm of another mem_cgroup than that just emptied).  And remain vulnerable
    until they're freed indefinitely later.
    
    This patch just fixes the oops by moving the unlock_page_cgroups down below
    adding to and removing from the list (only possible given the previous patch);
    and while we're at it, we might as well make it an invariant that
    page->page_cgroup is always set while pc is on lru.
    
    But this behaviour of force_empty seems highly unsatisfactory to me: why have
    a ref_cnt if we always have to cope with it being violated (as in the earlier
    page migration patch).  We may prefer force_empty to move pages to an orphan
    mem_cgroup (could be the root, but better not), from which other cgroups could
    recover them; we might need to reverse the locking again; but no time now for
    such concerns.
    Signed-off-by: default avatarHugh Dickins <hugh@veritas.com>
    Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
    Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
    fb59e9f1
memcontrol.c 27.2 KB