From 9fc7f8c015b627a978784779ed94b9ac99a9800b Mon Sep 17 00:00:00 2001 From: Tycho Andersen Date: Thu, 26 Mar 2015 15:36:53 -0600 Subject: [PATCH] c/r: tell CRIU about all external mounts in the config MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Signed-off-by: Tycho Andersen Acked-by: Stéphane Graber --- src/lxc/conf.c | 18 ++++++++--- src/lxc/conf.h | 2 ++ src/lxc/list.h | 11 +++++++ src/lxc/lxccontainer.c | 73 ++++++++++++++++++++++++++++++++++++------ 4 files changed, 91 insertions(+), 13 deletions(-) diff --git a/src/lxc/conf.c b/src/lxc/conf.c index 4e31a6d3c..f1e89d80a 100644 --- a/src/lxc/conf.c +++ b/src/lxc/conf.c @@ -2051,18 +2051,16 @@ static int setup_mount(const struct lxc_rootfs *rootfs, const char *fstab, return ret; } -static int setup_mount_entries(const struct lxc_rootfs *rootfs, struct lxc_list *mount, - const char *lxc_name) +FILE *write_mount_file(struct lxc_list *mount) { FILE *file; struct lxc_list *iterator; char *mount_entry; - int ret; file = tmpfile(); if (!file) { ERROR("tmpfile error: %m"); - return -1; + return NULL; } lxc_list_for_each(iterator, mount) { @@ -2071,6 +2069,18 @@ static int setup_mount_entries(const struct lxc_rootfs *rootfs, struct lxc_list } rewind(file); + return file; +} + +static int setup_mount_entries(const struct lxc_rootfs *rootfs, struct lxc_list *mount, + const char *lxc_name) +{ + FILE *file; + int ret; + + file = write_mount_file(mount); + if (!file) + return -1; ret = mount_file_entries(rootfs, file, lxc_name); diff --git a/src/lxc/conf.h b/src/lxc/conf.h index ae475edfd..0c0475e02 100644 --- a/src/lxc/conf.h +++ b/src/lxc/conf.h @@ -25,6 +25,7 @@ #include "config.h" +#include #include #include #include @@ -429,4 +430,5 @@ extern int parse_mntopts(const char *mntopts, unsigned long *mntflags, extern void tmp_proc_unmount(struct lxc_conf *lxc_conf); void remount_all_slave(void); extern void suggest_default_idmap(void); +FILE *write_mount_file(struct lxc_list *mount); #endif diff --git a/src/lxc/list.h b/src/lxc/list.h index 0882da05f..f16af54f6 100644 --- a/src/lxc/list.h +++ b/src/lxc/list.h @@ -99,4 +99,15 @@ static inline void lxc_list_del(struct lxc_list *list) prev->next = next; } +static inline int lxc_list_len(struct lxc_list *list) +{ + int i = 0; + struct lxc_list *iter; + lxc_list_for_each(iter, list) { + i++; + } + + return i; +} + #endif diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c index 4762b1354..ee664f7e4 100644 --- a/src/lxc/lxccontainer.c +++ b/src/lxc/lxccontainer.c @@ -35,6 +35,8 @@ #include #include #include +#include +#include #include #include @@ -3701,11 +3703,15 @@ struct criu_opts { static void exec_criu(struct criu_opts *opts) { - char **argv, log[PATH_MAX], buf[257]; + char **argv, log[PATH_MAX]; int static_args = 14, argc = 0, i, ret; int netnr = 0; struct lxc_list *it; + struct mntent mntent; + char buf[4096]; + FILE *mnts = NULL; + /* The command line always looks like: * criu $(action) --tcp-established --file-locks --link-remap --force-irmap \ * --manage-cgroups action-script foo.sh -D $(directory) \ @@ -3780,6 +3786,27 @@ static void exec_criu(struct criu_opts *opts) if (opts->verbose) DECLARE_ARG("-vvvvvv"); + /* + * Note: this macro is not intended to be called unless argc is equal + * to the length of the array; there is nothing that keeps track of the + * length of the array besides the location in the code that this is + * called. (Yes this is bad, and we should fix it.) + */ +#define RESIZE_ARGS(additional) \ + do { \ + void *m; \ + if (additional < 0) { \ + ERROR("resizing by negative amount"); \ + goto err; \ + } else if (additional == 0) \ + continue; \ + \ + m = realloc(argv, (argc + additional + 1) * sizeof(*argv)); \ + if (!m) \ + goto err; \ + argv = m; \ + } while (0) + if (strcmp(opts->action, "dump") == 0) { char pid[32]; @@ -3811,9 +3838,10 @@ static void exec_criu(struct criu_opts *opts) DECLARE_ARG("--cgroup-root"); DECLARE_ARG(opts->cgroup_path); + RESIZE_ARGS(lxc_list_len(&opts->c->lxc_conf->network) * 2); + lxc_list_for_each(it, &opts->c->lxc_conf->network) { char eth[128], *veth; - void *m; struct lxc_netdev *n = it->elem; if (n->name) { @@ -3829,18 +3857,42 @@ static void exec_criu(struct criu_opts *opts) if (ret < 0 || ret >= sizeof(buf)) goto err; - /* final NULL and --veth-pair eth0=vethASDF */ - m = realloc(argv, (argc + 1 + 2) * sizeof(*argv)); - if (!m) - goto err; - argv = m; - DECLARE_ARG("--veth-pair"); DECLARE_ARG(buf); - argv[argc] = NULL; + } + } + // CRIU wants to know about any external bind mounts the + // container has. + mnts = write_mount_file(&opts->c->lxc_conf->mount_list); + if (!mnts) + goto err; + + RESIZE_ARGS(lxc_list_len(&opts->c->lxc_conf->mount_list) * 2); + + while (getmntent_r(mnts, &mntent, buf, sizeof(buf))) { + char arg[2048], *key, *val; + int ret; + + if (strcmp(opts->action, "dump") == 0) { + key = mntent.mnt_fsname; + val = mntent.mnt_dir; + } else { + key = mntent.mnt_dir; + val = mntent.mnt_fsname; } + + ret = snprintf(arg, sizeof(arg), "%s:%s", key, val); + if (ret < 0 || ret >= sizeof(arg)) { + goto err; + } + + DECLARE_ARG("--ext-mount-map"); + DECLARE_ARG(arg); } + fclose(mnts); + + argv[argc] = NULL; netnr = 0; lxc_list_for_each(it, &opts->c->lxc_conf->network) { @@ -3876,8 +3928,11 @@ static void exec_criu(struct criu_opts *opts) } #undef DECLARE_ARG +#undef RESIZE_ARGS execv(argv[0], argv); err: + if (mnts) + fclose(mnts); for (i = 0; argv[i]; i++) free(argv[i]); free(argv); -- 2.47.2