Commit 9ae8f2b8 authored by Mike Kravetz's avatar Mike Kravetz Committed by Linus Torvalds

userfaultfd/selftests: enable hugetlb remap and remove event testing

With MADV_DONTNEED support added to hugetlb mappings, mremap testing can
also be enabled for hugetlb.

Modify the tests to use madvise MADV_DONTNEED and MADV_REMOVE instead of
fallocate hole puch for releasing hugetlb pages.

Link: https://lkml.kernel.org/r/20220215002348.128823-4-mike.kravetz@oracle.comSigned-off-by: default avatarMike Kravetz <mike.kravetz@oracle.com>
Reviewed-by: default avatarAxel Rasmussen <axelrasmussen@google.com>
Cc: Andrea Arcangeli <aarcange@redhat.com>
Cc: David Hildenbrand <david@redhat.com>
Cc: Michal Hocko <mhocko@suse.com>
Cc: Mike Rapoport <rppt@kernel.org>
Cc: Mina Almasry <almasrymina@google.com>
Cc: Naoya Horiguchi <naoya.horiguchi@linux.dev>
Cc: Peter Xu <peterx@redhat.com>
Cc: Shuah Khan <skhan@linuxfoundation.org>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent c4b6cb88
...@@ -208,14 +208,13 @@ echo "running userfaultfd_hugetlb" ...@@ -208,14 +208,13 @@ echo "running userfaultfd_hugetlb"
echo "---------------------------" echo "---------------------------"
# Test requires source and destination huge pages. Size of source # Test requires source and destination huge pages. Size of source
# (half_ufd_size_MB) is passed as argument to test. # (half_ufd_size_MB) is passed as argument to test.
./userfaultfd hugetlb $half_ufd_size_MB 32 $mnt/ufd_test_file ./userfaultfd hugetlb $half_ufd_size_MB 32
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
echo "[FAIL]" echo "[FAIL]"
exitcode=1 exitcode=1
else else
echo "[PASS]" echo "[PASS]"
fi fi
rm -f $mnt/ufd_test_file
echo "-------------------------" echo "-------------------------"
echo "running userfaultfd_shmem" echo "running userfaultfd_shmem"
......
...@@ -89,7 +89,6 @@ static bool test_uffdio_minor = false; ...@@ -89,7 +89,6 @@ static bool test_uffdio_minor = false;
static bool map_shared; static bool map_shared;
static int shm_fd; static int shm_fd;
static int huge_fd; static int huge_fd;
static char *huge_fd_off0;
static unsigned long long *count_verify; static unsigned long long *count_verify;
static int uffd = -1; static int uffd = -1;
static int uffd_flags, finished, *pipefd; static int uffd_flags, finished, *pipefd;
...@@ -128,9 +127,9 @@ const char *examples = ...@@ -128,9 +127,9 @@ const char *examples =
"./userfaultfd anon 100 99999\n\n" "./userfaultfd anon 100 99999\n\n"
"# Run share memory test on 1GiB region with 99 bounces:\n" "# Run share memory test on 1GiB region with 99 bounces:\n"
"./userfaultfd shmem 1000 99\n\n" "./userfaultfd shmem 1000 99\n\n"
"# Run hugetlb memory test on 256MiB region with 50 bounces (using /dev/hugepages/hugefile):\n" "# Run hugetlb memory test on 256MiB region with 50 bounces:\n"
"./userfaultfd hugetlb 256 50 /dev/hugepages/hugefile\n\n" "./userfaultfd hugetlb 256 50\n\n"
"# Run the same hugetlb test but using shmem:\n" "# Run the same hugetlb test but using shared file:\n"
"./userfaultfd hugetlb_shared 256 50 /dev/hugepages/hugefile\n\n" "./userfaultfd hugetlb_shared 256 50 /dev/hugepages/hugefile\n\n"
"# 10MiB-~6GiB 999 bounces anonymous test, " "# 10MiB-~6GiB 999 bounces anonymous test, "
"continue forever unless an error triggers\n" "continue forever unless an error triggers\n"
...@@ -227,10 +226,13 @@ static void noop_alias_mapping(__u64 *start, size_t len, unsigned long offset) ...@@ -227,10 +226,13 @@ static void noop_alias_mapping(__u64 *start, size_t len, unsigned long offset)
static void hugetlb_release_pages(char *rel_area) static void hugetlb_release_pages(char *rel_area)
{ {
if (fallocate(huge_fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, if (!map_shared) {
rel_area == huge_fd_off0 ? 0 : nr_pages * page_size, if (madvise(rel_area, nr_pages * page_size, MADV_DONTNEED))
nr_pages * page_size)) err("madvise(MADV_DONTNEED) failed");
err("fallocate() failed"); } else {
if (madvise(rel_area, nr_pages * page_size, MADV_REMOVE))
err("madvise(MADV_REMOVE) failed");
}
} }
static void hugetlb_allocate_area(void **alloc_area) static void hugetlb_allocate_area(void **alloc_area)
...@@ -238,26 +240,37 @@ static void hugetlb_allocate_area(void **alloc_area) ...@@ -238,26 +240,37 @@ static void hugetlb_allocate_area(void **alloc_area)
void *area_alias = NULL; void *area_alias = NULL;
char **alloc_area_alias; char **alloc_area_alias;
*alloc_area = mmap(NULL, nr_pages * page_size, PROT_READ | PROT_WRITE, if (!map_shared)
(map_shared ? MAP_SHARED : MAP_PRIVATE) | *alloc_area = mmap(NULL,
MAP_HUGETLB | nr_pages * page_size,
PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB |
(*alloc_area == area_src ? 0 : MAP_NORESERVE),
-1,
0);
else
*alloc_area = mmap(NULL,
nr_pages * page_size,
PROT_READ | PROT_WRITE,
MAP_SHARED |
(*alloc_area == area_src ? 0 : MAP_NORESERVE), (*alloc_area == area_src ? 0 : MAP_NORESERVE),
huge_fd, *alloc_area == area_src ? 0 : huge_fd,
nr_pages * page_size); *alloc_area == area_src ? 0 : nr_pages * page_size);
if (*alloc_area == MAP_FAILED) if (*alloc_area == MAP_FAILED)
err("mmap of hugetlbfs file failed"); err("mmap of hugetlbfs file failed");
if (map_shared) { if (map_shared) {
area_alias = mmap(NULL, nr_pages * page_size, PROT_READ | PROT_WRITE, area_alias = mmap(NULL,
MAP_SHARED | MAP_HUGETLB, nr_pages * page_size,
huge_fd, *alloc_area == area_src ? 0 : PROT_READ | PROT_WRITE,
nr_pages * page_size); MAP_SHARED,
huge_fd,
*alloc_area == area_src ? 0 : nr_pages * page_size);
if (area_alias == MAP_FAILED) if (area_alias == MAP_FAILED)
err("mmap of hugetlb file alias failed"); err("mmap of hugetlb file alias failed");
} }
if (*alloc_area == area_src) { if (*alloc_area == area_src) {
huge_fd_off0 = *alloc_area;
alloc_area_alias = &area_src_alias; alloc_area_alias = &area_src_alias;
} else { } else {
alloc_area_alias = &area_dst_alias; alloc_area_alias = &area_dst_alias;
...@@ -270,12 +283,7 @@ static void hugetlb_alias_mapping(__u64 *start, size_t len, unsigned long offset ...@@ -270,12 +283,7 @@ static void hugetlb_alias_mapping(__u64 *start, size_t len, unsigned long offset
{ {
if (!map_shared) if (!map_shared)
return; return;
/*
* We can't zap just the pagetable with hugetlbfs because
* MADV_DONTEED won't work. So exercise -EEXIST on a alias
* mapping where the pagetables are not established initially,
* this way we'll exercise the -EEXEC at the fs level.
*/
*start = (unsigned long) area_dst_alias + offset; *start = (unsigned long) area_dst_alias + offset;
} }
...@@ -428,7 +436,6 @@ static void uffd_test_ctx_clear(void) ...@@ -428,7 +436,6 @@ static void uffd_test_ctx_clear(void)
uffd = -1; uffd = -1;
} }
huge_fd_off0 = NULL;
munmap_area((void **)&area_src); munmap_area((void **)&area_src);
munmap_area((void **)&area_src_alias); munmap_area((void **)&area_src_alias);
munmap_area((void **)&area_dst); munmap_area((void **)&area_dst);
...@@ -926,10 +933,7 @@ static int faulting_process(int signal_test) ...@@ -926,10 +933,7 @@ static int faulting_process(int signal_test)
struct sigaction act; struct sigaction act;
unsigned long signalled = 0; unsigned long signalled = 0;
if (test_type != TEST_HUGETLB)
split_nr_pages = (nr_pages + 1) / 2; split_nr_pages = (nr_pages + 1) / 2;
else
split_nr_pages = nr_pages;
if (signal_test) { if (signal_test) {
sigbuf = &jbuf; sigbuf = &jbuf;
...@@ -986,9 +990,6 @@ static int faulting_process(int signal_test) ...@@ -986,9 +990,6 @@ static int faulting_process(int signal_test)
if (signal_test) if (signal_test)
return signalled != split_nr_pages; return signalled != split_nr_pages;
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)
...@@ -1676,7 +1677,7 @@ int main(int argc, char **argv) ...@@ -1676,7 +1677,7 @@ int main(int argc, char **argv)
} }
nr_pages = nr_pages_per_cpu * nr_cpus; nr_pages = nr_pages_per_cpu * nr_cpus;
if (test_type == TEST_HUGETLB) { if (test_type == TEST_HUGETLB && map_shared) {
if (argc < 5) if (argc < 5)
usage(); usage();
huge_fd = open(argv[4], O_CREAT | O_RDWR, 0755); huge_fd = open(argv[4], O_CREAT | O_RDWR, 0755);
......
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