]> git.ipfire.org Git - thirdparty/lxc.git/commitdiff
lxc: cgfs: handle lxcfs
authorUbuntu <ubuntu@localhost.localdomain>
Sat, 20 Feb 2016 02:25:55 +0000 (02:25 +0000)
committerStéphane Graber <stgraber@ubuntu.com>
Thu, 17 Nov 2016 22:55:29 +0000 (17:55 -0500)
When containers have lxcfs mounted instead of cgroupfs, we have to
process /proc/self/mountinfo a bit differently.  In particular, we
should look for fuse.lxcfs fstype, we need to look elsewhere for the
list of comounted controllers, and the mount_prefix is not a cgroup path
which was bind mounted, so we should ignore it, and named subsystems
show up without the 'name=' prefix.

With this patchset I can start containers inside a privileged lxd
container with lxcfs mounted (i.e. without cgroup namespaces).

Closes #830

Signed-off-by: Ubuntu <ubuntu@localhost.localdomain>
src/lxc/cgfs.c

index cb39b5b8e6c34303e6dfe9940e4558619e20421d..bb3c882934186a5d7ae4d8e010e21e1c99dc9c6c 100644 (file)
@@ -432,6 +432,7 @@ static bool find_hierarchy_mountpts( struct cgroup_meta_data *meta_data, char **
                struct cgroup_mount_point *mount_point;
                struct cgroup_hierarchy *h;
                char **subsystems;
+               bool is_lxcfs = false;
 
                if (line[0] && line[strlen(line) - 1] == '\n')
                        line[strlen(line) - 1] = '\0';
@@ -470,10 +471,18 @@ static bool find_hierarchy_mountpts( struct cgroup_meta_data *meta_data, char **
                        continue;
 
                /* not a cgroup filesystem */
-               if (strcmp(tokens[j + 1], "cgroup") != 0)
-                       continue;
-
-               subsystems = subsystems_from_mount_options(tokens[j + 3], kernel_subsystems);
+               if (strcmp(tokens[j + 1], "cgroup") != 0) {
+                       if (strcmp(tokens[j + 1], "fuse.lxcfs") != 0)
+                               continue;
+                       if (strncmp(tokens[4], "/sys/fs/cgroup/", 15) != 0)
+                               continue;
+                       is_lxcfs = true;
+                       char *curtok = tokens[4] + 15;
+                       subsystems = subsystems_from_mount_options(curtok,
+                                                        kernel_subsystems);
+               } else
+                       subsystems = subsystems_from_mount_options(tokens[j + 3],
+                                                        kernel_subsystems);
                if (!subsystems)
                        goto out;
 
@@ -502,8 +511,11 @@ static bool find_hierarchy_mountpts( struct cgroup_meta_data *meta_data, char **
                meta_data->mount_points[mount_point_count++] = mount_point;
 
                mount_point->hierarchy = h;
+               if (is_lxcfs)
+                       mount_point->mount_prefix = strdup("/");
+               else
+                       mount_point->mount_prefix = strdup(tokens[3]);
                mount_point->mount_point = strdup(tokens[4]);
-               mount_point->mount_prefix = strdup(tokens[3]);
                if (!mount_point->mount_point || !mount_point->mount_prefix)
                        goto out;
                mount_point->read_only = !lxc_string_in_list("rw", tokens[5], ',');
@@ -1703,16 +1715,20 @@ static char **subsystems_from_mount_options(const char *mount_options,
                 * subsystems provided by the kernel OR if it starts
                 * with name= for named hierarchies
                 */
-               if (!strncmp(token, "name=", 5) || lxc_string_in_array(token, (const char **)kernel_list)) {
-                       r = lxc_grow_array((void ***)&result, &result_capacity, result_count + 1, 12);
-                       if (r < 0)
-                               goto out_free;
-                       result[result_count + 1] = NULL;
+               r = lxc_grow_array((void ***)&result, &result_capacity, result_count + 1, 12);
+               if (r < 0)
+                       goto out_free;
+               result[result_count + 1] = NULL;
+               if (strncmp(token, "name=", 5) && !lxc_string_in_array(token, (const char **)kernel_list)) {
+                       // this is eg 'systemd' but the mount will be 'name=systemd'
+                       result[result_count] = malloc(strlen(token) + 6);
+                       if (result[result_count])
+                               sprintf(result[result_count], "name=%s", token);
+               } else
                        result[result_count] = strdup(token);
-                       if (!result[result_count])
-                               goto out_free;
-                       result_count++;
-               }
+               if (!result[result_count])
+                       goto out_free;
+               result_count++;
        }
 
        return result;