[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