c313de
From 4a7aa0ff6839fd9ccefce19d63c48beed32ee7f1 Mon Sep 17 00:00:00 2001
c313de
Message-Id: <4a7aa0ff6839fd9ccefce19d63c48beed32ee7f1@dist-git>
c313de
From: Pavel Hrdina <phrdina@redhat.com>
c313de
Date: Mon, 1 Jul 2019 17:07:25 +0200
c313de
Subject: [PATCH] vircgroup: introduce virCgroupV2MakeGroup
c313de
MIME-Version: 1.0
c313de
Content-Type: text/plain; charset=UTF-8
c313de
Content-Transfer-Encoding: 8bit
c313de
c313de
When creating cgroup hierarchy we need to enable controllers in the
c313de
parent cgroup in order to be usable.  That means writing "+{controller}"
c313de
into cgroup.subtree_control file.  We can enable only controllers that
c313de
are enabled for parent cgroup, that means we need to do that for the
c313de
whole cgroup tree.
c313de
c313de
Cgroups for threads needs to be handled differently in cgroup v2.  There
c313de
are two types of controllers:
c313de
c313de
    - domain controllers: these cannot be enabled for threads
c313de
    - threaded controllers: these can be enabled for threads
c313de
c313de
In addition there are multiple types of cgroups:
c313de
c313de
    - domain: normal cgroup
c313de
    - domain threaded: a domain cgroup that serves as root for threaded
c313de
                       cgroups
c313de
    - domain invalid: invalid cgroup, can be changed into threaded, this
c313de
                      is the default state if you create subgroup inside
c313de
                      domain threaded group or threaded group
c313de
    - threaded: threaded cgroup which can have domain threaded or
c313de
                threaded as parent group
c313de
c313de
In order to create threaded cgroup it's sufficient to write "threaded"
c313de
into cgroup.type file, it will automatically make parent cgroup
c313de
"domain threaded" if it was only "domain".  In case the parent cgroup
c313de
is already "domain threaded" or "threaded" it will modify only the type
c313de
of current cgroup.  After that we can enable threaded controllers.
c313de
c313de
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
c313de
(cherry picked from commit 89f52abd07d3f991ddd22990e5d61338ff350a99)
c313de
c313de
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
c313de
c313de
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
c313de
Message-Id: <165b3b0f0fd1e5a4b52e4b9e86e4137b3598f7ee.1561993100.git.phrdina@redhat.com>
c313de
Reviewed-by: Ján Tomko <jtomko@redhat.com>
c313de
---
c313de
 src/util/vircgroup.c        |  2 +-
c313de
 src/util/vircgroupbackend.h |  1 +
c313de
 src/util/vircgroupv2.c      | 76 +++++++++++++++++++++++++++++++++++++
c313de
 3 files changed, 78 insertions(+), 1 deletion(-)
