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;
+ 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) {
+ 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