From: Vladimir Davydov <vdavy...@virtuozzo.com>

Page table pages are batched-freed in release_pages on most
architectures.  If we want to charge them to kmemcg (this is what is
done later in this series), we need to teach mem_cgroup_uncharge_list to
handle kmem pages.

Link: 
http://lkml.kernel.org/r/18d5c09e97f80074ed25b97a7d0f32b95d875717.1464079538.git.vdavy...@virtuozzo.com
Signed-off-by: Vladimir Davydov <vdavy...@virtuozzo.com>
Cc: Johannes Weiner <han...@cmpxchg.org>
Cc: Michal Hocko <mho...@kernel.org>
Cc: Eric Dumazet <eric.duma...@gmail.com>
Cc: Minchan Kim <minc...@kernel.org>
Signed-off-by: Andrew Morton <a...@linux-foundation.org>
Signed-off-by: Linus Torvalds <torva...@linux-foundation.org>

https://jira.sw.ru/browse/PSBM-51558
(cherry picked from commit 5e8d35f849b1969b900695ae191326bfacf6bfc6)
Signed-off-by: Andrey Ryabinin <aryabi...@virtuozzo.com>
---
 mm/memcontrol.c | 37 +++++++++++++++++++++----------------
 1 file changed, 21 insertions(+), 16 deletions(-)

diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index cb7657e..880fa5b 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -6967,17 +6967,18 @@ void mem_cgroup_cancel_charge(struct page *page, struct 
mem_cgroup *memcg)
 static void uncharge_batch(struct mem_cgroup *memcg, unsigned long pgpgout,
                           unsigned long nr_mem, unsigned long nr_memsw,
                           unsigned long nr_anon, unsigned long nr_file,
-                          unsigned long nr_huge, struct page *dummy_page)
+                          unsigned long nr_huge, unsigned long nr_kmem,
+                          struct page *dummy_page)
 {
        unsigned long flags;
 
        if (!mem_cgroup_is_root(memcg)) {
                if (nr_mem)
                        res_counter_uncharge(&memcg->res,
-                                            nr_mem * PAGE_SIZE);
+                                            (nr_mem + nr_kmem) * PAGE_SIZE);
                if (nr_memsw)
                        res_counter_uncharge(&memcg->memsw,
-                                            nr_memsw * PAGE_SIZE);
+                                            (nr_memsw + nr_kmem) * PAGE_SIZE);
                memcg_oom_recover(memcg);
        }
 
@@ -6998,6 +6999,7 @@ static void uncharge_list(struct list_head *page_list)
        unsigned long nr_anon = 0;
        unsigned long nr_file = 0;
        unsigned long nr_huge = 0;
+       unsigned long nr_kmem = 0;
        unsigned long pgpgout = 0;
        unsigned long nr_mem = 0;
        struct list_head *next;
@@ -7027,23 +7029,26 @@ static void uncharge_list(struct list_head *page_list)
                if (memcg != pc->mem_cgroup) {
                        if (memcg) {
                                uncharge_batch(memcg, pgpgout, nr_mem, nr_memsw,
-                                              nr_anon, nr_file, nr_huge, page);
-                               pgpgout = nr_mem = nr_memsw = 0;
+                                       nr_anon, nr_file, nr_huge, nr_kmem, 
page);
+                               pgpgout = nr_mem = nr_memsw = nr_kmem = 0;
                                nr_anon = nr_file = nr_huge = 0;
                        }
                        memcg = pc->mem_cgroup;
                }
 
-               if (PageTransHuge(page)) {
-                       nr_pages <<= compound_order(page);
-                       VM_BUG_ON_PAGE(!PageTransHuge(page), page);
-                       nr_huge += nr_pages;
-               }
-
-               if (PageAnon(page))
-                       nr_anon += nr_pages;
-               else
-                       nr_file += nr_pages;
+               if (!PageKmemcg(page)) {
+                       if (PageTransHuge(page)) {
+                               nr_pages <<= compound_order(page);
+                               VM_BUG_ON_PAGE(!PageTransHuge(page), page);
+                               nr_huge += nr_pages;
+                       }
+                       if (PageAnon(page))
+                               nr_anon += nr_pages;
+                       else
+                               nr_file += nr_pages;
+                       pgpgout++;
+               } else
+                       nr_kmem += 1 << compound_order(page);
 
                if (pc->flags & PCG_MEM)
                        nr_mem += nr_pages;
@@ -7056,7 +7061,7 @@ static void uncharge_list(struct list_head *page_list)
 
        if (memcg)
                uncharge_batch(memcg, pgpgout, nr_mem, nr_memsw,
-                              nr_anon, nr_file, nr_huge, page);
+                              nr_anon, nr_file, nr_huge, nr_kmem, page);
 }
 
 /**
-- 
2.7.3

_______________________________________________
Devel mailing list
Devel@openvz.org
https://lists.openvz.org/mailman/listinfo/devel

Reply via email to