[PATCH] meminfo: show /proc/meminfo base on container's memcg

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



cgroup and namespaces are used for creating containers but some of
information is not isolated/virtualized. This patch is for isolating /proc/meminfo
information per container, which uses memory cgroup. By this, top,free
and other tools under container can work as expected(show container's
usage) without changes.

This patch is a trial to show memcg's info in /proc/meminfo if 'current'
is under a memcg other than root.

we show /proc/meminfo base on container's memory cgroup.
because there are lots of info can't be provide by memcg, and
the cmds such as top, free just use some entries of /proc/meminfo,
we replace those entries by memory cgroup.

if container has no memcg, we will show host's /proc/meminfo
as before.

there is no idea how to deal with Buffers,I just set it zero,
It's strange if Buffers bigger than MemTotal.

Signed-off-by: Gao feng <gaofeng@xxxxxxxxxxxxxx>
---
 fs/proc/meminfo.c          |   11 +++++---
 include/linux/memcontrol.h |   15 +++++++++++
 mm/memcontrol.c            |   56 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 78 insertions(+), 4 deletions(-)

diff --git a/fs/proc/meminfo.c b/fs/proc/meminfo.c
index 80e4645..29a1fcd 100644
--- a/fs/proc/meminfo.c
+++ b/fs/proc/meminfo.c
@@ -13,6 +13,7 @@
 #include <linux/atomic.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
+#include <linux/memcontrol.h>
 #include "internal.h"
 
 void __attribute__((weak)) arch_report_meminfo(struct seq_file *m)
@@ -27,7 +28,6 @@ static int meminfo_proc_show(struct seq_file *m, void *v)
 	struct vmalloc_info vmi;
 	long cached;
 	unsigned long pages[NR_LRU_LISTS];
-	int lru;
 
 /*
  * display in kilobytes.
@@ -39,16 +39,19 @@ static int meminfo_proc_show(struct seq_file *m, void *v)
 	allowed = ((totalram_pages - hugetlb_total_pages())
 		* sysctl_overcommit_ratio / 100) + total_swap_pages;
 
+	memcg_meminfo(&i);
 	cached = global_page_state(NR_FILE_PAGES) -
 			total_swapcache_pages - i.bufferram;
+	/*
+	 * If 'current' is in root memory cgroup, returns global status.
+	 * If not, returns the status of memcg under which current runs.
+	 */
+	sys_page_state(pages, &cached);
 	if (cached < 0)
 		cached = 0;
 
 	get_vmalloc_info(&vmi);
 
-	for (lru = LRU_BASE; lru < NR_LRU_LISTS; lru++)
-		pages[lru] = global_page_state(NR_LRU_BASE + lru);
-
 	/*
 	 * Tagged format, for easy grepping and expansion.
 	 */
diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h
index 0316197..6220764 100644
--- a/include/linux/memcontrol.h
+++ b/include/linux/memcontrol.h
@@ -21,6 +21,7 @@
 #define _LINUX_MEMCONTROL_H
 #include <linux/cgroup.h>
 #include <linux/vm_event_item.h>
+#include <linux/mm.h>
 
 struct mem_cgroup;
 struct page_cgroup;
@@ -116,6 +117,9 @@ struct mem_cgroup *mem_cgroup_iter(struct mem_cgroup *,
 				   struct mem_cgroup_reclaim_cookie *);
 void mem_cgroup_iter_break(struct mem_cgroup *, struct mem_cgroup *);
 
+extern void memcg_meminfo(struct sysinfo *si);
+extern void sys_page_state(unsigned long *page, long *cached);
+
 /*
  * For memory reclaim.
  */
