[Devel] [PATCH rh7 2/4] ub: make cached and shmem meminfo output more accurate

Vladimir Davydov vdavydov at virtuozzo.com
Thu May 5 03:23:27 PDT 2016


Currently, these fields are faked using file lru size and UB_SHMPAGES.
The result leaves a lot to be desired, because UB_SHMPAGES accounts
every shared pages as many times as it is mapped. Let's instead take
these values directly from memory cgroup where they are already properly
accounted.

Along the way, zap ub_page_stat and use mem_cgroup_get_nr_pages
directly.

Signed-off-by: Vladimir Davydov <vdavydov at virtuozzo.com>
---
 include/bc/beancounter.h |  3 ---
 kernel/bc/beancounter.c  | 15 ---------------
 kernel/bc/proc.c         | 15 ++++++++++-----
 kernel/bc/vm_pages.c     | 24 +++++++-----------------
 mm/memcontrol.c          | 19 +++++++++++++++++++
 5 files changed, 36 insertions(+), 40 deletions(-)

diff --git a/include/bc/beancounter.h b/include/bc/beancounter.h
index 8316cc4861a3..8f3119d214e9 100644
--- a/include/bc/beancounter.h
+++ b/include/bc/beancounter.h
@@ -288,9 +288,6 @@ extern void uncharge_warn(struct user_beancounter *ub, const char *resource,
 
 extern int ub_update_memcg(struct user_beancounter *ub);
 extern void ub_sync_memcg(struct user_beancounter *ub);
-extern void ub_page_stat(struct user_beancounter *ub,
-			 const nodemask_t *nodemask,
-			 unsigned long *pages);
 extern unsigned long ub_total_pages(struct user_beancounter *ub, bool swap);
 
 extern const char *ub_rnames[];
diff --git a/kernel/bc/beancounter.c b/kernel/bc/beancounter.c
index 90fc1ddf8f89..5023bd2b208d 100644
--- a/kernel/bc/beancounter.c
+++ b/kernel/bc/beancounter.c
@@ -231,21 +231,6 @@ void ub_sync_memcg(struct user_beancounter *ub)
 	css_put(css);
 }
 
