render / rpms / libvirt

Forked from rpms/libvirt 9 months ago
Clone
Blob Blame History Raw
From 4a7aa0ff6839fd9ccefce19d63c48beed32ee7f1 Mon Sep 17 00:00:00 2001
Message-Id: <4a7aa0ff6839fd9ccefce19d63c48beed32ee7f1@dist-git>
From: Pavel Hrdina <phrdina@redhat.com>
Date: Mon, 1 Jul 2019 17:07:25 +0200
Subject: [PATCH] vircgroup: introduce virCgroupV2MakeGroup
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

When creating cgroup hierarchy we need to enable controllers in the
parent cgroup in order to be usable.  That means writing "+{controller}"
into cgroup.subtree_control file.  We can enable only controllers that
are enabled for parent cgroup, that means we need to do that for the
whole cgroup tree.

Cgroups for threads needs to be handled differently in cgroup v2.  There
are two types of controllers:

    - domain controllers: these cannot be enabled for threads
    - threaded controllers: these can be enabled for threads

In addition there are multiple types of cgroups:

    - domain: normal cgroup
    - domain threaded: a domain cgroup that serves as root for threaded
                       cgroups
    - domain invalid: invalid cgroup, can be changed into threaded, this
                      is the default state if you create subgroup inside
                      domain threaded group or threaded group
    - threaded: threaded cgroup which can have domain threaded or
                threaded as parent group

In order to create threaded cgroup it's sufficient to write "threaded"
into cgroup.type file, it will automatically make parent cgroup
"domain threaded" if it was only "domain".  In case the parent cgroup
is already "domain threaded" or "threaded" it will modify only the type
of current cgroup.  After that we can enable threaded controllers.

Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
(cherry picked from commit 89f52abd07d3f991ddd22990e5d61338ff350a99)

Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297

Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
Message-Id: <165b3b0f0fd1e5a4b52e4b9e86e4137b3598f7ee.1561993100.git.phrdina@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
---
 src/util/vircgroup.c        |  2 +-
 src/util/vircgroupbackend.h |  1 +
 src/util/vircgroupv2.c      | 76 +++++++++++++++++++++++++++++++++++++
 3 files changed, 78 insertions(+), 1 deletion(-)

diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
index 42930582db..a859628241 100644
--- a/src/util/vircgroup.c
+++ b/src/util/vircgroup.c
@@ -942,7 +942,7 @@ virCgroupNewThread(virCgroupPtr domain,
     if (virCgroupNew(-1, name, domain, controllers, group) < 0)
         return -1;
 
-    if (virCgroupMakeGroup(domain, *group, create, VIR_CGROUP_NONE) < 0) {
+    if (virCgroupMakeGroup(domain, *group, create, VIR_CGROUP_THREAD) < 0) {
         virCgroupFree(group);
         return -1;
     }
diff --git a/src/util/vircgroupbackend.h b/src/util/vircgroupbackend.h
index b1f19233e4..86d1539e07 100644
--- a/src/util/vircgroupbackend.h
+++ b/src/util/vircgroupbackend.h
@@ -33,6 +33,7 @@ typedef enum {
                                        * before creating subcgroups and
                                        * attaching tasks
                                        */
+    VIR_CGROUP_THREAD = 1 << 1, /* cgroup v2 handles threads differently */
 } virCgroupBackendFlags;
 
 typedef enum {
diff --git a/src/util/vircgroupv2.c b/src/util/vircgroupv2.c
index 6695901766..cf8bd01317 100644
--- a/src/util/vircgroupv2.c
+++ b/src/util/vircgroupv2.c
@@ -338,6 +338,81 @@ virCgroupV2PathOfController(virCgroupPtr group,
 }
 
 
+static int
+virCgroupV2EnableController(virCgroupPtr parent,
+                            int controller)
+{
+    VIR_AUTOFREE(char *) val = NULL;
+
+    if (virAsprintf(&val, "+%s",
+                    virCgroupV2ControllerTypeToString(controller)) < 0) {
+        return -1;
+    }
+
+    if (virCgroupSetValueStr(parent, controller,
+                             "cgroup.subtree_control", val) < 0) {
+        return -1;
+    }
+
+    return 0;
+}
+
+
+static int
+virCgroupV2MakeGroup(virCgroupPtr parent ATTRIBUTE_UNUSED,
+                     virCgroupPtr group,
+                     bool create,
+                     unsigned int flags)
+{
+    VIR_AUTOFREE(char *) path = NULL;
+    int controller;
+
+    VIR_DEBUG("Make group %s", group->path);
+
+    controller = virCgroupV2GetAnyController(group);
+    if (virCgroupV2PathOfController(group, controller, "", &path) < 0)
+        return -1;
+
+    VIR_DEBUG("Make controller %s", path);
+
+    if (!virFileExists(path) &&
+        (!create || (mkdir(path, 0755) < 0 && errno != EEXIST))) {
+        virReportSystemError(errno, _("Failed to create v2 cgroup '%s'"),
+                             group->path);
+        return -1;
+    }
+
+    if (create) {
+        if (flags & VIR_CGROUP_THREAD) {
+            if (virCgroupSetValueStr(group, VIR_CGROUP_CONTROLLER_CPU,
+                                     "cgroup.type", "threaded") < 0) {
+                return -1;
+            }
+
+            if (virCgroupV2EnableController(parent,
+                                            VIR_CGROUP_CONTROLLER_CPU) < 0) {
+                return -1;
+            }
+        } else {
+            size_t i;
+            for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
+                if (!virCgroupV2HasController(parent, i))
+                    continue;
+
+                /* Controllers that are implicitly enabled if available. */
+                if (i == VIR_CGROUP_CONTROLLER_CPUACCT)
+                    continue;
+
+                if (virCgroupV2EnableController(parent, i) < 0)
+                    return -1;
+            }
+        }
+    }
+
+    return 0;
+}
+
+
 virCgroupBackend virCgroupV2Backend = {
     .type = VIR_CGROUP_BACKEND_TYPE_V2,
 
@@ -353,6 +428,7 @@ virCgroupBackend virCgroupV2Backend = {
     .hasController = virCgroupV2HasController,
     .getAnyController = virCgroupV2GetAnyController,
     .pathOfController = virCgroupV2PathOfController,
+    .makeGroup = virCgroupV2MakeGroup,
 };
 
 
-- 
2.22.0