]> git.ipfire.org Git - thirdparty/lxc.git/commitdiff
cgroups: cgfsng_attach: handle unified hierarchy
authorChristian Brauner <christian.brauner@ubuntu.com>
Wed, 31 Jan 2018 15:38:55 +0000 (16:38 +0100)
committerChristian Brauner <christian.brauner@ubuntu.com>
Wed, 7 Feb 2018 10:59:44 +0000 (11:59 +0100)
Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
src/lxc/cgroups/cgfsng.c
src/lxc/commands.c

index 5138b10b27b6f1b189ff82fcfd40e3744b849121..2166bb882a561d15967497973336ebebf61da75a 100644 (file)
@@ -2212,26 +2212,110 @@ static char *build_full_cgpath_from_monitorpath(struct hierarchy *h,
        return must_make_path(h->mountpoint, inpath, filename, NULL);
 }
 
+/* Technically, we're always at a delegation boundary here. (This is especially
+ * true when cgroup namespaces are available.) The reasoning is that in order
+ * for us to have been able to start a container in the first place the root
+ * cgroup must have been a leaf node.  Now, either the container's init system
+ * has populated the cgroup and kept it as a leaf node or it has created
+ * subtrees. In the former case we will simply attach to the leaf node we
+ * created when we started the container in the latter case we create our own
+ * cgroup for the attaching process.
+ */
+static int cg_attach_unified(const struct hierarchy *h, const char *name,
+                            const char *lxcpath, const char *pidstr,
+                            size_t pidstr_len, const char *controller)
+{
+       int ret;
+       size_t len;
+       int fret = -1, idx = 0;
+       char *base_path = NULL, *container_cgroup = NULL, *full_path = NULL;
+
+       container_cgroup = lxc_cmd_get_cgroup_path(name, lxcpath, controller);
+       /* not running */
+       if (!container_cgroup)
+               return 0;
+
+       base_path = must_make_path(h->mountpoint, container_cgroup, NULL);
+       full_path = must_make_path(base_path, "cgroup.procs", NULL);
+       /* cgroup is populated */
+       ret = lxc_write_to_file(full_path, pidstr, pidstr_len, false);
+       if (ret < 0 && errno != EBUSY)
+               goto on_error;
+
+       if (ret == 0)
+               goto on_success;
+
+       free(full_path);
+
+       len = strlen(base_path) + sizeof("/lxc-1000") - 1 +
+             sizeof("/cgroup-procs") - 1;
+       full_path = must_alloc(len + 1);
+       do {
+               if (idx)
+                       ret = snprintf(full_path, len + 1, "%s/lxc-%d",
+                                      base_path, idx);
+               else
+                       ret = snprintf(full_path, len + 1, "%s/lxc", base_path);
+               if (ret < 0 || (size_t)ret >= len + 1)
+                       goto on_error;
+
+               ret = mkdir_p(full_path, 0755);
+               if (ret < 0 && errno != EEXIST)
+                       goto on_error;
+
+               strcat(full_path, "/cgroup.procs");
+               ret = lxc_write_to_file(full_path, pidstr, len, false);
+               if (ret == 0)
+                       goto on_success;
+
+               /* this is a non-leaf node */
+               if (errno != EBUSY)
+                       goto on_error;
+
+       } while (++idx > 0 && idx < 1000);
+
+on_success:
+       if (idx < 1000)
+               fret = 0;
+
+on_error:
+       free(base_path);
+       free(container_cgroup);
+       free(full_path);
+
+       return fret;
+}
+
 static bool cgfsng_attach(const char *name, const char *lxcpath, pid_t pid)
 {
+       int i, len, ret;
        char pidstr[25];
-       int i, len;
 
        len = snprintf(pidstr, 25, "%d", pid);
        if (len < 0 || len > 25)
                return false;
 
        for (i = 0; hierarchies[i]; i++) {
-               char *path, *fullpath;
+               char *path;
+               char *fullpath = NULL;
                struct hierarchy *h = hierarchies[i];
 
+               if (h->version == CGROUP2_SUPER_MAGIC) {
+                       ret = cg_attach_unified(h, name, lxcpath, pidstr, len, h->controllers[0]);
+                       if (ret < 0)
+                               return false;
+
+                       continue;
+               }
+
                path = lxc_cmd_get_cgroup_path(name, lxcpath, h->controllers[0]);
-               if (!path) /* not running */
+               /* not running */
+               if (!path)
                        continue;
 
                fullpath = build_full_cgpath_from_monitorpath(h, path, "cgroup.procs");
-               free(path);
-               if (lxc_write_to_file(fullpath, pidstr, len, false) != 0) {
+               ret = lxc_write_to_file(fullpath, pidstr, len, false);
+               if (ret < 0) {
                        SYSERROR("Failed to attach %d to %s", (int)pid, fullpath);
                        free(fullpath);
                        return false;
index a2f57e79c909910c495ce60807e0eb05ca35d6f9..8f241d461b9d5a0ea0f22e594df69f308fe2a40a 100644 (file)
@@ -438,11 +438,16 @@ char *lxc_cmd_get_cgroup_path(const char *name, const char *lxcpath,
        struct lxc_cmd_rr cmd = {
                .req = {
                        .cmd = LXC_CMD_GET_CGROUP,
-                       .datalen = strlen(subsystem) + 1,
                        .data = subsystem,
+                       .datalen = 0,
                },
        };
 
+       cmd.req.data = subsystem;
+       cmd.req.datalen = 0;
+       if (subsystem)
+               cmd.req.datalen = strlen(subsystem) + 1;
+
        ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
        if (ret < 0)
                return NULL;
@@ -462,10 +467,10 @@ static int lxc_cmd_get_cgroup_callback(int fd, struct lxc_cmd_req *req,
        const char *path;
        struct lxc_cmd_rsp rsp;
 
-       if (req->datalen < 1)
-               return -1;
-
-       path = cgroup_get_cgroup(handler, req->data);
+       if (req->datalen > 0)
+               path = cgroup_get_cgroup(handler, req->data);
+       else
+               path = cgroup_get_cgroup(handler, NULL);
        if (!path)
                return -1;