]> git.ipfire.org Git - thirdparty/lxc.git/commitdiff
cgroupfs/cgfsng: improve cgroup2 handling
authorChristian Brauner <christian.brauner@ubuntu.com>
Tue, 31 Oct 2017 16:07:57 +0000 (17:07 +0100)
committerChristian Brauner <christian.brauner@ubuntu.com>
Thu, 9 Nov 2017 00:24:02 +0000 (01:24 +0100)
This fixes a bunch of bugs.

Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
src/lxc/cgroups/cgfsng.c
src/lxc/cgroups/cgroup_utils.c
src/lxc/cgroups/cgroup_utils.h

index 472e0766b801eead0eea7908e603d9e8aeaa8a34..77df4c3d14c55bc274d55c02fe1aaac1a759fdd6 100644 (file)
@@ -210,6 +210,8 @@ static void must_append_controller(char **klist, char **nlist, char ***clist, ch
                copy = must_copy_string(entry);
        else if (string_in_list(klist, entry))
                copy = must_copy_string(entry);
+       else if (!strcmp(entry, "cgroup2"))
+               copy = must_copy_string(entry);
        else
                copy = must_prefix_named(entry);
 
@@ -740,18 +742,14 @@ static bool all_controllers_found(void)
  * options.  But we simply assume that the mountpoint must be
  * /sys/fs/cgroup/controller-list
  */
-static char **get_controllers(char **klist, char **nlist, char *line)
+static char **get_controllers(char **klist, char **nlist, char *line, int type)
 {
        /* the fourth field is /sys/fs/cgroup/comma-delimited-controller-list */
        int i;
        char *dup, *p2, *tok;
-       bool is_cgroup_v2;
        char *p = line, *saveptr = NULL;
        char **aret = NULL;
 
-       /* handle cgroup v2 */
-       is_cgroup_v2 = is_cgroupfs_v2(line);
-
        for (i = 0; i < 4; i++) {
                p = strchr(p, ' ');
                if (!p)
@@ -775,7 +773,7 @@ static char **get_controllers(char **klist, char **nlist, char *line)
        *p2 = '\0';
 
        /* cgroup v2 does not have separate mountpoints for controllers */
-       if (is_cgroup_v2) {
+       if (type == CGROUP_V2) {
                must_append_controller(klist, nlist, &aret, "cgroup2");
                return aret;
        }
@@ -1070,13 +1068,14 @@ static bool parse_hierarchies(void)
        while (getline(&line, &len, f) != -1) {
                char **controller_list = NULL;
                char *mountpoint, *base_cgroup;
-               bool is_cgroup_v2, writeable;
+               bool writeable;
+               int type;
 
-               is_cgroup_v2 = is_cgroupfs_v2(line);
-               if (!is_cgroupfs_v1(line) && !is_cgroup_v2)
+               type = get_cgroup_version(line);
+               if (type < 0)
                        continue;
 
-               controller_list = get_controllers(klist, nlist, line);
+               controller_list = get_controllers(klist, nlist, line, type);
                if (!controller_list)
                        continue;
 
@@ -1102,7 +1101,7 @@ static bool parse_hierarchies(void)
 
                trim(base_cgroup);
                prune_init_scope(base_cgroup);
-               if (is_cgroup_v2)
+               if (type == CGROUP_V2)
                        writeable = test_writeable_v2(mountpoint, base_cgroup);
                else
                        writeable = test_writeable_v1(mountpoint, base_cgroup);
index c09ba168854e0a4ce1636736b5aa2e7e592e6f00..6dda1a6175822311a26d323067dd753629cfe1a4 100644 (file)
 #include "cgroup_utils.h"
 #include "utils.h"
 
+int get_cgroup_version(char *line)
+{
+       if (is_cgroupfs_v1(line))
+               return CGROUP_V1;
+
+       if (is_cgroupfs_v2(line))
+               return CGROUP_V2;
+
+       return -1;
+}
+
 bool is_cgroupfs_v1(char *line)
 {
        char *p = strstr(line, " - ");
@@ -67,20 +78,39 @@ bool test_writeable_v2(char *mountpoint, char *path)
         * file.
         */
        int ret;
-       char *cgroup_path, *cgroup_procs_file;
+       char *cgroup_path, *cgroup_procs_file, *cgroup_threads_file;
 
        cgroup_path = must_make_path(mountpoint, path, NULL);
        cgroup_procs_file = must_make_path(cgroup_path, "cgroup.procs", NULL);
 
        ret = access(cgroup_path, W_OK);
-       free(cgroup_path);
        if (ret < 0) {
+               free(cgroup_path);
                free(cgroup_procs_file);
                return false;
        }
 
        ret = access(cgroup_procs_file, W_OK);
        free(cgroup_procs_file);
+       if (ret < 0) {
+               free(cgroup_path);
+               return false;
+       }
+
+       /* Newer versions of cgroup2 now also require write access to the
+        * "cgroup.threads" file.
+        */
+       cgroup_threads_file = must_make_path(cgroup_path, "cgroup.threads", NULL);
+       free(cgroup_path);
+       if (!file_exists(cgroup_threads_file)) {
+               free(cgroup_threads_file);
+               return true;
+       }
+
+       ret = access(cgroup_threads_file, W_OK);
+       free(cgroup_threads_file);
+       if (ret < 0)
+               return false;
 
        return ret == 0;
 }
index 49aae856727e7588a2ec5c14fb9ba8babe77b892..e9e4448a6ecc9d158acb1b52208921a0070eef8f 100644 (file)
 #include <stdbool.h>
 #include <stdio.h>
 
+#define CGROUP_V1 0
+#define CGROUP_V2 1
+#define LXCFS_CGROUP 2
+
+/* Retrieve the cgroup version of a given entry from /proc/<pid>/mountinfo. */
+extern int get_cgroup_version(char *line);
+
 /* Check if given entry from /proc/<pid>/mountinfo is a cgroupfs v1 mount. */
 extern bool is_cgroupfs_v1(char *line);