[lxc-devel] [lxc/master] Cgroup root on dump
tych0 on Github
lxc-bot at linuxcontainers.org
Fri Sep 16 21:20:48 UTC 2016
A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 490 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20160916/7c4edec7/attachment.bin>
-------------- next part --------------
From 5f178bc983a7050205b0ba374163646e9e378cf6 Mon Sep 17 00:00:00 2001
From: Tycho Andersen <tycho.andersen at canonical.com>
Date: Mon, 12 Sep 2016 18:04:18 +0000
Subject: [PATCH 1/6] c/r: fix typo in comment
Signed-off-by: Tycho Andersen <tycho.andersen at canonical.com>
---
src/lxc/criu.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/lxc/criu.c b/src/lxc/criu.c
index 71c9b9c..2799102 100644
--- a/src/lxc/criu.c
+++ b/src/lxc/criu.c
@@ -140,7 +140,7 @@ static void exec_criu(struct criu_opts *opts)
/* The command line always looks like:
* criu $(action) --tcp-established --file-locks --link-remap \
- * --manage-cgroups=full action-script foo.sh -D $(directory) \
+ * --manage-cgroups=full --action-script foo.sh -D $(directory) \
* -o $(directory)/$(action).log --ext-mount-map auto
* --enable-external-sharing --enable-external-masters
* --enable-fs hugetlbfs --enable-fs tracefs --ext-mount-map console:/dev/pts/n
From 36662416441b051bf9d3bb0e1b5d08a61b3a6420 Mon Sep 17 00:00:00 2001
From: Tycho Andersen <tycho.andersen at canonical.com>
Date: Wed, 14 Sep 2016 14:38:46 +0000
Subject: [PATCH 2/6] cgroup: add new functions for interacting with hierachies
N.B. that these are only implemented in cgfsng, but,
15:28:28 tych0 | do we still use cgfs anywhere? or the cgm backend?
15:29:19 stgraber | not anywhere we care about
...I think that's okay.
Signed-off-by: Tycho Andersen <tycho.andersen at canonical.com>
---
src/lxc/cgroups/cgfs.c | 14 ++++++++++++++
src/lxc/cgroups/cgfsng.c | 27 +++++++++++++++++++++++++++
src/lxc/cgroups/cgmanager.c | 14 ++++++++++++++
src/lxc/cgroups/cgroup.c | 16 ++++++++++++++++
src/lxc/cgroups/cgroup.h | 4 ++++
5 files changed, 75 insertions(+)
diff --git a/src/lxc/cgroups/cgfs.c b/src/lxc/cgroups/cgfs.c
index 2d0de0c..80a336d 100644
--- a/src/lxc/cgroups/cgfs.c
+++ b/src/lxc/cgroups/cgfs.c
@@ -2434,6 +2434,18 @@ static bool cgfs_escape(void *hdata)
return ret;
}
+static int cgfs_num_hierarchies(void)
+{
+ /* not implemented */
+ return -1;
+}
+
+static bool cgfs_get_hierarchies(int i, char ***out)
+{
+ /* not implemented */
+ return false;
+}
+
static bool cgfs_unfreeze(void *hdata)
{
struct cgfs_data *d = hdata;
@@ -2627,6 +2639,8 @@ static struct cgroup_ops cgfs_ops = {
.get_cgroup = cgfs_get_cgroup,
.canonical_path = cgfs_canonical_path,
.escape = cgfs_escape,
+ .num_hierarchies = cgfs_num_hierarchies,
+ .get_hierarchies = cgfs_get_hierarchies,
.get = lxc_cgroupfs_get,
.set = lxc_cgroupfs_set,
.unfreeze = cgfs_unfreeze,
diff --git a/src/lxc/cgroups/cgfsng.c b/src/lxc/cgroups/cgfsng.c
index 95f29ca..5b61554 100644
--- a/src/lxc/cgroups/cgfsng.c
+++ b/src/lxc/cgroups/cgfsng.c
@@ -1457,6 +1457,31 @@ static bool cgfsng_escape()
return ret;
}
+static int cgfsng_num_hierarchies(void)
+{
+ int i;
+
+ for (i = 0; hierarchies[i]; i++)
+ ;
+
+ return i;
+}
+
+static bool cgfsng_get_hierarchies(int n, char ***out)
+{
+ int i;
+
+ /* sanity check n */
+ for (i = 0; i < n; i++) {
+ if (!hierarchies[i])
+ return false;
+ }
+
+ *out = hierarchies[i]->controllers;
+
+ return true;
+}
+
#define THAWED "THAWED"
#define THAWED_LEN (strlen(THAWED))
@@ -1674,6 +1699,8 @@ static struct cgroup_ops cgfsng_ops = {
.enter = cgfsng_enter,
.canonical_path = cgfsng_canonical_path,
.escape = cgfsng_escape,
+ .num_hierarchies = cgfsng_num_hierarchies,
+ .get_hierarchies = cgfsng_get_hierarchies,
.get_cgroup = cgfsng_get_cgroup,
.get = cgfsng_get,
.set = cgfsng_set,
diff --git a/src/lxc/cgroups/cgmanager.c b/src/lxc/cgroups/cgmanager.c
index 4da891d..f14eb17 100644
--- a/src/lxc/cgroups/cgmanager.c
+++ b/src/lxc/cgroups/cgmanager.c
@@ -337,6 +337,18 @@ static bool cgm_escape(void *hdata)
return ret;
}
+static int cgm_num_hierarchies(void)
+{
+ /* not implemented */
+ return -1;
+}
+
+static bool cgm_get_hierarchies(int i, char ***out)
+{
+ /* not implemented */
+ return false;
+}
+
struct chown_data {
const char *cgroup_path;
uid_t origuid;
@@ -1657,6 +1669,8 @@ static struct cgroup_ops cgmanager_ops = {
.get_cgroup = cgm_get_cgroup,
.canonical_path = cgm_canonical_path,
.escape = cgm_escape,
+ .num_hierarchies = cgm_num_hierarchies,
+ .get_hierarchies = cgm_get_hierarchies,
.get = cgm_get,
.set = cgm_set,
.unfreeze = cgm_unfreeze,
diff --git a/src/lxc/cgroups/cgroup.c b/src/lxc/cgroups/cgroup.c
index 91ef359..48cd403 100644
--- a/src/lxc/cgroups/cgroup.c
+++ b/src/lxc/cgroups/cgroup.c
@@ -132,6 +132,22 @@ const char *cgroup_canonical_path(struct lxc_handler *handler)
return NULL;
}
+int cgroup_num_hierarchies(void)
+{
+ if (!ops)
+ return -1;
+
+ return ops->num_hierarchies();
+}
+
+bool cgroup_get_hierarchies(int n, char ***out)
+{
+ if (!ops)
+ return false;
+
+ return ops->get_hierarchies(n, out);
+}
+
bool cgroup_unfreeze(struct lxc_handler *handler)
{
if (ops)
diff --git a/src/lxc/cgroups/cgroup.h b/src/lxc/cgroups/cgroup.h
index e56a115..f65cbfe 100644
--- a/src/lxc/cgroups/cgroup.h
+++ b/src/lxc/cgroups/cgroup.h
@@ -49,6 +49,8 @@ struct cgroup_ops {
const char *(*get_cgroup)(void *hdata, const char *subsystem);
const char *(*canonical_path)(void *hdata);
bool (*escape)();
+ int (*num_hierarchies)();
+ bool (*get_hierarchies)(int n, char ***out);
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);
@@ -74,6 +76,8 @@ 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);
extern bool cgroup_escape();
+extern int cgroup_num_hierarchies();
+extern bool cgroup_get_hierarchies(int i, char ***out);
/*
* Currently, this call only makes sense for privileged containers.
From aeb3682ff631e6afaa9c0b5d8a32654e8ebd2771 Mon Sep 17 00:00:00 2001
From: Tycho Andersen <tycho.andersen at canonical.com>
Date: Wed, 14 Sep 2016 14:46:47 +0000
Subject: [PATCH 3/6] utils: add lxc_deslashify
Signed-off-by: Tycho Andersen <tycho.andersen at canonical.com>
---
src/lxc/utils.c | 18 ++++++++++++++++++
src/lxc/utils.h | 2 ++
2 files changed, 20 insertions(+)
diff --git a/src/lxc/utils.c b/src/lxc/utils.c
index 27362da..9a6ef4b 100644
--- a/src/lxc/utils.c
+++ b/src/lxc/utils.c
@@ -716,6 +716,24 @@ char **lxc_normalize_path(const char *path)
return components;
}
+bool lxc_deslashify(char *path)
+{
+ char **parts = NULL, *path2;
+
+ parts = lxc_normalize_path(path);
+ if (!parts)
+ return false;
+
+ path2 = lxc_string_join("/", (const char **) parts, *path == '/');
+ lxc_free_array((void **) parts, free);
+ if (!path2)
+ return false;
+
+ strncpy(path, path2, strlen(path));
+ free(path2);
+ return true;
+}
+
char *lxc_append_paths(const char *first, const char *second)
{
size_t len = strlen(first) + strlen(second) + 1;
diff --git a/src/lxc/utils.h b/src/lxc/utils.h
index 98b4e13..c2eef50 100644
--- a/src/lxc/utils.h
+++ b/src/lxc/utils.h
@@ -248,6 +248,8 @@ extern char *lxc_string_join(const char *sep, const char **parts, bool use_as_pr
* foo//bar -> { foo, bar, NULL }
*/
extern char **lxc_normalize_path(const char *path);
+/* remove multiple slashes from the path, e.g. ///foo//bar -> /foo/bar */
+extern bool lxc_deslashify(char *path);
extern char *lxc_append_paths(const char *first, const char *second);
/* Note: the following two functions use strtok(), so they will never
* consider an empty element, even if two delimiters are next to
From 0ab5703fcff8aafc3512c8b3cb446780b1c6974c Mon Sep 17 00:00:00 2001
From: Tycho Andersen <tycho.andersen at canonical.com>
Date: Wed, 14 Sep 2016 14:47:38 +0000
Subject: [PATCH 4/6] c/r: pass --cgroup-roots on checkpoint
CRIU has added support for passing --cgroup-root on dump, which we should
use (see the criu commit 07d259f365f224b32914de26ea0fd59fc6db0001 for
details). Note that we don't have to do any version checking or anything,
because CRIU just ignored --cgroup-root on checkpoint before, so passing it
is safe, and will result in correct behavior when a sufficient version of
CRIU is present.
Signed-off-by: Tycho Andersen <tycho.andersen at canonical.com>
---
src/lxc/criu.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++++-----
1 file changed, 73 insertions(+), 6 deletions(-)
diff --git a/src/lxc/criu.c b/src/lxc/criu.c
index 2799102..0702ad2 100644
--- a/src/lxc/criu.c
+++ b/src/lxc/criu.c
@@ -69,7 +69,7 @@ struct criu_opts {
char tty_id[32]; /* the criu tty id for /dev/console, i.e. "tty[${rdev}:${dev}]" */
/* restore: the file to write the init process' pid into */
- const char *cgroup_path;
+ struct lxc_handler *handler;
int console_fd;
/* The path that is bind mounted from /dev/console, if any. We don't
* want to use `--ext-mount-map auto`'s result here because the pts
@@ -175,10 +175,10 @@ static void exec_criu(struct criu_opts *opts)
static_args += 2;
} else if (strcmp(opts->action, "restore") == 0) {
/* --root $(lxc_mount_point) --restore-detached
- * --restore-sibling --cgroup-root $foo
+ * --restore-sibling
* --lsm-profile apparmor:whatever
*/
- static_args += 8;
+ static_args += 6;
tty_info[0] = 0;
if (load_tty_major_minor(opts->user->directory, tty_info, sizeof(tty_info)))
@@ -191,6 +191,8 @@ static void exec_criu(struct criu_opts *opts)
return;
}
+ static_args += 2 * cgroup_num_hierarchies();
+
if (opts->user->verbose)
static_args++;
@@ -244,6 +246,66 @@ static void exec_criu(struct criu_opts *opts)
DECLARE_ARG("-o");
DECLARE_ARG(log);
+ for (i = 0; i < cgroup_num_hierarchies(); i++) {
+ char **controllers = NULL, *fullname;
+ char *path;
+
+ if (!cgroup_get_hierarchies(i, &controllers)) {
+ ERROR("failed to get hierarchy %d", i);
+ goto err;
+ }
+
+ /* if we are in a dump, we have to ask the monitor process what
+ * the right cgroup is. if this is a restore, we can just use
+ * the handler the restore task created.
+ */
+ if (!strcmp(opts->action, "dump") || !strcmp(opts->action, "pre-dump")) {
+ path = lxc_cmd_get_cgroup_path(opts->c->name, opts->c->config_path, controllers[0]);
+ if (!path) {
+ ERROR("failed to get cgroup path for %s", controllers[0]);
+ goto err;
+ }
+ } else {
+ const char *p;
+
+ p = cgroup_get_cgroup(opts->handler, controllers[0]);
+ if (!p) {
+ ERROR("failed to get cgroup path for %s", controllers[0]);
+ goto err;
+ }
+
+ path = strdup(p);
+ if (!path) {
+ ERROR("strdup failed");
+ goto err;
+ }
+ }
+
+ if (!lxc_deslashify(path)) {
+ ERROR("failed to deslashify %s", path);
+ free(path);
+ goto err;
+ }
+
+ fullname = lxc_string_join(",", (const char **) controllers, false);
+ if (!fullname) {
+ ERROR("failed to join controllers");
+ free(path);
+ goto err;
+ }
+
+ ret = sprintf(buf, "%s:%s", fullname, path);
+ free(path);
+ free(fullname);
+ if (ret < 0 || ret >= sizeof(buf)) {
+ ERROR("sprintf of cgroup root arg failed");
+ goto err;
+ }
+
+ DECLARE_ARG("--cgroup-root");
+ DECLARE_ARG(buf);
+ }
+
if (opts->user->verbose)
DECLARE_ARG("-vvvvvv");
@@ -329,8 +391,6 @@ static void exec_criu(struct criu_opts *opts)
DECLARE_ARG(opts->c->lxc_conf->rootfs.mount);
DECLARE_ARG("--restore-detached");
DECLARE_ARG("--restore-sibling");
- DECLARE_ARG("--cgroup-root");
- DECLARE_ARG(opts->cgroup_path);
if (tty_info[0]) {
if (opts->console_fd < 0) {
@@ -682,9 +742,9 @@ static void do_restore(struct lxc_container *c, int status_pipe, struct migrate_
os.action = "restore";
os.user = opts;
os.c = c;
- os.cgroup_path = cgroup_canonical_path(handler);
os.console_fd = c->lxc_conf->console.slave;
os.criu_version = criu_version;
+ os.handler = handler;
if (os.console_fd >= 0) {
/* Twiddle the FD_CLOEXEC bit. We want to pass this FD to criu
@@ -891,6 +951,13 @@ static bool do_dump(struct lxc_container *c, char *mode, struct migrate_opts *op
if (pid == 0) {
struct criu_opts os;
+ struct lxc_handler h;
+
+ h.name = c->name;
+ if (!cgroup_init(&h)) {
+ ERROR("failed to cgroup_init()");
+ exit(1);
+ }
os.action = mode;
os.user = opts;
From 6df334d1588dfcf99a405fb700971ac27cac438c Mon Sep 17 00:00:00 2001
From: Tycho Andersen <tycho.andersen at canonical.com>
Date: Wed, 14 Sep 2016 14:53:21 +0000
Subject: [PATCH 5/6] cgroup: get rid of weird hack in cgfsng_escape
We initialized cgfsng in a strange way inside of its implementation of
escape so we could use it during checkpoint. Instead, the previous patch
does a hacky initialization in criu.c, and we can get rid of the hacks
elsewhere :)
Signed-off-by: Tycho Andersen <tycho.andersen at canonical.com>
---
src/lxc/cgroups/cgfsng.c | 15 ++-------------
1 file changed, 2 insertions(+), 13 deletions(-)
diff --git a/src/lxc/cgroups/cgfsng.c b/src/lxc/cgroups/cgfsng.c
index 5b61554..0777bf3 100644
--- a/src/lxc/cgroups/cgfsng.c
+++ b/src/lxc/cgroups/cgfsng.c
@@ -1426,19 +1426,11 @@ static int cgfsng_nrtasks(void *hdata) {
/* Only root needs to escape to the cgroup of its init */
static bool cgfsng_escape()
{
- struct cgfsng_handler_data *d;
int i;
- bool ret = false;
if (geteuid())
return true;
- d = cgfsng_init("criu-temp-cgfsng");
- if (!d) {
- ERROR("cgfsng_init failed");
- return false;
- }
-
for (i = 0; hierarchies[i]; i++) {
char *fullpath = must_make_path(hierarchies[i]->mountpoint,
hierarchies[i]->base_cgroup,
@@ -1446,15 +1438,12 @@ static bool cgfsng_escape()
if (lxc_write_to_file(fullpath, "0", 2, false) != 0) {
SYSERROR("Failed to escape to %s", fullpath);
free(fullpath);
- goto out;
+ return false;
}
free(fullpath);
}
- ret = true;
-out:
- free_handler_data(d);
- return ret;
+ return true;
}
static int cgfsng_num_hierarchies(void)
From a0c91fccd9a1ae9c68a10880d4660d63a3b411e8 Mon Sep 17 00:00:00 2001
From: Tycho Andersen <tycho.andersen at canonical.com>
Date: Wed, 14 Sep 2016 14:58:38 +0000
Subject: [PATCH 6/6] cgroup: drop cgroup_canonical_path
This is almost never the right thing to use, and we don't use it any more
anyway.
Signed-off-by: Tycho Andersen <tycho.andersen at canonical.com>
---
src/lxc/cgroups/cgfs.c | 23 -----------------------
src/lxc/cgroups/cgfsng.c | 8 --------
src/lxc/cgroups/cgmanager.c | 10 ----------
src/lxc/cgroups/cgroup.c | 13 -------------
src/lxc/cgroups/cgroup.h | 6 ------
5 files changed, 60 deletions(-)
diff --git a/src/lxc/cgroups/cgfs.c b/src/lxc/cgroups/cgfs.c
index 80a336d..c5ba765 100644
--- a/src/lxc/cgroups/cgfs.c
+++ b/src/lxc/cgroups/cgfs.c
@@ -2363,28 +2363,6 @@ 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_escape(void *hdata)
{
struct cgroup_meta_data *md;
@@ -2637,7 +2615,6 @@ static struct cgroup_ops cgfs_ops = {
.enter = cgfs_enter,
.create_legacy = cgfs_create_legacy,
.get_cgroup = cgfs_get_cgroup,
- .canonical_path = cgfs_canonical_path,
.escape = cgfs_escape,
.num_hierarchies = cgfs_num_hierarchies,
.get_hierarchies = cgfs_get_hierarchies,
diff --git a/src/lxc/cgroups/cgfsng.c b/src/lxc/cgroups/cgfsng.c
index 0777bf3..ec94099 100644
--- a/src/lxc/cgroups/cgfsng.c
+++ b/src/lxc/cgroups/cgfsng.c
@@ -1087,13 +1087,6 @@ static inline bool cgfsng_create(void *hdata)
return false;
}
-static const char *cgfsng_canonical_path(void *hdata)
-{
- struct cgfsng_handler_data *d = hdata;
-
- return d->container_cgroup;
-}
-
static bool cgfsng_enter(void *hdata, pid_t pid)
{
char pidstr[25];
@@ -1686,7 +1679,6 @@ static struct cgroup_ops cgfsng_ops = {
.destroy = cgfsng_destroy,
.create = cgfsng_create,
.enter = cgfsng_enter,
- .canonical_path = cgfsng_canonical_path,
.escape = cgfsng_escape,
.num_hierarchies = cgfsng_num_hierarchies,
.get_hierarchies = cgfsng_get_hierarchies,
diff --git a/src/lxc/cgroups/cgmanager.c b/src/lxc/cgroups/cgmanager.c
index f14eb17..f2756b0 100644
--- a/src/lxc/cgroups/cgmanager.c
+++ b/src/lxc/cgroups/cgmanager.c
@@ -746,15 +746,6 @@ 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;
@@ -1667,7 +1658,6 @@ static struct cgroup_ops cgmanager_ops = {
.enter = cgm_enter,
.create_legacy = NULL,
.get_cgroup = cgm_get_cgroup,
- .canonical_path = cgm_canonical_path,
.escape = cgm_escape,
.num_hierarchies = cgm_num_hierarchies,
.get_hierarchies = cgm_get_hierarchies,
diff --git a/src/lxc/cgroups/cgroup.c b/src/lxc/cgroups/cgroup.c
index 48cd403..78472d4 100644
--- a/src/lxc/cgroups/cgroup.c
+++ b/src/lxc/cgroups/cgroup.c
@@ -119,19 +119,6 @@ bool cgroup_escape(struct lxc_handler *handler)
return false;
}
-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;
-}
-
int cgroup_num_hierarchies(void)
{
if (!ops)
diff --git a/src/lxc/cgroups/cgroup.h b/src/lxc/cgroups/cgroup.h
index f65cbfe..11b251e 100644
--- a/src/lxc/cgroups/cgroup.h
+++ b/src/lxc/cgroups/cgroup.h
@@ -47,7 +47,6 @@ 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);
bool (*escape)();
int (*num_hierarchies)();
bool (*get_hierarchies)(int n, char ***out);
@@ -78,11 +77,6 @@ extern const char *cgroup_get_cgroup(struct lxc_handler *handler, const char *su
extern bool cgroup_escape();
extern int cgroup_num_hierarchies();
extern bool cgroup_get_hierarchies(int i, char ***out);
-
-/*
- * 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);
extern cgroup_driver_t cgroup_driver(void);
More information about the lxc-devel
mailing list