]> git.proxmox.com Git - mirror_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>
Mon, 6 Nov 2017 23:54:28 +0000 (00:54 +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 cd0b5c72048fb4f6ef1b399321b803032f8fb146..cc11f12de7d2734a8f4dc4cadc6a4dc9c40bde1c 100644 (file)
@@ -215,6 +215,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);
 
@@ -749,18 +751,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)
@@ -784,7 +782,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;
        }
@@ -1083,13 +1081,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;
 
@@ -1115,7 +1114,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);