-void ub_page_stat(struct user_beancounter *ub, const nodemask_t *nodemask,
-		  unsigned long *pages)
-{
-	int nid;
-	struct cgroup_subsys_state *css;
-
-	memset(pages, 0, sizeof(unsigned long) * NR_LRU_LISTS);
-
-	css = ub_get_mem_css(ub);
-	for_each_node_mask(nid, *nodemask)
-		mem_cgroup_get_nr_pages(mem_cgroup_from_cont(css->cgroup),
-					nid, pages);
-	css_put(css);
-}
-
 unsigned long ub_total_pages(struct user_beancounter *ub, bool swap)
 {
 	struct cgroup_subsys_state *css;
diff --git a/kernel/bc/proc.c b/kernel/bc/proc.c
index 9e9fde4904a0..4c79550cb036 100644
--- a/kernel/bc/proc.c
+++ b/kernel/bc/proc.c
@@ -17,6 +17,7 @@
 #include <linux/mnt_namespace.h>
 #include <linux/lglock.h>
 #include <linux/ve.h>
+#include <linux/memcontrol.h>
 
 #include <bc/beancounter.h>
 #include <bc/proc.h>
@@ -129,18 +130,21 @@ static struct bc_proc_entry bc_meminfo_entry = {
 	.u.show = bc_proc_meminfo_show,
 };
 
+extern void mem_cgroup_get_nr_pages(struct mem_cgroup *memcg, int nid,
+				    unsigned long *pages);
+
 #define K(x) ((x) << (PAGE_SHIFT - 10))
 static int bc_proc_nodeinfo_show(struct seq_file *f, void *v)
 {
 	int nid;
-	struct user_beancounter *ub;
+	struct cgroup_subsys_state *css;
 	unsigned long pages[NR_LRU_LISTS];
 
-	ub = seq_beancounter(f);
+	css = ub_get_mem_css(seq_beancounter(f));
 	for_each_node_state(nid, N_HIGH_MEMORY) {
-		nodemask_t nodemask = nodemask_of_node(nid);
-
-		ub_page_stat(ub, &nodemask, pages);
+		memset(pages, 0, sizeof(pages));
+		mem_cgroup_get_nr_pages(mem_cgroup_from_cont(css->cgroup),
+					nid, pages);
 		seq_printf(f,
 			"Node %d Active:         %8lu kB\n"
 			"Node %d Inactive:       %8lu kB\n"
@@ -159,6 +163,7 @@ static int bc_proc_nodeinfo_show(struct seq_file *f, void *v)
 			nid, K(pages[LRU_INACTIVE_FILE]),
 			nid, K(pages[LRU_UNEVICTABLE]));
 	}
+	css_put(css);
 	return 0;
 }
 #undef K
diff --git a/kernel/bc/vm_pages.c b/kernel/bc/vm_pages.c
index b46da98fece2..5e588d1f036c 100644
--- a/kernel/bc/vm_pages.c
+++ b/kernel/bc/vm_pages.c
@@ -159,22 +159,23 @@ static int bc_fill_sysinfo(struct user_beancounter *ub,
 	return NOTIFY_OK;
 }
 
+extern void mem_cgroup_fill_meminfo(struct mem_cgroup *memcg, struct meminfo *mi);
+
 static int bc_fill_meminfo(struct user_beancounter *ub,
 		unsigned long meminfo_val, struct meminfo *mi)
 {
+	struct cgroup_subsys_state *css;
 	int cpu, ret;
-	long dcache;
 
 	ret = bc_fill_sysinfo(ub, meminfo_val, mi->si);
 	if (ret & NOTIFY_STOP_MASK)
 		goto out;
 
-	ub_sync_memcg(ub);
-	ub_page_stat(ub, &node_online_map, mi->pages);
+	css = ub_get_mem_css(ub);
+	mem_cgroup_fill_meminfo(mem_cgroup_from_cont(css->cgroup), mi);
+	css_put(css);
 
 	mi->locked = ub->ub_parms[UB_LOCKEDPAGES].held;
-	mi->shmem = ub->ub_parms[UB_SHMPAGES].held;
-	dcache = ub->ub_parms[UB_DCACHESIZE].held;
 
 	mi->dirty_pages = __ub_stat_get(ub, dirty_pages);
 	mi->writeback_pages = __ub_stat_get(ub, writeback_pages);
@@ -182,22 +183,11 @@ static int bc_fill_meminfo(struct user_beancounter *ub,
 		struct ub_percpu_struct *pcpu = ub_percpu(ub, cpu);
 
 		mi->dirty_pages	+= pcpu->dirty_pages;
-		mi->writeback_pages	+= pcpu->writeback_pages;
+		mi->writeback_pages += pcpu->writeback_pages;
 	}
 
 	mi->dirty_pages = max_t(long, 0, mi->dirty_pages);
 	mi->writeback_pages = max_t(long, 0, mi->writeback_pages);
-
-	mi->slab_reclaimable = DIV_ROUND_UP(max(0L, dcache), PAGE_SIZE);
-	mi->slab_unreclaimable =
-		DIV_ROUND_UP(max(0L, (long)ub->ub_parms[UB_KMEMSIZE].held -
-							dcache), PAGE_SIZE);
-
-	mi->cached = min(mi->si->totalram - mi->si->freeram -
-			mi->slab_reclaimable - mi->slab_unreclaimable,
-			mi->pages[LRU_INACTIVE_FILE] +
-			mi->pages[LRU_ACTIVE_FILE] +
-			ub->ub_parms[UB_SHMPAGES].held);
 out:
 	return ret;
 }
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 034bc451705f..f6037581cf09 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -53,6 +53,7 @@
 #include <linux/page_cgroup.h>
 #include <linux/cpu.h>
 #include <linux/oom.h>
+#include <linux/virtinfo.h>
 #include "internal.h"
 #include <net/sock.h>
 #include <net/ip.h>
@@ -5002,6 +5003,24 @@ static unsigned long mem_cgroup_recursive_stat(struct mem_cgroup *memcg,
 	return val;
 }
 
+void mem_cgroup_fill_meminfo(struct mem_cgroup *memcg, struct meminfo *mi)
+{
+	int nid;
+	unsigned long slab;
+
+	memset(&mi->pages, 0, sizeof(mi->pages));
+	for_each_online_node(nid)
+		mem_cgroup_get_nr_pages(memcg, nid, mi->pages);
+
+	slab = res_counter_read_u64(&memcg->kmem, RES_USAGE) >> PAGE_SHIFT;
+	mi->slab_reclaimable = res_counter_read_u64(&memcg->dcache, RES_USAGE)
+								>> PAGE_SHIFT;
+	mi->slab_unreclaimable = max_t(long, slab - mi->slab_reclaimable, 0);
+
+	mi->cached = mem_cgroup_recursive_stat(memcg, MEM_CGROUP_STAT_CACHE);
+	mi->shmem = mem_cgroup_recursive_stat(memcg, MEM_CGROUP_STAT_SHMEM);
+}
+
 static inline u64 mem_cgroup_usage(struct mem_cgroup *memcg, bool swap)
 {
 	u64 val;
-- 
2.1.4



More information about the Devel mailing list