]> git.proxmox.com Git - mirror_lxc.git/commitdiff
c/r: tell CRIU about all external mounts in the config
authorTycho Andersen <tycho.andersen@canonical.com>
Thu, 26 Mar 2015 21:36:53 +0000 (15:36 -0600)
committerStéphane Graber <stgraber@ubuntu.com>
Mon, 6 Apr 2015 16:52:09 +0000 (12:52 -0400)
Signed-off-by: Tycho Andersen <tycho.andersen@canonical.com>
Acked-by: Stéphane Graber <stgraber@ubuntu.com>
src/lxc/conf.c
src/lxc/conf.h
src/lxc/list.h
src/lxc/lxccontainer.c

index 4e31a6d3c0d3160798971d7def03dacf6a6e8962..f1e89d80ab1da9cf6b4ed78abb97be591145557d 100644 (file)
@@ -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);
 
index ae475edfd4dbf9b769e33a10d473e66d51db5f42..0c0475e029b56dd0946ca9f38b72e7c8051e268a 100644 (file)
@@ -25,6 +25,7 @@
 
 #include "config.h"
 
+#include <stdio.h>
 #include <netinet/in.h>
 #include <net/if.h>
 #include <sys/param.h>
@@ -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
index 0882da05ff68f626805a7cb6f78f5a9f115fd837..f16af54f6052d2c21bfea0e9aa671dce96305787 100644 (file)
@@ -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
index 4762b1354e3b76b8776487e4bb6303c47e95c18f..ee664f7e48a7987a899ba92bd310915c33c9f562 100644 (file)
@@ -35,6 +35,8 @@
 #include <libgen.h>
 #include <stdint.h>
 #include <grp.h>
+#include <stdio.h>
+#include <mntent.h>
 #include <sys/syscall.h>
 
 #include <lxc/lxccontainer.h>
@@ -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);