[Devel] [PATCH RH7] per-memcg negative dentries accounting
Vasily Averin
vvs at virtuozzo.com
Wed Jan 13 13:20:19 MSK 2021
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>
---
fs/dcache.c | 24 ++++++++++++++++++------
include/linux/memcontrol.h | 3 +++
mm/memcontrol.c | 36 ++++++++++++++++++++++++++++++++++++
3 files changed, 57 insertions(+), 6 deletions(-)
diff --git a/fs/dcache.c b/fs/dcache.c
index 96ac93f..a9a3bb5 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -393,8 +393,10 @@ static void dentry_unlink_inode(struct dentry * dentry)
struct inode *inode = dentry->d_inode;
__d_clear_type(dentry);
dentry->d_inode = NULL;
- if (dentry->d_flags & DCACHE_LRU_LIST)
+ if (dentry->d_flags & DCACHE_LRU_LIST) {
this_cpu_inc(nr_dentry_negative);
+ memcg_neg_dentry_inc(dentry);
+ }
hlist_del_init(&dentry->d_alias);
dentry_rcuwalk_invalidate(dentry);
spin_unlock(&dentry->d_lock);
@@ -432,8 +434,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));
}
@@ -442,8 +446,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));
}
@@ -474,8 +480,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);
}
@@ -484,8 +492,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);
}
@@ -1871,8 +1881,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);
+ }
__d_set_type(dentry, add_flags);
if (inode)
hlist_add_head(&dentry->d_alias, &inode->i_dentry);
diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h
index 5e16658..f609a15 100644
--- a/include/linux/memcontrol.h
+++ b/include/linux/memcontrol.h
@@ -229,6 +229,9 @@ static inline void mem_cgroup_dec_page_stat(struct page *page,
mem_cgroup_update_page_stat(page, idx, -1);
}
+void memcg_neg_dentry_inc(struct dentry *dentry);
+void memcg_neg_dentry_dec(struct dentry *dentry);
+
void mem_cgroup_fill_vmstat(struct mem_cgroup *memcg, unsigned long *stats);
unsigned long memcg_ws_activates(struct mem_cgroup *memcg);
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 1c32810..1eae25d 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -183,6 +183,7 @@ struct mem_cgroup_stat_cpu {
unsigned long events[MEM_CGROUP_EVENTS_NSTATS];
unsigned long nr_page_events;
unsigned long targets[MEM_CGROUP_NTARGETS];
+ unsigned long nr_dentry_neg;
};
struct mem_cgroup_stat2_cpu {
@@ -1165,6 +1166,40 @@ mem_cgroup_read_stat2(struct mem_cgroup *memcg, enum mem_cgroup_stat2_index idx)
return percpu_counter_sum_positive(&memcg->stat2.counters[idx]);
}
+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->stat->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_kmem(dentry);
+
+ if (memcg)
+ __this_cpu_inc(memcg->stat->nr_dentry_neg);
+}
+
+void memcg_neg_dentry_dec(struct dentry *dentry)
+{
+ struct mem_cgroup *memcg = mem_cgroup_from_kmem(dentry);
+
+ if (memcg)
+ __this_cpu_dec(memcg->stat->nr_dentry_neg);
+}
+
unsigned long memcg_ws_activates(struct mem_cgroup *memcg)
{
return percpu_counter_read_positive(&memcg->stat2.counters[MEM_CGROUP_STAT_WS_ACTIVATE]);
@@ -5738,6 +5773,7 @@ static int memcg_stat_show(struct cgroup *cont, struct cftype *cft,
seq_printf(m, "%s %lu\n", mem_cgroup_events_names[i],
mem_cgroup_read_events(memcg, i));
seq_printf(m, "oom %lu\n", atomic_long_read(&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", mem_cgroup_lru_names[i],
--
1.8.3.1
More information about the Devel
mailing list