[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