[lxc-devel] [PATCH 2/2] restore: create cgroups for criu

Tycho Andersen tycho.andersen at canonical.com
Tue Oct 7 19:33:08 UTC 2014


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 at canonical.com>
---
 src/lxc/cgfs.c         | 36 +++++++++++++++++++++++-------------
 src/lxc/cgmanager.c    | 11 ++++++++++-
 src/lxc/cgroup.c       | 25 ++++++++++++++++---------
 src/lxc/cgroup.h       |  8 ++++++--
 src/lxc/lxccontainer.c | 19 ++++++++++++-------
 5 files changed, 67 insertions(+), 32 deletions(-)

diff --git a/src/lxc/cgfs.c b/src/lxc/cgfs.c
index 0f181c6..9fa47cd 100644
--- a/src/lxc/cgfs.c
+++ b/src/lxc/cgfs.c
@@ -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,
 };
diff --git a/src/lxc/cgmanager.c b/src/lxc/cgmanager.c
index 4038c41..140f4cd 100644
--- a/src/lxc/cgmanager.c
+++ b/src/lxc/cgmanager.c
@@ -679,6 +679,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;
@@ -1307,13 +1316,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,
diff --git a/src/lxc/cgroup.c b/src/lxc/cgroup.c
index 56d0e56..a413832 100644
--- a/src/lxc/cgroup.c
+++ b/src/lxc/cgroup.c
@@ -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) {
diff --git a/src/lxc/cgroup.h b/src/lxc/cgroup.h
index 0c2e566..281f404 100644
--- a/src/lxc/cgroup.h
+++ b/src/lxc/cgroup.h
@@ -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);
 
diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c
index 7e3a6b2..74b1b12 100644
--- a/src/lxc/lxccontainer.c
+++ b/src/lxc/lxccontainer.c
@@ -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;
 	}
@@ -3603,6 +3605,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];
@@ -3828,6 +3832,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;
@@ -3861,6 +3870,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);
@@ -3897,11 +3907,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 groups");
-					goto out_fini_handler;
-				}
-
 				if (container_mem_lock(c))
 					goto out_fini_handler;
 
-- 
1.9.1



More information about the lxc-devel mailing list