Commit 0dfb0776 authored by Andrey Vagin's avatar Andrey Vagin Committed by Pavel Emelyanov

zdtm: test dumping character devices with help of custom callbacks

Signed-off-by: 's avatarAndrey Vagin <avagin@openvz.org>
Signed-off-by: 's avatarPavel Emelyanov <xemul@parallels.com>
parent 6bbdec26
......@@ -98,6 +98,7 @@ static/grow_map02
static/stopped
static/chroot
static/chroot-file
static/rtc
"
# Duplicate list with ns/ prefix
TEST_LIST=$TEST_LIST$(echo $TEST_LIST | tr ' ' '\n' | sed 's#^#ns/#')
......@@ -148,6 +149,7 @@ sk-netlink
tun
chroot
chroot-file
rtc
"
source $(readlink -f `dirname $0`/env.sh) || exit 1
......@@ -442,6 +444,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=
......
......@@ -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;
}
......
......@@ -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)),)
......
#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-log.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(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("/dev/rtc", O_RDWR);
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;
}
message criu_rtc {
required uint64 IRQP = 1;
}
../criu-rtc.so
\ No newline at end of file
#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;
}
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