vircgroup: use DBus call to systemd for some APIs

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@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
This commit is contained in:
Pavel Hrdina 2021-02-05 16:17:35 +01:00
parent d3fb774b1e
commit 9c1693eff4
4 changed files with 115 additions and 28 deletions

View File

@ -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);
}

View File

@ -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);

View File

@ -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);
}
}

View File

@ -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);
}
}