[lxc-devel] [lxc/master] lxc-checkpoint: enable dirty memory tracking in criu

adrianreber on Github lxc-bot at linuxcontainers.org
Mon Nov 14 16:41:16 UTC 2016


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 1761 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20161114/015b99bb/attachment.bin>
-------------- next part --------------
From 13df50e4941f7db39313a0d7506855e121ee9224 Mon Sep 17 00:00:00 2001
From: Adrian Reber <areber at redhat.com>
Date: Mon, 14 Nov 2016 14:44:04 +0000
Subject: [PATCH] lxc-checkpoint: enable dirty memory tracking in criu

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 at redhat.com>
---
 src/lxc/criu.c                 |  4 ++++
 src/lxc/tools/lxc_checkpoint.c | 43 ++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 45 insertions(+), 2 deletions(-)

diff --git a/src/lxc/criu.c b/src/lxc/criu.c
index 5456cc1..3a9925a 100644
--- a/src/lxc/criu.c
+++ b/src/lxc/criu.c
@@ -398,6 +398,10 @@ static void exec_criu(struct criu_opts *opts)
 		if (opts->user->predump_dir) {
 			DECLARE_ARG("--prev-images-dir");
 			DECLARE_ARG(opts->user->predump_dir);
+			/* Using --prev-images-dir works in older CRIU versions (2.3).
+			 * For newer CRIU versions like 2.8 --track-mem needs to
+			 * be added to the command-line. */
+			DECLARE_ARG("--track-mem");
 		}
 
 		if (opts->user->pageserver_address && opts->user->pageserver_port) {
diff --git a/src/lxc/tools/lxc_checkpoint.c b/src/lxc/tools/lxc_checkpoint.c
index 462aba3..eeddf59 100644
--- a/src/lxc/tools/lxc_checkpoint.c
+++ b/src/lxc/tools/lxc_checkpoint.c
@@ -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;
 	}


More information about the lxc-devel mailing list