|
|
c480ed |
From e1184bde63a7ed92fb99fc4eba4b4abdf6a01815 Mon Sep 17 00:00:00 2001
|
|
|
c480ed |
Message-Id: <e1184bde63a7ed92fb99fc4eba4b4abdf6a01815@dist-git>
|
|
|
c480ed |
From: Pavel Hrdina <phrdina@redhat.com>
|
|
|
c480ed |
Date: Mon, 1 Jul 2019 17:06:27 +0200
|
|
|
c480ed |
Subject: [PATCH] vircgroup: extract v1 detect functions
|
|
|
c480ed |
MIME-Version: 1.0
|
|
|
c480ed |
Content-Type: text/plain; charset=UTF-8
|
|
|
c480ed |
Content-Transfer-Encoding: 8bit
|
|
|
c480ed |
|
|
|
c480ed |
Reviewed-by: Fabiano Fidêncio <fidencio@redhat.com>
|
|
|
c480ed |
Reviewed-by: Ján Tomko <jtomko@redhat.com>
|
|
|
c480ed |
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
|
|
|
c480ed |
(cherry picked from commit 42a3fcc02bcaec4a0c037a5c59ca63f3fc90e90f)
|
|
|
c480ed |
|
|
|
c480ed |
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
|
|
|
c480ed |
|
|
|
c480ed |
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
|
|
|
c480ed |
Message-Id: <3a918fc4eda51c5e9aff5efc93fe14886470578e.1561993100.git.phrdina@redhat.com>
|
|
|
c480ed |
Reviewed-by: Ján Tomko <jtomko@redhat.com>
|
|
|
c480ed |
---
|
|
|
c480ed |
src/util/vircgroup.c | 138 ++-----------------------------
|
|
|
c480ed |
src/util/vircgroupbackend.h | 14 ++++
|
|
|
c480ed |
src/util/vircgroupv1.c | 158 ++++++++++++++++++++++++++++++++++++
|
|
|
c480ed |
3 files changed, 180 insertions(+), 130 deletions(-)
|
|
|
c480ed |
|
|
|
c480ed |
diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
|
|
|
c480ed |
index 9d644d37d1..10c99a66fd 100644
|
|
|
c480ed |
--- a/src/util/vircgroup.c
|
|
|
c480ed |
+++ b/src/util/vircgroup.c
|
|
|
c480ed |
@@ -235,82 +235,6 @@ virCgroupPartitionEscape(char **path)
|
|
|
c480ed |
}
|
|
|
c480ed |
|
|
|
c480ed |
|
|
|
c480ed |
-static int
|
|
|
c480ed |
-virCgroupResolveMountLink(const char *mntDir,
|
|
|
c480ed |
- const char *typeStr,
|
|
|
c480ed |
- virCgroupControllerPtr controller)
|
|
|
c480ed |
-{
|
|
|
c480ed |
- VIR_AUTOFREE(char *) linkSrc = NULL;
|
|
|
c480ed |
- VIR_AUTOFREE(char *) tmp = NULL;
|
|
|
c480ed |
- char *dirName;
|
|
|
c480ed |
- struct stat sb;
|
|
|
c480ed |
-
|
|
|
c480ed |
- if (VIR_STRDUP(tmp, mntDir) < 0)
|
|
|
c480ed |
- return -1;
|
|
|
c480ed |
-
|
|
|
c480ed |
- dirName = strrchr(tmp, '/');
|
|
|
c480ed |
- if (!dirName) {
|
|
|
c480ed |
- virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
c480ed |
- _("Missing '/' separator in cgroup mount '%s'"), tmp);
|
|
|
c480ed |
- return -1;
|
|
|
c480ed |
- }
|
|
|
c480ed |
-
|
|
|
c480ed |
- if (!strchr(dirName + 1, ','))
|
|
|
c480ed |
- return 0;
|
|
|
c480ed |
-
|
|
|
c480ed |
- *dirName = '\0';
|
|
|
c480ed |
- if (virAsprintf(&linkSrc, "%s/%s", tmp, typeStr) < 0)
|
|
|
c480ed |
- return -1;
|
|
|
c480ed |
- *dirName = '/';
|
|
|
c480ed |
-
|
|
|
c480ed |
- if (lstat(linkSrc, &sb) < 0) {
|
|
|
c480ed |
- if (errno == ENOENT) {
|
|
|
c480ed |
- VIR_WARN("Controller %s co-mounted at %s is missing symlink at %s",
|
|
|
c480ed |
- typeStr, tmp, linkSrc);
|
|
|
c480ed |
- } else {
|
|
|
c480ed |
- virReportSystemError(errno, _("Cannot stat %s"), linkSrc);
|
|
|
c480ed |
- return -1;
|
|
|
c480ed |
- }
|
|
|
c480ed |
- } else {
|
|
|
c480ed |
- if (!S_ISLNK(sb.st_mode)) {
|
|
|
c480ed |
- VIR_WARN("Expecting a symlink at %s for controller %s",
|
|
|
c480ed |
- linkSrc, typeStr);
|
|
|
c480ed |
- } else {
|
|
|
c480ed |
- VIR_STEAL_PTR(controller->linkPoint, linkSrc);
|
|
|
c480ed |
- }
|
|
|
c480ed |
- }
|
|
|
c480ed |
-
|
|
|
c480ed |
- return 0;
|
|
|
c480ed |
-}
|
|
|
c480ed |
-
|
|
|
c480ed |
-
|
|
|
c480ed |
-static bool
|
|
|
c480ed |
-virCgroupMountOptsMatchController(const char *mntOpts,
|
|
|
c480ed |
- const char *typeStr)
|
|
|
c480ed |
-{
|
|
|
c480ed |
- const char *tmp = mntOpts;
|
|
|
c480ed |
- int typeLen = strlen(typeStr);
|
|
|
c480ed |
-
|
|
|
c480ed |
- while (tmp) {
|
|
|
c480ed |
- const char *next = strchr(tmp, ',');
|
|
|
c480ed |
- int len;
|
|
|
c480ed |
- if (next) {
|
|
|
c480ed |
- len = next - tmp;
|
|
|
c480ed |
- next++;
|
|
|
c480ed |
- } else {
|
|
|
c480ed |
- len = strlen(tmp);
|
|
|
c480ed |
- }
|
|
|
c480ed |
-
|
|
|
c480ed |
- if (typeLen == len && STREQLEN(typeStr, tmp, len))
|
|
|
c480ed |
- return true;
|
|
|
c480ed |
-
|
|
|
c480ed |
- tmp = next;
|
|
|
c480ed |
- }
|
|
|
c480ed |
-
|
|
|
c480ed |
- return false;
|
|
|
c480ed |
-}
|
|
|
c480ed |
-
|
|
|
c480ed |
-
|
|
|
c480ed |
/*
|
|
|
c480ed |
* Process /proc/mounts figuring out what controllers are
|
|
|
c480ed |
* mounted and where
|
|
|
c480ed |
@@ -318,7 +242,6 @@ virCgroupMountOptsMatchController(const char *mntOpts,
|
|
|
c480ed |
static int
|
|
|
c480ed |
virCgroupDetectMounts(virCgroupPtr group)
|
|
|
c480ed |
{
|
|
|
c480ed |
- size_t i;
|
|
|
c480ed |
FILE *mounts = NULL;
|
|
|
c480ed |
struct mntent entry;
|
|
|
c480ed |
char buf[CGROUP_MAX_VAL];
|
|
|
c480ed |
@@ -331,34 +254,11 @@ virCgroupDetectMounts(virCgroupPtr group)
|
|
|
c480ed |
}
|
|
|
c480ed |
|
|
|
c480ed |
while (getmntent_r(mounts, &entry, buf, sizeof(buf)) != NULL) {
|
|
|
c480ed |
- if (STRNEQ(entry.mnt_type, "cgroup"))
|
|
|
c480ed |
- continue;
|
|
|
c480ed |
-
|
|
|
c480ed |
- for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
|
|
|
c480ed |
- const char *typestr = virCgroupControllerTypeToString(i);
|
|
|
c480ed |
-
|
|
|
c480ed |
- if (virCgroupMountOptsMatchController(entry.mnt_opts, typestr)) {
|
|
|
c480ed |
- /* Note that the lines in /proc/mounts have the same
|
|
|
c480ed |
- * order than the mount operations, and that there may
|
|
|
c480ed |
- * be duplicates due to bind mounts. This means
|
|
|
c480ed |
- * that the same mount point may be processed more than
|
|
|
c480ed |
- * once. We need to save the results of the last one,
|
|
|
c480ed |
- * and we need to be careful to release the memory used
|
|
|
c480ed |
- * by previous processing. */
|
|
|
c480ed |
- virCgroupControllerPtr controller = &group->controllers[i];
|
|
|
c480ed |
-
|
|
|
c480ed |
- VIR_FREE(controller->mountPoint);
|
|
|
c480ed |
- VIR_FREE(controller->linkPoint);
|
|
|
c480ed |
- if (VIR_STRDUP(controller->mountPoint, entry.mnt_dir) < 0)
|
|
|
c480ed |
- goto cleanup;
|
|
|
c480ed |
-
|
|
|
c480ed |
- /* If it is a co-mount it has a filename like "cpu,cpuacct"
|
|
|
c480ed |
- * and we must identify the symlink path */
|
|
|
c480ed |
- if (virCgroupResolveMountLink(entry.mnt_dir, typestr,
|
|
|
c480ed |
- controller) < 0) {
|
|
|
c480ed |
- goto cleanup;
|
|
|
c480ed |
- }
|
|
|
c480ed |
- }
|
|
|
c480ed |
+ if (group->backend->detectMounts(group,
|
|
|
c480ed |
+ entry.mnt_type,
|
|
|
c480ed |
+ entry.mnt_opts,
|
|
|
c480ed |
+ entry.mnt_dir) < 0) {
|
|
|
c480ed |
+ goto cleanup;
|
|
|
c480ed |
}
|
|
|
c480ed |
}
|
|
|
c480ed |
|
|
|
c480ed |
@@ -432,7 +332,6 @@ virCgroupDetectPlacement(virCgroupPtr group,
|
|
|
c480ed |
pid_t pid,
|
|
|
c480ed |
const char *path)
|
|
|
c480ed |
{
|
|
|
c480ed |
- size_t i;
|
|
|
c480ed |
FILE *mapping = NULL;
|
|
|
c480ed |
char line[1024];
|
|
|
c480ed |
int ret = -1;
|
|
|
c480ed |
@@ -472,30 +371,9 @@ virCgroupDetectPlacement(virCgroupPtr group,
|
|
|
c480ed |
controllers++;
|
|
|
c480ed |
selfpath++;
|
|
|
c480ed |
|
|
|
c480ed |
- for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
|
|
|
c480ed |
- const char *typestr = virCgroupControllerTypeToString(i);
|
|
|
c480ed |
-
|
|
|
c480ed |
- if (virCgroupMountOptsMatchController(controllers, typestr) &&
|
|
|
c480ed |
- group->controllers[i].mountPoint != NULL &&
|
|
|
c480ed |
- group->controllers[i].placement == NULL) {
|
|
|
c480ed |
- /*
|
|
|
c480ed |
- * selfpath == "/" + path="" -> "/"
|
|
|
c480ed |
- * selfpath == "/libvirt.service" + path == "" -> "/libvirt.service"
|
|
|
c480ed |
- * selfpath == "/libvirt.service" + path == "foo" -> "/libvirt.service/foo"
|
|
|
c480ed |
- */
|
|
|
c480ed |
- if (i == VIR_CGROUP_CONTROLLER_SYSTEMD) {
|
|
|
c480ed |
- if (VIR_STRDUP(group->controllers[i].placement,
|
|
|
c480ed |
- selfpath) < 0)
|
|
|
c480ed |
- goto cleanup;
|
|
|
c480ed |
- } else {
|
|
|
c480ed |
- if (virAsprintf(&group->controllers[i].placement,
|
|
|
c480ed |
- "%s%s%s", selfpath,
|
|
|
c480ed |
- (STREQ(selfpath, "/") ||
|
|
|
c480ed |
- STREQ(path, "") ? "" : "/"),
|
|
|
c480ed |
- path) < 0)
|
|
|
c480ed |
- goto cleanup;
|
|
|
c480ed |
- }
|
|
|
c480ed |
- }
|
|
|
c480ed |
+ if (group->backend->detectPlacement(group, path, controllers,
|
|
|
c480ed |
+ selfpath) < 0) {
|
|
|
c480ed |
+ goto cleanup;
|
|
|
c480ed |
}
|
|
|
c480ed |
}
|
|
|
c480ed |
|
|
|
c480ed |
diff --git a/src/util/vircgroupbackend.h b/src/util/vircgroupbackend.h
|
|
|
c480ed |
index 81ee597fc8..fadc7efdcf 100644
|
|
|
c480ed |
--- a/src/util/vircgroupbackend.h
|
|
|
c480ed |
+++ b/src/util/vircgroupbackend.h
|
|
|
c480ed |
@@ -45,6 +45,18 @@ typedef int
|
|
|
c480ed |
(*virCgroupCopyMountsCB)(virCgroupPtr group,
|
|
|
c480ed |
virCgroupPtr parent);
|
|
|
c480ed |
|
|
|
c480ed |
+typedef int
|
|
|
c480ed |
+(*virCgroupDetectMountsCB)(virCgroupPtr group,
|
|
|
c480ed |
+ const char *mntType,
|
|
|
c480ed |
+ const char *mntOpts,
|
|
|
c480ed |
+ const char *mntDir);
|
|
|
c480ed |
+
|
|
|
c480ed |
+typedef int
|
|
|
c480ed |
+(*virCgroupDetectPlacementCB)(virCgroupPtr group,
|
|
|
c480ed |
+ const char *path,
|
|
|
c480ed |
+ const char *controllers,
|
|
|
c480ed |
+ const char *selfpath);
|
|
|
c480ed |
+
|
|
|
c480ed |
struct _virCgroupBackend {
|
|
|
c480ed |
virCgroupBackendType type;
|
|
|
c480ed |
|
|
|
c480ed |
@@ -52,6 +64,8 @@ struct _virCgroupBackend {
|
|
|
c480ed |
virCgroupAvailableCB available;
|
|
|
c480ed |
virCgroupValidateMachineGroupCB validateMachineGroup;
|
|
|
c480ed |
virCgroupCopyMountsCB copyMounts;
|
|
|
c480ed |
+ virCgroupDetectMountsCB detectMounts;
|
|
|
c480ed |
+ virCgroupDetectPlacementCB detectPlacement;
|
|
|
c480ed |
};
|
|
|
c480ed |
typedef struct _virCgroupBackend virCgroupBackend;
|
|
|
c480ed |
typedef virCgroupBackend *virCgroupBackendPtr;
|
|
|
c480ed |
diff --git a/src/util/vircgroupv1.c b/src/util/vircgroupv1.c
|
|
|
c480ed |
index 50b58ab413..bd9f28f6e9 100644
|
|
|
c480ed |
--- a/src/util/vircgroupv1.c
|
|
|
c480ed |
+++ b/src/util/vircgroupv1.c
|
|
|
c480ed |
@@ -23,6 +23,7 @@
|
|
|
c480ed |
#if defined HAVE_MNTENT_H && defined HAVE_GETMNTENT_R
|
|
|
c480ed |
# include <mntent.h>
|
|
|
c480ed |
#endif
|
|
|
c480ed |
+#include <sys/stat.h>
|
|
|
c480ed |
|
|
|
c480ed |
#include "internal.h"
|
|
|
c480ed |
|
|
|
c480ed |
@@ -38,6 +39,7 @@
|
|
|
c480ed |
#include "virlog.h"
|
|
|
c480ed |
#include "virstring.h"
|
|
|
c480ed |
#include "virsystemd.h"
|
|
|
c480ed |
+#include "virerror.h"
|
|
|
c480ed |
|
|
|
c480ed |
VIR_LOG_INIT("util.cgroup");
|
|
|
c480ed |
|
|
|
c480ed |
@@ -181,12 +183,168 @@ virCgroupV1CopyMounts(virCgroupPtr group,
|
|
|
c480ed |
}
|
|
|
c480ed |
|
|
|
c480ed |
|
|
|
c480ed |
+static int
|
|
|
c480ed |
+virCgroupV1ResolveMountLink(const char *mntDir,
|
|
|
c480ed |
+ const char *typeStr,
|
|
|
c480ed |
+ virCgroupControllerPtr controller)
|
|
|
c480ed |
+{
|
|
|
c480ed |
+ VIR_AUTOFREE(char *) linkSrc = NULL;
|
|
|
c480ed |
+ VIR_AUTOFREE(char *) tmp = NULL;
|
|
|
c480ed |
+ char *dirName;
|
|
|
c480ed |
+ struct stat sb;
|
|
|
c480ed |
+
|
|
|
c480ed |
+ if (VIR_STRDUP(tmp, mntDir) < 0)
|
|
|
c480ed |
+ return -1;
|
|
|
c480ed |
+
|
|
|
c480ed |
+ dirName = strrchr(tmp, '/');
|
|
|
c480ed |
+ if (!dirName) {
|
|
|
c480ed |
+ virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
c480ed |
+ _("Missing '/' separator in cgroup mount '%s'"), tmp);
|
|
|
c480ed |
+ return -1;
|
|
|
c480ed |
+ }
|
|
|
c480ed |
+
|
|
|
c480ed |
+ if (!strchr(dirName + 1, ','))
|
|
|
c480ed |
+ return 0;
|
|
|
c480ed |
+
|
|
|
c480ed |
+ *dirName = '\0';
|
|
|
c480ed |
+ if (virAsprintf(&linkSrc, "%s/%s", tmp, typeStr) < 0)
|
|
|
c480ed |
+ return -1;
|
|
|
c480ed |
+ *dirName = '/';
|
|
|
c480ed |
+
|
|
|
c480ed |
+ if (lstat(linkSrc, &sb) < 0) {
|
|
|
c480ed |
+ if (errno == ENOENT) {
|
|
|
c480ed |
+ VIR_WARN("Controller %s co-mounted at %s is missing symlink at %s",
|
|
|
c480ed |
+ typeStr, tmp, linkSrc);
|
|
|
c480ed |
+ } else {
|
|
|
c480ed |
+ virReportSystemError(errno, _("Cannot stat %s"), linkSrc);
|
|
|
c480ed |
+ return -1;
|
|
|
c480ed |
+ }
|
|
|
c480ed |
+ } else {
|
|
|
c480ed |
+ if (!S_ISLNK(sb.st_mode)) {
|
|
|
c480ed |
+ VIR_WARN("Expecting a symlink at %s for controller %s",
|
|
|
c480ed |
+ linkSrc, typeStr);
|
|
|
c480ed |
+ } else {
|
|
|
c480ed |
+ VIR_STEAL_PTR(controller->linkPoint, linkSrc);
|
|
|
c480ed |
+ }
|
|
|
c480ed |
+ }
|
|
|
c480ed |
+
|
|
|
c480ed |
+ return 0;
|
|
|
c480ed |
+}
|
|
|
c480ed |
+
|
|
|
c480ed |
+
|
|
|
c480ed |
+static bool
|
|
|
c480ed |
+virCgroupV1MountOptsMatchController(const char *mntOpts,
|
|
|
c480ed |
+ const char *typeStr)
|
|
|
c480ed |
+{
|
|
|
c480ed |
+ const char *tmp = mntOpts;
|
|
|
c480ed |
+ int typeLen = strlen(typeStr);
|
|
|
c480ed |
+
|
|
|
c480ed |
+ while (tmp) {
|
|
|
c480ed |
+ const char *next = strchr(tmp, ',');
|
|
|
c480ed |
+ int len;
|
|
|
c480ed |
+ if (next) {
|
|
|
c480ed |
+ len = next - tmp;
|
|
|
c480ed |
+ next++;
|
|
|
c480ed |
+ } else {
|
|
|
c480ed |
+ len = strlen(tmp);
|
|
|
c480ed |
+ }
|
|
|
c480ed |
+
|
|
|
c480ed |
+ if (typeLen == len && STREQLEN(typeStr, tmp, len))
|
|
|
c480ed |
+ return true;
|
|
|
c480ed |
+
|
|
|
c480ed |
+ tmp = next;
|
|
|
c480ed |
+ }
|
|
|
c480ed |
+
|
|
|
c480ed |
+ return false;
|
|
|
c480ed |
+}
|
|
|
c480ed |
+
|
|
|
c480ed |
+
|
|
|
c480ed |
+static int
|
|
|
c480ed |
+virCgroupV1DetectMounts(virCgroupPtr group,
|
|
|
c480ed |
+ const char *mntType,
|
|
|
c480ed |
+ const char *mntOpts,
|
|
|
c480ed |
+ const char *mntDir)
|
|
|
c480ed |
+{
|
|
|
c480ed |
+ size_t i;
|
|
|
c480ed |
+
|
|
|
c480ed |
+ if (STRNEQ(mntType, "cgroup"))
|
|
|
c480ed |
+ return 0;
|
|
|
c480ed |
+
|
|
|
c480ed |
+ for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
|
|
|
c480ed |
+ const char *typestr = virCgroupV1ControllerTypeToString(i);
|
|
|
c480ed |
+
|
|
|
c480ed |
+ if (virCgroupV1MountOptsMatchController(mntOpts, typestr)) {
|
|
|
c480ed |
+ /* Note that the lines in /proc/mounts have the same
|
|
|
c480ed |
+ * order than the mount operations, and that there may
|
|
|
c480ed |
+ * be duplicates due to bind mounts. This means
|
|
|
c480ed |
+ * that the same mount point may be processed more than
|
|
|
c480ed |
+ * once. We need to save the results of the last one,
|
|
|
c480ed |
+ * and we need to be careful to release the memory used
|
|
|
c480ed |
+ * by previous processing. */
|
|
|
c480ed |
+ virCgroupControllerPtr controller = &group->controllers[i];
|
|
|
c480ed |
+
|
|
|
c480ed |
+ VIR_FREE(controller->mountPoint);
|
|
|
c480ed |
+ VIR_FREE(controller->linkPoint);
|
|
|
c480ed |
+ if (VIR_STRDUP(controller->mountPoint, mntDir) < 0)
|
|
|
c480ed |
+ return -1;
|
|
|
c480ed |
+
|
|
|
c480ed |
+ /* If it is a co-mount it has a filename like "cpu,cpuacct"
|
|
|
c480ed |
+ * and we must identify the symlink path */
|
|
|
c480ed |
+ if (virCgroupV1ResolveMountLink(mntDir, typestr, controller) < 0)
|
|
|
c480ed |
+ return -1;
|
|
|
c480ed |
+ }
|
|
|
c480ed |
+ }
|
|
|
c480ed |
+
|
|
|
c480ed |
+ return 0;
|
|
|
c480ed |
+}
|
|
|
c480ed |
+
|
|
|
c480ed |
+
|
|
|
c480ed |
+static int
|
|
|
c480ed |
+virCgroupV1DetectPlacement(virCgroupPtr group,
|
|
|
c480ed |
+ const char *path,
|
|
|
c480ed |
+ const char *controllers,
|
|
|
c480ed |
+ const char *selfpath)
|
|
|
c480ed |
+{
|
|
|
c480ed |
+ size_t i;
|
|
|
c480ed |
+
|
|
|
c480ed |
+ for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
|
|
|
c480ed |
+ const char *typestr = virCgroupV1ControllerTypeToString(i);
|
|
|
c480ed |
+
|
|
|
c480ed |
+ if (virCgroupV1MountOptsMatchController(controllers, typestr) &&
|
|
|
c480ed |
+ group->controllers[i].mountPoint != NULL &&
|
|
|
c480ed |
+ group->controllers[i].placement == NULL) {
|
|
|
c480ed |
+ /*
|
|
|
c480ed |
+ * selfpath == "/" + path="" -> "/"
|
|
|
c480ed |
+ * selfpath == "/libvirt.service" + path == "" -> "/libvirt.service"
|
|
|
c480ed |
+ * selfpath == "/libvirt.service" + path == "foo" -> "/libvirt.service/foo"
|
|
|
c480ed |
+ */
|
|
|
c480ed |
+ if (i == VIR_CGROUP_CONTROLLER_SYSTEMD) {
|
|
|
c480ed |
+ if (VIR_STRDUP(group->controllers[i].placement,
|
|
|
c480ed |
+ selfpath) < 0)
|
|
|
c480ed |
+ return -1;
|
|
|
c480ed |
+ } else {
|
|
|
c480ed |
+ if (virAsprintf(&group->controllers[i].placement,
|
|
|
c480ed |
+ "%s%s%s", selfpath,
|
|
|
c480ed |
+ (STREQ(selfpath, "/") ||
|
|
|
c480ed |
+ STREQ(path, "") ? "" : "/"),
|
|
|
c480ed |
+ path) < 0)
|
|
|
c480ed |
+ return -1;
|
|
|
c480ed |
+ }
|
|
|
c480ed |
+ }
|
|
|
c480ed |
+ }
|
|
|
c480ed |
+
|
|
|
c480ed |
+ return 0;
|
|
|
c480ed |
+}
|
|
|
c480ed |
+
|
|
|
c480ed |
+
|
|
|
c480ed |
virCgroupBackend virCgroupV1Backend = {
|
|
|
c480ed |
.type = VIR_CGROUP_BACKEND_TYPE_V1,
|
|
|
c480ed |
|
|
|
c480ed |
.available = virCgroupV1Available,
|
|
|
c480ed |
.validateMachineGroup = virCgroupV1ValidateMachineGroup,
|
|
|
c480ed |
.copyMounts = virCgroupV1CopyMounts,
|
|
|
c480ed |
+ .detectMounts = virCgroupV1DetectMounts,
|
|
|
c480ed |
+ .detectPlacement = virCgroupV1DetectPlacement,
|
|
|
c480ed |
};
|
|
|
c480ed |
|
|
|
c480ed |
|
|
|
c480ed |
--
|
|
|
c480ed |
2.22.0
|
|
|
c480ed |
|