Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

selftests: add a MREMAP_DONTUNMAP selftest for shmem

This test extends the current mremap tests to validate that the
MREMAP_DONTUNMAP operation can be performed on shmem mappings.

Link: https://lkml.kernel.org/r/20210323182520.2712101-3-bgeffon@google.com
Signed-off-by: Brian Geffon <bgeffon@google.com>
Cc: Axel Rasmussen <axelrasmussen@google.com>
Cc: Lokesh Gidra <lokeshgidra@google.com>
Cc: Mike Rapoport <rppt@linux.vnet.ibm.com>
Cc: Peter Xu <peterx@redhat.com>
Cc: Hugh Dickins <hughd@google.com>
Cc: "Michael S . Tsirkin" <mst@redhat.com>
Cc: Brian Geffon <bgeffon@google.com>
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Vlastimil Babka <vbabka@suse.cz>
Cc: Andrea Arcangeli <aarcange@redhat.com>
Cc: Sonny Rao <sonnyrao@google.com>
Cc: Minchan Kim <minchan@kernel.org>
Cc: "Kirill A . Shutemov" <kirill@shutemov.name>
Cc: Dmitry Safonov <dima@arista.com>
Cc: Michael Kerrisk <mtk.manpages@gmail.com>
Cc: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Brian Geffon and committed by
Linus Torvalds
85931004 14d07113

+52
+52
tools/testing/selftests/vm/mremap_dontunmap.c
··· 127 127 "unable to unmap source mapping"); 128 128 } 129 129 130 + // This test validates that MREMAP_DONTUNMAP on a shared mapping works as expected. 131 + static void mremap_dontunmap_simple_shmem() 132 + { 133 + unsigned long num_pages = 5; 134 + 135 + int mem_fd = memfd_create("memfd", MFD_CLOEXEC); 136 + BUG_ON(mem_fd < 0, "memfd_create"); 137 + 138 + BUG_ON(ftruncate(mem_fd, num_pages * page_size) < 0, 139 + "ftruncate"); 140 + 141 + void *source_mapping = 142 + mmap(NULL, num_pages * page_size, PROT_READ | PROT_WRITE, 143 + MAP_FILE | MAP_SHARED, mem_fd, 0); 144 + BUG_ON(source_mapping == MAP_FAILED, "mmap"); 145 + 146 + BUG_ON(close(mem_fd) < 0, "close"); 147 + 148 + memset(source_mapping, 'a', num_pages * page_size); 149 + 150 + // Try to just move the whole mapping anywhere (not fixed). 151 + void *dest_mapping = 152 + mremap(source_mapping, num_pages * page_size, num_pages * page_size, 153 + MREMAP_DONTUNMAP | MREMAP_MAYMOVE, NULL); 154 + if (dest_mapping == MAP_FAILED && errno == EINVAL) { 155 + // Old kernel which doesn't support MREMAP_DONTUNMAP on shmem. 156 + BUG_ON(munmap(source_mapping, num_pages * page_size) == -1, 157 + "unable to unmap source mapping"); 158 + return; 159 + } 160 + 161 + BUG_ON(dest_mapping == MAP_FAILED, "mremap"); 162 + 163 + // Validate that the pages have been moved, we know they were moved if 164 + // the dest_mapping contains a's. 165 + BUG_ON(check_region_contains_byte 166 + (dest_mapping, num_pages * page_size, 'a') != 0, 167 + "pages did not migrate"); 168 + 169 + // Because the region is backed by shmem, we will actually see the same 170 + // memory at the source location still. 171 + BUG_ON(check_region_contains_byte 172 + (source_mapping, num_pages * page_size, 'a') != 0, 173 + "source should have no ptes"); 174 + 175 + BUG_ON(munmap(dest_mapping, num_pages * page_size) == -1, 176 + "unable to unmap destination mapping"); 177 + BUG_ON(munmap(source_mapping, num_pages * page_size) == -1, 178 + "unable to unmap source mapping"); 179 + } 180 + 130 181 // This test validates MREMAP_DONTUNMAP will move page tables to a specific 131 182 // destination using MREMAP_FIXED, also while validating that the source 132 183 // remains intact. ··· 351 300 BUG_ON(page_buffer == MAP_FAILED, "unable to mmap a page."); 352 301 353 302 mremap_dontunmap_simple(); 303 + mremap_dontunmap_simple_shmem(); 354 304 mremap_dontunmap_simple_fixed(); 355 305 mremap_dontunmap_partial_mapping(); 356 306 mremap_dontunmap_partial_mapping_overwrite();