The interface is slightly reworked to be more v2 like:

- rename memory.cache.limit/usage_in_bytes -> memory.cache.max/current
- show "max" when uninitialized and allow to write it
- memcg_max_mutex with page_counter_set_max replaced with simple xchg
- we set limit first before looping and then try to enforce it if
  needed, no more enforce before setting logic
- retry reclaim couple of times if it fails to enforce the limit and
  then just give up (memory_max_write triggers oom in this case, but we
  probably do not want to trigger oom due to cache limit)

https://virtuozzo.atlassian.net/browse/PSBM-154207
Signed-off-by: Pavel Tikhomirov <ptikhomi...@virtuozzo.com>

Feature: mm: Memory cgroup page cache limit
---
 mm/memcontrol.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 75 insertions(+)

diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 9000dc00ed03..28a39b50cbe1 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -8810,3 +8810,78 @@ static int __init mem_cgroup_swap_init(void)
 subsys_initcall(mem_cgroup_swap_init);
 
 #endif /* CONFIG_SWAP */
+
+static int cache_max_show(struct seq_file *m, void *v)
+{
+       return seq_puts_memcg_tunable(m,
+               READ_ONCE(mem_cgroup_from_seq(m)->cache.max));
+}
+
+static ssize_t cache_max_write(struct kernfs_open_file *of,
+                              char *buf, size_t nbytes, loff_t off)
+{
+       struct mem_cgroup *memcg = mem_cgroup_from_css(of_css(of));
+       unsigned int nr_reclaims = MAX_RECLAIM_RETRIES;
+       unsigned long max;
+       int err;
+
+       buf = strstrip(buf);
+       err = page_counter_memparse(buf, "max", &max);
+       if (err)
+               return err;
+
+       xchg(&memcg->cache.max, max);
+
+       for (;;) {
+               unsigned long nr_cache = page_counter_read(&memcg->cache);
+
+               if (nr_cache <= max)
+                       break;
+
+               if (signal_pending(current))
+                       break;
+
+               if (!nr_reclaims)
+                       break;
+
+               if (!try_to_free_mem_cgroup_pages(memcg, nr_cache - max,
+                   GFP_KERNEL, false))
+                       nr_reclaims--;
+       }
+
+       memcg_wb_domain_size_changed(memcg);
+       return nbytes;
+}
+
+static u64 cache_current_read(struct cgroup_subsys_state *css,
+                              struct cftype *cft)
+{
+       struct mem_cgroup *memcg = mem_cgroup_from_css(css);
+
+       return (u64)page_counter_read(&memcg->cache) * PAGE_SIZE;
+}
+
+static struct cftype cache_files[] = {
+       {
+               .name = "cache.max",
+               .flags = CFTYPE_NOT_ON_ROOT,
+               .seq_show = cache_max_show,
+               .write = cache_max_write,
+       },
+       {
+               .name = "cache.current",
+               .flags = CFTYPE_NOT_ON_ROOT,
+               .read_u64 = cache_current_read,
+       },
+       { }     /* terminate */
+};
+
+static int __init mem_cgroup_cache_init(void)
+{
+       if (mem_cgroup_disabled())
+               return 0;
+
+       WARN_ON(cgroup_add_dfl_cftypes(&memory_cgrp_subsys, cache_files));
+       return 0;
+}
+subsys_initcall(mem_cgroup_cache_init);
-- 
2.43.0

_______________________________________________
Devel mailing list
Devel@openvz.org
https://lists.openvz.org/mailman/listinfo/devel

Reply via email to