[CRIU] [PATCH 8/8] zdtm: test dumping character devices with help of custom callbacks

Andrey Vagin avagin at openvz.org
Mon Dec 16 03:26:46 PST 2013


Signed-off-by: Andrey Vagin <avagin at openvz.org>
---
 test/zdtm.sh                          |   6 ++
 test/zdtm/lib/ns.c                    |   2 +
 test/zdtm/live/static/Makefile        |  13 +++-
 test/zdtm/live/static/criu-rtc.c      | 114 ++++++++++++++++++++++++++++++++++
 test/zdtm/live/static/criu-rtc.proto  |   3 +
 test/zdtm/live/static/lib/criu-rtc.so |   1 +
 test/zdtm/live/static/rtc.c           |  61 ++++++++++++++++++
 7 files changed, 198 insertions(+), 2 deletions(-)
 create mode 100644 test/zdtm/live/static/criu-rtc.c
 create mode 100644 test/zdtm/live/static/criu-rtc.proto
 create mode 120000 test/zdtm/live/static/lib/criu-rtc.so
 create mode 100644 test/zdtm/live/static/rtc.c

diff --git a/test/zdtm.sh b/test/zdtm.sh
index cf3e672..c35b92d 100755
--- a/test/zdtm.sh
+++ b/test/zdtm.sh
@@ -98,6 +98,7 @@ static/stopped
 static/chroot
 static/chroot-file
 static/socket-tcpbuf-local
+static/rtc
 "
 # Duplicate list with ns/ prefix
 TEST_LIST=$TEST_LIST$(echo $TEST_LIST | tr ' ' '\n' | sed 's#^#ns/#')
@@ -147,6 +148,7 @@ sk-netlink
 tun
 chroot
 chroot-file
+rtc
 "
 
 source $(readlink -f `dirname $0`/env.sh) || exit 1
@@ -441,6 +443,10 @@ EOF
 		args="--root $ZDTM_ROOT --pidfile $TPID $args"
 	fi
 
+	if [ $tname = "rtc" ]; then
+		args="$args -L `pwd`/$tdir/lib"
+	fi
+
 	for i in `seq $ITERATIONS`; do
 		local dump_only=
 		local postdump=
diff --git a/test/zdtm/lib/ns.c b/test/zdtm/lib/ns.c
index cd082d8..3550caf 100644
--- a/test/zdtm/lib/ns.c
+++ b/test/zdtm/lib/ns.c
@@ -93,6 +93,8 @@ static int prepare_mntns()
 	mkdir("/dev/net", 0777);
 	mknod("/dev/net/tun", 0777 | S_IFCHR, makedev(10, 200));
 	chmod("/dev/net/tun", 0777);
+	mknod("/dev/rtc", 0777 | S_IFCHR, makedev(254, 0));
+	chmod("/dev/rtc", 0777);
 	return 0;
 }
 
diff --git a/test/zdtm/live/static/Makefile b/test/zdtm/live/static/Makefile
index 6a15659..0e542e0 100644
--- a/test/zdtm/live/static/Makefile
+++ b/test/zdtm/live/static/Makefile
@@ -103,6 +103,7 @@ TST_NOFILE	=				\
 		grow_map02			\
 		tun				\
 		stopped				\
+		rtc				\
 #		jobctl00			\
 
 TST_FILE	=				\
@@ -175,7 +176,7 @@ DEPEND.c = $(COMPILE.c) -MM -MP
 %.d:	%.c
 	$(DEPEND.c) $(OUTPUT_OPTION) $<
 
-all:	$(TST)
+all:	$(TST) criu-rtc.so
 install: all
 
 inotify_system_nodel.c: inotify_system.c
@@ -260,7 +261,7 @@ $(LIB):	force
 	$(Q) $(MAKE) -C $(LIBDIR)
 
 clean:
-	$(RM) -f $(OBJ) $(TST) *~
+	$(RM) -f $(OBJ) $(TST) *~ criu-rtc.so criu-rtc.pb-c.c criu-rtc.pb-c.h
 
 cleandep:	clean
 	$(RM) -f $(DEP)
@@ -273,6 +274,14 @@ cleanout:
 
 realclean:	cleandep cleanout
 
+rtc.c: criu-rtc.so
+
+criu-rtc.pb-c.c: criu-rtc.proto
+	protoc-c --proto_path=. --c_out=. criu-rtc.proto
+
+criu-rtc.so: criu-rtc.c criu-rtc.pb-c.c
+	gcc -g -Wall -shared -nostartfiles criu-rtc.c criu-rtc.pb-c.c -o criu-rtc.so -iquote ../../../../include -fPIC
+
 .PHONY:	force clean cleandep cleanout realclean start check_start stop wait_stop
 
 ifeq ($(filter-out no-deps-targets, $(MAKECMDGOALS)),)
