Commit 094affbd authored by Pavel Emelyanov's avatar Pavel Emelyanov

test: Test and example of external bind mounts plugin

Signed-off-by: 's avatarPavel Emelyanov <xemul@parallels.com>
parent c18b30d0
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
#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;
}
#!/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}
#!/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 &
#!/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
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment