397dc2
From 205289d2792aacf68ed2cb8563d1860bd36137a0 Mon Sep 17 00:00:00 2001
397dc2
Message-Id: <205289d2792aacf68ed2cb8563d1860bd36137a0@dist-git>
397dc2
From: Pavel Hrdina <phrdina@redhat.com>
397dc2
Date: Fri, 19 Feb 2021 13:33:55 +0100
397dc2
Subject: [PATCH] vircgroup: use DBus call to systemd for some APIs
397dc2
MIME-Version: 1.0
397dc2
Content-Type: text/plain; charset=UTF-8
397dc2
Content-Transfer-Encoding: 8bit
397dc2
397dc2
When running on host with systemd we register VMs with machined.
397dc2
In this case systemd creates the root VM cgroup for us. This has some
397dc2
implications where one of them is that systemd owns all files inside
397dc2
the root VM cgroup and we should not touch them.
397dc2
397dc2
If we change any value in file that systemd knows about it will be
397dc2
changed to what systemd thinks it should be when executing
397dc2
`systemctl daemon-reload`.
397dc2
397dc2
These are the APIs that we need to call using systemd because they set
397dc2
limits that are proportional to sibling cgroups.
397dc2
397dc2
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
397dc2
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
397dc2
(cherry picked from commit 9c1693eff427661616ce1bd2795688f87288a412)
397dc2
397dc2
Conflicts:
397dc2
    src/util/vircgroup.c
397dc2
        - missing upstream g_autofree rewrite
397dc2
        - missing upstream glib dbus rewrite, hence the ugly macro
397dc2
          instead of a function
397dc2
397dc2
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1798463
397dc2
397dc2
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
397dc2
Message-Id: <5d22d307112333f1da565cb642ea9001a7b8b55b.1613737828.git.phrdina@redhat.com>
397dc2
Reviewed-by: Ján Tomko <jtomko@redhat.com>
397dc2
---
397dc2
 src/util/vircgroup.c     | 11 ++++++++++
397dc2
 src/util/vircgrouppriv.h | 25 +++++++++++++++++++++++
397dc2
 src/util/vircgroupv1.c   | 44 +++++++++++++++++++++++++++-------------
397dc2
 src/util/vircgroupv2.c   | 44 +++++++++++++++++++++++++++-------------
397dc2
 tests/Makefile.am        |  1 +
397dc2
 5 files changed, 97 insertions(+), 28 deletions(-)
397dc2
397dc2
diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
397dc2
index a45c2e7f2f..10b934291c 100644
397dc2
--- a/src/util/vircgroup.c
397dc2
+++ b/src/util/vircgroup.c
397dc2
@@ -1027,6 +1027,10 @@ virCgroupNewDetectMachine(const char *name,
397dc2
         }
397dc2
     }
397dc2
 
397dc2
+    (*group)->unitName = virSystemdGetMachineUnitByPID(pid);
397dc2
+    if (virSystemdHasMachined() == 0 && !(*group)->unitName)
397dc2
+        return -1;
397dc2
+
397dc2
     return 0;
397dc2
 }
397dc2
 
397dc2
@@ -1146,6 +1150,12 @@ virCgroupNewMachineSystemd(const char *name,
397dc2
         return -1;
397dc2
     }
397dc2
 
