[CRIU] [RFC PATCH v2 23/23] test: add basic test for uffd events

Mike Rapoport rppt at linux.vnet.ibm.com
Mon Feb 6 03:44:16 PST 2017


Signed-off-by: Mike Rapoport <rppt at linux.vnet.ibm.com>
---
 test/zdtm/static/Makefile      |   1 +
 test/zdtm/static/uffd-events.c | 188 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 189 insertions(+)
 create mode 100644 test/zdtm/static/uffd-events.c

diff --git a/test/zdtm/static/Makefile b/test/zdtm/static/Makefile
index c24ee8f..080a7b8 100644
--- a/test/zdtm/static/Makefile
+++ b/test/zdtm/static/Makefile
@@ -172,6 +172,7 @@ TST_NOFILE	:=				\
 		macvlan			\
 		cr_veth				\
 		sock_peercred			\
+		uffd-events			\
 #		jobctl00			\
 
 ifneq ($(SRCARCH),arm)
diff --git a/test/zdtm/static/uffd-events.c b/test/zdtm/static/uffd-events.c
new file mode 100644
index 0000000..9939c86
--- /dev/null
+++ b/test/zdtm/static/uffd-events.c
@@ -0,0 +1,188 @@
+#define _GNU_SOURCE
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <linux/limits.h>
+#include "zdtmtst.h"
+
+const char *test_doc	= "Test uffd events";
+const char *test_author	= "Mike Rapoport <rppt at linux.vnet.ibm.com>";
+
+#define NR_MAPS		5
+#define MAP_SIZE	(1 << 20)
+
+static void *map[NR_MAPS];
+
+static int create_mappings(void)
+{
+	uint32_t crc;
+	int i;
+
+	for (i = 0; i < NR_MAPS; i++) {
+		map[i] = mmap(NULL, MAP_SIZE, PROT_READ | PROT_WRITE,
+			      MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
+		if (map[i] == MAP_FAILED) {
+			fail("mmap failed");
+			return 1;
+		}
+
+		crc = i;
+		datagen(map[i], MAP_SIZE, &crc);
+	}
+
+	return 0;
+}
+
+static int verify_zeroes(void *m)
+{
+	int i;
+
+	for (i = 0; i < MAP_SIZE; i += PAGE_SIZE) {
+		char *p = m + i;
+		if (*p != 0)
+			return 1;
+	}
+
+	return 0;
+}
+
+static int check_madv_dn(int idx)
+{
+	void *m = map[idx];
+
+	if (madvise(m, MAP_SIZE, MADV_DONTNEED)) {
+		fail("madvise failed");
+		return 1;
+	}
+
+	if (verify_zeroes(m)) {
+		fail("not zero");
+		return 1;
+	}
+
+	return 0;
+}
+
+static int check_mremap_grow(int idx)
+{
+	void *m = map[idx];
+	uint32_t crc = idx;
+
+	m = mremap(m, MAP_SIZE, MAP_SIZE * 2, MREMAP_MAYMOVE);
+	if (m == MAP_FAILED) {
+		fail("mremap failed");
+		return 1;
+	}
+
+	if (datachk(m, MAP_SIZE, &crc)) {
+		fail("Mem corrupted");
+		return 1;
+	}
+
+	/* the new part of the mapping should be filled with zeroes */
+	m += MAP_SIZE;
+	if (verify_zeroes(m)) {
+		fail("not zeroes");
+		return 1;
+	}
+
+	return 0;
+}
+
+static int check_swapped_mappings(int idx)
+{
+	uint32_t crc = idx;
+	void *m1 = map[idx];
+	void *m2 = map[idx + 1];
+	void *p = map[0];
+
+	p = mremap(m1, MAP_SIZE, MAP_SIZE, MREMAP_MAYMOVE | MREMAP_FIXED, p);
+	if (p == MAP_FAILED) {
+		fail("mremap failed");
+		return 1;
+	}
+
+	m1 = mremap(m2, MAP_SIZE, MAP_SIZE, MREMAP_MAYMOVE | MREMAP_FIXED, m1);
+	if (m1 == MAP_FAILED) {
+		fail("mremap failed");
+		return 1;
+	}
+
+	m2 = mremap(p, MAP_SIZE, MAP_SIZE, MREMAP_MAYMOVE | MREMAP_FIXED, m2);
+	if (m2 == MAP_FAILED) {
+		fail("mremap failed");
+		return 1;
+	}
+
+	if (datachk(m2, MAP_SIZE, &crc)) {
+		fail("Mem corrupted");
+		return 1;
+	}
+
+	crc = idx + 1;
+	if (datachk(m1, MAP_SIZE, &crc)) {
+		fail("Mem corrupted");
+		return 1;
+	}
+
+	return 0;
+}
+
+int main(int argc, char ** argv)
+{
+	uint32_t crc;
+	int pid;
+
+	test_init(argc, argv);
+
+	if (create_mappings())
+		return -1;
+
+	test_daemon();
+	test_waitsig();
+
+	/* run some page faults */
+	crc = 0;
+	if (datachk(map[0], MAP_SIZE, &crc)) {
+		fail("Mem corrupted");
+		return 1;
+	}
+
+	pid = fork();
+	if (pid < 0) {
+		fail("Can't fork");
+		return 1;
+	}
+
+	/* check madvise(MADV_DONTNEED) */
+	if (check_madv_dn(1))
+		return 1;
+
+	/* check growing mremap */
+	if (check_mremap_grow(2))
+		return 1;
+
+	/* check swapped mappings */
+	if (check_swapped_mappings(3))
+		return 1;
+
+	if (pid) {
+		int status;
+
+		waitpid(-1, &status, 0);
+		if (status) {
+			fail("child failed");
+			return status;
+		}
+	}
+
+	pass();
+	return 0;
+}
-- 
1.9.1



More information about the CRIU mailing list