[Devel] [PATCH rh7 2/2] mm/memcg: fix overcharging in cgroup try_charge() for !cache_charge
Andrey Ryabinin
aryabinin at virtuozzo.com
Mon Feb 26 20:44:12 MSK 2018
Normally, try_charge() tries to charge 32 pages, and if succesfull,
puts the rest (32-nr_pages) into stock. So the next try_charge() looks
into the stock only and avoid calling expensive page_counter_try_charge(),
(at least untill stock has some pages).
This stopped to work after commit:
15fd42f8580f ("mm/memcg: limit page cache in memcg hack")
If cache_charge=false in try_charge() we always call refill_stock() which
undoes stock charge and fallback to slowpath which charges 32 pages and puts
rest into the stock. So we have constantly growing stock and page_counter.
Eventually we hit the limit and call drain_all_stock_async() which uncharges
all accumulated stock pages from page_counter and page_counter goes
back to sane value. But before that happens mem_cgroup_enough_memory() may
read over-charges ->memsw counter and return ENOMEM to user-space.
https://jira.sw.ru/browse/PSBM-81750
Signed-off-by: Andrey Ryabinin <aryabinin at virtuozzo.com>
---
mm/memcontrol.c | 13 ++++++-------
1 file changed, 6 insertions(+), 7 deletions(-)
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 50cbcdc38f60..b4d61d72ccbf 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -2769,13 +2769,12 @@ retry:
goto charge;
}
- if (cache_charge && !page_counter_try_charge(
- &memcg->cache, nr_pages, &counter))
- goto done;
-
- refill_stock(memcg, nr_pages);
- if (kmem_charge)
- page_counter_uncharge(&memcg->kmem, nr_pages);
+ if (cache_charge && page_counter_try_charge(
+ &memcg->cache, nr_pages, &counter)) {
+ refill_stock(memcg, nr_pages);
+ goto charge;
+ }
+ goto done;
}
charge:
--
2.16.1
More information about the Devel
mailing list