From 256b5d94a9b764ad5acfa01166421cc2bf37dcd9 Mon Sep 17 00:00:00 2001 From: Yang Shi Date: Wed, 14 Aug 2019 05:45:18 +0800 Subject: [PATCH] alios: mm: memcontrol: add background reclaim support for cgroupv2 Like v1, add background reclaim support for cgroup v2. The interfaces are exactly same with v1. However, if high limit is setup for v2, the water mark would be calculated by high limit instead of max limit. Reviewed-by: Gavin Shan Reviewed-by: Xunlei Pang Signed-off-by: Yang Shi --- Documentation/admin-guide/cgroup-v2.rst | 32 ++++++++++++++ mm/memcontrol.c | 55 ++++++++++++++++++++++++- 2 files changed, 86 insertions(+), 1 deletion(-) diff --git a/Documentation/admin-guide/cgroup-v2.rst b/Documentation/admin-guide/cgroup-v2.rst index 342388f92110..2c86a6cffd88 100644 --- a/Documentation/admin-guide/cgroup-v2.rst +++ b/Documentation/admin-guide/cgroup-v2.rst @@ -1084,6 +1084,38 @@ PAGE_SIZE multiple when read back. high limit is used and monitored properly, this limit's utility is limited to providing the final safety net. + memory.wmark_ratio + A read-write single value file which exists on non-root + cgroups. The default is 0. + + Memory usage water mark. Valid value is from 0 to 100, which + represents percentage of max limit or high limit if high is setup. + The wmark_low and wmark_high would be calculated by max limit and + wmark_ratio. 0 means water mark is disabled, both wmark_low and + wmark_high would be max, which is the default value. + + Once water mark is setup correctly, when charging pages to memcg, + if the usage exceeds wmark_high, which means available memory is low, + a work would be scheduled to reclaim pages in background to try to + reduce memory usage to wmark_low if possible. + + If memory.low is greater than memory.wmark_high, back ground reclaim + may not take effect at all due to low protection. + + memory.wmark_high + A read-only single value file which exists on non-root cgroups. + The default is max. + + Memory usage high water mark, which means the available memory is low. + For details, please refer to the above wmark_ratio section. + + memory.wmark_low + A read-only single value file which exists on non-root cgroups. + The default is max. + + Memory usage low water mark, which means the available memory is ok. + For details, please refer to the above wmark_ratio section. + memory.oom.group A read-write single value file which exists on non-root cgroups. The default value is "0". diff --git a/mm/memcontrol.c b/mm/memcontrol.c index d516877c2f6e..ad8d304edcf5 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -2945,7 +2945,8 @@ static void setup_memcg_wmark(struct mem_cgroup *memcg) { unsigned long high_wmark; unsigned long low_wmark; - unsigned long max = memcg->memory.max; + unsigned long max = memcg->high > memcg->memory.max ? + memcg->memory.max : memcg->high; unsigned int wmark_ratio = memcg->wmark_ratio; if (wmark_ratio) { @@ -5791,10 +5792,41 @@ static ssize_t memory_high_write(struct kernfs_open_file *of, try_to_free_mem_cgroup_pages(memcg, nr_pages - high, GFP_KERNEL, true); + setup_memcg_wmark(memcg); + + if (!is_wmark_ok(memcg, true)) + queue_work(memcg_wmark_wq, &memcg->wmark_work); + memcg_wb_domain_size_changed(memcg); return nbytes; } +static int memory_wmark_low_show(struct seq_file *m, void *v) +{ + struct mem_cgroup *memcg = mem_cgroup_from_css(seq_css(m)); + unsigned long wmark_low = READ_ONCE(memcg->memory.wmark_low); + + if (wmark_low == PAGE_COUNTER_MAX) + seq_puts(m, "max\n"); + else + seq_printf(m, "%llu\n", (u64)wmark_low * PAGE_SIZE); + + return 0; +} + +static int memory_wmark_high_show(struct seq_file *m, void *v) +{ + struct mem_cgroup *memcg = mem_cgroup_from_css(seq_css(m)); + unsigned long wmark_high = READ_ONCE(memcg->memory.wmark_high); + + if (wmark_high == PAGE_COUNTER_MAX) + seq_puts(m, "max\n"); + else + seq_printf(m, "%llu\n", (u64)wmark_high * PAGE_SIZE); + + return 0; +} + static int memory_max_show(struct seq_file *m, void *v) { struct mem_cgroup *memcg = mem_cgroup_from_css(seq_css(m)); @@ -5853,6 +5885,11 @@ static ssize_t memory_max_write(struct kernfs_open_file *of, break; } + setup_memcg_wmark(memcg); + + if (!is_wmark_ok(memcg, true)) + queue_work(memcg_wmark_wq, &memcg->wmark_work); + memcg_wb_domain_size_changed(memcg); return nbytes; } @@ -6013,6 +6050,22 @@ static struct cftype memory_files[] = { .seq_show = memory_max_show, .write = memory_max_write, }, + { + .name = "wmark_ratio", + .flags = CFTYPE_NOT_ON_ROOT, + .seq_show = memory_wmark_ratio_show, + .write = memory_wmark_ratio_write, + }, + { + .name = "wmark_high", + .flags = CFTYPE_NOT_ON_ROOT, + .seq_show = memory_wmark_high_show, + }, + { + .name = "wmark_low", + .flags = CFTYPE_NOT_ON_ROOT, + .seq_show = memory_wmark_low_show, + }, { .name = "events", .flags = CFTYPE_NOT_ON_ROOT, -- GitLab