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>
#include "virerror.h"
#include "virlog.h"
#include "virfile.h"
+#include "virgdbus.h"
#include "virhash.h"
#include "virstring.h"
#include "virsystemd.h"
}
+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)
}
}
+ newGroup->unitName = virSystemdGetMachineUnitByPID(pid);
+ if (virSystemdHasMachined() == 0 && !newGroup->unitName)
+ return -1;
+
*group = g_steal_pointer(&newGroup);
return 0;
}
if (virCgroupEnableMissingControllers(path, controllers, &newGroup) < 0)
return -1;
+ newGroup->unitName = virSystemdGetMachineUnitByPID(pidleader);
+ if (!newGroup->unitName)
+ return -1;
+
if (virCgroupAddProcess(newGroup, pidleader) < 0) {
virErrorPtr saved;
g_free(group->unified.mountPoint);
g_free(group->unified.placement);
+ g_free(group->unitName);
g_free(group);
}
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);
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) {
return -1;
}
- value = g_strdup_printf("%u", weight);
+ if (group->unitName) {
+ GVariant *value = g_variant_new("t", weight);
+
+ return virCgroupSetValueDBus(group->unitName, "BlockIOWeight", value);
+ } else {
+ g_autofree char *value = g_strdup_printf("%u", weight);
- return virCgroupSetValueRaw(path, value);
+ return virCgroupSetValueRaw(path, value);
+ }
}
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;
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);
+ }
}
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);
+ }
}
unsigned int weight)
{
g_autofree char *path = NULL;
- g_autofree char *value = NULL;
const char *format = "%u";
if (virCgroupV2PathOfController(group, VIR_CGROUP_CONTROLLER_BLKIO,
return -1;
}
- value = g_strdup_printf(format, weight);
+ if (group->unitName) {
+ GVariant *value = g_variant_new("t", weight);
+
+ return virCgroupSetValueDBus(group->unitName, "IOWeight", value);
+ } else {
+ g_autofree char *value = g_strdup_printf(format, weight);
- return virCgroupSetValueRaw(path, value);
+ return virCgroupSetValueRaw(path, value);
+ }
}
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) {
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);
+ }
}
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);
+ }
}