[CRIU] Re: [PATCH 0/4] C/R for madvise() bits

Cyrill Gorcunov gorcunov at openvz.org
Thu Oct 25 11:48:56 EDT 2012


On Thu, Oct 25, 2012 at 05:45:32PM +0400, Cyrill Gorcunov wrote:
> On Thu, Oct 25, 2012 at 05:43:16PM +0400, Pavel Emelyanov wrote:
> > On 10/25/2012 05:20 PM, Cyrill Gorcunov wrote:
> > > Please take a look on.
> > 
> > +zdtm test. W/o it I will not apply the patches.
> 
> Yup, I'm just not sure what is the best way of testing it, seems
> I'll need to parse smaps in the testcase.

Something like below I think.
-------------- next part --------------
>From 707831838a15a5704093c75ca03ce32b7714021f Mon Sep 17 00:00:00 2001
From: Cyrill Gorcunov <gorcunov at openvz.org>
Date: Thu, 25 Oct 2012 19:47:51 +0400
Subject: [PATCH] zdtm: Add maps02 test-case

To test new bits we fetch from VmFlags smaps interface.

Signed-off-by: Cyrill Gorcunov <gorcunov at openvz.org>
---
 test/zdtm.sh                   |    1 +
 test/zdtm/live/static/Makefile |    1 +
 test/zdtm/live/static/maps02.c |  229 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 231 insertions(+), 0 deletions(-)
 create mode 100644 test/zdtm/live/static/maps02.c

diff --git a/test/zdtm.sh b/test/zdtm.sh
index 3b00cb1..fbc009c 100644
--- a/test/zdtm.sh
+++ b/test/zdtm.sh
@@ -10,6 +10,7 @@ static/cwd00
 static/env00
 static/maps00
 static/maps01
+static/maps02
 static/mprotect00
 static/mtime_mmap
 static/sleeping00
diff --git a/test/zdtm/live/static/Makefile b/test/zdtm/live/static/Makefile
index 858562f..03e40fe 100644
--- a/test/zdtm/live/static/Makefile
+++ b/test/zdtm/live/static/Makefile
@@ -51,6 +51,7 @@ TST_NOFILE	=				\
 		selfexe00			\
 		sem				\
 		maps01				\
+		maps02				\
 		xids00				\
 		groups				\
 		file_fown			\
