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