]> git.ipfire.org Git - thirdparty/lxc.git/commitdiff
restore: create cgroups for criu
authorTycho Andersen <tycho.andersen@canonical.com>
Tue, 7 Oct 2014 19:33:08 +0000 (19:33 +0000)
committerSerge Hallyn <serge.hallyn@ubuntu.com>
Wed, 8 Oct 2014 17:47:30 +0000 (12:47 -0500)
Previously, we let criu create the cgroups for a container as it was restoring
things. In some cases (i.e. migration across hosts), if the container being
migrated was in /lxc/u1-3, it would be migrated to the target host in
/lxc/u1-3, even if there was no /lxc/u1-2 (or worse, if there was already an
alive container in u1-3).

Instead, we use lxc's cgroup_create, and then tell criu where to restore to.

Signed-off-by: Tycho Andersen <tycho.andersen@canonical.com>
Acked-by: Serge E. Hallyn <serge.hallyn@ubuntu.com>
src/lxc/cgfs.c
src/lxc/cgmanager.c
src/lxc/cgroup.c
src/lxc/cgroup.h
src/lxc/lxccontainer.c

index 0f181c6499198112c8e80e1124145b526de0f89b..9fa47cd76070baeaf6c8e4dfbc79b40fb628080a 100644 (file)
@@ -2319,6 +2319,28 @@ static const char *cgfs_get_cgroup(void *hdata, const char *subsystem)
        return lxc_cgroup_get_hierarchy_path_data(subsystem, d);
 }
 
