When running on host with systemd we register VMs with machined. In this case systemd creates the root VM cgroup for us. This has some implications where one of them is that systemd owns all files inside the root VM cgroup and we should not touch them. If we change any value in file that systemd knows about it will be changed to what systemd thinks it should be when executing `systemctl daemon-reload`. These are the APIs that we need to call using systemd because they set limits that are proportional to sibling cgroups. Signed-off-by: Pavel Hrdina <phrdina@xxxxxxxxxx> --- src/util/vircgroup.c | 41 ++++++++++++++++++++++++++++++++++ src/util/vircgrouppriv.h | 6 +++++ src/util/vircgroupv1.c | 48 ++++++++++++++++++++++++++++------------ src/util/vircgroupv2.c | 48 ++++++++++++++++++++++++++++------------ 4 files changed, 115 insertions(+), 28 deletions(-) diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c index b5c74e94de..7a0e14eb73 100644 --- a/src/util/vircgroup.c +++ b/src/util/vircgroup.c @@ -41,6 +41,7 @@ #include "virerror.h" #include "virlog.h" #include "virfile.h" +#include "virgdbus.h" #include "virhash.h" #include "virstring.h" #include "virsystemd.h" @@ -484,6 +485,37 @@ virCgroupGetBlockDevString(const char *path) } +int +virCgroupSetValueDBus(const char *unitName, + const char *key, + GVariant *value) +{ + GDBusConnection *conn; + g_autoptr(GVariant) message = NULL; + GVariantBuilder builder; + GVariant *props = NULL; + + g_variant_builder_init(&builder, G_VARIANT_TYPE("a(sv)")); + g_variant_builder_add(&builder, "(sv)", key, value); + props = g_variant_builder_end(&builder); + + message = g_variant_new("(sb@a(sv))", unitName, true, props); + + if (!(conn = virGDBusGetSystemBus())) + return -1; + + return virGDBusCallMethod(conn, + NULL, + NULL, + NULL, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "SetUnitProperties", + message); +} + + int virCgroupSetValueRaw(const char *path, const char *value) @@ -1129,6 +1161,10 @@ virCgroupNewDetectMachine(const char *name, } } + newGroup->unitName = virSystemdGetMachineUnitByPID(pid); + if (virSystemdHasMachined() == 0 && !newGroup->unitName) + return -1; + *group = g_steal_pointer(&newGroup); return 0; } @@ -1229,6 +1265,10 @@ virCgroupNewMachineSystemd(const char *name, if (virCgroupEnableMissingControllers(path, controllers, &newGroup) < 0) return -1; + newGroup->unitName = virSystemdGetMachineUnitByPID(pidleader); + if (!newGroup->unitName) + return -1; + if (virCgroupAddProcess(newGroup, pidleader) < 0) { virErrorPtr saved; @@ -3588,6 +3628,7 @@ virCgroupFree(virCgroupPtr group) g_free(group->unified.mountPoint); g_free(group->unified.placement); + g_free(group->unitName); g_free(group); } diff --git a/src/util/vircgrouppriv.h b/src/util/vircgrouppriv.h index 85ba5393e0..f88d00814d 100644 --- a/src/util/vircgrouppriv.h +++ b/src/util/vircgrouppriv.h @@ -64,8 +64,14 @@ struct _virCgroup { virCgroupV1Controller legacy[VIR_CGROUP_CONTROLLER_LAST]; virCgroupV2Controller unified; + + char *unitName; }; +int virCgroupSetValueDBus(const char *unitName, + const char *key, + GVariant *value); + int virCgroupSetValueRaw(const char *path, const char *value); diff --git a/src/util/vircgroupv1.c b/src/util/vircgroupv1.c index 2b4d625c35..edb2c23bbc 100644 --- a/src/util/vircgroupv1.c +++ b/src/util/vircgroupv1.c @@ -946,7 +946,6 @@ virCgroupV1SetBlkioWeight(virCgroupPtr group, unsigned int weight) { g_autofree char *path = NULL; - g_autofree char *value = NULL; if (virCgroupV1PathOfController(group, VIR_CGROUP_CONTROLLER_BLKIO, "blkio.bfq.weight", &path) < 0) { @@ -968,9 +967,15 @@ virCgroupV1SetBlkioWeight(virCgroupPtr group, return -1; } - value = g_strdup_printf("%u", weight); + if (group->unitName) { + GVariant *value = g_variant_new("t", weight); - return virCgroupSetValueRaw(path, value); + return virCgroupSetValueDBus(group->unitName, "BlockIOWeight", value); + } else { + g_autofree char *value = g_strdup_printf("%u", weight); + + return virCgroupSetValueRaw(path, value); + } } @@ -1203,15 +1208,8 @@ virCgroupV1SetBlkioDeviceWeight(virCgroupPtr group, const char *devPath, unsigned int weight) { - g_autofree char *str = NULL; - g_autofree char *blkstr = NULL; g_autofree char *path = NULL; - if (!(blkstr = virCgroupGetBlockDevString(devPath))) - return -1; - - str = g_strdup_printf("%s%d", blkstr, weight); - if (virCgroupV1PathOfController(group, VIR_CGROUP_CONTROLLER_BLKIO, "blkio.weight_device", &path) < 0) { return -1; @@ -1223,7 +1221,23 @@ virCgroupV1SetBlkioDeviceWeight(virCgroupPtr group, return -1; } - return virCgroupSetValueRaw(path, str); + if (group->unitName) { + GVariant *value = NULL; + + value = g_variant_new_parsed("[(%s, uint64 %u)]", path, weight); + + return virCgroupSetValueDBus(group->unitName, "BlockIODeviceWeight", value); + } else { + g_autofree char *str = NULL; + g_autofree char *blkstr = NULL; + + if (!(blkstr = virCgroupGetBlockDevString(devPath))) + return -1; + + str = g_strdup_printf("%s%d", blkstr, weight); + + return virCgroupSetValueRaw(path, str); + } } @@ -1862,9 +1876,15 @@ static int virCgroupV1SetCpuShares(virCgroupPtr group, unsigned long long shares) { - return virCgroupSetValueU64(group, - VIR_CGROUP_CONTROLLER_CPU, - "cpu.shares", shares); + if (group->unitName) { + GVariant *value = g_variant_new("t", shares); + + return virCgroupSetValueDBus(group->unitName, "CPUShares", value); + } else { + return virCgroupSetValueU64(group, + VIR_CGROUP_CONTROLLER_CPU, + "cpu.shares", shares); + } } diff --git a/src/util/vircgroupv2.c b/src/util/vircgroupv2.c index 4a239f067a..3f3e5ac83d 100644 --- a/src/util/vircgroupv2.c +++ b/src/util/vircgroupv2.c @@ -609,7 +609,6 @@ virCgroupV2SetBlkioWeight(virCgroupPtr group, unsigned int weight) { g_autofree char *path = NULL; - g_autofree char *value = NULL; const char *format = "%u"; if (virCgroupV2PathOfController(group, VIR_CGROUP_CONTROLLER_BLKIO, @@ -633,9 +632,15 @@ virCgroupV2SetBlkioWeight(virCgroupPtr group, return -1; } - value = g_strdup_printf(format, weight); + if (group->unitName) { + GVariant *value = g_variant_new("t", weight); - return virCgroupSetValueRaw(path, value); + return virCgroupSetValueDBus(group->unitName, "IOWeight", value); + } else { + g_autofree char *value = g_strdup_printf(format, weight); + + return virCgroupSetValueRaw(path, value); + } } @@ -820,13 +825,6 @@ virCgroupV2SetBlkioDeviceWeight(virCgroupPtr group, unsigned int weight) { g_autofree char *path = NULL; - g_autofree char *str = NULL; - g_autofree char *blkstr = NULL; - - if (!(blkstr = virCgroupGetBlockDevString(devPath))) - return -1; - - str = g_strdup_printf("%s%d", blkstr, weight); if (virCgroupV2PathOfController(group, VIR_CGROUP_CONTROLLER_BLKIO, "io.weight", &path) < 0) { @@ -839,7 +837,23 @@ virCgroupV2SetBlkioDeviceWeight(virCgroupPtr group, return -1; } - return virCgroupSetValueRaw(path, str); + if (group->unitName) { + GVariant *value = NULL; + + value = g_variant_new_parsed("[(%s, uint64 %u)]", path, weight); + + return virCgroupSetValueDBus(group->unitName, "IODeviceWeight", value); + } else { + g_autofree char *str = NULL; + g_autofree char *blkstr = NULL; + + if (!(blkstr = virCgroupGetBlockDevString(devPath))) + return -1; + + str = g_strdup_printf("%s%d", blkstr, weight); + + return virCgroupSetValueRaw(path, str); + } } @@ -1458,9 +1472,15 @@ static int virCgroupV2SetCpuShares(virCgroupPtr group, unsigned long long shares) { - return virCgroupSetValueU64(group, - VIR_CGROUP_CONTROLLER_CPU, - "cpu.weight", shares); + if (group->unitName) { + GVariant *value = g_variant_new("t", shares); + + return virCgroupSetValueDBus(group->unitName, "CPUWeight", value); + } else { + return virCgroupSetValueU64(group, + VIR_CGROUP_CONTROLLER_CPU, + "cpu.weight", shares); + } } -- 2.29.2