Blame SOURCES/libvirt-virt-host-validate-rewrite-cgroup-detection-to-use-util-vircgroup.patch

c480ed
From 0ede215415509022d94092b75ef075495c91a5d5 Mon Sep 17 00:00:00 2001
c480ed
Message-Id: <0ede215415509022d94092b75ef075495c91a5d5@dist-git>
c480ed
From: Pavel Hrdina <phrdina@redhat.com>
c480ed
Date: Mon, 1 Jul 2019 17:08:03 +0200
c480ed
Subject: [PATCH] virt-host-validate: rewrite cgroup detection to use
c480ed
 util/vircgroup
c480ed
MIME-Version: 1.0
c480ed
Content-Type: text/plain; charset=UTF-8
c480ed
Content-Transfer-Encoding: 8bit
c480ed
c480ed
This removes code duplication and simplifies cgroup detection.
c480ed
As a drawback we will not have separate messages to enable cgroup
c480ed
controller in kernel or to mount it.  On the other side the rewrite
c480ed
adds support for cgroup v2.
c480ed
c480ed
The kernel config support was wrong because it was parsing
c480ed
'/proc/self/cgroup' instead of '/proc/cgroups/' file.
c480ed
c480ed
The mount suggestion is removed as well because it will not work
c480ed
with cgroup v2.
c480ed
c480ed
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
c480ed
(cherry picked from commit 0f4d7daa8cd43b62911413c2cc1614f87380e459)
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: <0a79b9dcaee25d04b993c4e6576d75ce7c45ac0f.1561993100.git.phrdina@redhat.com>
c480ed
Reviewed-by: Ján Tomko <jtomko@redhat.com>
c480ed
---
c480ed
 tools/virt-host-validate-common.c | 164 ++++++------------------------
c480ed
 tools/virt-host-validate-common.h |   7 +-
c480ed
 tools/virt-host-validate-lxc.c    |  38 ++-----
c480ed
 tools/virt-host-validate-qemu.c   |  38 ++-----
c480ed
 4 files changed, 53 insertions(+), 194 deletions(-)
c480ed
c480ed
diff --git a/tools/virt-host-validate-common.c b/tools/virt-host-validate-common.c
c480ed
index c45dfc5d8c..73165d673a 100644
c480ed
--- a/tools/virt-host-validate-common.c
c480ed
+++ b/tools/virt-host-validate-common.c
c480ed
@@ -26,12 +26,10 @@
c480ed
 #include <stdio.h>
c480ed
 #include <unistd.h>
c480ed
 #include <sys/utsname.h>
c480ed
-#ifdef HAVE_MNTENT_H
c480ed
-# include <mntent.h>
c480ed
-#endif /* HAVE_MNTENT_H */
c480ed
 #include <sys/stat.h>
c480ed
 
c480ed
 #include "viralloc.h"
c480ed
+#include "vircgroup.h"
c480ed
 #include "virfile.h"
c480ed
 #include "virt-host-validate-common.h"
c480ed
 #include "virstring.h"
c480ed
@@ -290,152 +288,50 @@ int virHostValidateLinuxKernel(const char *hvname,
c480ed
     }
c480ed
 }
c480ed
 
