Patch "userfaultfd/selftests: fix hugetlb area allocations" has been added to the 5.15-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is a note to let you know that I've just added the patch titled

    userfaultfd/selftests: fix hugetlb area allocations

to the 5.15-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     userfaultfd-selftests-fix-hugetlb-area-allocations.patch
and it can be found in the queue-5.15 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit 4fa34242c1451b24c9b94a9e5292e00aca9b9ce3
Author: Mike Kravetz <mike.kravetz@xxxxxxxxxx>
Date:   Thu Dec 30 20:12:31 2021 -0800

    userfaultfd/selftests: fix hugetlb area allocations
    
    [ Upstream commit f5c73297181c6b3ad76537bad98eaad6d29b9333 ]
    
    Currently, userfaultfd selftest for hugetlb as run from run_vmtests.sh
    or any environment where there are 'just enough' hugetlb pages will
    always fail with:
    
      testing events (fork, remap, remove):
                    ERROR: UFFDIO_COPY error: -12 (errno=12, line=616)
    
    The ENOMEM error code implies there are not enough hugetlb pages.
    However, there are free hugetlb pages but they are all reserved.  There
    is a basic problem with the way the test allocates hugetlb pages which
    has existed since the test was originally written.
    
    Due to the way 'cleanup' was done between different phases of the test,
    this issue was masked until recently.  The issue was uncovered by commit
    8ba6e8640844 ("userfaultfd/selftests: reinitialize test context in each
    test").
    
    For the hugetlb test, src and dst areas are allocated as PRIVATE
    mappings of a hugetlb file.  This means that at mmap time, pages are
    reserved for the src and dst areas.  At the start of event testing (and
    other tests) the src area is populated which results in allocation of
    huge pages to fill the area and consumption of reserves associated with
    the area.  Then, a child is forked to fault in the dst area.  Note that
    the dst area was allocated in the parent and hence the parent owns the
    reserves associated with the mapping.  The child has normal access to
    the dst area, but can not use the reserves created/owned by the parent.
    Thus, if there are no other huge pages available allocation of a page
    for the dst by the child will fail.
    
    Fix by not creating reserves for the dst area.  In this way the child
    can use free (non-reserved) pages.
    
    Also, MAP_PRIVATE of a file only makes sense if you are interested in
    the contents of the file before making a COW copy.  The test does not do
    this.  So, just use MAP_ANONYMOUS | MAP_HUGETLB to create an anonymous
    hugetlb mapping.  There is no need to create a hugetlb file in the
    non-shared case.
    
    Link: https://lkml.kernel.org/r/20211217172919.7861-1-mike.kravetz@xxxxxxxxxx
    Signed-off-by: Mike Kravetz <mike.kravetz@xxxxxxxxxx>
    Cc: Axel Rasmussen <axelrasmussen@xxxxxxxxxx>
    Cc: Peter Xu <peterx@xxxxxxxxxx>
    Cc: Andrea Arcangeli <aarcange@xxxxxxxxxx>
    Cc: Mina Almasry <almasrymina@xxxxxxxxxx>
    Cc: Shuah Khan <shuah@xxxxxxxxxx>
    Signed-off-by: Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx>
    Signed-off-by: Linus Torvalds <torvalds@xxxxxxxxxxxxxxxxxxxx>
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/tools/testing/selftests/vm/userfaultfd.c b/tools/testing/selftests/vm/userfaultfd.c
index 60aa1a4fc69b6..81690f1737c80 100644
--- a/tools/testing/selftests/vm/userfaultfd.c
+++ b/tools/testing/selftests/vm/userfaultfd.c
@@ -86,7 +86,7 @@ static bool test_uffdio_minor = false;
 
 static bool map_shared;
 static int shm_fd;
-static int huge_fd;
+static int huge_fd = -1;	/* only used for hugetlb_shared test */
 static char *huge_fd_off0;
 static unsigned long long *count_verify;
 static int uffd = -1;
@@ -222,6 +222,9 @@ static void noop_alias_mapping(__u64 *start, size_t len, unsigned long offset)
 
 static void hugetlb_release_pages(char *rel_area)
 {
+	if (huge_fd == -1)
+		return;
+
 	if (fallocate(huge_fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
 		      rel_area == huge_fd_off0 ? 0 : nr_pages * page_size,
 		      nr_pages * page_size))
@@ -234,16 +237,17 @@ static void hugetlb_allocate_area(void **alloc_area)
 	char **alloc_area_alias;
 
 	*alloc_area = mmap(NULL, nr_pages * page_size, PROT_READ | PROT_WRITE,
-			   (map_shared ? MAP_SHARED : MAP_PRIVATE) |
-			   MAP_HUGETLB,
-			   huge_fd, *alloc_area == area_src ? 0 :
-			   nr_pages * page_size);
+			   map_shared ? MAP_SHARED :
+			   MAP_PRIVATE | MAP_HUGETLB |
+			   (*alloc_area == area_src ? 0 : MAP_NORESERVE),
+			   huge_fd,
+			   *alloc_area == area_src ? 0 : nr_pages * page_size);
 	if (*alloc_area == MAP_FAILED)
 		err("mmap of hugetlbfs file failed");
 
 	if (map_shared) {
 		area_alias = mmap(NULL, nr_pages * page_size, PROT_READ | PROT_WRITE,
-				  MAP_SHARED | MAP_HUGETLB,
+				  MAP_SHARED,
 				  huge_fd, *alloc_area == area_src ? 0 :
 				  nr_pages * page_size);
 		if (area_alias == MAP_FAILED)



[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux