[Devel] [PATCH RHEL8 COMMIT] mm: per-memcg negative dentries accounting

Konstantin Khorenko khorenko at virtuozzo.com
Wed Jun 23 18:47:50 MSK 2021


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.48
------>
commit 24375477ca10dd08c0663b56dccd1383852cdd76
Author: Vasily Averin <vvs at virtuozzo.com>
Date:   Wed Jun 23 14:07:06 2021 +0300

    mm: per-memcg negative dentries accounting
    
    This patch adds per-memcg negative dentries accounting
    and makes them visible in userspace via memcg statistic
    
    https://jira.sw.ru/browse/PSBM-104223
    https://bugs.openvz.org/browse/OVZ-7225
    Signed-off-by: Vasily Averin <vvs at virtuozzo.com>
    
    (cherry-picked from vz7 commit ("8d980b969c46 per-memcg negative dentries
    accounting"))
    
    conflicts:
            - mem_cgroup_from_kmem changed to mem_cgroup_from_obj
            - memcg->stat changed to memcg->vmstats_percpu
    
    https://jira.sw.ru/browse/PSBM-127858
    Signed-off-by: Valeriy Vdovin <valeriy.vdovin at virtuozzo.com>
    
    +++
    mm: memory.stat format fix "negative dentries"
    
    mFixes: 8d980b969c46d ("per-memcg negative dentries accounting")
    
    https://jira.sw.ru/browse/PSBM-125735
    
    Signed-off-by: Alexander Mikhalitsyn <alexander.mikhalitsyn at virtuozzo.com>
    (cherry-picked from c59eb09a181a666cdf9d6e71ead567ba1f4eda20)
    https://jira.sw.ru/browse/PSBM-127858
    
    Signed-off-by: Valeriy Vdovin <valeriy.vdovin at virtuozzo.com>
---
 fs/dcache.c                | 21 ++++++++++++++++-----
 include/linux/memcontrol.h |  4 ++++
 mm/memcontrol.c            | 35 +++++++++++++++++++++++++++++++++++
 3 files changed, 55 insertions(+), 5 deletions(-)

diff --git a/fs/dcache.c b/fs/dcache.c
index 44e3f102baab..dda99aaccaf5 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -30,6 +30,7 @@
 #include <linux/bit_spinlock.h>
 #include <linux/rculist_bl.h>
 #include <linux/list_lru.h>
+#include <linux/memcontrol.h>
 #include "internal.h"
 #include "mount.h"
 
@@ -399,8 +400,10 @@ static void d_lru_add(struct dentry *dentry)
 	D_FLAG_VERIFY(dentry, 0);
 	dentry->d_flags |= DCACHE_LRU_LIST;
 	this_cpu_inc(nr_dentry_unused);
-	if (d_is_negative(dentry))
+	if (d_is_negative(dentry)) {
 		this_cpu_inc(nr_dentry_negative);
+		memcg_neg_dentry_inc(dentry);
+	}
 	WARN_ON_ONCE(!list_lru_add(&dentry->d_sb->s_dentry_lru, &dentry->d_lru));
 }
 
@@ -409,8 +412,10 @@ static void d_lru_del(struct dentry *dentry)
 	D_FLAG_VERIFY(dentry, DCACHE_LRU_LIST);
 	dentry->d_flags &= ~DCACHE_LRU_LIST;
 	this_cpu_dec(nr_dentry_unused);
-	if (d_is_negative(dentry))
+	if (d_is_negative(dentry)) {
 		this_cpu_dec(nr_dentry_negative);
+		memcg_neg_dentry_dec(dentry);
+	}
 	WARN_ON_ONCE(!list_lru_del(&dentry->d_sb->s_dentry_lru, &dentry->d_lru));
 }
 
@@ -441,8 +446,10 @@ static void d_lru_isolate(struct list_lru_one *lru, struct dentry *dentry)
 	D_FLAG_VERIFY(dentry, DCACHE_LRU_LIST);
 	dentry->d_flags &= ~DCACHE_LRU_LIST;
 	this_cpu_dec(nr_dentry_unused);
-	if (d_is_negative(dentry))
+	if (d_is_negative(dentry)) {
 		this_cpu_dec(nr_dentry_negative);
+		memcg_neg_dentry_dec(dentry);
+	}
 	list_lru_isolate(lru, &dentry->d_lru);
 }
 