c480ed
-
c480ed
-static int virHostValidateCGroupSupport(const char *hvname,
c480ed
-                                        const char *cg_name,
c480ed
-                                        virHostValidateLevel level,
c480ed
-                                        const char *config_name)
c480ed
+#ifdef __linux__
c480ed
+int virHostValidateCGroupControllers(const char *hvname,
c480ed
+                                     int controllers,
c480ed
+                                     virHostValidateLevel level)
c480ed
 {
c480ed
-    virHostMsgCheck(hvname, "for cgroup '%s' controller support", cg_name);
c480ed
-    FILE *fp = fopen("/proc/self/cgroup", "r");
c480ed
-    size_t len = 0;
c480ed
-    char *line = NULL;
c480ed
-    ssize_t ret;
c480ed
-    bool matched = false;
c480ed
+    virCgroupPtr group = NULL;
c480ed
+    int ret = 0;
c480ed
+    size_t i;
c480ed
 
c480ed
-    if (!fp)
c480ed
-        goto error;
c480ed
+    if (virCgroupNewSelf(&group) < 0)
c480ed
+        return -1;
c480ed
 
c480ed
-    while ((ret = getline(&line, &len, fp)) >= 0 && !matched) {
c480ed
-        char **cgroups;
c480ed
-        char *start;
c480ed
-        char *end;
c480ed
-        size_t ncgroups;
c480ed
-        size_t i;
c480ed
+    for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
c480ed
+        int flag = 1 << i;
c480ed
+        const char *cg_name = virCgroupControllerTypeToString(i);
c480ed
 
c480ed
-        /* Each line in this file looks like
c480ed
-         *
c480ed
-         *   4:cpu,cpuacct:/machine.slice/machine-qemu\x2dtest.scope/emulator
c480ed
-         *
c480ed
-         * Since multiple cgroups can be part of the same line and some cgroup
c480ed
-         * names can appear as part of other cgroup names (eg. 'cpu' is a
c480ed
-         * prefix for both 'cpuacct' and 'cpuset'), it's not enough to simply
c480ed
-         * check whether the cgroup name is present somewhere inside the file.
c480ed
-         *
c480ed
-         * Moreover, there's nothing stopping the cgroup name from appearing
c480ed
-         * in an unrelated mount point name as well */
c480ed
-
c480ed
-        /* Look for the first colon.
c480ed
-         * The part we're interested in starts right after it */
c480ed
-        if (!(start = strchr(line, ':')))
c480ed
-            continue;
c480ed
-        start++;
c480ed
-
c480ed
-        /* Look for the second colon.
c480ed
-         * The part we're interested in ends exactly there */
c480ed
-        if (!(end = strchr(start, ':')))
c480ed
-            continue;
c480ed
-        *end = '\0';
c480ed
-
c480ed
-        if (!(cgroups = virStringSplitCount(start, ",", 0, &ncgroups)))
c480ed
+        if (!(controllers & flag))
c480ed
             continue;
c480ed
 
c480ed
-        /* Look for the matching cgroup */
c480ed
-        for (i = 0; i < ncgroups; i++) {
c480ed
-            if (STREQ(cgroups[i], cg_name))
c480ed
-                matched = true;
c480ed
+        virHostMsgCheck(hvname, "for cgroup '%s' controller support", cg_name);
c480ed
+
c480ed
+        if (!virCgroupHasController(group, i)) {
c480ed
+            ret = -1;
c480ed
+            virHostMsgFail(level, "Enable '%s' in kernel Kconfig file or "
c480ed
+                           "mount/enable cgroup controller in your system",
c480ed
+                           cg_name);
c480ed
+        } else {
c480ed
+            virHostMsgPass();
c480ed
         }
c480ed
-
c480ed
-        virStringListFreeCount(cgroups, ncgroups);
c480ed
     }
c480ed
 
c480ed
-    VIR_FREE(line);
c480ed
-    VIR_FORCE_FCLOSE(fp);
c480ed
-    if (!matched)
c480ed
-        goto error;
c480ed
+    virCgroupFree(&group);
c480ed
 
c480ed
-    virHostMsgPass();
c480ed
-    return 0;
c480ed
-
c480ed
- error:
c480ed
-    VIR_FREE(line);
c480ed
-    virHostMsgFail(level, "Enable CONFIG_%s in kernel Kconfig file", config_name);
c480ed
-    return -1;
c480ed
+    return ret;
c480ed
 }
c480ed
-
c480ed
-#ifdef HAVE_MNTENT_H
c480ed
-static int virHostValidateCGroupMount(const char *hvname,
c480ed
-                                      const char *cg_name,
c480ed
-                                      virHostValidateLevel level)
c480ed
+#else /*  !__linux__ */
c480ed
+int virHostValidateCGroupControllers(const char *hvname,
c480ed
+                                     int controllers,
c480ed
+                                     virHostValidateLevel level)
c480ed
 {
c480ed
-    virHostMsgCheck(hvname, "for cgroup '%s' controller mount-point", cg_name);
c480ed
-    FILE *fp = setmntent("/proc/mounts", "r");
c480ed
-    struct mntent ent;
c480ed
-    char mntbuf[1024];
c480ed
-    bool matched = false;
c480ed
-
c480ed
-    if (!fp)
c480ed
-        goto error;
c480ed
-
c480ed
-    while (getmntent_r(fp, &ent, mntbuf, sizeof(mntbuf)) && !matched) {
c480ed
-        char **opts;
c480ed
-        size_t nopts;
c480ed
-        size_t i;
c480ed
-
c480ed
-        /* Ignore non-cgroup mounts */
c480ed
-        if (STRNEQ(ent.mnt_type, "cgroup"))
c480ed
-            continue;
c480ed
-
c480ed
-        if (!(opts = virStringSplitCount(ent.mnt_opts, ",", 0, &nopts)))
c480ed
-            continue;
c480ed
-
c480ed
-        /* Look for a mount option matching the cgroup name */
c480ed
-        for (i = 0; i < nopts; i++) {
c480ed
-            if (STREQ(opts[i], cg_name))
c480ed
-                matched = true;
c480ed
-        }
c480ed
-
c480ed
-        virStringListFreeCount(opts, nopts);
c480ed
-    }
c480ed
-    endmntent(fp);
c480ed
-    if (!matched)
c480ed
-        goto error;
c480ed
-
c480ed
-    virHostMsgPass();
c480ed
-    return 0;
c480ed
-
c480ed
- error:
c480ed
-    virHostMsgFail(level, "Mount '%s' cgroup controller (suggested at /sys/fs/cgroup/%s)",
c480ed
-                   cg_name, cg_name);
c480ed
-    return -1;
c480ed
-}
c480ed
-#else /* ! HAVE_MNTENT_H */
c480ed
-static int virHostValidateCGroupMount(const char *hvname,
c480ed
-                                      const char *cg_name,
c480ed
-                                      virHostValidateLevel level)
c480ed
-{
c480ed
-    virHostMsgCheck(hvname, "for cgroup '%s' controller mount-point", cg_name);
c480ed
     virHostMsgFail(level, "%s", "This platform does not support cgroups");
c480ed
     return -1;
c480ed
 }
c480ed
-#endif /* ! HAVE_MNTENT_H */
c480ed
-
c480ed
-int virHostValidateCGroupController(const char *hvname,
c480ed
-                                    const char *cg_name,
c480ed
-                                    virHostValidateLevel level,
c480ed
-                                    const char *config_name)
c480ed
-{
c480ed
-    if (virHostValidateCGroupSupport(hvname,
c480ed
-                                     cg_name,
c480ed
-                                     level,
c480ed
-                                     config_name) < 0)
c480ed
-        return -1;
c480ed
-    if (virHostValidateCGroupMount(hvname,
c480ed
-                                   cg_name,
c480ed
-                                   level) < 0)
c480ed
-        return -1;
c480ed
-    return 0;
c480ed
-}
c480ed
+#endif /* !__linux__ */
c480ed
 
c480ed
 int virHostValidateIOMMU(const char *hvname,
c480ed
                          virHostValidateLevel level)
c480ed
diff --git a/tools/virt-host-validate-common.h b/tools/virt-host-validate-common.h
c480ed
index b6fe17daa7..b23dd7cdbe 100644
c480ed
--- a/tools/virt-host-validate-common.h
c480ed
+++ b/tools/virt-host-validate-common.h
c480ed
@@ -77,10 +77,9 @@ int virHostValidateNamespace(const char *hvname,
c480ed
                              virHostValidateLevel level,
c480ed
                              const char *hint);
c480ed
 
c480ed
-int virHostValidateCGroupController(const char *hvname,
c480ed
-                                    const char *cg_name,
c480ed
-                                    virHostValidateLevel level,
c480ed
-                                    const char *config_name);
c480ed
+int virHostValidateCGroupControllers(const char *hvname,
c480ed
+                                     int controllers,
c480ed
+                                     virHostValidateLevel level);
c480ed
 
c480ed
 int virHostValidateIOMMU(const char *hvname,
c480ed
                          virHostValidateLevel level);
c480ed
diff --git a/tools/virt-host-validate-lxc.c b/tools/virt-host-validate-lxc.c
c480ed
index 64d9279c30..3c55b1b26d 100644
c480ed
--- a/tools/virt-host-validate-lxc.c
c480ed
+++ b/tools/virt-host-validate-lxc.c
c480ed
@@ -23,6 +23,7 @@
c480ed
 
c480ed
 #include "virt-host-validate-lxc.h"
c480ed
 #include "virt-host-validate-common.h"
c480ed
+#include "vircgroup.h"
c480ed
 
c480ed
 int virHostValidateLXC(void)
c480ed
 {
c480ed
@@ -63,35 +64,16 @@ int virHostValidateLXC(void)
c480ed
                                  _("User namespace support is recommended")) < 0)
