render / rpms / libvirt

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