Message ID | ZcvlhOZ4VBEX9raZ@host1.jankratochvil.net (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | [v4] cgroup2: New memory.max.effective like cgroup1 hierarchical_memory_limit | expand |
Hello. I have some advise about patch desription and only nitpick about implementation. On Wed, Feb 14, 2024 at 05:56:20AM +0800, "Jan Kratochvil (Azul)" <jkratochvil@azul.com> wrote: > which are useful for userland to easily and performance-wise find out the > effective cgroup limits being applied. I think this is a weak reasoning for in-kernel implementation. It may be faster but how often do you need to read that limit? > Otherwise userland has to Userland is at loss when running inside cgroupns with limited ancestors out of the cgroupns. Thus I think this is the reason why kernel can provide such an effective value. (And be subject line of the commit, I think bringing up cgroup1 is misleading.) > For cgroup1 it was implemented by: > memcg: show real limit under hierarchy mode > https://github.com/torvalds/linux/commit/fee7b548e6f2bd4bfd03a1a45d3afd593de7d5e9 > Date: Wed Jan 7 18:08:26 2009 -0800 FTR, commits are usually referenced more concisely like fee7b548e6f2 ("memcg: show real limit under hierarchy mode") (the document Waiman linked previously has some tips how to get this from git). > +static int memory_max_effective_show(struct seq_file *m, void *v) > +{ > + unsigned long memory; > + struct mem_cgroup *mi; > + > + /* Hierarchical information */ > + memory = PAGE_COUNTER_MAX; > + for (mi = mem_cgroup_from_seq(m); mi; mi = parent_mem_cgroup(mi)) > + memory = min(memory, READ_ONCE(mi->memory.max)); root_mem_cgroup is never charged (thus limited), so you can terminate the iteration on !mem_cgroup_is_root(mi), one level earlier > +static int swap_max_effective_show(struct seq_file *m, void *v) > +{ > + unsigned long swap; > + struct mem_cgroup *mi; > + > + /* Hierarchical information */ > + swap = PAGE_COUNTER_MAX; > + for (mi = mem_cgroup_from_seq(m); mi; mi = parent_mem_cgroup(mi)) > + swap = min(swap, READ_ONCE(mi->swap.max)); ditto HTH, Michal
diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 1ed40f9d3..8c4cb5f60 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -6845,6 +6845,19 @@ static ssize_t memory_max_write(struct kernfs_open_file *of, return nbytes; } +static int memory_max_effective_show(struct seq_file *m, void *v) +{ + unsigned long memory; + struct mem_cgroup *mi; + + /* Hierarchical information */ + memory = PAGE_COUNTER_MAX; + for (mi = mem_cgroup_from_seq(m); mi; mi = parent_mem_cgroup(mi)) + memory = min(memory, READ_ONCE(mi->memory.max)); + + return seq_puts_memcg_tunable(m, memory); +} + /* * Note: don't forget to update the 'samples/cgroup/memcg_event_listener' * if any new events become available. @@ -7038,6 +7051,11 @@ static struct cftype memory_files[] = { .seq_show = memory_max_show, .write = memory_max_write, }, + { + .name = "max.effective", + .flags = CFTYPE_NOT_ON_ROOT, + .seq_show = memory_max_effective_show, + }, { .name = "events", .flags = CFTYPE_NOT_ON_ROOT, @@ -8040,6 +8058,19 @@ static ssize_t swap_max_write(struct kernfs_open_file *of, return nbytes; } +static int swap_max_effective_show(struct seq_file *m, void *v) +{ + unsigned long swap; + struct mem_cgroup *mi; + + /* Hierarchical information */ + swap = PAGE_COUNTER_MAX; + for (mi = mem_cgroup_from_seq(m); mi; mi = parent_mem_cgroup(mi)) + swap = min(swap, READ_ONCE(mi->swap.max)); + + return seq_puts_memcg_tunable(m, swap); +} + static int swap_events_show(struct seq_file *m, void *v) { struct mem_cgroup *memcg = mem_cgroup_from_seq(m); @@ -8072,6 +8103,11 @@ static struct cftype swap_files[] = { .seq_show = swap_max_show, .write = swap_max_write, }, + { + .name = "swap.max.effective", + .flags = CFTYPE_NOT_ON_ROOT, + .seq_show = swap_max_effective_show, + }, { .name = "swap.peak", .flags = CFTYPE_NOT_ON_ROOT,
Implement cgroup2 "memory.max.effective" and "memory.swap.max.effective" files similar to existing "cpuset.cpus.effective". cgroup1 (by function memcg1_stat_format) contains two lines hierarchical_memory_limit %llu hierarchical_memsw_limit %llu which are useful for userland to easily and performance-wise find out the effective cgroup limits being applied. Otherwise userland has to open+read+close the file "memory.max" and/or "memory.swap.max" in multiple parent directories of a nested cgroup. For cgroup1 it was implemented by: memcg: show real limit under hierarchy mode https://github.com/torvalds/linux/commit/fee7b548e6f2bd4bfd03a1a45d3afd593de7d5e9 Date: Wed Jan 7 18:08:26 2009 -0800 But for cgroup2 it has been missing so far. v4: Adjust the commit message. v3: memory.stat fields -> *.max.effective separate files suggested by Michal Koutny v2: hierarchical_memsw_limit -> hierarchical_swap_limit fix found by Waiman Long v1: hierarchical_memory_limit && hierarchical_memsw_limit in memory.stat Signed-off-by: Jan Kratochvil (Azul) <jkratochvil@azul.com> mm/memcontrol.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+)