[CRIU] [PATCH cr] zdtm: add a smoke test for cow memory

Andrey Vagin avagin at openvz.org
Thu Oct 11 03:58:31 EDT 2012


A test allocates and filles one page, creates a new child, then
compares pfn-s for both processes.

Signed-off-by: Andrey Vagin <avagin at openvz.org>
---
 test/zdtm/live/static/Makefile |    1 +
 test/zdtm/live/static/cow00.c  |  113 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 114 insertions(+), 0 deletions(-)
 create mode 100644 test/zdtm/live/static/cow00.c

diff --git a/test/zdtm/live/static/Makefile b/test/zdtm/live/static/Makefile
index f0da788..6ed79a3 100644
--- a/test/zdtm/live/static/Makefile
+++ b/test/zdtm/live/static/Makefile
@@ -65,6 +65,7 @@ TST_NOFILE	=				\
 		session01			\
 		socket-ext			\
 		unhashed_proc			\
+		cow00				\
 #		jobctl00			\
 
 TST_FILE	=				\
diff --git a/test/zdtm/live/static/cow00.c b/test/zdtm/live/static/cow00.c
new file mode 100644
index 0000000..c995bea
--- /dev/null
+++ b/test/zdtm/live/static/cow00.c
@@ -0,0 +1,113 @@
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <stdio.h>
+#include <string.h>
+#include <signal.h>
+#include <unistd.h>
+#include <sys/wait.h>
+#include <linux/limits.h>
+#include <sys/user.h>
+
+#include "zdtmtst.h"
+
+const char *test_doc	= "Check that cow memory are restored";
+const char *test_author	= "Andrey Vagin <avagin at parallels.com";
+
+static int is_cow(void *addr, pid_t p1, pid_t p2)
+{
+	char buf[PATH_MAX];
+	unsigned long pfn = (unsigned long) addr / PAGE_SIZE;
+	uint64_t map1, map2;
+	int fd1, fd2, ret, i;
+
+	snprintf(buf, sizeof(buf), "/proc/%d/pagemap", p1);
+	fd1 = open(buf, O_RDONLY);
+	if (fd1 < 0) {
+		err("Unable to open file %s", buf);
+		return -1;
+	}
+
+	snprintf(buf, sizeof(buf), "/proc/%d/pagemap", p2);
+	fd2 = open(buf, O_RDONLY);
+	if (fd1 < 0) {
+		err("Unable to open file %s", buf);
+		return -1;
+	}
+
+	lseek(fd1, pfn * sizeof(map1), SEEK_SET);
+	lseek(fd2, pfn * sizeof(map2), SEEK_SET);
+
+	/*
+	 * A page can be swapped or unswapped,
+	 * so we should do several iterations.
+	 */
+	for (i = 0; i < 10; i++) {
+		ret = read(fd1, &map1, sizeof(map1));
+		if (ret != sizeof(map1)) {
+			err("Unable to read data");
+			return -1;
+		}
+		ret = read(fd2, &map2, sizeof(map2));
+		if (ret != sizeof(map2)) {
+			err("Unable to read data");
+			return -1;
+		}
+
+		if (map1 == map2)
+			break;
+	}
+
+	close(fd1);
+	close(fd2);
+
+	return map1 == map2;
+}
+
+int main(int argc, char ** argv)
+{
+	void *addr;
+	pid_t pid;
+	int ret = 1;
+
+	test_init(argc, argv);
+
+	addr = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+	if (addr == MAP_FAILED) {
+		err("Can't allocate memory\n");
+		return 1;
+	}
+
+	memset(addr, 1, PAGE_SIZE);
+
+	pid = test_fork();
+	if (pid < 0) {
+		err("Unable to fork a new process\n");
+		return 1;
+	} else if (pid == 0) {
+		test_waitsig();
+		return 0;
+	}
+
+	if (is_cow(addr, pid, getpid()) == 1)
+		test_msg("OK\n");
+	else {
+		err("A page is not shared");
+		goto out;
+	}
+
+	test_daemon();
+
+	test_waitsig();
+
+	if (is_cow(addr, pid, getpid()) == 1)
+		pass();
+	else
+		fail("A page is not shared");
+
+	ret = 0;
+out:
+	kill(pid, SIGTERM);
+	wait(NULL);
+
+	return ret;
+}
-- 
1.7.1



More information about the CRIU mailing list