On 2024/7/2 8:41, Xiu Jianfeng wrote: > Introduce misc.peak to record the historical maximum usage of the > resource, as in some scenarios the value of misc.max could be > adjusted based on the peak usage of the resource. > > Signed-off-by: Xiu Jianfeng <xiujianfeng@xxxxxxxxxx> > > --- > v2: use cmpxchg to update the watermark > --- > Documentation/admin-guide/cgroup-v2.rst | 9 ++++++ > include/linux/misc_cgroup.h | 2 ++ > kernel/cgroup/misc.c | 39 +++++++++++++++++++++++++ > 3 files changed, 50 insertions(+) > > diff --git a/Documentation/admin-guide/cgroup-v2.rst b/Documentation/admin-guide/cgroup-v2.rst > index ae0fdb6fc618..468a95379009 100644 > --- a/Documentation/admin-guide/cgroup-v2.rst > +++ b/Documentation/admin-guide/cgroup-v2.rst > @@ -2646,6 +2646,15 @@ Miscellaneous controller provides 3 interface files. If two misc resources (res_ > res_a 3 > res_b 0 > > + misc.peak > + A read-only flat-keyed file shown in all cgroups. It shows the > + historical maximum usage of the resources in the cgroup and its > + children.:: > + > + $ cat misc.peak > + res_a 10 > + res_b 8 > + > misc.max > A read-write flat-keyed file shown in the non root cgroups. Allowed > maximum usage of the resources in the cgroup and its children.:: > diff --git a/include/linux/misc_cgroup.h b/include/linux/misc_cgroup.h > index e799b1f8d05b..faf72a537596 100644 > --- a/include/linux/misc_cgroup.h > +++ b/include/linux/misc_cgroup.h > @@ -30,11 +30,13 @@ struct misc_cg; > /** > * struct misc_res: Per cgroup per misc type resource > * @max: Maximum limit on the resource. > + * @watermark: Historical maximum usage of the resource. > * @usage: Current usage of the resource. > * @events: Number of times, the resource limit exceeded. > */ > struct misc_res { > u64 max; > + u64 watermark; > atomic64_t usage; > atomic64_t events; > }; > diff --git a/kernel/cgroup/misc.c b/kernel/cgroup/misc.c > index 79a3717a5803..42642a96f4dc 100644 > --- a/kernel/cgroup/misc.c > +++ b/kernel/cgroup/misc.c > @@ -121,6 +121,17 @@ static void misc_cg_cancel_charge(enum misc_res_type type, struct misc_cg *cg, > misc_res_name[type]); > } > > +static void misc_cg_update_watermark(struct misc_res *res, u64 new_usage) > +{ > + u64 old; > + > + do { > + old = READ_ONCE(res->watermark); > + if (cmpxchg(&res->watermark, old, new_usage) == old) > + break; > + } while (0); oops! should be while (1) here. > +} > + > /** > * misc_cg_try_charge() - Try charging the misc cgroup. > * @type: Misc res type to charge. > @@ -159,6 +170,7 @@ int misc_cg_try_charge(enum misc_res_type type, struct misc_cg *cg, u64 amount) > ret = -EBUSY; > goto err_charge; > } > + misc_cg_update_watermark(res, new_usage); > } > return 0; > > @@ -307,6 +319,29 @@ static int misc_cg_current_show(struct seq_file *sf, void *v) > return 0; > } > > +/** > + * misc_cg_peak_show() - Show the peak usage of the misc cgroup. > + * @sf: Interface file > + * @v: Arguments passed > + * > + * Context: Any context. > + * Return: 0 to denote successful print. > + */ > +static int misc_cg_peak_show(struct seq_file *sf, void *v) > +{ > + int i; > + u64 watermark; > + struct misc_cg *cg = css_misc(seq_css(sf)); > + > + for (i = 0; i < MISC_CG_RES_TYPES; i++) { > + watermark = READ_ONCE(cg->res[i].watermark); > + if (READ_ONCE(misc_res_capacity[i]) || watermark) > + seq_printf(sf, "%s %llu\n", misc_res_name[i], watermark); > + } > + > + return 0; > +} > + > /** > * misc_cg_capacity_show() - Show the total capacity of misc res on the host. > * @sf: Interface file > @@ -357,6 +392,10 @@ static struct cftype misc_cg_files[] = { > .name = "current", > .seq_show = misc_cg_current_show, > }, > + { > + .name = "peak", > + .seq_show = misc_cg_peak_show, > + }, > { > .name = "capacity", > .seq_show = misc_cg_capacity_show,