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

mm, hugepages: make memory size variable in hugepage-mremap selftest

The hugetlb vma mremap() test currently maps 1GB of memory to trigger
pmd sharing and make sure that 'unshare' path in mremap code works. The
test originally only mapped 10MB of memory (as specified by the header
comment) but was later modified to 1GB to tackle this case.

However, not all machines will have 1GB of memory to spare for this
test. Adding a mapping size arg will allow run_vmtest.sh to pass an
adequate mapping size, while allowing users to run the test
independently with arbitrary size mappings.

Link: https://lkml.kernel.org/r/20211124203805.3700355-1-yosryahmed@google.com
Signed-off-by: Yosry Ahmed <yosryahmed@google.com>
Cc: Shuah Khan <shuah@kernel.org>
Cc: Mina Almasry <almasrymina@google.com>
Cc: Mike Kravetz <mike.kravetz@oracle.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Yosry Ahmed and committed by
Linus Torvalds
f77a286d f4776199

+31 -17
+30 -16
tools/testing/selftests/vm/hugepage-mremap.c
··· 4 4 * 5 5 * Example of remapping huge page memory in a user application using the 6 6 * mremap system call. Code assumes a hugetlbfs filesystem is mounted 7 - * at './huge'. The code will use 10MB worth of huge pages. 7 + * at './huge'. The amount of memory used by this test is decided by a command 8 + * line argument in MBs. If missing, the default amount is 10MB. 9 + * 10 + * To make sure the test triggers pmd sharing and goes through the 'unshare' 11 + * path in the mremap code use 1GB (1024) or more. 8 12 */ 9 13 10 14 #define _GNU_SOURCE ··· 22 18 #include <linux/userfaultfd.h> 23 19 #include <sys/ioctl.h> 24 20 25 - #define LENGTH (1UL * 1024 * 1024 * 1024) 21 + #define DEFAULT_LENGTH_MB 10UL 22 + #define MB_TO_BYTES(x) (x * 1024 * 1024) 26 23 24 + #define FILE_NAME "huge/hugepagefile" 27 25 #define PROTECTION (PROT_READ | PROT_WRITE | PROT_EXEC) 28 26 #define FLAGS (MAP_SHARED | MAP_ANONYMOUS) 29 27 ··· 34 28 printf("First hex is %x\n", *((unsigned int *)addr)); 35 29 } 36 30 37 - static void write_bytes(char *addr) 31 + static void write_bytes(char *addr, size_t len) 38 32 { 39 33 unsigned long i; 40 34 41 - for (i = 0; i < LENGTH; i++) 35 + for (i = 0; i < len; i++) 42 36 *(addr + i) = (char)i; 43 37 } 44 38 45 - static int read_bytes(char *addr) 39 + static int read_bytes(char *addr, size_t len) 46 40 { 47 41 unsigned long i; 48 42 49 43 check_bytes(addr); 50 - for (i = 0; i < LENGTH; i++) 44 + for (i = 0; i < len; i++) 51 45 if (*(addr + i) != (char)i) { 52 46 printf("Mismatch at %lu\n", i); 53 47 return 1; ··· 105 99 } 106 100 } 107 101 108 - int main(void) 102 + int main(int argc, char *argv[]) 109 103 { 104 + /* Read memory length as the first arg if valid, otherwise fallback to 105 + * the default length. Any additional args are ignored. 106 + */ 107 + size_t length = argc > 1 ? (size_t)atoi(argv[1]) : 0UL; 108 + 109 + length = length > 0 ? length : DEFAULT_LENGTH_MB; 110 + length = MB_TO_BYTES(length); 111 + 110 112 int ret = 0; 111 113 112 - int fd = open("/huge/test", O_CREAT | O_RDWR, 0755); 114 + int fd = open(FILE_NAME, O_CREAT | O_RDWR, 0755); 113 115 114 116 if (fd < 0) { 115 117 perror("Open failed"); ··· 126 112 127 113 /* mmap to a PUD aligned address to hopefully trigger pmd sharing. */ 128 114 unsigned long suggested_addr = 0x7eaa40000000; 129 - void *haddr = mmap((void *)suggested_addr, LENGTH, PROTECTION, 115 + void *haddr = mmap((void *)suggested_addr, length, PROTECTION, 130 116 MAP_HUGETLB | MAP_SHARED | MAP_POPULATE, fd, 0); 131 117 printf("Map haddr: Returned address is %p\n", haddr); 132 118 if (haddr == MAP_FAILED) { ··· 136 122 137 123 /* mmap again to a dummy address to hopefully trigger pmd sharing. */ 138 124 suggested_addr = 0x7daa40000000; 139 - void *daddr = mmap((void *)suggested_addr, LENGTH, PROTECTION, 125 + void *daddr = mmap((void *)suggested_addr, length, PROTECTION, 140 126 MAP_HUGETLB | MAP_SHARED | MAP_POPULATE, fd, 0); 141 127 printf("Map daddr: Returned address is %p\n", daddr); 142 128 if (daddr == MAP_FAILED) { ··· 146 132 147 133 suggested_addr = 0x7faa40000000; 148 134 void *vaddr = 149 - mmap((void *)suggested_addr, LENGTH, PROTECTION, FLAGS, -1, 0); 135 + mmap((void *)suggested_addr, length, PROTECTION, FLAGS, -1, 0); 150 136 printf("Map vaddr: Returned address is %p\n", vaddr); 151 137 if (vaddr == MAP_FAILED) { 152 138 perror("mmap2"); 153 139 exit(1); 154 140 } 155 141 156 - register_region_with_uffd(haddr, LENGTH); 142 + register_region_with_uffd(haddr, length); 157 143 158 - void *addr = mremap(haddr, LENGTH, LENGTH, 144 + void *addr = mremap(haddr, length, length, 159 145 MREMAP_MAYMOVE | MREMAP_FIXED, vaddr); 160 146 if (addr == MAP_FAILED) { 161 147 perror("mremap"); ··· 164 150 165 151 printf("Mremap: Returned address is %p\n", addr); 166 152 check_bytes(addr); 167 - write_bytes(addr); 168 - ret = read_bytes(addr); 153 + write_bytes(addr, length); 154 + ret = read_bytes(addr, length); 169 155 170 - munmap(addr, LENGTH); 156 + munmap(addr, length); 171 157 172 158 return ret; 173 159 }
+1 -1
tools/testing/selftests/vm/run_vmtests.sh
··· 111 111 echo "-----------------------" 112 112 echo "running hugepage-mremap" 113 113 echo "-----------------------" 114 - ./hugepage-mremap 114 + ./hugepage-mremap 256 115 115 if [ $? -ne 0 ]; then 116 116 echo "[FAIL]" 117 117 exitcode=1