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