c480ed
         ret = -1;
c480ed
 
c480ed
-    if (virHostValidateCGroupController("LXC", "memory",
c480ed
-                                        VIR_HOST_VALIDATE_FAIL,
c480ed
-                                        "MEMCG") < 0)
c480ed
-        ret = -1;
c480ed
-
c480ed
-    if (virHostValidateCGroupController("LXC", "cpu",
c480ed
-                                        VIR_HOST_VALIDATE_FAIL,
c480ed
-                                        "CGROUP_CPU") < 0)
c480ed
-        ret = -1;
c480ed
-
c480ed
-    if (virHostValidateCGroupController("LXC", "cpuacct",
c480ed
-                                        VIR_HOST_VALIDATE_FAIL,
c480ed
-                                        "CGROUP_CPUACCT") < 0)
c480ed
-        ret = -1;
c480ed
-
c480ed
-    if (virHostValidateCGroupController("LXC", "cpuset",
c480ed
-                                        VIR_HOST_VALIDATE_FAIL,
c480ed
-                                        "CPUSETS") < 0)
c480ed
-        ret = -1;
c480ed
-
c480ed
-    if (virHostValidateCGroupController("LXC", "devices",
c480ed
-                                        VIR_HOST_VALIDATE_FAIL,
c480ed
-                                        "CGROUP_DEVICE") < 0)
c480ed
-        ret = -1;
c480ed
-
c480ed
-    if (virHostValidateCGroupController("LXC", "blkio",
c480ed
-                                        VIR_HOST_VALIDATE_FAIL,
c480ed
-                                        "BLK_CGROUP") < 0)
c480ed
+    if (virHostValidateCGroupControllers("LXC",
c480ed
+                                         (1 << VIR_CGROUP_CONTROLLER_MEMORY) |
c480ed
+                                         (1 << VIR_CGROUP_CONTROLLER_CPU) |
c480ed
+                                         (1 << VIR_CGROUP_CONTROLLER_CPUACCT) |
c480ed
+                                         (1 << VIR_CGROUP_CONTROLLER_CPUSET) |
c480ed
+                                         (1 << VIR_CGROUP_CONTROLLER_DEVICES) |
c480ed
+                                         (1 << VIR_CGROUP_CONTROLLER_BLKIO),
c480ed
+                                         VIR_HOST_VALIDATE_FAIL) < 0) {
c480ed
         ret = -1;
c480ed
+    }
c480ed
 
