[rh7] memcg, bc/vm_pages.c: account some swapped memory as used in CT in /proc/meminfo

Submitted by Andrey Ryabinin on March 17, 2020, 2:37 p.m.

Details

Message ID 20200317143739.16320-1-aryabinin@virtuozzo.com
State New
Series "memcg, bc/vm_pages.c: account some swapped memory as used in CT in /proc/meminfo"
Headers show

Commit Message

Andrey Ryabinin March 17, 2020, 2:37 p.m.
If swapped memory of container exceed CT's swap size (can happen
on external memory pressure) it's unaccounted in /proc/meminfo.

Fix this by adding swapped above swap size to used counter.
Ideally we should also add this to inactive anon and/or shmem, but
we don't really know what was swapped, so leave it as is.

https://jira.sw.ru/browse/PSBM-102266
Signed-off-by: Andrey Ryabinin <aryabinin@virtuozzo.com>
---
 kernel/bc/vm_pages.c | 33 +++++----------------------------
 mm/memcontrol.c      | 29 +++++++++++++++++++++++++++++
 2 files changed, 34 insertions(+), 28 deletions(-)

Patch hide | download patch | download mbox

diff --git a/kernel/bc/vm_pages.c b/kernel/bc/vm_pages.c
index 0e44c8e86118..e5019c0a44a3 100644
--- a/kernel/bc/vm_pages.c
+++ b/kernel/bc/vm_pages.c
@@ -155,42 +155,19 @@  int ub_enough_memory(struct mm_struct *mm, long pages)
 	return ret;
 }
 
+extern void mem_cgroup_fill_sysinfo(struct mem_cgroup *memcg, struct sysinfo *si);
 static int bc_fill_sysinfo(struct user_beancounter *ub,
 		unsigned long meminfo_val, struct sysinfo *si)
 {
-	unsigned long used, total;
-	unsigned long totalram, totalswap;
+	struct cgroup_subsys_state *css;
 
 	/* No virtualization */
 	if (meminfo_val == VE_MEMINFO_SYSTEM)
 		return NOTIFY_DONE | NOTIFY_STOP_MASK;
 
-	totalram = si->totalram;
-	totalswap = si->totalswap;
-
-	memset(si, 0, sizeof(*si));
-
-	ub_sync_memcg(ub);
-
-	total = ub->ub_parms[UB_PHYSPAGES].limit;
-	used = ub->ub_parms[UB_PHYSPAGES].held;
-
-	if (total == UB_MAXVALUE)
-		total = totalram;
-
-	si->totalram = total;
-	si->freeram = (total > used ? total - used : 0);
-
-	total = ub->ub_parms[UB_SWAPPAGES].limit;
-	used = ub->ub_parms[UB_SWAPPAGES].held;
-
-	if (total == UB_MAXVALUE)
-		total = totalswap;
-
-	si->totalswap = total;
-	si->freeswap = (total > used ? total - used : 0);
-
-	si->mem_unit = PAGE_SIZE;
+	css = ub_get_mem_css(ub);
+	mem_cgroup_fill_sysinfo(mem_cgroup_from_cont(css->cgroup), si);
+	css_put(css);
 
 	return NOTIFY_OK;
 }
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 4846e7a9bf63..897913b1b8d8 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -4650,6 +4650,35 @@  void mem_cgroup_fill_meminfo(struct mem_cgroup *memcg, struct meminfo *mi)
 	mi->available += mi->slab_reclaimable;
 }
 
+void mem_cgroup_fill_sysinfo(struct mem_cgroup *memcg, struct sysinfo *si)
+{
+	unsigned long totalram, totalswap;
+	unsigned long swaped, used;
+
+	totalram = si->totalram;
+	totalswap = si->totalswap;
+
+	memset(si, 0, sizeof(*si));
+
+	used = page_counter_read(&memcg->memory);
+	si->totalram = min(totalram, memcg->memory.limit);
+
+	swaped = page_counter_read(&memcg->memsw) - page_counter_read(&memcg->memory);
+	si->totalswap = min(totalswap, memcg->memsw.limit - memcg->memory.limit);
+
+	used = page_counter_read(&memcg->memory);
+
+	if (swaped > si->totalswap) {
+		si->freeswap = 0;
+		used += swaped - si->totalswap;
+	} else {
+		si->freeswap = si->totalswap - swaped;
+	}
+
+	si->freeram = (si->totalram > used ? si->totalram - used : 0);
+	si->mem_unit = PAGE_SIZE;
+}
+
 int mem_cgroup_enough_memory(struct mem_cgroup *memcg, long pages)
 {
 	long free;