Patch "mm: memcontrol: fix swap counter leak on swapout from offline cgroup" has been added to the 4.6-stable tree
Subsystems (3)
This is a note to let you know that I've just added the patch titled
mm: memcontrol: fix swap counter leak on swapout from offline cgroup
to the 4.6-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
mm-memcontrol-fix-swap-counter-leak-on-swapout-from-offline-cgroup.patch
and it can be found in the queue-4.6 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.
Quoted 1 line
From
1f47b61fb4077936465dcde872a4e5cc4fe708daMon Sep 17 00:00:00 2001
From: Vladimir Davydov <[email protected]>
Date: Thu, 11 Aug 2016 15:33:00 -0700
Subject: mm: memcontrol: fix swap counter leak on swapout from offline cgroup
From: Vladimir Davydov <[email protected]>
commit 1f47b61fb4077936465dcde872a4e5cc4fe708da upstream.
An offline memory cgroup might have anonymous memory or shmem left charged to it and no swap. Since only swap entries pin the id of an offline cgroup, such a cgroup will have no id and so an attempt to swapout its anon/shmem will not store memory cgroup info in the swap cgroup map. As a result, memcg->swap or memcg->memsw will never get uncharged from it and any of its ascendants.
Fix this by always charging swapout to the first ancestor cgroup that hasn't released its id yet.
--- mm/memcontrol.c | 44 ++++++++++++++++++++++++++++++++++++++------ 1 file changed, 38 insertions(+), 6 deletions(-)
mm/memcontrol.c +38 -6
@@ -4069,6 +4069,24 @@ static void mem_cgroup_id_get(struct mematomic_inc (&memcg->id.ref); } +static struct mem_cgroup *mem_cgroup_id_get_online (struct mem_cgroup *memcg) +{ +while (!atomic_inc_not_zero (&memcg->id.ref)) { +/* +* The root cgroup cannot be destroyed, so it's refcount must +* always be >= 1. +*/ +if (WARN_ON_ONCE (memcg == root_mem_cgroup)) { +VM_BUG_ON (1 ); +break ; + } + memcg =parent_mem_cgroup (memcg); +if (!memcg) + memcg = root_mem_cgroup; + } +return memcg; +} +static void mem_cgroup_id_put (struct mem_cgroup *memcg) {if (atomic_dec_and_test (&memcg->id.ref)) {
@@ -5785,7 +5803,7 @@ subsys_initcall(mem_cgroup_init);*/ void mem_cgroup_swapout (struct page *page,swp_entry_t entry) { -struct mem_cgroup *memcg; +struct mem_cgroup *memcg, *swap_memcg;unsigned short oldid;VM_BUG_ON_PAGE (PageLRU (page), page);
@@ -5800,16 +5818,27 @@ void mem_cgroup_swapout(struct page *pagif (!memcg)return ; -mem_cgroup_id_get (memcg); - oldid =swap_cgroup_record (entry,mem_cgroup_id (memcg)); +/* +* In case the memcg owning these pages has been offlined and doesn't +* have an ID allocated to it anymore, charge the closest online +* ancestor for the swap instead and transfer the memory+swap charge. +*/ + swap_memcg =mem_cgroup_id_get_online (memcg); + oldid =swap_cgroup_record (entry,mem_cgroup_id (swap_memcg));VM_BUG_ON_PAGE (oldid, page); -mem_cgroup_swap_statistics (memcg, true); +mem_cgroup_swap_statistics (swap_memcg, true); page->mem_cgroup =NULL ;if (!mem_cgroup_is_root (memcg))page_counter_uncharge (&memcg->memory,1 ); +if (memcg != swap_memcg) { +if (!mem_cgroup_is_root (swap_memcg)) +page_counter_charge (&swap_memcg->memsw,1 ); +page_counter_uncharge (&memcg->memsw,1 ); + } +/* * Interrupts should be disabled here because the caller holds the * mapping->tree_lock lock which is taken with interrupts-off. It is
@@ -5848,11 +5877,14 @@ int mem_cgroup_try_charge_swap(struct paif (!memcg)return 0 ; + memcg =mem_cgroup_id_get_online (memcg); +if (!mem_cgroup_is_root (memcg) && - !page_counter_try_charge (&memcg->swap,1 , &counter)) + !page_counter_try_charge (&memcg->swap,1 , &counter)) { +mem_cgroup_id_put (memcg);return -ENOMEM ; + } -mem_cgroup_id_get (memcg); oldid =swap_cgroup_record (entry,mem_cgroup_id (memcg));VM_BUG_ON_PAGE (oldid, page);mem_cgroup_swap_statistics (memcg, true);
Patches currently in stable-queue which might be from [email protected] are
queue-4.6/mm-memcontrol-fix-memcg-id-ref-counter-on-swap-charge-move.patch queue-4.6/mm-memcontrol-fix-swap-counter-leak-on-swapout-from-offline-cgroup.patch