On Fri, Apr 24, 2026 at 12:36:44PM +0200, Michal Privoznik via Devel wrote: > From: Michal Privoznik <[email protected]> > > With CGroupsV2 the freezer controller is split into two files: > > 1) cgroup.freeze where an integer is written to thaw(0)/freeze(1) > processes within the cgroup, and > 2) cgroup.events where the frozen status can be read. > > Now, freezing/thawing a cgroup is as simple as writing > corresponding integer into cgroup.freeze. But similarly to > CGroupsV1, it may take some time to actually freeze all processes > inside the cgroup. So read both file and map combination of their > values according to this table: > > | frozen from cgroup.events > cgroup.freeze | 0 | 1 > --------------+------------+------------- > 0 | THAWED | N/A > --+------------+------------- > 1 | FREEZING | FROZEN > > Resolves: https://gitlab.com/libvirt/libvirt/-/work_items/870 > Signed-off-by: Michal Privoznik <[email protected]> > --- > src/util/vircgroupv2.c | 87 ++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 87 insertions(+) > > diff --git a/src/util/vircgroupv2.c b/src/util/vircgroupv2.c > index 3fbd67fbda..1f2ba72c4d 100644 > --- a/src/util/vircgroupv2.c > +++ b/src/util/vircgroupv2.c > @@ -1907,6 +1907,90 @@ virCgroupV2DenyAllDevices(virCgroup *group) > } > > > +static int > +virCgroupV2SetFreezerState(virCgroup *group, > + virCgroupFreezerState state) > +{ > + unsigned long long val; > + > + switch (state) { > + case VIR_CGROUP_FREEZER_STATE_THAWED: > + val = 0; break; > + case VIR_CGROUP_FREEZER_STATE_FROZEN: > + val = 1; break;
Currently not in our coding style docs but I would prefer having break
on separate line.
> + case VIR_CGROUP_FREEZER_STATE_FREEZING:
> + case VIR_CGROUP_FREEZER_STATE_LAST:
> + default:
> + virReportEnumRangeError(virCgroupFreezerState, state);
> + return -1;
> + }
> +
> + return virCgroupSetValueU64(group,
> + VIR_CGROUP_CONTROLLER_FREEZER,
> + "cgroup.freeze",
> + val);
> +}
> +
> +
> +static int
> +virCgroupV2GetFreezerState(virCgroup *group,
> + virCgroupFreezerState *state)
> +{
> + unsigned long long freezeReqested;
> + g_autofree char *eventsStr = NULL;
> + const char *frozenStr = "frozen ";
> + const char *tmp;
> +
> + if (virCgroupGetValueU64(group,
> + VIR_CGROUP_CONTROLLER_FREEZER,
> + "cgroup.freeze", &freezeReqested) < 0) {
> +
> + return -1;
> + }
> +
> + if (freezeReqested == 0) {
> + /* No freeze is requested. */
> + *state = VIR_CGROUP_FREEZER_STATE_THAWED;
> + return 0;
> + } else if (freezeReqested != 1) {
No need ot use `else if` as the previous condition returns if true.
> + virReportError(VIR_ERR_INTERNAL_ERROR,
> + _("Unknown value of freezer controller: %1$llu"),
> + freezeReqested);
> + return -1;
> + }
> +
> + /* Now look at cgroup.events at 'frozen' state. If it's 0, then some
> + * processes inside the CGroup are still being frozen. If it's 1,
> + * then all processes are frozen. */
> + if (virCgroupGetValueStr(group,
> + VIR_CGROUP_CONTROLLER_FREEZER,
> + "cgroup.events", &eventsStr) < 0) {
> + return -1;
> + }
> +
> + if (!eventsStr ||
> + !(tmp = strstr(eventsStr, frozenStr))) {
> + virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> + _("Invalid format of cgroup.events file"));
> + return -1;
> + }
> +
> + tmp += strlen(frozenStr);
> + if (*tmp == '0') {
> + *state = VIR_CGROUP_FREEZER_STATE_FREEZING;
> + } else if (*tmp == '1') {
> + *state = VIR_CGROUP_FREEZER_STATE_FROZEN;
> + } else {
> + virReportError(VIR_ERR_INTERNAL_ERROR,
> + _("Unknown state of freezer controller: %1$s"),
> + tmp);
> + return -1;
> + }
> +
> + return 0;
> +}
> +
> +
> virCgroupBackend virCgroupV2Backend = {
> .type = VIR_CGROUP_BACKEND_TYPE_V2,
>
> @@ -1980,6 +2064,9 @@ virCgroupBackend virCgroupV2Backend = {
> .getCpusetMemoryMigrate = virCgroupV2GetCpusetMemoryMigrate,
> .setCpusetCpus = virCgroupV2SetCpusetCpus,
> .getCpusetCpus = virCgroupV2GetCpusetCpus,
> +
> + .setFreezerState = virCgroupV2SetFreezerState,
> + .getFreezerState = virCgroupV2GetFreezerState,
> };
>
>
> --
> 2.53.0
>
signature.asc
Description: PGP signature