diff --git a/test/zdtm/live/static/criu-rtc.c b/test/zdtm/live/static/criu-rtc.c
new file mode 100644
index 0000000..2ba3fa7
--- /dev/null
+++ b/test/zdtm/live/static/criu-rtc.c
@@ -0,0 +1,114 @@
+#include <stdio.h>
+#include <linux/rtc.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <linux/limits.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include "criu-plugin.h"
+#include "criu-rtc.pb-c.h"
+
+extern cr_plugin_dump_file_t cr_plugin_dump_file;
+extern cr_plugin_restore_file_t cr_plugin_restore_file;
+
+int cr_plugin_dump_file(int fd, int id)
+{
+	CriuRtc e = CRIU_RTC__INIT;
+	char img_path[PATH_MAX];
+	unsigned char buf[4096];
+	int img_fd, ret, len;
+	unsigned long irqp;
+	struct stat st;
+
+	if (fstat(fd, &st) == -1) {
+		pr_perror("fstat");
+		return -1;
+	}
+
+	if (major(st.st_rdev) != 254 || minor(st.st_rdev) != 0)
+		return -ENOTSUP;
+
+	if (ioctl(fd, RTC_IRQP_READ, &irqp) == -1) {
+		pr_perror("RTC_IRQP_READ");
+		return -1;
+	}
+
+	e.irqp = irqp;
+
+	snprintf(img_path, sizeof(img_path), "rtc.%x", id);
+	img_fd = openat(criu_get_image_dir(), img_path, O_WRONLY | O_CREAT);
+	if (img_fd < 0) {
+		pr_perror("Can't open %s", img_path);
+		return -1;
+	}
+
+	len = criu_rtc__get_packed_size(&e);
+	if (len > sizeof(buf))
+		return -1;
+
+	criu_rtc__pack(&e, buf);
+
+	ret = write(img_fd,  buf, len);
+	if (ret != len) {
+		pr_perror("Unable to write in %s", img_path);
+		close(img_fd);
+		return -1;
+	}
+
+	close(img_fd);
+	return 0;
+}
+
+int cr_plugin_restore_file(const char *path, int flags, int id)
+{
+	unsigned char buf[4096];
+	char img_path[PATH_MAX];
+	int img_fd, len, fd;
+	CriuRtc *e;
+
+	snprintf(img_path, sizeof(img_path), "rtc.%x", id);
+	img_fd = openat(criu_get_image_dir(), img_path, O_RDONLY);
+	if (img_fd < 0) {
+		pr_perror("open(%s)", img_path);
+		return -ENOTSUP;
+	}
+
+	len = read(img_fd, &buf, sizeof(buf));
+	if (len <= 0) {
+		pr_perror("Unable to read from %s", img_path);
+		close(img_fd);
+		return -1;
+	}
+	close(img_fd);
+
+	e = criu_rtc__unpack(NULL, len, buf);
+	if (e == NULL) {
+		pr_err("Unable to parse the RTC message %#x", id);
+		return -1;
+	}
+
+	fd = open(path, flags);
+	if (fd < 0) {
+		pr_perror("open");
+		return -1;
+	}
+
+	if (ioctl(fd, RTC_IRQP_SET, e->irqp) == -1) {
+		pr_perror("RTC_IRQP_SET");
+		close(fd);
+		return -1;
+	}
+
+	criu_rtc__free_unpacked(e, NULL);
+
+	if (ioctl(fd, RTC_PIE_ON, 0) == -1) {
+		pr_perror("RTC_PIE_ON");
+		close(fd);
+		return -1;
+	}
+
+	return fd;
+}
diff --git a/test/zdtm/live/static/criu-rtc.proto b/test/zdtm/live/static/criu-rtc.proto
new file mode 100644
index 0000000..5d5cee9
--- /dev/null
+++ b/test/zdtm/live/static/criu-rtc.proto
@@ -0,0 +1,3 @@
+message criu_rtc {
+	required uint64	IRQP = 1;
+}
diff --git a/test/zdtm/live/static/lib/criu-rtc.so b/test/zdtm/live/static/lib/criu-rtc.so
new file mode 120000
index 0000000..17f3ef7
--- /dev/null
+++ b/test/zdtm/live/static/lib/criu-rtc.so
@@ -0,0 +1 @@
+../criu-rtc.so
\ No newline at end of file
diff --git a/test/zdtm/live/static/rtc.c b/test/zdtm/live/static/rtc.c
new file mode 100644
index 0000000..b2d094c
--- /dev/null
+++ b/test/zdtm/live/static/rtc.c
@@ -0,0 +1,61 @@
+#include <stdio.h>
+#include <linux/rtc.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include "zdtmtst.h"
+
+#define TEST_HZ 4
+#define NR_FAILS 5
+
+int main(int argc, char **argv)
+{
+	unsigned long data, delta;
+	int fd, fail = NR_FAILS, to_pass = NR_FAILS;
+	struct timeval start, end;
+
+	test_init(argc, argv);
+
+	fd = open("/dev/rtc", O_RDWR);
+	if (fd < 0) {
+		err("open");
+		return 1;
+	}
+
+	if (ioctl(fd, RTC_IRQP_SET, TEST_HZ) == -1) {
+		err("RTC_IRQP_SET");
+		return 1;
+	}
+
+	if (ioctl(fd, RTC_PIE_ON, 0) == -1) {
+		err("RTC_PIE_ON");
+		return 1;
+	}
+
+	test_daemon();
+
+	gettimeofday(&start, NULL);
+	start.tv_usec += start.tv_sec * 1000000;
+	while (test_go() || to_pass--) {
+		if (read(fd, &data, sizeof(unsigned long)) == -1)
+			return 1;
+		gettimeofday(&end, NULL);
+		end.tv_usec += end.tv_sec * 1000000;
+		delta = end.tv_usec - start.tv_usec;
+		if (labs(delta - 1000000 / TEST_HZ ) > 100000) {
+			err("delta = %ld\n", delta);
+			fail--;
+			if (fail == 0)
+				return 1;
+		}
+		start = end;
+	}
+	pass();
+
+	return 0;
+}
-- 
1.8.3.1



More information about the CRIU mailing list