Skip to content

Commit b2a79f6

Browse files
t-8chakpm00
authored andcommitted
selftests/mm: virtual_address_range: unmap chunks after validation
For each accessed chunk a PTE is created. More than 1GiB of PTEs is used in this way. Remove each PTE after validating a chunk to reduce peak memory usage. It is important to only unmap memory that previously mmap()ed, as unmapping other mappings like the stack, heap or executable mappings will crash the process. The mappings read from /proc/self/maps and the return values from mmap() don't allow a simple correlation due to merging and no guaranteed order. To correlate the pointers and mappings use prctl(PR_SET_VMA_ANON_NAME). While it introduces a test dependency, other alternatives would introduce runtime or development overhead. Link: https://lkml.kernel.org/r/20250114-virtual_address_range-tests-v4-2-6fd7269934a5@linutronix.de Fixes: 0104096 ("selftests/mm: confirm VA exhaustion without reliance on correctness of mmap()") Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de> Acked-by: David Hildenbrand <david@redhat.com> Cc: Anshuman Khandual <khandual@linux.vnet.ibm.com> Cc: Dev Jain <dev.jain@arm.com> Cc: kernel test robot <oliver.sang@intel.com> Cc: Shuah Khan (Samsung OSG) <shuah@kernel.org> Cc: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
1 parent a005145 commit b2a79f6

File tree

2 files changed

+32
-2
lines changed

2 files changed

+32
-2
lines changed

tools/testing/selftests/mm/config

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@ CONFIG_TEST_HMM=m
77
CONFIG_GUP_TEST=y
88
CONFIG_TRANSPARENT_HUGEPAGE=y
99
CONFIG_MEM_SOFT_DIRTY=y
10+
CONFIG_ANON_VMA_NAME=y

tools/testing/selftests/mm/virtual_address_range.c

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <string.h>
1111
#include <unistd.h>
1212
#include <errno.h>
13+
#include <sys/prctl.h>
1314
#include <sys/mman.h>
1415
#include <sys/time.h>
1516
#include <fcntl.h>
@@ -82,6 +83,24 @@ static void validate_addr(char *ptr, int high_addr)
8283
ksft_exit_fail_msg("Bad address %lx\n", addr);
8384
}
8485

86+
static void mark_range(char *ptr, size_t size)
87+
{
88+
if (prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, ptr, size, "virtual_address_range") == -1) {
89+
if (errno == EINVAL) {
90+
/* Depends on CONFIG_ANON_VMA_NAME */
91+
ksft_test_result_skip("prctl(PR_SET_VMA_ANON_NAME) not supported\n");
92+
ksft_finished();
93+
} else {
94+
ksft_exit_fail_perror("prctl(PR_SET_VMA_ANON_NAME) failed\n");
95+
}
96+
}
97+
}
98+
99+
static int is_marked_vma(const char *vma_name)
100+
{
101+
return vma_name && !strcmp(vma_name, "[anon:virtual_address_range]\n");
102+
}
103+
85104
static int validate_lower_address_hint(void)
86105
{
87106
char *ptr;
@@ -116,12 +135,17 @@ static int validate_complete_va_space(void)
116135

117136
prev_end_addr = 0;
118137
while (fgets(line, sizeof(line), file)) {
138+
const char *vma_name = NULL;
139+
int vma_name_start = 0;
119140
unsigned long hop;
120141

121-
if (sscanf(line, "%lx-%lx %s[rwxp-]",
122-
&start_addr, &end_addr, prot) != 3)
142+
if (sscanf(line, "%lx-%lx %4s %*s %*s %*s %n",
143+
&start_addr, &end_addr, prot, &vma_name_start) != 3)
123144
ksft_exit_fail_msg("cannot parse /proc/self/maps\n");
124145

146+
if (vma_name_start)
147+
vma_name = line + vma_name_start;
148+
125149
/* end of userspace mappings; ignore vsyscall mapping */
126150
if (start_addr & (1UL << 63))
127151
return 0;
@@ -149,6 +173,9 @@ static int validate_complete_va_space(void)
149173
return 1;
150174
lseek(fd, 0, SEEK_SET);
151175

176+
if (is_marked_vma(vma_name))
177+
munmap((char *)(start_addr + hop), MAP_CHUNK_SIZE);
178+
152179
hop += MAP_CHUNK_SIZE;
153180
}
154181
}
@@ -175,6 +202,7 @@ int main(int argc, char *argv[])
175202
break;
176203
}
177204

205+
mark_range(ptr[i], MAP_CHUNK_SIZE);
178206
validate_addr(ptr[i], 0);
179207
}
180208
lchunks = i;
@@ -192,6 +220,7 @@ int main(int argc, char *argv[])
192220
if (hptr[i] == MAP_FAILED)
193221
break;
194222

223+
mark_range(ptr[i], MAP_CHUNK_SIZE);
195224
validate_addr(hptr[i], 1);
196225
}
197226
hchunks = i;

0 commit comments

Comments
 (0)