]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
virt-host-validate: rewrite cgroup detection to use util/vircgroup
authorPavel Hrdina <phrdina@redhat.com>
Sat, 29 Sep 2018 19:37:22 +0000 (21:37 +0200)
committerPavel Hrdina <phrdina@redhat.com>
Fri, 5 Oct 2018 13:53:29 +0000 (15:53 +0200)
This removes code duplication and simplifies cgroup detection.
As a drawback we will not have separate messages to enable cgroup
controller in kernel or to mount it.  On the other side the rewrite
adds support for cgroup v2.

The kernel config support was wrong because it was parsing
'/proc/self/cgroup' instead of '/proc/cgroups/' file.

The mount suggestion is removed as well because it will not work
with cgroup v2.

Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
tools/virt-host-validate-common.c
tools/virt-host-validate-common.h
tools/virt-host-validate-lxc.c
tools/virt-host-validate-qemu.c

index ccbd764c84f2eb74d1122bd53372930ba416aa79..4e70fe9e9cd6ba9ba06d830114cff99153f1a5cb 100644 (file)
 #include <stdarg.h>
 #include <unistd.h>
 #include <sys/utsname.h>
-#ifdef HAVE_MNTENT_H
-# include <mntent.h>
-#endif /* HAVE_MNTENT_H */
 #include <sys/stat.h>
 
 #include "viralloc.h"
+#include "vircgroup.h"
 #include "virfile.h"
 #include "virt-host-validate-common.h"
 #include "virstring.h"
@@ -288,152 +286,50 @@ int virHostValidateLinuxKernel(const char *hvname,
     }
 }
 
-
-static int virHostValidateCGroupSupport(const char *hvname,
-                                        const char *cg_name,
-                                        virHostValidateLevel level,
-                                        const char *config_name)
+#ifdef __linux__
+int virHostValidateCGroupControllers(const char *hvname,
+                                     int controllers,
+                                     virHostValidateLevel level)
 {
-    virHostMsgCheck(hvname, "for cgroup '%s' controller support", cg_name);
-    FILE *fp = fopen("/proc/self/cgroup", "r");
-    size_t len = 0;
-    char *line = NULL;
-    ssize_t ret;
-    bool matched = false;
-
-    if (!fp)
-        goto error;
-
-    while ((ret = getline(&line, &len, fp)) >= 0 && !matched) {
-        char **cgroups;
-        char *start;
-        char *end;
-        size_t ncgroups;
-        size_t i;
-
-        /* Each line in this file looks like
-         *
-         *   4:cpu,cpuacct:/machine.slice/machine-qemu\x2dtest.scope/emulator
-         *
-         * Since multiple cgroups can be part of the same line and some cgroup
-         * names can appear as part of other cgroup names (eg. 'cpu' is a
-         * prefix for both 'cpuacct' and 'cpuset'), it's not enough to simply
-         * check whether the cgroup name is present somewhere inside the file.
-         *
-         * Moreover, there's nothing stopping the cgroup name from appearing
-         * in an unrelated mount point name as well */
-
-        /* Look for the first colon.
-         * The part we're interested in starts right after it */
-        if (!(start = strchr(line, ':')))
-            continue;
-        start++;
-
-        /* Look for the second colon.
-         * The part we're interested in ends exactly there */
-        if (!(end = strchr(start, ':')))
-            continue;
-        *end = '\0';
-
-        if (!(cgroups = virStringSplitCount(start, ",", 0, &ncgroups)))
-            continue;
-
-        /* Look for the matching cgroup */
-        for (i = 0; i < ncgroups; i++) {
-            if (STREQ(cgroups[i], cg_name))
-                matched = true;
-        }
-
-        virStringListFreeCount(cgroups, ncgroups);
-    }
-
-    VIR_FREE(line);
-    VIR_FORCE_FCLOSE(fp);
-    if (!matched)
-        goto error;
-
-    virHostMsgPass();
-    return 0;
+    virCgroupPtr group = NULL;
+    int ret = 0;
+    size_t i;
 
- error:
-    VIR_FREE(line);
-    virHostMsgFail(level, "Enable CONFIG_%s in kernel Kconfig file", config_name);
-    return -1;
-}
+    if (virCgroupNewSelf(&group) < 0)
+        return -1;
 
-#ifdef HAVE_MNTENT_H
-static int virHostValidateCGroupMount(const char *hvname,
-                                      const char *cg_name,
-                                      virHostValidateLevel level)
-{
-    virHostMsgCheck(hvname, "for cgroup '%s' controller mount-point", cg_name);
-    FILE *fp = setmntent("/proc/mounts", "r");
-    struct mntent ent;
-    char mntbuf[1024];
-    bool matched = false;
-
-    if (!fp)
-        goto error;
-
-    while (getmntent_r(fp, &ent, mntbuf, sizeof(mntbuf)) && !matched) {
-        char **opts;
-        size_t nopts;
-        size_t i;
+    for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
+        int flag = 1 << i;
+        const char *cg_name = virCgroupControllerTypeToString(i);
 
-        /* Ignore non-cgroup mounts */
-        if (STRNEQ(ent.mnt_type, "cgroup"))
+        if (!(controllers & flag))
             continue;
 
-        if (!(opts = virStringSplitCount(ent.mnt_opts, ",", 0, &nopts)))
-            continue;
+        virHostMsgCheck(hvname, "for cgroup '%s' controller support", cg_name);
 
-        /* Look for a mount option matching the cgroup name */
-        for (i = 0; i < nopts; i++) {
-            if (STREQ(opts[i], cg_name))
-                matched = true;
+        if (!virCgroupHasController(group, i)) {
+            ret = -1;
+            virHostMsgFail(level, "Enable '%s' in kernel Kconfig file or "
+                           "mount/enable cgroup controller in your system",
+                           cg_name);
+        } else {
+            virHostMsgPass();
         }
-
-        virStringListFreeCount(opts, nopts);
     }
-    endmntent(fp);
-    if (!matched)
-        goto error;
 
-    virHostMsgPass();
-    return 0;
+    virCgroupFree(&group);
 
- error:
-    virHostMsgFail(level, "Mount '%s' cgroup controller (suggested at /sys/fs/cgroup/%s)",
-                   cg_name, cg_name);
-    return -1;
+    return ret;
 }
-#else /* ! HAVE_MNTENT_H */
-static int virHostValidateCGroupMount(const char *hvname,
-                                      const char *cg_name,
-                                      virHostValidateLevel level)
+#else /*  !__linux__ */
+int virHostValidateCGroupControllers(const char *hvname,
+                                     int controllers,
+                                     virHostValidateLevel level)
 {
-    virHostMsgCheck(hvname, "for cgroup '%s' controller mount-point", cg_name);
     virHostMsgFail(level, "%s", "This platform does not support cgroups");
     return -1;
 }
-#endif /* ! HAVE_MNTENT_H */
-
-int virHostValidateCGroupController(const char *hvname,
-                                    const char *cg_name,
-                                    virHostValidateLevel level,
-                                    const char *config_name)
-{
-    if (virHostValidateCGroupSupport(hvname,
-                                     cg_name,
-                                     level,
-                                     config_name) < 0)
-        return -1;
-    if (virHostValidateCGroupMount(hvname,
-                                   cg_name,
-                                   level) < 0)
-        return -1;
-    return 0;
-}
+#endif /* !__linux__ */
 
 int virHostValidateIOMMU(const char *hvname,
                          virHostValidateLevel level)
index b6fe17daa7e657ca05eed731b172db22b6c1ca5f..b23dd7cdbeb233915df312594e52593897f96bc9 100644 (file)
@@ -77,10 +77,9 @@ int virHostValidateNamespace(const char *hvname,
                              virHostValidateLevel level,
                              const char *hint);
 
-int virHostValidateCGroupController(const char *hvname,
-                                    const char *cg_name,
-                                    virHostValidateLevel level,
-                                    const char *config_name);
+int virHostValidateCGroupControllers(const char *hvname,
+                                     int controllers,
+                                     virHostValidateLevel level);
 
 int virHostValidateIOMMU(const char *hvname,
                          virHostValidateLevel level);
index 64d9279c3046e8992ce29e671b2a4bb79d433c52..3c55b1b26dba38c7f875f6a2f1e92f61cf0df2e1 100644 (file)
@@ -23,6 +23,7 @@
 
 #include "virt-host-validate-lxc.h"
 #include "virt-host-validate-common.h"
+#include "vircgroup.h"
 
 int virHostValidateLXC(void)
 {
@@ -63,35 +64,16 @@ int virHostValidateLXC(void)
                                  _("User namespace support is recommended")) < 0)
         ret = -1;
 