c313de
c313de
diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
c313de
index 42930582db..a859628241 100644
c313de
--- a/src/util/vircgroup.c
c313de
+++ b/src/util/vircgroup.c
c313de
@@ -942,7 +942,7 @@ virCgroupNewThread(virCgroupPtr domain,
c313de
     if (virCgroupNew(-1, name, domain, controllers, group) < 0)
c313de
         return -1;
c313de
 
c313de
-    if (virCgroupMakeGroup(domain, *group, create, VIR_CGROUP_NONE) < 0) {
c313de
+    if (virCgroupMakeGroup(domain, *group, create, VIR_CGROUP_THREAD) < 0) {
c313de
         virCgroupFree(group);
c313de
         return -1;
c313de
     }
c313de
diff --git a/src/util/vircgroupbackend.h b/src/util/vircgroupbackend.h
c313de
index b1f19233e4..86d1539e07 100644
c313de
--- a/src/util/vircgroupbackend.h
c313de
+++ b/src/util/vircgroupbackend.h
c313de
@@ -33,6 +33,7 @@ typedef enum {
c313de
                                        * before creating subcgroups and
c313de
                                        * attaching tasks
c313de
                                        */
c313de
+    VIR_CGROUP_THREAD = 1 << 1, /* cgroup v2 handles threads differently */
c313de
 } virCgroupBackendFlags;
c313de
 
c313de
 typedef enum {
c313de
diff --git a/src/util/vircgroupv2.c b/src/util/vircgroupv2.c
c313de
index 6695901766..cf8bd01317 100644
c313de
--- a/src/util/vircgroupv2.c
c313de
+++ b/src/util/vircgroupv2.c
c313de
@@ -338,6 +338,81 @@ virCgroupV2PathOfController(virCgroupPtr group,
c313de
 }
c313de
 
c313de
 
c313de
+static int
c313de
+virCgroupV2EnableController(virCgroupPtr parent,
c313de
+                            int controller)
c313de
+{
c313de
+    VIR_AUTOFREE(char *) val = NULL;
c313de
+
c313de
+    if (virAsprintf(&val, "+%s",
c313de
+                    virCgroupV2ControllerTypeToString(controller)) < 0) {
c313de
+        return -1;
c313de
+    }
c313de
+
c313de
+    if (virCgroupSetValueStr(parent, controller,
c313de
+                             "cgroup.subtree_control", val) < 0) {
c313de
+        return -1;
c313de
+    }
c313de
+
c313de
+    return 0;
c313de
+}
c313de
+
c313de
+
c313de
+static int
c313de
+virCgroupV2MakeGroup(virCgroupPtr parent ATTRIBUTE_UNUSED,
c313de
+                     virCgroupPtr group,
c313de
+                     bool create,
c313de
+                     unsigned int flags)
c313de
+{
c313de
+    VIR_AUTOFREE(char *) path = NULL;
c313de
+    int controller;
c313de
+
c313de
+    VIR_DEBUG("Make group %s", group->path);
c313de
+
c313de
+    controller = virCgroupV2GetAnyController(group);
c313de
+    if (virCgroupV2PathOfController(group, controller, "", &path) < 0)
c313de
+        return -1;
c313de
+
c313de
+    VIR_DEBUG("Make controller %s", path);
c313de
+
c313de
+    if (!virFileExists(path) &&
c313de
+        (!create || (mkdir(path, 0755) < 0 && errno != EEXIST))) {
c313de
+        virReportSystemError(errno, _("Failed to create v2 cgroup '%s'"),
c313de
+                             group->path);
c313de
+        return -1;
c313de
+    }
c313de
+
c313de
+    if (create) {
c313de
+        if (flags & VIR_CGROUP_THREAD) {
c313de
+            if (virCgroupSetValueStr(group, VIR_CGROUP_CONTROLLER_CPU,
c313de
+                                     "cgroup.type", "threaded") < 0) {
c313de
+                return -1;
c313de
+            }
c313de
+
c313de
+            if (virCgroupV2EnableController(parent,
c313de
+                                            VIR_CGROUP_CONTROLLER_CPU) < 0) {
c313de
+                return -1;
c313de
+            }
c313de
+        } else {
c313de
+            size_t i;
c313de
+            for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
c313de
+                if (!virCgroupV2HasController(parent, i))
c313de
+                    continue;
c313de
+
c313de
+                /* Controllers that are implicitly enabled if available. */
c313de
+                if (i == VIR_CGROUP_CONTROLLER_CPUACCT)
c313de
+                    continue;
c313de
+
c313de
+                if (virCgroupV2EnableController(parent, i) < 0)
c313de
+                    return -1;
c313de
+            }
c313de
+        }
c313de
+    }
c313de
+
c313de
+    return 0;
c313de
+}
c313de
+
c313de
+
c313de
 virCgroupBackend virCgroupV2Backend = {
c313de
     .type = VIR_CGROUP_BACKEND_TYPE_V2,
c313de
 
c313de
@@ -353,6 +428,7 @@ virCgroupBackend virCgroupV2Backend = {
c313de
     .hasController = virCgroupV2HasController,
c313de
     .getAnyController = virCgroupV2GetAnyController,
c313de
     .pathOfController = virCgroupV2PathOfController,
c313de
+    .makeGroup = virCgroupV2MakeGroup,
c313de
 };
c313de
 
c313de
 
c313de
-- 
c313de
2.22.0
c313de