The commit is pushed to "branch-rh8-4.18.0-240.1.1.vz8.5.x-ovz" and will appear 
at https://src.openvz.org/scm/ovz/vzkernel.git
after rh8-4.18.0-240.1.1.vz8.5.32
------>
commit 5f48326db336587620c96699ee9a3ddaae5a9b56
Author: Pavel Tikhomirov <[email protected]>
Date:   Mon May 24 17:25:11 2021 +0300

    ve/memcg: Virtualize /proc/vmstat view inside CT
    
    When users read /proc/vmstat inside container they expect to see
    agregated stats of all container cgroups.
    
    Note: We've had /proc/meminfo, /proc/vmstat, /proc/swaps and sysinfo(),
    virtualized in containers in VZ7, we need the same in VZ8. In VZ7 this
    was done via virtinfo subsystem which is dropped.
    
    https://jira.sw.ru/browse/PSBM-127780
    
    Signed-off-by: Pavel Tikhomirov <[email protected]>
---
 include/linux/memcontrol.h |  6 ++++++
 mm/memcontrol.c            | 54 ++++++++++++++++++++++++++++++++++++++++++++++
 mm/vmstat.c                | 16 +++++++++++++-
 3 files changed, 75 insertions(+), 1 deletion(-)

diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h
index c2ed042104ef..c3dc019d2d20 100644
--- a/include/linux/memcontrol.h
+++ b/include/linux/memcontrol.h
@@ -879,6 +879,7 @@ void mem_cgroup_split_huge_fixup(struct page *head);
 #endif
 
 void mem_cgroup_fill_meminfo(struct mem_cgroup *memcg, struct meminfo *mi);
+void mem_cgroup_fill_vmstat(struct mem_cgroup *memcg, unsigned long *stats);
 
 #else /* CONFIG_MEMCG */
 
@@ -1280,6 +1281,11 @@ static void mem_cgroup_fill_meminfo(struct mem_cgroup 
*memcg, struct meminfo *mi
 {
 }
 
+static inline void mem_cgroup_fill_vmstat(struct mem_cgroup *memcg,
+                                         unsigned long *stats)
+{
+}
+
 #endif /* CONFIG_MEMCG */
 
 /* idx can be of type enum memcg_stat_item or node_stat_item */
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index c783e6cbc177..a7d971c42367 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -3814,6 +3814,60 @@ void mem_cgroup_fill_meminfo(struct mem_cgroup *memcg, 
struct meminfo *mi)
        /* mi->locked = 0; */
 }
 
+void mem_cgroup_fill_vmstat(struct mem_cgroup *memcg, unsigned long *stats)
+{
+       int cpu, i;
+       unsigned long limit = READ_ONCE(memcg->memory.max);
+       unsigned long memory = page_counter_read(&memcg->memory);
+       unsigned long *zone_stats = stats;
+       unsigned long *node_stats = stats +
+                                   NR_VM_ZONE_STAT_ITEMS +
+                                   NR_VM_NUMA_STAT_ITEMS;
+       unsigned long *vm_stats = node_stats +
+                                 NR_VM_NODE_STAT_ITEMS +
+                                 NR_VM_WRITEBACK_STAT_ITEMS;
+
+
+
+       zone_stats[NR_FREE_PAGES] = memory > limit ? 0 : limit- memory;
+
+       for (i = LRU_BASE; i < NR_LRU_LISTS; i++) {
+               struct mem_cgroup *iter;
+
+               for_each_mem_cgroup_tree(iter, memcg)
+                       node_stats[NR_LRU_BASE + i] = 
mem_cgroup_nr_lru_pages(iter, BIT(i));
+       }
+
+       node_stats[NR_ANON_MAPPED] = node_stats[NR_ACTIVE_ANON] +
+               node_stats[NR_INACTIVE_ANON];
+       node_stats[NR_FILE_PAGES] = node_stats[NR_ACTIVE_FILE] +
+               node_stats[NR_INACTIVE_FILE];
+
+       node_stats[NR_SLAB_RECLAIMABLE] = mem_page_state_recursive(
+                       memcg, NR_SLAB_RECLAIMABLE);
+       node_stats[NR_SLAB_UNRECLAIMABLE] = mem_page_state_recursive(
+                       memcg, NR_SLAB_UNRECLAIMABLE);
+       node_stats[NR_FILE_MAPPED] = mem_page_state_recursive(
+                       memcg, NR_FILE_MAPPED);
+       node_stats[NR_SHMEM] = mem_page_state_recursive(
+                       memcg, NR_SHMEM);
+
+
+
+#ifdef CONFIG_VM_EVENT_COUNTERS
+       for_each_possible_cpu(cpu) {
+               vm_stats[PSWPIN] += per_cpu(
+                       memcg->vmstats_local->events[PSWPIN], cpu);
+               vm_stats[PSWPOUT] += per_cpu(
+                       memcg->vmstats_local->events[PSWPOUT], cpu);
+               vm_stats[PGFAULT] += per_cpu(
+                       memcg->vmstats_local->events[PGFAULT], cpu);
+               vm_stats[PGMAJFAULT] += per_cpu(
+                       memcg->vmstats_local->events[PGMAJFAULT], cpu);
+       }
+#endif
+}
+
 static int memcg_numa_stat_show(struct seq_file *m, void *v)
 {
        struct numa_stat {
diff --git a/mm/vmstat.c b/mm/vmstat.c
index 112dbe91ee98..0dafca5a8e59 100644
--- a/mm/vmstat.c
+++ b/mm/vmstat.c
@@ -27,6 +27,8 @@
 #include <linux/mm_inline.h>
 #include <linux/page_ext.h>
 #include <linux/page_owner.h>
+#include <linux/memcontrol.h>
+#include <linux/ve.h>
 
 #include "internal.h"
 
@@ -1661,8 +1663,18 @@ static const struct seq_operations zoneinfo_op = {
                         (IS_ENABLED(CONFIG_VM_EVENT_COUNTERS) ? \
                          NR_VM_EVENT_ITEMS : 0))
 
+static void fill_vmstat_ve(unsigned long *stat, struct ve_struct *ve)
+{
+       struct cgroup_subsys_state *css;
+
+       css = ve_get_init_css(ve, memory_cgrp_id);
+       mem_cgroup_fill_vmstat(mem_cgroup_from_css(css), stat);
+       css_put(css);
+}
+
 static void *vmstat_start(struct seq_file *m, loff_t *pos)
 {
+       struct ve_struct *ve;
        unsigned long *v;
        int i;
 
@@ -1675,8 +1687,10 @@ static void *vmstat_start(struct seq_file *m, loff_t 
*pos)
        if (!v)
                return ERR_PTR(-ENOMEM);
 
-       if (!ve_is_super(get_exec_env())) {
+       ve = get_exec_env();
+       if (!ve_is_super(ve)) {
                memset(v, 0, NR_VMSTAT_ITEMS * sizeof(unsigned long));
+               fill_vmstat_ve(v, ve);
                return (unsigned long *)m->private + *pos;
        }
 
_______________________________________________
Devel mailing list
[email protected]
https://lists.openvz.org/mailman/listinfo/devel

Reply via email to