[LTP] [PATCH v2] syscall: Add userfaultfd testcase
Jan Stancek
jstancek@redhat.com
Thu Mar 14 12:42:40 CET 2019
----- Original Message -----
> This tests the userfaultfd syscall to handle pagefault events.
> It does so by registering a userfaultfd object to the address of
> a memory page. In a second thread it handles the event and writes
> data in the monitored memory page to indicate success.
>
> Signed-off-by: Christian Amann <camann@suse.com>
Hi,
my main concern is that direct include of linux header.
Other than that it looks ok, but you could use more SAFE_ macros
which do the common checks and print error messages for you.
<snip>
> +
> +/*
> + * Test userfaultfd
> + *
> + * Force a pagefault event and handle it using userfaultfd
> + * from a different thread
> + *
> + */
> +
> +#include "tst_test.h"
> +#include "lapi/syscalls.h"
> +#include <linux/userfaultfd.h>
This doesn't look like it will compile on older kernels.
> +#include <pthread.h>
> +#include <poll.h>
> +
> +static int page_size;
> +static char *page;
> +static void *copy_page;
> +
> +static int sys_userfaultfd(int flags)
> +{
> + return tst_syscall(__NR_userfaultfd, flags);
> +}
> +
> +static void set_pages(void)
> +{
> + page_size = sysconf(_SC_PAGE_SIZE);
> + page = mmap(NULL, page_size, PROT_READ | PROT_WRITE,
> + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
> + copy_page = mmap(NULL, page_size, PROT_READ | PROT_WRITE,
> + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
Please use SAFE_MMAP
> +}
> +
> +static void *handle_thread(void *arg)
> +{
> + static struct uffd_msg msg;
> + long uffd;
> + struct uffdio_copy uffdio_copy;
> + ssize_t nread;
> +
> + uffd = (long) arg;
> +
> + struct pollfd pollfd;
> + int nready;
> +
> + pollfd.fd = uffd;
> + pollfd.events = POLLIN;
> + nready = poll(&pollfd, 1, -1);
SAFE_POLL
> + if (nready == -1)
> + tst_brk(TBROK | TERRNO,
> + "Error on poll");
> +
> + nread = read(uffd, &msg, sizeof(msg));
SAFE_READ should work here too if you pass len_strict=1
> + if (nread <= 0)
> + tst_brk(TBROK | TERRNO, "Error on read");
> +
> + if (msg.event != UFFD_EVENT_PAGEFAULT)
> + tst_brk(TBROK | TERRNO,
> + "Received unexpected UFFD_EVENT");
> +
> + memset(copy_page, 'X', page_size);
> +
> + uffdio_copy.src = (unsigned long) copy_page;
> +
> + uffdio_copy.dst = (unsigned long) msg.arg.pagefault.address
> + & ~(page_size - 1);
> + uffdio_copy.len = page_size;
> + uffdio_copy.mode = 0;
> + uffdio_copy.copy = 0;
> + if (ioctl(uffd, UFFDIO_COPY, &uffdio_copy) == -1)
> + tst_brk(TBROK | TERRNO,
> + "ioctl returned error for UFFDIO_COPY");
SAFE_IOCTL
> + close(uffd);
> +}
> +
> +static void run(void)
> +{
> + long uffd;
> + pthread_t thr;
> + struct uffdio_api uffdio_api;
> + struct uffdio_register uffdio_register;
> + int thread_ret;
> +
> + set_pages();
> +
> + uffd = sys_userfaultfd(O_CLOEXEC | O_NONBLOCK);
> + if (uffd == -1)
> + tst_brk(TBROK | TERRNO,
> + "Could not create userfault file descriptor");
> +
> + uffdio_api.api = UFFD_API;
> + uffdio_api.features = 0;
> + if (ioctl(uffd, UFFDIO_API, &uffdio_api) == -1)
> + tst_brk(TBROK | TERRNO, "ioctl returned error for UFFDIO_API");
SAFE_IOCTL
> +
> + uffdio_register.range.start = (unsigned long) page;
> + uffdio_register.range.len = page_size;
> + uffdio_register.mode = UFFDIO_REGISTER_MODE_MISSING;
> +
> + if (ioctl(uffd, UFFDIO_REGISTER, &uffdio_register) == -1)
> + tst_brk(TBROK | TERRNO,
> + "ioctl returned error for UFFDIO_REGISTER");
SAFE_IOCTL
> +
> + thread_ret = pthread_create(&thr, NULL,
> + handle_thread, (void *) uffd);
SAFE_PTHREAD_CREATE
> + if (thread_ret != 0) {
> + errno = thread_ret;
> + tst_brk(TBROK | TERRNO, "Could not create pthread");
> + }
> +
> + char c = page[0xf];
> +
> + if (c == 'X')
> + tst_res(TPASS, "Pagefault handled!");
> + else
> + tst_res(TFAIL, "Pagefault not handled!");
> +
> + pthread_join(thr, NULL);
SAFE_PTHREAD_JOIN
Regards,
Jan
> +}
> +
> +static struct tst_test test = {
> + .test_all = run,
> + .min_kver = "4.3",
> + .timeout = 20
> +};
> --
> 2.16.4
>
>
> --
> Mailing list info: https://lists.linux.it/listinfo/ltp
>
More information about the ltp
mailing list