The commit is pushed to "branch-rh7-3.10.0-1160.11.1.vz7.172.x-ovz" and will 
appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-1160.11.1.vz7.172.9
------>
commit 8d980b969c46db524938d67a252b6f986999a67c
Author: Vasily Averin <v...@virtuozzo.com>
Date:   Wed Jan 13 13:25:44 2021 +0300

    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 <v...@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],
_______________________________________________
Devel mailing list
Devel@openvz.org
https://lists.openvz.org/mailman/listinfo/devel

Reply via email to