c480ed
 #if WITH_FUSE
c480ed
     if (virHostValidateDeviceExists("LXC", "/sys/fs/fuse/connections",
c480ed
diff --git a/tools/virt-host-validate-qemu.c b/tools/virt-host-validate-qemu.c
c480ed
index d7573ea8b3..ff3c1f0231 100644
c480ed
--- a/tools/virt-host-validate-qemu.c
c480ed
+++ b/tools/virt-host-validate-qemu.c
c480ed
@@ -26,6 +26,7 @@
c480ed
 #include "virt-host-validate-common.h"
c480ed
 #include "virarch.h"
c480ed
 #include "virbitmap.h"
c480ed
+#include "vircgroup.h"
c480ed
 
c480ed
 int virHostValidateQEMU(void)
c480ed
 {
c480ed
@@ -96,35 +97,16 @@ int virHostValidateQEMU(void)
c480ed
                                     _("Load the 'tun' module to enable networking for QEMU guests")) < 0)
c480ed
         ret = -1;
c480ed
 
c480ed
-    if (virHostValidateCGroupController("QEMU", "memory",
c480ed
-                                        VIR_HOST_VALIDATE_WARN,
c480ed
-                                        "MEMCG") < 0)
c480ed
-        ret = -1;
c480ed
-
c480ed
-    if (virHostValidateCGroupController("QEMU", "cpu",
c480ed
-                                        VIR_HOST_VALIDATE_WARN,
c480ed
-                                        "CGROUP_CPU") < 0)
c480ed
-        ret = -1;
c480ed
-
c480ed
-    if (virHostValidateCGroupController("QEMU", "cpuacct",
c480ed
-                                        VIR_HOST_VALIDATE_WARN,
c480ed
-                                        "CGROUP_CPUACCT") < 0)
c480ed
-        ret = -1;
c480ed
-
c480ed
-    if (virHostValidateCGroupController("QEMU", "cpuset",
c480ed
-                                        VIR_HOST_VALIDATE_WARN,
c480ed
-                                        "CPUSETS") < 0)
c480ed
-        ret = -1;
c480ed
-
c480ed
-    if (virHostValidateCGroupController("QEMU", "devices",
c480ed
-                                        VIR_HOST_VALIDATE_WARN,
c480ed
-                                        "CGROUP_DEVICES") < 0)
c480ed
-        ret = -1;
c480ed
-
c480ed
-    if (virHostValidateCGroupController("QEMU", "blkio",
c480ed
-                                        VIR_HOST_VALIDATE_WARN,
c480ed
-                                        "BLK_CGROUP") < 0)
c480ed
+    if (virHostValidateCGroupControllers("QEMU",
c480ed
+                                         (1 << VIR_CGROUP_CONTROLLER_MEMORY) |
c480ed
+                                         (1 << VIR_CGROUP_CONTROLLER_CPU) |
c480ed
+                                         (1 << VIR_CGROUP_CONTROLLER_CPUACCT) |
c480ed
+                                         (1 << VIR_CGROUP_CONTROLLER_CPUSET) |
c480ed
+                                         (1 << VIR_CGROUP_CONTROLLER_DEVICES) |
c480ed
+                                         (1 << VIR_CGROUP_CONTROLLER_BLKIO),
c480ed
+                                         VIR_HOST_VALIDATE_WARN) < 0) {
c480ed
         ret = -1;
c480ed
+    }
c480ed
 
c480ed
     if (virHostValidateIOMMU("QEMU",
c480ed
                              VIR_HOST_VALIDATE_WARN) < 0)
c480ed
-- 
c480ed
2.22.0
c480ed