-    if (virHostValidateCGroupController("LXC", "memory",
-                                        VIR_HOST_VALIDATE_FAIL,
-                                        "MEMCG") < 0)
-        ret = -1;
-
-    if (virHostValidateCGroupController("LXC", "cpu",
-                                        VIR_HOST_VALIDATE_FAIL,
-                                        "CGROUP_CPU") < 0)
-        ret = -1;
-
-    if (virHostValidateCGroupController("LXC", "cpuacct",
-                                        VIR_HOST_VALIDATE_FAIL,
-                                        "CGROUP_CPUACCT") < 0)
-        ret = -1;
-
-    if (virHostValidateCGroupController("LXC", "cpuset",
-                                        VIR_HOST_VALIDATE_FAIL,
-                                        "CPUSETS") < 0)
-        ret = -1;
-
-    if (virHostValidateCGroupController("LXC", "devices",
-                                        VIR_HOST_VALIDATE_FAIL,
-                                        "CGROUP_DEVICE") < 0)
-        ret = -1;
-
-    if (virHostValidateCGroupController("LXC", "blkio",
-                                        VIR_HOST_VALIDATE_FAIL,
-                                        "BLK_CGROUP") < 0)
+    if (virHostValidateCGroupControllers("LXC",
+                                         (1 << VIR_CGROUP_CONTROLLER_MEMORY) |
+                                         (1 << VIR_CGROUP_CONTROLLER_CPU) |
+                                         (1 << VIR_CGROUP_CONTROLLER_CPUACCT) |
+                                         (1 << VIR_CGROUP_CONTROLLER_CPUSET) |
+                                         (1 << VIR_CGROUP_CONTROLLER_DEVICES) |
+                                         (1 << VIR_CGROUP_CONTROLLER_BLKIO),
+                                         VIR_HOST_VALIDATE_FAIL) < 0) {
         ret = -1;
+    }
 
 #if WITH_FUSE
     if (virHostValidateDeviceExists("LXC", "/sys/fs/fuse/connections",
index d7573ea8b3ddee0312ff8764d1984a438ea6bc16..ff3c1f02315b562fbc5a4a9a24c0d39840a03886 100644 (file)
@@ -26,6 +26,7 @@
 #include "virt-host-validate-common.h"
 #include "virarch.h"
 #include "virbitmap.h"
+#include "vircgroup.h"
 
 int virHostValidateQEMU(void)
 {
@@ -96,35 +97,16 @@ int virHostValidateQEMU(void)
                                     _("Load the 'tun' module to enable networking for QEMU guests")) < 0)
         ret = -1;
 
-    if (virHostValidateCGroupController("QEMU", "memory",
-                                        VIR_HOST_VALIDATE_WARN,
-                                        "MEMCG") < 0)
-        ret = -1;
-
-    if (virHostValidateCGroupController("QEMU", "cpu",
-                                        VIR_HOST_VALIDATE_WARN,
-                                        "CGROUP_CPU") < 0)
-        ret = -1;
-
-    if (virHostValidateCGroupController("QEMU", "cpuacct",
-                                        VIR_HOST_VALIDATE_WARN,
-                                        "CGROUP_CPUACCT") < 0)
-        ret = -1;
-
-    if (virHostValidateCGroupController("QEMU", "cpuset",
-                                        VIR_HOST_VALIDATE_WARN,
-                                        "CPUSETS") < 0)
-        ret = -1;
-
-    if (virHostValidateCGroupController("QEMU", "devices",
-                                        VIR_HOST_VALIDATE_WARN,
-                                        "CGROUP_DEVICES") < 0)
-        ret = -1;
-
-    if (virHostValidateCGroupController("QEMU", "blkio",
-                                        VIR_HOST_VALIDATE_WARN,
-                                        "BLK_CGROUP") < 0)
+    if (virHostValidateCGroupControllers("QEMU",
+                                         (1 << VIR_CGROUP_CONTROLLER_MEMORY) |
+                                         (1 << VIR_CGROUP_CONTROLLER_CPU) |
+                                         (1 << VIR_CGROUP_CONTROLLER_CPUACCT) |
+                                         (1 << VIR_CGROUP_CONTROLLER_CPUSET) |
+                                         (1 << VIR_CGROUP_CONTROLLER_DEVICES) |
+                                         (1 << VIR_CGROUP_CONTROLLER_BLKIO),
+                                         VIR_HOST_VALIDATE_WARN) < 0) {
         ret = -1;
+    }
 
     if (virHostValidateIOMMU("QEMU",
                              VIR_HOST_VALIDATE_WARN) < 0)