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

Pavel Emelyanov xemul at virtuozzo.com
Wed Feb 8 01:27:18 PST 2017


Please, add a comment -- why do we need some special test for
this and why existing ~300 tests are not enough :)

On 02/06/2017 02:44 PM, Mike Rapoport wrote:
> 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;
> +}
> 



More information about the CRIU mailing list