[Devel] [PATCH RHEL7 COMMIT] mm/memcg: Bypass charges to offlined cgroup
Konstantin Khorenko
khorenko at virtuozzo.com
Fri Jul 13 15:34:48 MSK 2018
The commit is pushed to "branch-rh7-3.10.0-862.6.3.vz7.62.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-862.6.3.vz7.62.3
------>
commit 90633e808c57ac222f9efeedf851500ec6133965
Author: Andrey Ryabinin <aryabinin at virtuozzo.com>
Date: Fri Jul 13 15:34:48 2018 +0300
mm/memcg: Bypass charges to offlined cgroup
Charges to offlined cgroup can happen. E.g. swapped KSM page may charge to
offlined cgroup. If such charge races with reparenting during the offlining
process it may result in hang in mem_cgroup_reparent_charges().
Let's say we have cgroup A and cgroup B. A is parent of B, B is offlined
already, and A in the process of offlining. During offline of A, we walk
through all childs of A and reparent their charges. After that, we reparent the
A itself.
If charge to B cgroup will appear after the reparenting of B and before
reparenting A, the reparanting of A will hang. Charge to B also increases
->memory counter of its parent A, so mem_cgroup_reparent_charges(A) will never
satisfy the condition
'A->memory - A->kmem > 0'
which is required to break the loop.
https://jira.sw.ru/browse/PSBM-86092
Signed-off-by: Andrey Ryabinin <aryabinin at virtuozzo.com>
---
mm/memcontrol.c | 22 ++++++++++++++++++++++
1 file changed, 22 insertions(+)
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 59cf47972f9e..8b979d88045c 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -2909,6 +2909,28 @@ static int try_charge(struct mem_cgroup *memcg, gfp_t gfp_mask, bool kmem_charge
return -EINTR;
done_restock:
+
+ /*
+ * Cancel charge in case if cgroup was offlined while we were here,
+ * otherwise we can get a pending user memory charge to an offline
+ * cgroup, which might race with reparanting in mem_cgroup_css_offline()
+ * and result in hang.
+ *
+ * Note, no need to issue an explicit barrier here, because a
+ * successful charge implies full memory barrier.
+ */
+ if (unlikely(memcg->is_offline)) {
+ page_counter_uncharge(&memcg->memory, batch);
+ if (do_swap_account)
+ page_counter_uncharge(&memcg->memsw, batch);
+ if (cache_charge)
+ page_counter_uncharge(&memcg->cache, nr_pages);
+ if (kmem_charge)
+ page_counter_uncharge(&memcg->kmem, nr_pages);
+
+ goto bypass;
+ }
+
if (batch > nr_pages)
refill_stock(memcg, batch - nr_pages);
done:
More information about the Devel
mailing list