[Devel] [PATCH vz9 12/16] mm: per-memcg negative dentries accounting
Nikita Yushchenko
nikita.yushchenko at virtuozzo.com
Wed Sep 29 10:00:13 MSK 2021
From: Vasily Averin <vvs at virtuozzo.com>
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"
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>
Cherry-picked from vz8 commit 12cf7352a1ce ("mm: per-memcg negative
dentries accounting").
Added empty static inline functions for !CONFIG_MEMCG case.
Signed-off-by: Nikita Yushchenko <nikita.yushchenko at virtuozzo.com>
---
fs/dcache.c | 21 ++++++++++++++++-----
include/linux/memcontrol.h | 12 ++++++++++++
mm/memcontrol.c | 35 +++++++++++++++++++++++++++++++++++
3 files changed, 63 insertions(+), 5 deletions(-)
diff --git a/fs/dcache.c b/fs/dcache.c
index fa0a8fe12bfd..18e97f1c4d30 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -32,6 +32,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"
@@ -403,8 +404,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));
}
@@ -413,8 +416,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));
}
@@ -445,8 +450,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);
}
@@ -455,8 +462,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);
}
@@ -1978,8 +1987,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 46b92cc0bdc5..a4e0e9830d29 100644
--- a/include/linux/memcontrol.h
+++ b/include/linux/memcontrol.h
@@ -88,6 +88,7 @@ struct memcg_vmstats_percpu {
/* Cgroup1: threshold notifications & softlimit tree updates */
unsigned long nr_page_events;
unsigned long targets[MEM_CGROUP_NTARGETS];
+ unsigned long nr_dentry_neg;
};
struct memcg_vmstats {
@@ -1163,6 +1164,9 @@ unsigned long mem_cgroup_soft_limit_reclaim(pg_data_t *pgdat, int order,
void mem_cgroup_fill_meminfo(struct mem_cgroup *memcg, struct meminfo *mi);
+void memcg_neg_dentry_inc(struct dentry *dentry);
+void memcg_neg_dentry_dec(struct dentry *dentry);
+
#else /* CONFIG_MEMCG */
#define MEM_CGROUP_ID_SHIFT 0
@@ -1556,6 +1560,14 @@ static void mem_cgroup_fill_meminfo(struct mem_cgroup *memcg, struct meminfo *mi
{
}
+static inline void memcg_neg_dentry_inc(struct dentry *dentry)
+{
+}
+
+static inline void memcg_neg_dentry_dec(struct dentry *dentry)
+{
+}
+
#endif /* CONFIG_MEMCG */
static inline void __inc_lruvec_kmem_state(void *p, enum node_stat_item idx)
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index e92919d8ce06..7cb3e3e8d9fc 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -3576,6 +3576,40 @@ unsigned long mem_cgroup_soft_limit_reclaim(pg_data_t *pgdat, int order,
return nr_reclaimed;
}
+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);
+}
+
/*
* Reclaims as many pages from the given memcg as possible.
*
@@ -4177,6 +4211,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),
--
2.30.2
More information about the Devel
mailing list