diff --git a/test/zdtm/live/static/maps02.c b/test/zdtm/live/static/maps02.c
new file mode 100644
index 0000000..5394a71
--- /dev/null
+++ b/test/zdtm/live/static/maps02.c
@@ -0,0 +1,229 @@
+#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"
+
+#ifndef MAP_HUGETLB
+# define MAP_HUGETLB 0x40000
+#endif
+
+#ifndef MADV_HUGEPAGE
+# define MADV_HUGEPAGE 14
+#endif
+
+#ifndef MADV_NOHUGEPAGE
+# define MADV_NOHUGEPAGE 15
+#endif
+
+#ifndef MADV_DONTDUMP
+# define MADV_DONTDUMP 16
+#endif
+
+const char *test_doc	= "Test shared memory with advises";
+const char *test_author	= "Cyrill Gorcunov <gorcunov at openvz.org>";
+
+struct mmap_data {
+	void		*start;
+	unsigned long	orig_flags;
+	unsigned long	orig_madv;
+	unsigned long	new_flags;
+	unsigned long	new_madv;
+};
+
+static void parse_vmflags(char *buf, unsigned long *flags, unsigned long *madv)
+{
+	char *tok;
+
+	if (!buf[0])
+		return;
+
+	tok = strtok(buf, " \n");
+	if (!tok)
+		return;
+
+#define _vmflag_match(_t, _s) (_t[0] == _s[0] && _t[1] == _s[1])
+
+	do {
+		/* mmap() block */
+		if (_vmflag_match(tok, "gd"))
+			*flags |= MAP_GROWSDOWN;
+		else if (_vmflag_match(tok, "lo"))
+			*flags |= MAP_LOCKED;
+		else if (_vmflag_match(tok, "nr"))
+			*flags |= MAP_NORESERVE;
+		else if (_vmflag_match(tok, "ht"))
+			*flags |= MAP_HUGETLB;
+
+		/* madvise() block */
+		if (_vmflag_match(tok, "sr"))
+			*madv |= (1ul << MADV_SEQUENTIAL);
+		else if (_vmflag_match(tok, "rr"))
+			*madv |= (1ul << MADV_RANDOM);
+		else if (_vmflag_match(tok, "dc"))
+			*madv |= (1ul << MADV_DONTFORK);
+		else if (_vmflag_match(tok, "dd"))
+			*madv |= (1ul << MADV_DONTDUMP);
+		else if (_vmflag_match(tok, "mg"))
+			*madv |= (1ul << MADV_MERGEABLE);
+		else if (_vmflag_match(tok, "hg"))
+			*madv |= (1ul << MADV_HUGEPAGE);
+		else if (_vmflag_match(tok, "nh"))
+			*madv |= (1ul << MADV_NOHUGEPAGE);
+
+		/*
+		 * Anything else is just ignored.
+		 */
+	} while ((tok = strtok(NULL, " \n")));
+
+#undef _vmflag_match
+}
+
+#define is_hex_digit(c)				\
+	(((c) >= '0' && (c) <= '9')	||	\
+	 ((c) >= 'a' && (c) <= 'f')	||	\
+	 ((c) >= 'A' && (c) <= 'F'))
+
+static int is_vma_range_fmt(char *line, unsigned long *start, unsigned long *end)
+{
+	char *p = line;
+	while (*line && is_hex_digit(*line))
+		line++;
+
+	if (*line++ != '-')
+		return 0;
+
+	while (*line && is_hex_digit(*line))
+		line++;
+
+	if (*line++ != ' ')
+		return 0;
+
+	sscanf(p, "%lx-%lx", start, end);
+	return 1;
+}
+
+static int get_smaps_bits(unsigned long where, unsigned long *flags, unsigned long *madv)
+{
+	unsigned long start = 0, end = 0;
+	FILE *smaps = NULL;
+	char buf[1024];
+
+	smaps = fopen("/proc/self/smaps", "r");
+	if (!smaps) {
+		err("Can't open smaps: %m");
+		return -1;
+	}
+
+	while (fgets(buf, sizeof(buf), smaps)) {
+		is_vma_range_fmt(buf, &start, &end);
+
+		if (!strncmp(buf, "VmFlags: ", 9) && start == where) {
+			parse_vmflags(buf, flags, madv);
+			break;
+		}
+	}
+
+	fclose(smaps);
+
+	if (start == end) {
+		err("VmFlags not found for %lx\n", where);
+		return -1;
+	}
+
+	return 0;
+}
+
+#define MEM_SIZE (8192)
+
+static int alloc_anon_mmap(struct mmap_data *m, int flags, int adv)
+{
+	m->start = mmap(NULL, MEM_SIZE, PROT_READ | PROT_WRITE,
+			flags, -1, 0);
+	if (m->start == MAP_FAILED) {
+		err("mmap failed: %m");
+		return -1;
+	}
+
+	if (madvise(m->start, MEM_SIZE, adv)) {
+		err("madvise failed: %m");
+		return -1;
+	}
+
+	return 0;
+}
+
+int main(int argc, char **argv)
+{
+	struct mmap_data m[5] = { };
+	size_t i;
+
+	test_init(argc, argv);
+
+	test_msg("Alloc growsdown\n");
+	if (alloc_anon_mmap(&m[0], MAP_PRIVATE | MAP_ANONYMOUS, MADV_DONTFORK))
+		return -1;
+
+	test_msg("Alloc locked/sequential\n");
+	if (alloc_anon_mmap(&m[1], MAP_PRIVATE | MAP_ANONYMOUS | MAP_LOCKED, MADV_SEQUENTIAL))
+		return -1;
+
+	test_msg("Alloc noreserve/dontdump\n");
+	if (alloc_anon_mmap(&m[2], MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE, MADV_DONTDUMP))
+		return -1;
+
+	test_msg("Alloc hugetlb/hugepage\n");
+	if (alloc_anon_mmap(&m[3], MAP_PRIVATE | MAP_ANONYMOUS, MADV_HUGEPAGE))
+		return -1;
+
+	test_msg("Alloc dontfork/random|mergeable\n");
+	if (alloc_anon_mmap(&m[4], MAP_PRIVATE | MAP_ANONYMOUS, MADV_MERGEABLE))
+		return -1;
+
+	test_msg("Fetch existing flags/adv\n");
+	for (i = 0; i < sizeof(m)/sizeof(m[0]); i++) {
+		if (get_smaps_bits((unsigned long)m[i].start,
+				   &m[i].orig_flags,
+				   &m[i].orig_madv))
+			return -1;
+	}
+
+	test_daemon();
+	test_waitsig();
+
+	test_msg("Fetch restored flags/adv\n");
+	for (i = 0; i < sizeof(m)/sizeof(m[0]); i++) {
+		if (get_smaps_bits((unsigned long)m[i].start,
+				   &m[i].new_flags,
+				   &m[i].new_madv))
+			return -1;
+
+		if (m[i].orig_flags != m[i].new_flags) {
+			err("Flags are changed %lx %lx -> %lx (%d)\n",
+			    (unsigned long)m[i].start,
+			    m[i].orig_flags, m[i].new_flags, i);
+			fail();
+			return -1;
+		}
+
+		if (m[i].orig_madv != m[i].new_madv) {
+			err("Madvs are changed %lx %lx -> %lx (%d)\n",
+			    (unsigned long)m[i].start,
+			    m[i].orig_madv, m[i].new_madv, i);
+			fail();
+			return -1;
+		}
+
+	}
+
+	pass();
+
+	return 0;
+}
-- 
1.7.7.6



More information about the CRIU mailing list