+static const char *cgfs_canonical_path(void *hdata)
+{
+       struct cgfs_data *d = hdata;
+       struct cgroup_process_info *info_ptr;
+       char *path = NULL;
+
+       if (!d)
+               return NULL;
+
+       for (info_ptr = d->info; info_ptr; info_ptr = info_ptr->next) {
+               if (!path)
+                       path = info_ptr->cgroup_path;
+               else if (strcmp(path, info_ptr->cgroup_path) != 0) {
+                       ERROR("not all paths match %s, %s has path %s", path,
+                               info_ptr->hierarchy->subsystems[0], info_ptr->cgroup_path);
+                       return NULL;
+               }
+       }
+
+       return path;
+}
+
 static bool cgfs_unfreeze(void *hdata)
 {
        struct cgfs_data *d = hdata;
@@ -2376,18 +2398,6 @@ static bool lxc_cgroupfs_attach(const char *name, const char *lxcpath, pid_t pid
        return true;
 }
 
-static bool cgfs_parse_existing_cgroups(void *hdata, pid_t init)
-{
-       struct cgfs_data *d = hdata;
-
-       if (!d)
-               return false;
-
-       d->info = lxc_cgroup_process_info_get(init, d->meta);
-
-       return !!(d->info);
-}
-
 static struct cgroup_ops cgfs_ops = {
        .init = cgfs_init,
        .destroy = cgfs_destroy,
@@ -2395,6 +2405,7 @@ static struct cgroup_ops cgfs_ops = {
        .enter = cgfs_enter,
        .create_legacy = cgfs_create_legacy,
        .get_cgroup = cgfs_get_cgroup,
+       .canonical_path = cgfs_canonical_path,
        .get = lxc_cgroupfs_get,
        .set = lxc_cgroupfs_set,
        .unfreeze = cgfs_unfreeze,
@@ -2402,7 +2413,6 @@ static struct cgroup_ops cgfs_ops = {
        .name = "cgroupfs",
        .attach = lxc_cgroupfs_attach,
        .chown = NULL,
-       .parse_existing_cgroups = cgfs_parse_existing_cgroups,
        .mount_cgroup = cgroupfs_mount_cgroup,
        .nrtasks = cgfs_nrtasks,
 };
index 0aad9e5700ad70b676fa9434e18406984db5a914..4e26cc0e987f5604985f9c72c2fc51a13c9f28e1 100644 (file)
@@ -727,6 +727,15 @@ static const char *cgm_get_cgroup(void *hdata, const char *subsystem)
        return d->cgroup_path;
 }
 
+static const char *cgm_canonical_path(void *hdata)
+{
+       struct cgm_data *d = hdata;
+
+       if (!d || !d->cgroup_path)
+               return NULL;
+       return d->cgroup_path;
+}
+
 #if HAVE_CGMANAGER_GET_PID_CGROUP_ABS_SYNC
 static inline bool abs_cgroup_supported(void) {
        return api_version >= CGM_SUPPORTS_GET_ABS;
@@ -1366,13 +1375,13 @@ static struct cgroup_ops cgmanager_ops = {
        .enter = cgm_enter,
        .create_legacy = NULL,
        .get_cgroup = cgm_get_cgroup,
+       .canonical_path = cgm_canonical_path,
        .get = cgm_get,
        .set = cgm_set,
        .unfreeze = cgm_unfreeze,
        .setup_limits = cgm_setup_limits,
        .name = "cgmanager",
        .chown = cgm_chown,
-       .parse_existing_cgroups = NULL,
        .attach = cgm_attach,
        .mount_cgroup = cgm_mount_cgroup,
        .nrtasks = cgm_get_nrtasks,
index 56d0e564f4329b2c71c5ebcb8a4ac0a2a1333976..a413832c38b8389a463726e1f0576bf3db5b7503 100644 (file)
@@ -21,6 +21,9 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
+#include <unistd.h>
+#include <sys/types.h>
+
 #include "cgroup.h"
 #include "conf.h"
 #include "log.h"
@@ -106,6 +109,19 @@ const char *cgroup_get_cgroup(struct lxc_handler *handler, const char *subsystem
        return NULL;
 }
 
+const char *cgroup_canonical_path(struct lxc_handler *handler)
+{
+       if (geteuid()) {
+               WARN("cgroup_canonical_path only makes sense for privileged containers.\n");
+               return NULL;
+       }
+
+       if (ops)
+               return ops->canonical_path(handler->cgroup_data);
+
+       return NULL;
+}
+
 bool cgroup_unfreeze(struct lxc_handler *handler)
 {
        if (ops)
@@ -128,15 +144,6 @@ bool cgroup_chown(struct lxc_handler *handler)
        return true;
 }
 
-bool cgroup_parse_existing_cgroups(struct lxc_handler *handler)
-{
-       if (ops && ops->parse_existing_cgroups)
-               return ops->parse_existing_cgroups(handler->cgroup_data, handler->pid);
-
-       /* cgmanager does this automatically */
-       return true;
-}
-
 bool cgroup_mount(const char *root, struct lxc_handler *handler, int type)
 {
        if (ops) {
index 0c2e566fe9b595d2d2e37aafa054b74d2c6369d7..281f40423609008e2830f42f0d48f1494c927778 100644 (file)
@@ -41,12 +41,12 @@ struct cgroup_ops {
        bool (*enter)(void *hdata, pid_t pid);
        bool (*create_legacy)(void *hdata, pid_t pid);
        const char *(*get_cgroup)(void *hdata, const char *subsystem);
+       const char *(*canonical_path)(void *hdata);
        int (*set)(const char *filename, const char *value, const char *name, const char *lxcpath);
        int (*get)(const char *filename, char *value, size_t len, const char *name, const char *lxcpath);
        bool (*unfreeze)(void *hdata);
        bool (*setup_limits)(void *hdata, struct lxc_list *cgroup_conf, bool with_devices);
        bool (*chown)(void *hdata, struct lxc_conf *conf);
-       bool (*parse_existing_cgroups)(void *hdata, pid_t pid);
        bool (*attach)(const char *name, const char *lxcpath, pid_t pid);
        bool (*mount_cgroup)(void *hdata, const char *root, int type);
        int (*nrtasks)(void *hdata);
@@ -60,12 +60,16 @@ extern bool cgroup_init(struct lxc_handler *handler);
 extern bool cgroup_create(struct lxc_handler *handler);
 extern bool cgroup_setup_limits(struct lxc_handler *handler, bool with_devices);
 extern bool cgroup_chown(struct lxc_handler *handler);
-extern bool cgroup_parse_existing_cgroups(struct lxc_handler *handler);
 extern bool cgroup_enter(struct lxc_handler *handler);
 extern void cgroup_cleanup(struct lxc_handler *handler);
 extern bool cgroup_create_legacy(struct lxc_handler *handler);
 extern int cgroup_nrtasks(struct lxc_handler *handler);
 extern const char *cgroup_get_cgroup(struct lxc_handler *handler, const char *subsystem);
+
+/*
+ * Currently, this call  only makes sense for privileged containers.
+ */
+extern const char *cgroup_canonical_path(struct lxc_handler *handler);
 extern bool cgroup_unfreeze(struct lxc_handler *handler);
 extern void cgroup_disconnect(void);
 
index 4b31f5c37b4496fae15fd70365dcc337c7358c45..4c3d4d5849b62043fcd3bec49fee1a3d2eb440ea 100644 (file)
@@ -3485,6 +3485,7 @@ struct criu_opts {
 
        /* restore: the file to write the init process' pid into */
        char *pidfile;
+       const char *cgroup_path;
 };
 
 /*
@@ -3533,8 +3534,9 @@ static void exec_criu(struct criu_opts *opts)
                if (!opts->stop)
                        static_args++;
        } else if (strcmp(opts->action, "restore") == 0) {
-               /* --root $(lxc_mount_point) --restore-detached --restore-sibling --pidfile $foo */
-               static_args += 6;
+               /* --root $(lxc_mount_point) --restore-detached
+                * --restore-sibling --pidfile $foo --cgroup-root $foo */
+               static_args += 8;
        } else {
                return;
        }
@@ -3607,6 +3609,8 @@ static void exec_criu(struct criu_opts *opts)
                DECLARE_ARG("--restore-sibling");
                DECLARE_ARG("--pidfile");
                DECLARE_ARG(opts->pidfile);
+               DECLARE_ARG("--cgroup-root");
+               DECLARE_ARG(opts->cgroup_path);
 
                lxc_list_for_each(it, &opts->c->lxc_conf->network) {
                        char eth[128], veth[128], buf[257];
@@ -3832,6 +3836,11 @@ static bool lxcapi_restore(struct lxc_container *c, char *directory, bool verbos
                goto out_fini_handler;
        }
 
+       if (!cgroup_create(handler)) {
+               ERROR("failed creating groups");
+               goto out_fini_handler;
+       }
+
        pid = fork();
        if (pid < 0)
                goto out_fini_handler;
@@ -3865,6 +3874,7 @@ static bool lxcapi_restore(struct lxc_container *c, char *directory, bool verbos
                os.c = c;
                os.pidfile = pidfile;
                os.verbose = verbose;
+               os.cgroup_path = cgroup_canonical_path(handler);
 
                /* exec_criu() returning is an error */
                exec_criu(&os);
@@ -3901,11 +3911,6 @@ static bool lxcapi_restore(struct lxc_container *c, char *directory, bool verbos
                                        goto out_fini_handler;
                                }
 
-                               if (!cgroup_parse_existing_cgroups(handler)) {
-                                       ERROR("failed creating cgroups");
-                                       goto out_fini_handler;
-                               }
-
                                if (container_mem_lock(c))
                                        goto out_fini_handler;