The commit is pushed to "branch-rh7-3.10.0-229.7.2.vz7.8.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git after rh7-3.10.0-229.7.2.vz7.8.8 ------> commit 6157411c658b2aa2702432b018bd679a017e5416 Author: Vladimir Davydov <vdavy...@virtuozzo.com> Date: Tue Oct 20 15:59:31 2015 +0400
memcg: allow to disable cleancache per memcg Currently, it is only possible to disable tcache system-wide, but it might be useful to disable it for a particular container while leaving it enabled for others, e.g. in case the container is known to generate tons of used-once page cache (backup). This patch introduces memory.disable_cleancache per memcg knob. Writing 1 to it disables cleancache for the corresponding cgroup. Cleancache may be re-enabled by writing 0 to it. https://jira.sw.ru/browse/PSBM-34163 Signed-off-by: Vladimir Davydov <vdavy...@virtuozzo.com> Reviewed-by: Kirill Tkhai <ktk...@viztuozzo.com> --- include/linux/memcontrol.h | 6 ++++ mm/cleancache.c | 10 +++++-- mm/memcontrol.c | 71 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 85 insertions(+), 2 deletions(-) diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h index 0c85642..5835c8c 100644 --- a/include/linux/memcontrol.h +++ b/include/linux/memcontrol.h @@ -118,6 +118,7 @@ void mem_cgroup_iter_break(struct mem_cgroup *, struct mem_cgroup *); */ int mem_cgroup_inactive_anon_is_low(struct lruvec *lruvec); bool mem_cgroup_low(struct mem_cgroup *root, struct mem_cgroup *memcg); +bool mem_cgroup_cleancache_disabled(struct page *page); int mem_cgroup_select_victim_node(struct mem_cgroup *memcg); unsigned long mem_cgroup_get_lru_size(struct lruvec *lruvec, enum lru_list); void mem_cgroup_update_lru_size(struct lruvec *, enum lru_list, int); @@ -353,6 +354,11 @@ static inline bool mem_cgroup_low(struct mem_cgroup *root, return false; } +static inline bool mem_cgroup_cleancache_disabled(struct page *page) +{ + return false; +} + static inline unsigned long mem_cgroup_get_lru_size(struct lruvec *lruvec, enum lru_list lru) { diff --git a/mm/cleancache.c b/mm/cleancache.c index a3308bc..16fc1d7 100644 --- a/mm/cleancache.c +++ b/mm/cleancache.c @@ -15,6 +15,7 @@ #include <linux/fs.h> #include <linux/exportfs.h> #include <linux/mm.h> +#include <linux/memcontrol.h> #include <linux/debugfs.h> #include <linux/cleancache.h> @@ -227,8 +228,13 @@ void __cleancache_put_page(struct page *page) pool_id = page->mapping->host->i_sb->cleancache_poolid; if (pool_id >= 0 && cleancache_get_key(page->mapping->host, &key) >= 0) { - cleancache_ops->put_page(pool_id, key, page->index, page); - cleancache_puts++; + if (!mem_cgroup_cleancache_disabled(page)) { + cleancache_ops->put_page(pool_id, key, + page->index, page); + cleancache_puts++; + } else + cleancache_ops->invalidate_page(pool_id, key, + page->index); } } EXPORT_SYMBOL(__cleancache_put_page); diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 14e6aee..234ed8d 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -315,6 +315,20 @@ struct mem_cgroup { /* set when res.limit == memsw.limit */ bool memsw_is_minimum; +#ifdef CONFIG_CLEANCACHE + /* + * cleancache_disabled_toggle: toggled by writing to + * memory.disable_cleancache + * + * cleancache_disabled: set iff cleancache_disabled_toggle is + * set in this cgroup or any of its ascendants; controls whether + * cleancache callback is called when a page is evicted from + * this cgroup + */ + bool cleancache_disabled_toggle; + bool cleancache_disabled; +#endif + /* protect arrays of thresholds */ struct mutex thresholds_lock; @@ -1578,6 +1592,27 @@ bool mem_cgroup_low(struct mem_cgroup *root, struct mem_cgroup *memcg) return true; } +#ifdef CONFIG_CLEANCACHE +bool mem_cgroup_cleancache_disabled(struct page *page) +{ + struct page_cgroup *pc; + bool ret = false; + + if (mem_cgroup_disabled()) + return false; + + pc = lookup_page_cgroup(page); + if (!PageCgroupUsed(pc)) + return false; + + lock_page_cgroup(pc); + if (likely(PageCgroupUsed(pc))) + ret = pc->mem_cgroup->cleancache_disabled; + unlock_page_cgroup(pc); + return ret; +} +#endif + void mem_cgroup_note_oom_kill(struct mem_cgroup *root_memcg, struct task_struct *task) { @@ -5191,6 +5226,31 @@ static int mem_cgroup_oom_guarantee_write(struct cgroup *cont, return 0; } +#ifdef CONFIG_CLEANCACHE +static u64 mem_cgroup_disable_cleancache_read(struct cgroup *cgrp, + struct cftype *cft) +{ + return mem_cgroup_from_cont(cgrp)->cleancache_disabled_toggle; +} + +static int mem_cgroup_disable_cleancache_write(struct cgroup *cgrp, + struct cftype *cft, u64 val) +{ + struct mem_cgroup *memcg = mem_cgroup_from_cont(cgrp); + struct mem_cgroup *iter, *parent; + + mutex_lock(&memcg_create_mutex); + memcg->cleancache_disabled_toggle = !!val; + for_each_mem_cgroup_tree(iter, memcg) { + parent = parent_mem_cgroup(iter); + iter->cleancache_disabled = parent->cleancache_disabled || + iter->cleancache_disabled_toggle; + } + mutex_unlock(&memcg_create_mutex); + return 0; +} +#endif + static void memcg_get_hierarchical_limit(struct mem_cgroup *memcg, unsigned long long *mem_limit, unsigned long long *memsw_limit) { @@ -6131,6 +6191,14 @@ static struct cftype mem_cgroup_files[] = { .read_seq_string = memcg_numa_stat_show, }, #endif +#ifdef CONFIG_CLEANCACHE + { + .name = "disable_cleancache", + .flags = CFTYPE_NOT_ON_ROOT, + .read_u64 = mem_cgroup_disable_cleancache_read, + .write_u64 = mem_cgroup_disable_cleancache_write, + }, +#endif #ifdef CONFIG_MEMCG_KMEM { .name = "kmem.limit_in_bytes", @@ -6385,6 +6453,9 @@ mem_cgroup_css_online(struct cgroup *cont) memcg->use_hierarchy = parent->use_hierarchy; memcg->oom_kill_disable = parent->oom_kill_disable; memcg->swappiness = mem_cgroup_swappiness(parent); +#ifdef CONFIG_CLEANCACHE + memcg->cleancache_disabled = parent->cleancache_disabled; +#endif if (parent->use_hierarchy) { res_counter_init(&memcg->res, &parent->res); _______________________________________________ Devel mailing list Devel@openvz.org https://lists.openvz.org/mailman/listinfo/devel