397dc2
+    (*group)->unitName = virSystemdGetMachineUnitByPID(pidleader);
397dc2
+    if (!(*group)->unitName) {
397dc2
+        virCgroupFree(group);
397dc2
+        return -1;
397dc2
+    }
397dc2
+
397dc2
     if (virCgroupAddProcess(*group, pidleader) < 0) {
397dc2
         virErrorPtr saved;
397dc2
 
397dc2
@@ -3553,6 +3563,7 @@ virCgroupFree(virCgroupPtr *group)
397dc2
 
397dc2
     VIR_FREE((*group)->unified.mountPoint);
397dc2
     VIR_FREE((*group)->unified.placement);
397dc2
+    VIR_FREE((*group)->unitName);
397dc2
 
397dc2
     VIR_FREE((*group)->path);
397dc2
     VIR_FREE(*group);
397dc2
diff --git a/src/util/vircgrouppriv.h b/src/util/vircgrouppriv.h
397dc2
index f2a80aeb82..b4a9e0b379 100644
397dc2
--- a/src/util/vircgrouppriv.h
397dc2
+++ b/src/util/vircgrouppriv.h
397dc2
@@ -27,6 +27,7 @@
397dc2
 
397dc2
 #include "vircgroup.h"
397dc2
 #include "vircgroupbackend.h"
397dc2
+#include "virdbus.h"
397dc2
 
397dc2
 struct _virCgroupV1Controller {
397dc2
     int type;
397dc2
@@ -66,8 +67,32 @@ struct _virCgroup {
397dc2
 
397dc2
     virCgroupV1Controller legacy[VIR_CGROUP_CONTROLLER_LAST];
397dc2
     virCgroupV2Controller unified;
397dc2
+
397dc2
+    char *unitName;
397dc2
 };
397dc2
 
397dc2
+#define virCgroupSetValueDBus(unitName, key, ...) \
397dc2
+    ({ \
397dc2
+        int __ret = -1; \
397dc2
+        do { \
397dc2
+            DBusConnection *__conn; \
397dc2
+            if (!(__conn = virDBusGetSystemBus())) \
397dc2
+                break; \
397dc2
+            __ret = virDBusCallMethod(__conn, NULL, NULL, \
397dc2
+                                      "org.freedesktop.systemd1", \
397dc2
+                                      "/org/freedesktop/systemd1", \
397dc2
+                                      "org.freedesktop.systemd1.Manager", \
397dc2
+                                      "SetUnitProperties", \
397dc2
+                                      "sba(sv)", \
397dc2
+                                      unitName, \
397dc2
+                                      true, \
397dc2
+                                      1, \
397dc2
+                                      key, \
397dc2
+                                      __VA_ARGS__); \
397dc2
+        } while (0); \
397dc2
+        __ret; \
397dc2
+    })
397dc2
+
397dc2
 int virCgroupSetValueRaw(const char *path,
397dc2
                          const char *value);
397dc2
 
397dc2
diff --git a/src/util/vircgroupv1.c b/src/util/vircgroupv1.c
397dc2
index c35088a3c4..7ec8f3a316 100644
397dc2
--- a/src/util/vircgroupv1.c
397dc2
+++ b/src/util/vircgroupv1.c
397dc2
@@ -931,7 +931,6 @@ virCgroupV1SetBlkioWeight(virCgroupPtr group,
397dc2
                           unsigned int weight)
397dc2
 {
397dc2
     g_autofree char *path = NULL;
397dc2
-    g_autofree char *value = NULL;
397dc2
 
397dc2
     if (virCgroupV1PathOfController(group, VIR_CGROUP_CONTROLLER_BLKIO,
397dc2
                                     "blkio.bfq.weight", &path) < 0) {
397dc2
@@ -953,9 +952,14 @@ virCgroupV1SetBlkioWeight(virCgroupPtr group,
397dc2
         return -1;
397dc2
     }
397dc2
 
397dc2
-    value = g_strdup_printf("%u", weight);
397dc2
+    if (group->unitName) {
397dc2
+        return virCgroupSetValueDBus(group->unitName, "BlockIOWeight",
397dc2
+                                     "t", (unsigned long long) weight);
397dc2
+    } else {
397dc2
+        g_autofree char *value = g_strdup_printf("%u", weight);
397dc2
 
397dc2
-    return virCgroupSetValueRaw(path, value);
397dc2
+        return virCgroupSetValueRaw(path, value);
397dc2
+    }
397dc2
 }
397dc2
 
397dc2
 
397dc2
@@ -1188,15 +1192,8 @@ virCgroupV1SetBlkioDeviceWeight(virCgroupPtr group,
397dc2
                                 const char *devPath,
397dc2
                                 unsigned int weight)
397dc2
 {
397dc2
-    g_autofree char *str = NULL;
397dc2
-    g_autofree char *blkstr = NULL;
397dc2
     g_autofree char *path = NULL;
397dc2
 
397dc2
-    if (!(blkstr = virCgroupGetBlockDevString(devPath)))
397dc2
-        return -1;
397dc2
-
397dc2
-    str = g_strdup_printf("%s%d", blkstr, weight);
397dc2
-
397dc2
     if (virCgroupV1PathOfController(group, VIR_CGROUP_CONTROLLER_BLKIO,
397dc2
                                     "blkio.weight_device", &path) < 0) {
397dc2
         return -1;
397dc2
@@ -1208,7 +1205,21 @@ virCgroupV1SetBlkioDeviceWeight(virCgroupPtr group,
397dc2
         return -1;
397dc2
     }
397dc2
 
397dc2
-    return virCgroupSetValueRaw(path, str);
397dc2
+    if (group->unitName) {
397dc2
+        return virCgroupSetValueDBus(group->unitName, "BlockIODeviceWeight",
397dc2
+                                     "a(st)",
397dc2
+                                     1, path, (unsigned long long) weight);
397dc2
+    } else {
397dc2
+        g_autofree char *str = NULL;
397dc2
+        g_autofree char *blkstr = NULL;
397dc2
+
397dc2
+        if (!(blkstr = virCgroupGetBlockDevString(devPath)))
397dc2
+            return -1;
397dc2
+
397dc2
+        str = g_strdup_printf("%s%d", blkstr, weight);
397dc2
+
397dc2
+        return virCgroupSetValueRaw(path, str);
397dc2
+    }
397dc2
 }
397dc2
 
397dc2
 
397dc2
@@ -1849,9 +1860,14 @@ static int
397dc2
 virCgroupV1SetCpuShares(virCgroupPtr group,
397dc2
                         unsigned long long shares)
397dc2
 {
397dc2
-    return virCgroupSetValueU64(group,
397dc2
-                                VIR_CGROUP_CONTROLLER_CPU,
397dc2
-                                "cpu.shares", shares);
397dc2
+    if (group->unitName) {
397dc2
+        return virCgroupSetValueDBus(group->unitName, "CPUShares",
397dc2
+                                     "t", shares);
397dc2
+    } else {
397dc2
+        return virCgroupSetValueU64(group,
397dc2
+                                    VIR_CGROUP_CONTROLLER_CPU,
397dc2
+                                    "cpu.shares", shares);
397dc2
+    }
397dc2
 }
397dc2
 
397dc2
 
397dc2
diff --git a/src/util/vircgroupv2.c b/src/util/vircgroupv2.c
397dc2
index 4682a6a920..8fe4894a9e 100644
397dc2
--- a/src/util/vircgroupv2.c
397dc2
+++ b/src/util/vircgroupv2.c
397dc2
@@ -606,7 +606,6 @@ virCgroupV2SetBlkioWeight(virCgroupPtr group,
397dc2
                           unsigned int weight)
397dc2
 {
397dc2
     g_autofree char *path = NULL;
397dc2
-    g_autofree char *value = NULL;
397dc2
     const char *format = "%u";
397dc2
 
397dc2
     if (virCgroupV2PathOfController(group, VIR_CGROUP_CONTROLLER_BLKIO,
397dc2
@@ -630,9 +629,14 @@ virCgroupV2SetBlkioWeight(virCgroupPtr group,
397dc2
         return -1;
397dc2
     }
397dc2
 
397dc2
-    value = g_strdup_printf(format, weight);
397dc2
+    if (group->unitName) {
397dc2
+        return virCgroupSetValueDBus(group->unitName, "IOWeight",
397dc2
+                                     "t", (unsigned long long) weight);
397dc2
+    } else {
397dc2
+        g_autofree char *value = g_strdup_printf(format, weight);
397dc2
 
397dc2
-    return virCgroupSetValueRaw(path, value);
397dc2
+        return virCgroupSetValueRaw(path, value);
397dc2
+    }
397dc2
 }
397dc2
 
397dc2
 
397dc2
@@ -817,13 +821,6 @@ virCgroupV2SetBlkioDeviceWeight(virCgroupPtr group,
397dc2
                                 unsigned int weight)
397dc2
 {
397dc2
     g_autofree char *path = NULL;
397dc2
-    g_autofree char *str = NULL;
397dc2
-    g_autofree char *blkstr = NULL;
397dc2
-
397dc2
-    if (!(blkstr = virCgroupGetBlockDevString(devPath)))
397dc2
-        return -1;
397dc2
-
397dc2
-    str = g_strdup_printf("%s%d", blkstr, weight);
397dc2
 
397dc2
     if (virCgroupV2PathOfController(group, VIR_CGROUP_CONTROLLER_BLKIO,
397dc2
                                     "io.weight", &path) < 0) {
397dc2
@@ -836,7 +833,21 @@ virCgroupV2SetBlkioDeviceWeight(virCgroupPtr group,
397dc2
         return -1;
397dc2
     }
397dc2
 
397dc2
-    return virCgroupSetValueRaw(path, str);
397dc2
+    if (group->unitName) {
397dc2
+        return virCgroupSetValueDBus(group->unitName, "IODeviceWeight",
397dc2
+                                     "a(st)",
397dc2
+                                     1, path, (unsigned long long) weight);
397dc2
+    } else {
397dc2
+        g_autofree char *str = NULL;
397dc2
+        g_autofree char *blkstr = NULL;
397dc2
+
397dc2
+        if (!(blkstr = virCgroupGetBlockDevString(devPath)))
397dc2
+            return -1;
397dc2
+
397dc2
+        str = g_strdup_printf("%s%d", blkstr, weight);
397dc2
+
397dc2
+        return virCgroupSetValueRaw(path, str);
397dc2
+    }
397dc2
 }
397dc2
 
397dc2
 
397dc2
@@ -1455,9 +1466,14 @@ static int
397dc2
 virCgroupV2SetCpuShares(virCgroupPtr group,
397dc2
                         unsigned long long shares)
397dc2
 {
397dc2
-    return virCgroupSetValueU64(group,
397dc2
-                                VIR_CGROUP_CONTROLLER_CPU,
397dc2
-                                "cpu.weight", shares);
397dc2
+    if (group->unitName) {
397dc2
+        return virCgroupSetValueDBus(group->unitName, "CPUWeight",
397dc2
+                                     "t", shares);
397dc2
+    } else {
397dc2
+        return virCgroupSetValueU64(group,
397dc2
+                                    VIR_CGROUP_CONTROLLER_CPU,
397dc2
+                                    "cpu.weight", shares);
397dc2
+    }
397dc2
 }
397dc2
 
397dc2
 
397dc2
diff --git a/tests/Makefile.am b/tests/Makefile.am
397dc2
index f957c7d1ba..b030d0e8f6 100644
397dc2
--- a/tests/Makefile.am
397dc2
+++ b/tests/Makefile.am
397dc2
@@ -1188,6 +1188,7 @@ libvirportallocatormock_la_LIBADD = $(MOCKLIBS_LIBS)
397dc2
 
397dc2
 vircgrouptest_SOURCES = \
397dc2
 	vircgrouptest.c testutils.h testutils.c
397dc2
+vircgrouptest_CFLAGS = $(DBUS_CFLAGS) $(AM_CFLAGS)
397dc2
 vircgrouptest_LDADD = $(LDADDS)
397dc2
 
397dc2
 libvircgroupmock_la_SOURCES = \
397dc2
-- 
397dc2
2.30.0
397dc2