[CRIU] [PATCH 7/7] test: Test and example of external bind mounts plugin

Pavel Emelyanov xemul at parallels.com
Wed Dec 25 04:55:11 PST 2013


Signed-off-by: Pavel Emelyanov <xemul at parallels.com>
---
 test/mounts/ext/Makefile    |   4 ++
 test/mounts/ext/ext-mount.c | 101 ++++++++++++++++++++++++++++++++++++++++++++
 test/mounts/ext/run.sh      |  57 +++++++++++++++++++++++++
 test/mounts/ext/run_ns.sh   |  53 +++++++++++++++++++++++
 test/mounts/ext/run_wait.sh |  20 +++++++++
 5 files changed, 235 insertions(+)
 create mode 100644 test/mounts/ext/Makefile
 create mode 100644 test/mounts/ext/ext-mount.c
 create mode 100755 test/mounts/ext/run.sh
 create mode 100755 test/mounts/ext/run_ns.sh
 create mode 100755 test/mounts/ext/run_wait.sh

diff --git a/test/mounts/ext/Makefile b/test/mounts/ext/Makefile
new file mode 100644
index 0000000..d2315e2
--- /dev/null
+++ b/test/mounts/ext/Makefile
@@ -0,0 +1,4 @@
+all: ext-mount.so
+
+ext-mount.so: ext-mount.c
+	gcc -g -Werror -Wall -shared -nostartfiles ext-mount.c -o ext-mount.so -iquote ../../../include -fPIC
diff --git a/test/mounts/ext/ext-mount.c b/test/mounts/ext/ext-mount.c
new file mode 100644
index 0000000..3ad3b25
--- /dev/null
+++ b/test/mounts/ext/ext-mount.c
@@ -0,0 +1,101 @@
+#include <sys/mount.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "criu-plugin.h"
+#include "criu-log.h"
+
+#define IMG_NAME	"ext-mount-test-%d.img"
+
+extern cr_plugin_init_t cr_plugin_init;
+extern cr_plugin_dump_ext_mount_t cr_plugin_dump_ext_mount;
+extern cr_plugin_restore_ext_mount_t cr_plugin_restore_ext_mount;
+
+int cr_plugin_init(void)
+{
+	pr_info("Initialized ext mount c/r\n");
+	return 0;
+}
+
+int cr_plugin_dump_ext_mount(char *mountpoint, int id)
+{
+	char *aux, *dst;
+	int fd;
+	char img[64];
+
+	pr_info("Check for ext mount %s being mine\n", mountpoint);
+	aux = strrchr(mountpoint, '/');
+	if (!aux) {
+		pr_err("Bad path provided\n");
+		return -ENOTSUP;
+	}
+
+	dst = getenv("dfile");
+	if (!dst) {
+		pr_err("No dfile env\n");
+		return -1;
+	}
+
+	if (strcmp(aux + 1, dst)) {
+		pr_info("Not mine\n");
+		return -ENOTSUP;
+	}
+
+	pr_info("Dumping my mount %d\n", id);
+	sprintf(img, IMG_NAME, id);
+	fd = openat(criu_get_image_dir(), img,
+			O_RDWR | O_CREAT | O_TRUNC, 0600);
+	if (fd < 0) {
+		pr_perror("Can't open image");
+		return -1;
+	}
+
+	close(fd);
+	return 0;
+}
+
+int cr_plugin_restore_ext_mount(int id, char *mountpoint, char *old_root, int *is_file)
+{
+	int fd;
+	char img[64], src[256], *src_file;
+
+	pr_info("Restoring my mount %d?\n", id);
+	sprintf(img, IMG_NAME, id);
+	fd = openat(criu_get_image_dir(), img, O_RDONLY);
+	if (fd < 0) {
+		if (errno == ENOENT)
+			return -ENOTSUP;
+		pr_perror("Can't open my image");
+		return -1;
+	}
+	close(fd);
+
+	src_file = getenv("sfpath");
+	if (!src_file) {
+		pr_err("Can't get sfpath env\n");
+		return -1;
+	}
+
+	if (creat(mountpoint, 0600) < 0) {
+		if (errno != EEXIST) {
+			pr_perror("Can't make mountpoint");
+			return -1;
+		}
+	}
+
+	if (is_file)
+		*is_file = 1;
+
+	sprintf(src, "/%s/%s", old_root, src_file);
+	pr_info("Mount %s -> %s\n", src, mountpoint);
+	if (mount(src, mountpoint, NULL, MS_BIND, NULL) < 0) {
+		pr_perror("Can't bind mount");
+		return -1;
+	}
+
+	return 0;
+}
diff --git a/test/mounts/ext/run.sh b/test/mounts/ext/run.sh
new file mode 100755
index 0000000..886295a
--- /dev/null
+++ b/test/mounts/ext/run.sh
@@ -0,0 +1,57 @@
+#!/bin/bash
+
+set -x
+
+function fail {
+	echo $@
+	exit 1
+}
+
+make || fail "Can't compile library"
+
+criu="../../../criu"
+
+finf="finish"
+outf="run_output"
+pidfile="pid_wait"
+tempd="temp_dir"
+sfile="source_file"
+tdir="test_dir"
+dfile="dest_file"
+mesg="msg-$((RANDOM % 128))"
+export finf
+export outf
+export pidfile
+export sfile
+export dfile
+export tempd
+export mesg
+export tdir
+
+mkdir dump/
+mkdir $tdir
+mount --bind "/" ${tdir} || fail "Can't bind root"
+mount --make-rprivate "${tdir}"
+
+unshare --mount ./run_ns.sh || fail "Can't unshare ns"
+cat $pidfile
+
+sleep 2
+$criu dump -t $(cat $pidfile) -D dump/ -o dump.log -v4 --lib $(pwd) && echo OK
+sleep 1
+
+mkdir $tempd
+mount -t tmpfs none "$tempd"
+echo "$mesg" > "$tempd/$sfile"
+sfpath="/$(pwd)/$tempd/$sfile"
+export sfpath
+
+$criu restore -D dump/ -o restore.log -v4 --lib $(pwd) --root "$(pwd)/$tdir" -d && echo OK
+
+umount "$tempd"
+
+touch $finf
+sleep 1 # Shitty, but...
+tail $outf
+
+umount ${tdir}
diff --git a/test/mounts/ext/run_ns.sh b/test/mounts/ext/run_ns.sh
new file mode 100755
index 0000000..ca97675
--- /dev/null
+++ b/test/mounts/ext/run_ns.sh
@@ -0,0 +1,53 @@
+#!/bin/bash
+
+set -x
+set -e
+
+odir="mexold"
+# finf & outf came from parent
+cur="$(pwd)"
+
+function fail {
+	echo $@
+	exit 1
+}
+
+# Don't mirror further bind mounts in the original namespace
+mount --make-rprivate "/"
+
+# Clean previous stuff
+rm -rf "$tempd" "$finf" "$outf" "/$odir"
+mkdir "$tempd"
+touch "$tdir/$dfile"
+
+# Create source file. Make it on a new mountpoint to "hide"
+# it in the target mount tree (see below)
+mount -t tmpfs none "$tempd"
+echo "$mesg" > "$tempd/$sfile"
+
+# Create destination file. It's a bind mount to the source one.
+mount --bind "$tempd/$sfile" "$tdir/$cur/$tdir/$dfile"
+
+# Make clean and small mounts set
+cd "$tdir"
+mkdir "$odir"
+pivot_root "." "./$odir"
+mount -t proc none "/proc"
+umount -lif "/$odir"
+
+# This would show root, proc and the bind mount to some "unknown"
+# file. Unknown, since it's on a tempfs mount that is not seen
+cat "/proc/self/mountinfo"
+
+set +e
+
+cd "$cur"
+
+# Will be in "logs" so that caller can do "sanity eye-check"
+ls
+cat "$tempd/$sfile"
+cat "$tdir/$dfile"
+
+# Start waiting for C/R on us
+# Exec also fixes the maps/exe/fd links relative to new mounts
+exec setsid "./run_wait.sh" "$tdir/$dfile" "$mesg" < /dev/null > "$outf" 2>&1 &
diff --git a/test/mounts/ext/run_wait.sh b/test/mounts/ext/run_wait.sh
new file mode 100755
index 0000000..3374ca7
--- /dev/null
+++ b/test/mounts/ext/run_wait.sh
@@ -0,0 +1,20 @@
+#!/bin/bash
+
+echo $$ > $pidfile
+
+echo "My mounts (before)"
+cat "/proc/self/mountinfo"
+
+while [ ! -e "$finf" ]; do
+	echo "WAIT"
+	sleep 1;
+done
+
+echo "My mounts (after)"
+cat "/proc/self/mountinfo"
+
+if fgrep "$2" "$1" ; then
+	echo "PASS"
+else
+	echo "FAIL"
+fi
-- 
1.8.3.1


More information about the CRIU mailing list