@@ -323,6 +327,17 @@ static inline void mem_cgroup_iter_break(struct mem_cgroup *root,
 {
 }
 
+static inline void memcg_meminfo(struct sysinfo *si)
+{
+}
+
+static inline void sys_page_state(unsigned long *pages, long *cached)
+{
+	int lru;
+	for (lru = LRU_BASE; lru < NR_LRU_LISTS; lru++)
+		pages[lru] = global_page_state(NR_LRU_BASE + lru);
+}
+
 static inline bool mem_cgroup_disabled(void)
 {
 	return true;
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index f142ea9..c25e160 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -52,6 +52,7 @@
 #include "internal.h"
 #include <net/sock.h>
 #include <net/tcp_memcontrol.h>
+#include <linux/pid_namespace.h>
 
 #include <asm/uaccess.h>
 
@@ -4345,6 +4346,61 @@ mem_cgroup_get_total_stat(struct mem_cgroup *memcg, struct mcs_total_stat *s)
 		mem_cgroup_get_local_stat(iter, s);
 }
 
+void memcg_meminfo(struct sysinfo *val)
+{
+	struct mem_cgroup *memcg = mem_cgroup_from_task(current);
+	__kernel_ulong_t totalram, totalswap;
+	if (current->nsproxy->pid_ns == &init_pid_ns ||
+	    memcg == NULL || mem_cgroup_is_root(memcg))
+		return;
+
+	totalram = res_counter_read_u64(&memcg->res,
+					RES_LIMIT) >> PAGE_SHIFT;
+	if (totalram < val->totalram) {
+		__kernel_ulong_t usageram;
+		usageram = res_counter_read_u64(&memcg->res,
+						RES_USAGE) >> PAGE_SHIFT;
+		val->totalram = totalram;
+		val->freeram = totalram - usageram;
+		val->bufferram = 0;
+		val->totalhigh = 0;
+		val->freehigh = 0;
+	} else
+		return;
+
+	totalswap = res_counter_read_u64(&memcg->memsw,
+					 RES_LIMIT) >> PAGE_SHIFT;
+	if (totalswap < val->totalswap) {
+		__kernel_ulong_t usageswap;
+		usageswap = res_counter_read_u64(&memcg->memsw,
+						 RES_USAGE) >> PAGE_SHIFT;
+		val->totalswap = totalswap - val->totalram;
+		val->freeswap = totalswap - usageswap - val->freeram;
+	}
+}
+
+void sys_page_state(unsigned long *pages, long *cached)
+{
+	struct mem_cgroup *memcg = mem_cgroup_from_task(current);
+
+	if (current->nsproxy->pid_ns == &init_pid_ns ||
+	    memcg == NULL || mem_cgroup_is_root(memcg)) {
+		int lru;
+		for (lru = LRU_BASE; lru < NR_LRU_LISTS; lru++)
+			pages[lru] = global_page_state(NR_LRU_BASE + lru);
+	} else {
+		struct mcs_total_stat s;
+		memset(&s, 0, sizeof(s));
+		mem_cgroup_get_total_stat(memcg, &s);
+		*cached = s.stat[MCS_CACHE] >> PAGE_SHIFT;
+		pages[LRU_ACTIVE_ANON] = s.stat[MCS_ACTIVE_ANON] >> PAGE_SHIFT;
+		pages[LRU_ACTIVE_FILE] = s.stat[MCS_ACTIVE_FILE] >> PAGE_SHIFT;
+		pages[LRU_INACTIVE_ANON] = s.stat[MCS_INACTIVE_ANON] >> PAGE_SHIFT;
+		pages[LRU_INACTIVE_FILE] = s.stat[MCS_INACTIVE_FILE] >> PAGE_SHIFT;
+		pages[LRU_UNEVICTABLE] = s.stat[MCS_UNEVICTABLE] >> PAGE_SHIFT;
+	}
+}
+
 #ifdef CONFIG_NUMA
 static int mem_control_numa_stat_show(struct seq_file *m, void *arg)
 {
-- 
1.7.7.6

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@xxxxxxxxx.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"dont@xxxxxxxxx";> email@xxxxxxxxx </a>


[Index of Archives]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Bugtraq]     [Linux]     [Linux OMAP]     [Linux MIPS]     [ECOS]     [Asterisk Internet PBX]     [Linux API]