]> git.ipfire.org Git - thirdparty/lxc.git/commitdiff
lxc-checkpoint: enable dirty memory tracking in criu 1299/head
authorAdrian Reber <areber@redhat.com>
Mon, 14 Nov 2016 14:44:04 +0000 (14:44 +0000)
committerAdrian Reber <areber@redhat.com>
Tue, 15 Nov 2016 14:10:03 +0000 (14:10 +0000)
CRIU supports dirty memory tracking to take incremental checkpoints.
Incremental checkpoints are one way of reducing downtime during
migration. The first checkpoint dumps all the memory pages and the
second (and third, and fourth, ...) only dumps pages which have changed.

Most of the necessary code has already been implemented. This just adds
the existing functionality to lxc-checkpoint:

  -p, --pre-dump            Only pre-dump the memory of the container.
                            Container keeps on running and following
                            checkpoints will only dump the changes.
  --predump-dir=DIR         path to images from previous dump (relative to -D)

The following is an example from a container running CentOS 7 with psql
and tomcat:

 # lxc-checkpoint -n c7 -D /tmp/cp -p
Container keeps on running
 # du -h /tmp/cp
 229M /tmp/cp
Sync initial checkpoint to destination
 # rsync -a /tmp/cp host2:/tmp/
Sync file-system
 # rsync -a /var/lib/lxc/c7 host2:/var/lib/lxc/
Final dump; container is stopped
 # lxc-checkpoint -n c7 -D /tmp/cp --predump-dir=../cp -s
 # du -h /tmp/cp2
 90M /tmp/cp2

After transferring the second (incremental checkpoint) and the changes
to the container's file system the container can be restored on the
second host by pointing lxc-checkpoint to the second checkpoint
directory:

 # lxc-checkpoint -n c7 -D /tmp/cp2 -r

Signed-off-by: Adrian Reber <areber@redhat.com>
src/lxc/criu.c
src/lxc/tools/lxc_checkpoint.c

index 5456cc1e643afa50a16ef11f91d182c99cb78a98..9523af3b41f8a88a59ef3d5b71f4fbbb54b3d1d6 100644 (file)
@@ -398,6 +398,7 @@ static void exec_criu(struct criu_opts *opts)
                if (opts->user->predump_dir) {
                        DECLARE_ARG("--prev-images-dir");
                        DECLARE_ARG(opts->user->predump_dir);
+                       DECLARE_ARG("--track-mem");
                }
 
                if (opts->user->pageserver_address && opts->user->pageserver_port) {
index 462aba3ee789b61f39a6f734563000b23e8fa0af..eeddf59162184376f0e2c58a6ff959d290124cd2 100644 (file)
@@ -36,6 +36,10 @@ static bool stop = false;
 static bool verbose = false;
 static bool do_restore = false;
 static bool daemonize_set = false;
+static bool pre_dump = false;
+static char *predump_dir = NULL;
+
+#define OPT_PREDUMP_DIR OPT_USAGE+1
 
 static const struct option my_longopts[] = {
        {"checkpoint-dir", required_argument, 0, 'D'},
@@ -44,6 +48,8 @@ static const struct option my_longopts[] = {
        {"restore", no_argument, 0, 'r'},
        {"daemon", no_argument, 0, 'd'},
        {"foreground", no_argument, 0, 'F'},
+       {"pre-dump", no_argument, 0, 'p'},
+       {"predump-dir", required_argument, 0, OPT_PREDUMP_DIR},
        LXC_COMMON_OPTIONS
 };
 
@@ -63,6 +69,11 @@ static int my_checker(const struct lxc_arguments *args)
                return -1;
        }
 
+       if (pre_dump && do_restore) {
+               lxc_error(args, "-p not compatible with -r.");
+               return -1;
+       }
+
        return 0;
 }
 
@@ -91,6 +102,14 @@ static int my_parser(struct lxc_arguments *args, int c, char *arg)
                args->daemonize = 0;
                daemonize_set = true;
                break;
+       case 'p':
+               pre_dump = true;
+               break;
+       case OPT_PREDUMP_DIR:
+               predump_dir = strdup(arg);
+               if (!predump_dir)
+                       return -1;
+               break;
        }
        return 0;
 }
@@ -111,6 +130,10 @@ Options :\n\
   -v, --verbose             Enable verbose criu logs\n\
   Checkpoint options:\n\
   -s, --stop                Stop the container after checkpointing.\n\
+  -p, --pre-dump            Only pre-dump the memory of the container.\n\
+                            Container keeps on running and following\n\
+                            checkpoints will only dump the changes.\n\
+  --predump-dir=DIR         path to images from previous dump (relative to -D)\n\
   Restore options:\n\
   -d, --daemon              Daemonize the container (default)\n\
   -F, --foreground          Start with the current tty attached to /dev/console\n\
@@ -124,7 +147,9 @@ Options :\n\
 
 static bool checkpoint(struct lxc_container *c)
 {
+       struct migrate_opts opts;
        bool ret;
+       int mode;
 
        if (!c->is_running(c)) {
                fprintf(stderr, "%s not running, not checkpointing.\n", my_args.name);
@@ -132,10 +157,24 @@ static bool checkpoint(struct lxc_container *c)
                return false;
        }
 
-       ret = c->checkpoint(c, checkpoint_dir, stop, verbose);
+       memset(&opts, 0, sizeof(opts));
+
+       opts.directory = checkpoint_dir;
+       opts.stop = stop;
+       opts.verbose = verbose;
+       opts.predump_dir = predump_dir;
+
+       if (pre_dump)
+               mode = MIGRATE_PRE_DUMP;
+       else
+               mode = MIGRATE_DUMP;
+
+       ret = c->migrate(c, mode, &opts, sizeof(opts));
        lxc_container_put(c);
 
-       if (!ret) {
+       /* the migrate() API does not negate the return code like
+        * checkpoint() and restore() does. */
+       if (ret) {
                fprintf(stderr, "Checkpointing %s failed.\n", my_args.name);
                return false;
        }