[Devel] [PATCH rh7 v2] memcg: allow to disable cleancache per memcg
Kirill Tkhai
ktkhai at odin.com
Tue Oct 20 03:34:52 PDT 2015
On 16.10.2015 12:53, Vladimir Davydov wrote:
> From: Vladimir Davydov <vdavydov at parallels.com>
>
> 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 <vdavydov at parallels.com>
Reviewed-by: Kirill Tkhai <ktkhai@[parallels,odin,viztuozzo].com>
> ---
> Changes in v2:
> - place cleancache_disable bool near another bool so as not to increase
> size of struct mem_cgroup
> - optimize mem_cgroup_cleancache_disabled check: do not ascend up the
> hierarchy tree there
>
> 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 0c856425ab7a..5835c8ca199d 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 a3308bcaa116..16fc1d7c90ae 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 14e6aee94c32..234ed8de3f85 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);
>
More information about the Devel
mailing list