[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