@@ -451,8 +458,10 @@ static void d_lru_shrink_move(struct list_lru_one *lru, struct dentry *dentry,
 {
 	D_FLAG_VERIFY(dentry, DCACHE_LRU_LIST);
 	dentry->d_flags |= DCACHE_SHRINK_LIST;
-	if (d_is_negative(dentry))
+	if (d_is_negative(dentry)) {
 		this_cpu_dec(nr_dentry_negative);
+		memcg_neg_dentry_dec(dentry);
+	}
 	list_lru_isolate_move(lru, &dentry->d_lru, list);
 }
 
@@ -1848,8 +1857,10 @@ static void __d_instantiate(struct dentry *dentry, struct inode *inode)
 	/*
 	 * Decrement negative dentry count if it was in the LRU list.
 	 */
-	if (dentry->d_flags & DCACHE_LRU_LIST)
+	if (dentry->d_flags & DCACHE_LRU_LIST) {
 		this_cpu_dec(nr_dentry_negative);
+		memcg_neg_dentry_dec(dentry);
+	}
 	hlist_add_head(&dentry->d_u.d_alias, &inode->i_dentry);
 	raw_write_seqcount_begin(&dentry->d_seq);
 	__d_set_inode_and_type(dentry, inode, add_flags);
diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h
index c3dc019d2d20..0154df93ae68 100644
--- a/include/linux/memcontrol.h
+++ b/include/linux/memcontrol.h
@@ -109,6 +109,7 @@ struct RH_KABI_RENAME(mem_cgroup_stat_cpu, memcg_vmstats_percpu) {
 	unsigned long events[NR_VM_EVENT_ITEMS];
 	unsigned long nr_page_events;
 	unsigned long targets[MEM_CGROUP_NTARGETS];
+	unsigned long nr_dentry_neg;
 };
 
 struct mem_cgroup_reclaim_iter {
@@ -878,6 +879,9 @@ static inline void memcg_memory_event_mm(struct mm_struct *mm,
 void mem_cgroup_split_huge_fixup(struct page *head);
 #endif
 
+void memcg_neg_dentry_inc(struct dentry *dentry);
+void memcg_neg_dentry_dec(struct dentry *dentry);
+
 void mem_cgroup_fill_meminfo(struct mem_cgroup *memcg, struct meminfo *mi);
 void mem_cgroup_fill_vmstat(struct mem_cgroup *memcg, unsigned long *stats);
 
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 4958d2a6aad7..f78e3b669cde 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -995,6 +995,40 @@ struct mem_cgroup *get_mem_cgroup_from_page(struct page *page)
 }
 EXPORT_SYMBOL(get_mem_cgroup_from_page);
 
+static inline unsigned long
+mem_cgroup_read_nd(struct mem_cgroup *memcg)
+{
+	long val = 0;
+	int cpu;
+
+	/* Per-cpu values can be negative, use a signed accumulator */
+	for_each_possible_cpu(cpu)
+		val += per_cpu(memcg->vmstats_percpu->nr_dentry_neg, cpu);
+	/*
+	 * Summing races with updates, so val may be negative.  Avoid exposing
+	 * transient negative values.
+	 */
+	if (val < 0)
+		val = 0;
+	return val;
+}
+
+void memcg_neg_dentry_inc(struct dentry *dentry)
+{
+	struct mem_cgroup *memcg = mem_cgroup_from_obj(dentry);
+
+	if (memcg)
+		__this_cpu_inc(memcg->vmstats_percpu->nr_dentry_neg);
+}
+
+void memcg_neg_dentry_dec(struct dentry *dentry)
+{
+	struct mem_cgroup *memcg = mem_cgroup_from_obj(dentry);
+
+	if (memcg)
+		__this_cpu_dec(memcg->vmstats_percpu->nr_dentry_neg);
+}
+
 /**
  * If current->active_memcg is non-NULL, do not fallback to current->mm->memcg.
  */
@@ -4340,6 +4374,7 @@ static int memcg_stat_show(struct seq_file *m, void *v)
 	else
 		seq_printf(m, "oom %lu\n",
 			atomic_long_read(&memcg->memory_events[MEMCG_OOM]));
+	seq_printf(m, "negative_dentries %lu\n", mem_cgroup_read_nd(memcg));
 
 	for (i = 0; i < NR_LRU_LISTS; i++)
 		seq_printf(m, "%s %lu\n", lru_list_name(i),


More information about the Devel mailing list