Commit b6ad1976 authored by Mike Rapoport's avatar Mike Rapoport Committed by Linus Torvalds

userfaultfd: selftest: combine all cases into a single executable

Currently, selftest for userfaultfd is compiled three times: for
anonymous, shared and hugetlb memory.  Let's combine all the cases into
a single executable which will have a command line option for selection
of the test type.

Link: http://lkml.kernel.org/r/1490869741-5913-1-git-send-email-rppt@linux.vnet.ibm.comSigned-off-by: default avatarMike Rapoport <rppt@linux.vnet.ibm.com>
Reviewed-by: default avatarMike Kravetz <mike.kravetz@oracle.com>
Cc: Andrea Arcangeli <aarcange@redhat.com>
Cc: Shuah Khan <shuah@kernel.org>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent ac2e8e40
...@@ -15,21 +15,14 @@ TEST_GEN_FILES += on-fault-limit ...@@ -15,21 +15,14 @@ TEST_GEN_FILES += on-fault-limit
TEST_GEN_FILES += thuge-gen TEST_GEN_FILES += thuge-gen
TEST_GEN_FILES += transhuge-stress TEST_GEN_FILES += transhuge-stress
TEST_GEN_FILES += userfaultfd TEST_GEN_FILES += userfaultfd
TEST_GEN_FILES += userfaultfd_hugetlb
TEST_GEN_FILES += userfaultfd_shmem
TEST_GEN_FILES += mlock-random-test TEST_GEN_FILES += mlock-random-test
TEST_PROGS := run_vmtests TEST_PROGS := run_vmtests
include ../lib.mk include ../lib.mk
$(OUTPUT)/userfaultfd: LDLIBS += -lpthread ../../../../usr/include/linux/kernel.h $(OUTPUT)/userfaultfd: ../../../../usr/include/linux/kernel.h
$(OUTPUT)/userfaultfd: LDLIBS += -lpthread
$(OUTPUT)/userfaultfd_hugetlb: userfaultfd.c ../../../../usr/include/linux/kernel.h
$(CC) $(CFLAGS) -DHUGETLB_TEST -O2 -o $@ $< -lpthread
$(OUTPUT)/userfaultfd_shmem: userfaultfd.c ../../../../usr/include/linux/kernel.h
$(CC) $(CFLAGS) -DSHMEM_TEST -O2 -o $@ $< -lpthread
$(OUTPUT)/mlock-random-test: LDLIBS += -lcap $(OUTPUT)/mlock-random-test: LDLIBS += -lcap
......
...@@ -95,7 +95,7 @@ echo " hugetlb regression testing." ...@@ -95,7 +95,7 @@ echo " hugetlb regression testing."
echo "--------------------" echo "--------------------"
echo "running userfaultfd" echo "running userfaultfd"
echo "--------------------" echo "--------------------"
./userfaultfd 128 32 ./userfaultfd anon 128 32
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
echo "[FAIL]" echo "[FAIL]"
exitcode=1 exitcode=1
...@@ -107,7 +107,7 @@ echo "----------------------------" ...@@ -107,7 +107,7 @@ echo "----------------------------"
echo "running userfaultfd_hugetlb" echo "running userfaultfd_hugetlb"
echo "----------------------------" echo "----------------------------"
# 258MB total huge pages == 128MB src and 128MB dst # 258MB total huge pages == 128MB src and 128MB dst
./userfaultfd_hugetlb 128 32 $mnt/ufd_test_file ./userfaultfd hugetlb 128 32 $mnt/ufd_test_file
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
echo "[FAIL]" echo "[FAIL]"
exitcode=1 exitcode=1
...@@ -119,7 +119,7 @@ rm -f $mnt/ufd_test_file ...@@ -119,7 +119,7 @@ rm -f $mnt/ufd_test_file
echo "----------------------------" echo "----------------------------"
echo "running userfaultfd_shmem" echo "running userfaultfd_shmem"
echo "----------------------------" echo "----------------------------"
./userfaultfd_shmem 128 32 ./userfaultfd shmem 128 32
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
echo "[FAIL]" echo "[FAIL]"
exitcode=1 exitcode=1
......
...@@ -77,10 +77,13 @@ static unsigned long nr_cpus, nr_pages, nr_pages_per_cpu, page_size; ...@@ -77,10 +77,13 @@ static unsigned long nr_cpus, nr_pages, nr_pages_per_cpu, page_size;
#define BOUNCE_POLL (1<<3) #define BOUNCE_POLL (1<<3)
static int bounces; static int bounces;
#ifdef HUGETLB_TEST #define TEST_ANON 1
#define TEST_HUGETLB 2
#define TEST_SHMEM 3
static int test_type;
static int huge_fd; static int huge_fd;
static char *huge_fd_off0; static char *huge_fd_off0;
#endif
static unsigned long long *count_verify; static unsigned long long *count_verify;
static int uffd, uffd_flags, finished, *pipefd; static int uffd, uffd_flags, finished, *pipefd;
static char *area_src, *area_dst; static char *area_src, *area_dst;
...@@ -102,14 +105,7 @@ pthread_attr_t attr; ...@@ -102,14 +105,7 @@ pthread_attr_t attr;
~(unsigned long)(sizeof(unsigned long long) \ ~(unsigned long)(sizeof(unsigned long long) \
- 1))) - 1)))
#if !defined(HUGETLB_TEST) && !defined(SHMEM_TEST) static int anon_release_pages(char *rel_area)
/* Anonymous memory */
#define EXPECTED_IOCTLS ((1 << _UFFDIO_WAKE) | \
(1 << _UFFDIO_COPY) | \
(1 << _UFFDIO_ZEROPAGE))
static int release_pages(char *rel_area)
{ {
int ret = 0; int ret = 0;
...@@ -121,7 +117,7 @@ static int release_pages(char *rel_area) ...@@ -121,7 +117,7 @@ static int release_pages(char *rel_area)
return ret; return ret;
} }
static void allocate_area(void **alloc_area) static void anon_allocate_area(void **alloc_area)
{ {
if (posix_memalign(alloc_area, page_size, nr_pages * page_size)) { if (posix_memalign(alloc_area, page_size, nr_pages * page_size)) {
fprintf(stderr, "out of memory\n"); fprintf(stderr, "out of memory\n");
...@@ -129,14 +125,9 @@ static void allocate_area(void **alloc_area) ...@@ -129,14 +125,9 @@ static void allocate_area(void **alloc_area)
} }
} }
#else /* HUGETLB_TEST or SHMEM_TEST */
#define EXPECTED_IOCTLS UFFD_API_RANGE_IOCTLS_BASIC
#ifdef HUGETLB_TEST
/* HugeTLB memory */ /* HugeTLB memory */
static int release_pages(char *rel_area) static int hugetlb_release_pages(char *rel_area)
{ {
int ret = 0; int ret = 0;
...@@ -152,7 +143,7 @@ static int release_pages(char *rel_area) ...@@ -152,7 +143,7 @@ static int release_pages(char *rel_area)
} }
static void allocate_area(void **alloc_area) static void hugetlb_allocate_area(void **alloc_area)
{ {
*alloc_area = mmap(NULL, nr_pages * page_size, PROT_READ | PROT_WRITE, *alloc_area = mmap(NULL, nr_pages * page_size, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_HUGETLB, huge_fd, MAP_PRIVATE | MAP_HUGETLB, huge_fd,
...@@ -167,10 +158,8 @@ static void allocate_area(void **alloc_area) ...@@ -167,10 +158,8 @@ static void allocate_area(void **alloc_area)
huge_fd_off0 = *alloc_area; huge_fd_off0 = *alloc_area;
} }
#elif defined(SHMEM_TEST)
/* Shared memory */ /* Shared memory */
static int release_pages(char *rel_area) static int shmem_release_pages(char *rel_area)
{ {
int ret = 0; int ret = 0;
...@@ -182,7 +171,7 @@ static int release_pages(char *rel_area) ...@@ -182,7 +171,7 @@ static int release_pages(char *rel_area)
return ret; return ret;
} }
static void allocate_area(void **alloc_area) static void shmem_allocate_area(void **alloc_area)
{ {
*alloc_area = mmap(NULL, nr_pages * page_size, PROT_READ | PROT_WRITE, *alloc_area = mmap(NULL, nr_pages * page_size, PROT_READ | PROT_WRITE,
MAP_ANONYMOUS | MAP_SHARED, -1, 0); MAP_ANONYMOUS | MAP_SHARED, -1, 0);
...@@ -192,11 +181,35 @@ static void allocate_area(void **alloc_area) ...@@ -192,11 +181,35 @@ static void allocate_area(void **alloc_area)
} }
} }
#else /* SHMEM_TEST */ struct uffd_test_ops {
#error "Undefined test type" unsigned long expected_ioctls;
#endif /* HUGETLB_TEST */ void (*allocate_area)(void **alloc_area);
int (*release_pages)(char *rel_area);
#endif /* !defined(HUGETLB_TEST) && !defined(SHMEM_TEST) */ };
#define ANON_EXPECTED_IOCTLS ((1 << _UFFDIO_WAKE) | \
(1 << _UFFDIO_COPY) | \
(1 << _UFFDIO_ZEROPAGE))
static struct uffd_test_ops anon_uffd_test_ops = {
.expected_ioctls = ANON_EXPECTED_IOCTLS,
.allocate_area = anon_allocate_area,
.release_pages = anon_release_pages,
};
static struct uffd_test_ops shmem_uffd_test_ops = {
.expected_ioctls = UFFD_API_RANGE_IOCTLS_BASIC,
.allocate_area = shmem_allocate_area,
.release_pages = shmem_release_pages,
};
static struct uffd_test_ops hugetlb_uffd_test_ops = {
.expected_ioctls = UFFD_API_RANGE_IOCTLS_BASIC,
.allocate_area = hugetlb_allocate_area,
.release_pages = hugetlb_release_pages,
};
static struct uffd_test_ops *uffd_test_ops;
static int my_bcmp(char *str1, char *str2, size_t n) static int my_bcmp(char *str1, char *str2, size_t n)
{ {
...@@ -505,7 +518,7 @@ static int stress(unsigned long *userfaults) ...@@ -505,7 +518,7 @@ static int stress(unsigned long *userfaults)
* UFFDIO_COPY without writing zero pages into area_dst * UFFDIO_COPY without writing zero pages into area_dst
* because the background threads already completed). * because the background threads already completed).
*/ */
if (release_pages(area_src)) if (uffd_test_ops->release_pages(area_src))
return 1; return 1;
for (cpu = 0; cpu < nr_cpus; cpu++) { for (cpu = 0; cpu < nr_cpus; cpu++) {
...@@ -577,12 +590,12 @@ static int faulting_process(void) ...@@ -577,12 +590,12 @@ static int faulting_process(void)
{ {
unsigned long nr; unsigned long nr;
unsigned long long count; unsigned long long count;
unsigned long split_nr_pages;
#ifndef HUGETLB_TEST if (test_type != TEST_HUGETLB)
unsigned long split_nr_pages = (nr_pages + 1) / 2; split_nr_pages = (nr_pages + 1) / 2;
#else else
unsigned long split_nr_pages = nr_pages; split_nr_pages = nr_pages;
#endif
for (nr = 0; nr < split_nr_pages; nr++) { for (nr = 0; nr < split_nr_pages; nr++) {
count = *area_count(area_dst, nr); count = *area_count(area_dst, nr);
...@@ -594,7 +607,9 @@ static int faulting_process(void) ...@@ -594,7 +607,9 @@ static int faulting_process(void)
} }
} }
#ifndef HUGETLB_TEST if (test_type == TEST_HUGETLB)
return 0;
area_dst = mremap(area_dst, nr_pages * page_size, nr_pages * page_size, area_dst = mremap(area_dst, nr_pages * page_size, nr_pages * page_size,
MREMAP_MAYMOVE | MREMAP_FIXED, area_src); MREMAP_MAYMOVE | MREMAP_FIXED, area_src);
if (area_dst == MAP_FAILED) if (area_dst == MAP_FAILED)
...@@ -610,7 +625,7 @@ static int faulting_process(void) ...@@ -610,7 +625,7 @@ static int faulting_process(void)
} }
} }
if (release_pages(area_dst)) if (uffd_test_ops->release_pages(area_dst))
return 1; return 1;
for (nr = 0; nr < nr_pages; nr++) { for (nr = 0; nr < nr_pages; nr++) {
...@@ -618,8 +633,6 @@ static int faulting_process(void) ...@@ -618,8 +633,6 @@ static int faulting_process(void)
fprintf(stderr, "nr %lu is not zero\n", nr), exit(1); fprintf(stderr, "nr %lu is not zero\n", nr), exit(1);
} }
#endif /* HUGETLB_TEST */
return 0; return 0;
} }
...@@ -627,7 +640,9 @@ static int uffdio_zeropage(int ufd, unsigned long offset) ...@@ -627,7 +640,9 @@ static int uffdio_zeropage(int ufd, unsigned long offset)
{ {
struct uffdio_zeropage uffdio_zeropage; struct uffdio_zeropage uffdio_zeropage;
int ret; int ret;
unsigned long has_zeropage = EXPECTED_IOCTLS & (1 << _UFFDIO_ZEROPAGE); unsigned long has_zeropage;
has_zeropage = uffd_test_ops->expected_ioctls & (1 << _UFFDIO_ZEROPAGE);
if (offset >= nr_pages * page_size) if (offset >= nr_pages * page_size)
fprintf(stderr, "unexpected offset %lu\n", fprintf(stderr, "unexpected offset %lu\n",
...@@ -675,7 +690,7 @@ static int userfaultfd_zeropage_test(void) ...@@ -675,7 +690,7 @@ static int userfaultfd_zeropage_test(void)
printf("testing UFFDIO_ZEROPAGE: "); printf("testing UFFDIO_ZEROPAGE: ");
fflush(stdout); fflush(stdout);
if (release_pages(area_dst)) if (uffd_test_ops->release_pages(area_dst))
return 1; return 1;
if (userfaultfd_open(0) < 0) if (userfaultfd_open(0) < 0)
...@@ -686,7 +701,7 @@ static int userfaultfd_zeropage_test(void) ...@@ -686,7 +701,7 @@ static int userfaultfd_zeropage_test(void)
if (ioctl(uffd, UFFDIO_REGISTER, &uffdio_register)) if (ioctl(uffd, UFFDIO_REGISTER, &uffdio_register))
fprintf(stderr, "register failure\n"), exit(1); fprintf(stderr, "register failure\n"), exit(1);
expected_ioctls = EXPECTED_IOCTLS; expected_ioctls = uffd_test_ops->expected_ioctls;
if ((uffdio_register.ioctls & expected_ioctls) != if ((uffdio_register.ioctls & expected_ioctls) !=
expected_ioctls) expected_ioctls)
fprintf(stderr, fprintf(stderr,
...@@ -716,7 +731,7 @@ static int userfaultfd_events_test(void) ...@@ -716,7 +731,7 @@ static int userfaultfd_events_test(void)
printf("testing events (fork, remap, remove): "); printf("testing events (fork, remap, remove): ");
fflush(stdout); fflush(stdout);
if (release_pages(area_dst)) if (uffd_test_ops->release_pages(area_dst))
return 1; return 1;
features = UFFD_FEATURE_EVENT_FORK | UFFD_FEATURE_EVENT_REMAP | features = UFFD_FEATURE_EVENT_FORK | UFFD_FEATURE_EVENT_REMAP |
...@@ -731,7 +746,7 @@ static int userfaultfd_events_test(void) ...@@ -731,7 +746,7 @@ static int userfaultfd_events_test(void)
if (ioctl(uffd, UFFDIO_REGISTER, &uffdio_register)) if (ioctl(uffd, UFFDIO_REGISTER, &uffdio_register))
fprintf(stderr, "register failure\n"), exit(1); fprintf(stderr, "register failure\n"), exit(1);
expected_ioctls = EXPECTED_IOCTLS; expected_ioctls = uffd_test_ops->expected_ioctls;
if ((uffdio_register.ioctls & expected_ioctls) != if ((uffdio_register.ioctls & expected_ioctls) !=
expected_ioctls) expected_ioctls)
fprintf(stderr, fprintf(stderr,
...@@ -773,10 +788,10 @@ static int userfaultfd_stress(void) ...@@ -773,10 +788,10 @@ static int userfaultfd_stress(void)
int err; int err;
unsigned long userfaults[nr_cpus]; unsigned long userfaults[nr_cpus];
allocate_area((void **)&area_src); uffd_test_ops->allocate_area((void **)&area_src);
if (!area_src) if (!area_src)
return 1; return 1;
allocate_area((void **)&area_dst); uffd_test_ops->allocate_area((void **)&area_dst);
if (!area_dst) if (!area_dst)
return 1; return 1;
...@@ -856,7 +871,7 @@ static int userfaultfd_stress(void) ...@@ -856,7 +871,7 @@ static int userfaultfd_stress(void)
fprintf(stderr, "register failure\n"); fprintf(stderr, "register failure\n");
return 1; return 1;
} }
expected_ioctls = EXPECTED_IOCTLS; expected_ioctls = uffd_test_ops->expected_ioctls;
if ((uffdio_register.ioctls & expected_ioctls) != if ((uffdio_register.ioctls & expected_ioctls) !=
expected_ioctls) { expected_ioctls) {
fprintf(stderr, fprintf(stderr,
...@@ -888,7 +903,7 @@ static int userfaultfd_stress(void) ...@@ -888,7 +903,7 @@ static int userfaultfd_stress(void)
* MADV_DONTNEED only after the UFFDIO_REGISTER, so it's * MADV_DONTNEED only after the UFFDIO_REGISTER, so it's
* required to MADV_DONTNEED here. * required to MADV_DONTNEED here.
*/ */
if (release_pages(area_dst)) if (uffd_test_ops->release_pages(area_dst))
return 1; return 1;
/* bounce pass */ /* bounce pass */
...@@ -934,36 +949,6 @@ static int userfaultfd_stress(void) ...@@ -934,36 +949,6 @@ static int userfaultfd_stress(void)
return userfaultfd_zeropage_test() || userfaultfd_events_test(); return userfaultfd_zeropage_test() || userfaultfd_events_test();
} }
#ifndef HUGETLB_TEST
int main(int argc, char **argv)
{
if (argc < 3)
fprintf(stderr, "Usage: <MiB> <bounces>\n"), exit(1);
nr_cpus = sysconf(_SC_NPROCESSORS_ONLN);
page_size = sysconf(_SC_PAGE_SIZE);
if ((unsigned long) area_count(NULL, 0) + sizeof(unsigned long long) * 2
> page_size)
fprintf(stderr, "Impossible to run this test\n"), exit(2);
nr_pages_per_cpu = atol(argv[1]) * 1024*1024 / page_size /
nr_cpus;
if (!nr_pages_per_cpu) {
fprintf(stderr, "invalid MiB\n");
fprintf(stderr, "Usage: <MiB> <bounces>\n"), exit(1);
}
bounces = atoi(argv[2]);
if (bounces <= 0) {
fprintf(stderr, "invalid bounces\n");
fprintf(stderr, "Usage: <MiB> <bounces>\n"), exit(1);
}
nr_pages = nr_pages_per_cpu * nr_cpus;
printf("nr_pages: %lu, nr_pages_per_cpu: %lu\n",
nr_pages, nr_pages_per_cpu);
return userfaultfd_stress();
}
#else /* HUGETLB_TEST */
/* /*
* Copied from mlock2-tests.c * Copied from mlock2-tests.c
*/ */
...@@ -988,48 +973,78 @@ unsigned long default_huge_page_size(void) ...@@ -988,48 +973,78 @@ unsigned long default_huge_page_size(void)
return hps; return hps;
} }
int main(int argc, char **argv) static void set_test_type(const char *type)
{ {
if (argc < 4) if (!strcmp(type, "anon")) {
fprintf(stderr, "Usage: <MiB> <bounces> <hugetlbfs_file>\n"), test_type = TEST_ANON;
exit(1); uffd_test_ops = &anon_uffd_test_ops;
nr_cpus = sysconf(_SC_NPROCESSORS_ONLN); } else if (!strcmp(type, "hugetlb")) {
page_size = default_huge_page_size(); test_type = TEST_HUGETLB;
uffd_test_ops = &hugetlb_uffd_test_ops;
} else if (!strcmp(type, "shmem")) {
test_type = TEST_SHMEM;
uffd_test_ops = &shmem_uffd_test_ops;
} else {
fprintf(stderr, "Unknown test type: %s\n", type), exit(1);
}
if (test_type == TEST_HUGETLB)
page_size = default_huge_page_size();
else
page_size = sysconf(_SC_PAGE_SIZE);
if (!page_size) if (!page_size)
fprintf(stderr, "Unable to determine huge page size\n"), fprintf(stderr, "Unable to determine page size\n"),
exit(2); exit(2);
if ((unsigned long) area_count(NULL, 0) + sizeof(unsigned long long) * 2 if ((unsigned long) area_count(NULL, 0) + sizeof(unsigned long long) * 2
> page_size) > page_size)
fprintf(stderr, "Impossible to run this test\n"), exit(2); fprintf(stderr, "Impossible to run this test\n"), exit(2);
nr_pages_per_cpu = atol(argv[1]) * 1024*1024 / page_size / }
int main(int argc, char **argv)
{
if (argc < 4)
fprintf(stderr, "Usage: <test type> <MiB> <bounces> [hugetlbfs_file]\n"),
exit(1);
set_test_type(argv[1]);
nr_cpus = sysconf(_SC_NPROCESSORS_ONLN);
nr_pages_per_cpu = atol(argv[2]) * 1024*1024 / page_size /
nr_cpus; nr_cpus;
if (!nr_pages_per_cpu) { if (!nr_pages_per_cpu) {
fprintf(stderr, "invalid MiB\n"); fprintf(stderr, "invalid MiB\n");
fprintf(stderr, "Usage: <MiB> <bounces>\n"), exit(1); fprintf(stderr, "Usage: <MiB> <bounces>\n"), exit(1);
} }
bounces = atoi(argv[2]);
bounces = atoi(argv[3]);
if (bounces <= 0) { if (bounces <= 0) {
fprintf(stderr, "invalid bounces\n"); fprintf(stderr, "invalid bounces\n");
fprintf(stderr, "Usage: <MiB> <bounces>\n"), exit(1); fprintf(stderr, "Usage: <MiB> <bounces>\n"), exit(1);
} }
nr_pages = nr_pages_per_cpu * nr_cpus; nr_pages = nr_pages_per_cpu * nr_cpus;
huge_fd = open(argv[3], O_CREAT | O_RDWR, 0755);
if (huge_fd < 0) { if (test_type == TEST_HUGETLB) {
fprintf(stderr, "Open of %s failed", argv[3]); if (argc < 5)
perror("open"); fprintf(stderr, "Usage: hugetlb <MiB> <bounces> <hugetlbfs_file>\n"),
exit(1); exit(1);
} huge_fd = open(argv[4], O_CREAT | O_RDWR, 0755);
if (ftruncate(huge_fd, 0)) { if (huge_fd < 0) {
fprintf(stderr, "ftruncate %s to size 0 failed", argv[3]); fprintf(stderr, "Open of %s failed", argv[3]);
perror("ftruncate"); perror("open");
exit(1); exit(1);
}
if (ftruncate(huge_fd, 0)) {
fprintf(stderr, "ftruncate %s to size 0 failed", argv[3]);
perror("ftruncate");
exit(1);
}
} }
printf("nr_pages: %lu, nr_pages_per_cpu: %lu\n", printf("nr_pages: %lu, nr_pages_per_cpu: %lu\n",
nr_pages, nr_pages_per_cpu); nr_pages, nr_pages_per_cpu);
return userfaultfd_stress(); return userfaultfd_stress();
} }
#endif
#else /* __NR_userfaultfd */ #else /* __NR_userfaultfd */
#warning "missing __NR_userfaultfd definition" #warning "missing __NR_userfaultfd definition"
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment