* [PATCH v4] selftests/mm: khugepaged: initialize file contents via mmap
@ 2026-04-28 13:31 Vineet Agarwal
2026-04-28 13:49 ` David Hildenbrand (Arm)
2026-04-28 19:56 ` Zi Yan
0 siblings, 2 replies; 9+ messages in thread
From: Vineet Agarwal @ 2026-04-28 13:31 UTC (permalink / raw)
To: akpm, david, ljs, shuah
Cc: linux-mm, linux-kselftest, linux-kernel, Vineet Agarwal
file_setup_area() currently allocates anonymous memory, fills it,
and writes it into the backing file used for collapse testing.
Instead of copying data through write(), resize the file with
ftruncate(), map it directly with MAP_SHARED, and initialize the
mapped area in place.
This simplifies the setup path and avoids the need for explicit
partial write handling.
Signed-off-by: Vineet Agarwal <agarwal.vineet2006@gmail.com>
v3 -> v4:
- Restore unrelated blank line removal
- Restore original close()/munmap() ordering
---
tools/testing/selftests/mm/khugepaged.c | 14 ++++++++++++--
1 file changed, 12 insertions(+), 2 deletions(-)
diff --git a/tools/testing/selftests/mm/khugepaged.c b/tools/testing/selftests/mm/khugepaged.c
index 3fe7ef04ac62..6e929a484a1b 100644
--- a/tools/testing/selftests/mm/khugepaged.c
+++ b/tools/testing/selftests/mm/khugepaged.c
@@ -381,9 +381,19 @@ static void *file_setup_area(int nr_hpages)
}
size = nr_hpages * hpage_pmd_size;
- p = alloc_mapping(nr_hpages);
+ if (ftruncate(fd, size)) {
+ perror("ftruncate()");
+ close(fd);
+ exit(EXIT_FAILURE);
+ }
+ p = mmap(BASE_ADDR, size, PROT_READ | PROT_WRITE,
+ MAP_SHARED, fd, 0);
+ if (p == MAP_FAILED || p != BASE_ADDR) {
+ perror("mmap()");
+ close(fd);
+ exit(EXIT_FAILURE);
+ }
fill_memory(p, 0, size);
- write(fd, p, size);
close(fd);
munmap(p, size);
success("OK");
--
2.54.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH v4] selftests/mm: khugepaged: initialize file contents via mmap
2026-04-28 13:31 [PATCH v4] selftests/mm: khugepaged: initialize file contents via mmap Vineet Agarwal
@ 2026-04-28 13:49 ` David Hildenbrand (Arm)
2026-04-28 19:56 ` Zi Yan
1 sibling, 0 replies; 9+ messages in thread
From: David Hildenbrand (Arm) @ 2026-04-28 13:49 UTC (permalink / raw)
To: Vineet Agarwal, akpm, ljs, shuah; +Cc: linux-mm, linux-kselftest, linux-kernel
On 4/28/26 15:31, Vineet Agarwal wrote:
> file_setup_area() currently allocates anonymous memory, fills it,
> and writes it into the backing file used for collapse testing.
>
> Instead of copying data through write(), resize the file with
> ftruncate(), map it directly with MAP_SHARED, and initialize the
> mapped area in place.
>
> This simplifies the setup path and avoids the need for explicit
> partial write handling.
>
> Signed-off-by: Vineet Agarwal <agarwal.vineet2006@gmail.com>
>
> v3 -> v4:
> - Restore unrelated blank line removal
> - Restore original close()/munmap() ordering
> ---
> tools/testing/selftests/mm/khugepaged.c | 14 ++++++++++++--
> 1 file changed, 12 insertions(+), 2 deletions(-)
>
> diff --git a/tools/testing/selftests/mm/khugepaged.c b/tools/testing/selftests/mm/khugepaged.c
> index 3fe7ef04ac62..6e929a484a1b 100644
> --- a/tools/testing/selftests/mm/khugepaged.c
> +++ b/tools/testing/selftests/mm/khugepaged.c
> @@ -381,9 +381,19 @@ static void *file_setup_area(int nr_hpages)
> }
>
> size = nr_hpages * hpage_pmd_size;
> - p = alloc_mapping(nr_hpages);
> + if (ftruncate(fd, size)) {
> + perror("ftruncate()");
> + close(fd);
> + exit(EXIT_FAILURE);
> + }
> + p = mmap(BASE_ADDR, size, PROT_READ | PROT_WRITE,
> + MAP_SHARED, fd, 0);
> + if (p == MAP_FAILED || p != BASE_ADDR) {
p != BASE_ADDR
is sufficient as it includes p == MAP_FAILED.
> + perror("mmap()");
> + close(fd);
> + exit(EXIT_FAILURE);
> + }
> fill_memory(p, 0, size);
> - write(fd, p, size);
> close(fd);
> munmap(p, size);
> success("OK");
Thanks!
Acked-by: David Hildenbrand (Arm) <david@kernel.org>
--
Cheers,
David
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v4] selftests/mm: khugepaged: initialize file contents via mmap
2026-04-28 13:31 [PATCH v4] selftests/mm: khugepaged: initialize file contents via mmap Vineet Agarwal
2026-04-28 13:49 ` David Hildenbrand (Arm)
@ 2026-04-28 19:56 ` Zi Yan
2026-04-28 20:07 ` David Hildenbrand (Arm)
1 sibling, 1 reply; 9+ messages in thread
From: Zi Yan @ 2026-04-28 19:56 UTC (permalink / raw)
To: Vineet Agarwal
Cc: akpm, david, ljs, shuah, linux-mm, linux-kselftest, linux-kernel
On 28 Apr 2026, at 9:31, Vineet Agarwal wrote:
> file_setup_area() currently allocates anonymous memory, fills it,
> and writes it into the backing file used for collapse testing.
>
> Instead of copying data through write(), resize the file with
> ftruncate(), map it directly with MAP_SHARED, and initialize the
> mapped area in place.
>
> This simplifies the setup path and avoids the need for explicit
> partial write handling.
>
> Signed-off-by: Vineet Agarwal <agarwal.vineet2006@gmail.com>
>
> v3 -> v4:
> - Restore unrelated blank line removal
> - Restore original close()/munmap() ordering
> ---
> tools/testing/selftests/mm/khugepaged.c | 14 ++++++++++++--
> 1 file changed, 12 insertions(+), 2 deletions(-)
This patch breaks the khugepaged test for READ_ONLY_THP_FOR_FS.
When I ran sudo ./khugepaged all:file ~/ on ext4,
collapse_max_ptes_none (khugepaged:file) fails.
Run test: collapse_max_ptes_none (khugepaged:file)
Creating /mnt/test/collapse_test_file for collapse... OK
Opening /mnt/test/collapse_test_file read only for collapse... OK
Maybe collapse with max_ptes_none exceeded.... Fail
Unexpected huge page
Restore THP and khugepaged settings... OK
Reverting the change fixes the issue.
It is also causing issues for my READ_ONLY_THP_FOR_FS removal patchset.
>
> diff --git a/tools/testing/selftests/mm/khugepaged.c b/tools/testing/selftests/mm/khugepaged.c
> index 3fe7ef04ac62..6e929a484a1b 100644
> --- a/tools/testing/selftests/mm/khugepaged.c
> +++ b/tools/testing/selftests/mm/khugepaged.c
> @@ -381,9 +381,19 @@ static void *file_setup_area(int nr_hpages)
> }
>
> size = nr_hpages * hpage_pmd_size;
> - p = alloc_mapping(nr_hpages);
> + if (ftruncate(fd, size)) {
> + perror("ftruncate()");
> + close(fd);
> + exit(EXIT_FAILURE);
> + }
> + p = mmap(BASE_ADDR, size, PROT_READ | PROT_WRITE,
> + MAP_SHARED, fd, 0);
> + if (p == MAP_FAILED || p != BASE_ADDR) {
> + perror("mmap()");
> + close(fd);
> + exit(EXIT_FAILURE);
> + }
> fill_memory(p, 0, size);
> - write(fd, p, size);
> close(fd);
> munmap(p, size);
> success("OK");
> --
> 2.54.0
The code looks OK, but I have not had time to look into it yet.
Best Regards,
Yan, Zi
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v4] selftests/mm: khugepaged: initialize file contents via mmap
2026-04-28 19:56 ` Zi Yan
@ 2026-04-28 20:07 ` David Hildenbrand (Arm)
2026-04-28 20:17 ` Zi Yan
0 siblings, 1 reply; 9+ messages in thread
From: David Hildenbrand (Arm) @ 2026-04-28 20:07 UTC (permalink / raw)
To: Zi Yan, Vineet Agarwal
Cc: akpm, ljs, shuah, linux-mm, linux-kselftest, linux-kernel
On 4/28/26 21:56, Zi Yan wrote:
> On 28 Apr 2026, at 9:31, Vineet Agarwal wrote:
>
>> file_setup_area() currently allocates anonymous memory, fills it,
>> and writes it into the backing file used for collapse testing.
>>
>> Instead of copying data through write(), resize the file with
>> ftruncate(), map it directly with MAP_SHARED, and initialize the
>> mapped area in place.
>>
>> This simplifies the setup path and avoids the need for explicit
>> partial write handling.
>>
>> Signed-off-by: Vineet Agarwal <agarwal.vineet2006@gmail.com>
>>
>> v3 -> v4:
>> - Restore unrelated blank line removal
>> - Restore original close()/munmap() ordering
>> ---
>> tools/testing/selftests/mm/khugepaged.c | 14 ++++++++++++--
>> 1 file changed, 12 insertions(+), 2 deletions(-)
>
> This patch breaks the khugepaged test for READ_ONLY_THP_FOR_FS.
>
> When I ran sudo ./khugepaged all:file ~/ on ext4,
>
> collapse_max_ptes_none (khugepaged:file) fails.
madvise() still works? Is it maybe because of dirty folios? (but that should
also be the case on write ...)
--
Cheers,
David
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v4] selftests/mm: khugepaged: initialize file contents via mmap
2026-04-28 20:07 ` David Hildenbrand (Arm)
@ 2026-04-28 20:17 ` Zi Yan
2026-04-28 20:19 ` David Hildenbrand (Arm)
0 siblings, 1 reply; 9+ messages in thread
From: Zi Yan @ 2026-04-28 20:17 UTC (permalink / raw)
To: David Hildenbrand (Arm)
Cc: Vineet Agarwal, akpm, ljs, shuah, linux-mm, linux-kselftest,
linux-kernel
On 28 Apr 2026, at 16:07, David Hildenbrand (Arm) wrote:
> On 4/28/26 21:56, Zi Yan wrote:
>> On 28 Apr 2026, at 9:31, Vineet Agarwal wrote:
>>
>>> file_setup_area() currently allocates anonymous memory, fills it,
>>> and writes it into the backing file used for collapse testing.
>>>
>>> Instead of copying data through write(), resize the file with
>>> ftruncate(), map it directly with MAP_SHARED, and initialize the
>>> mapped area in place.
>>>
>>> This simplifies the setup path and avoids the need for explicit
>>> partial write handling.
>>>
>>> Signed-off-by: Vineet Agarwal <agarwal.vineet2006@gmail.com>
>>>
>>> v3 -> v4:
>>> - Restore unrelated blank line removal
>>> - Restore original close()/munmap() ordering
>>> ---
>>> tools/testing/selftests/mm/khugepaged.c | 14 ++++++++++++--
>>> 1 file changed, 12 insertions(+), 2 deletions(-)
>>
>> This patch breaks the khugepaged test for READ_ONLY_THP_FOR_FS.
>>
>> When I ran sudo ./khugepaged all:file ~/ on ext4,
>>
>> collapse_max_ptes_none (khugepaged:file) fails.
>
> madvise() still works? Is it maybe because of dirty folios? (but that should
> also be the case on write ...)
I asked codex instead.
Basically, mmap(MMAP_SHARED) makes the written folio dirty and the folio
survives the later drop_caches. Adding msync() fixes the issue.
The patch below fixes the issue.
From fdf796e52a94b7e21614c8cfb6cc947146221d28 Mon Sep 17 00:00:00 2001
From: Zi Yan <ziy@nvidia.com>
Date: Tue, 28 Apr 2026 16:12:08 -0400
Subject: [PATCH] flush dirty folio so that drop_caches can work
Signed-off-by: Zi Yan <ziy@nvidia.com>
---
tools/testing/selftests/mm/khugepaged.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/tools/testing/selftests/mm/khugepaged.c b/tools/testing/selftests/mm/khugepaged.c
index 87ca031cb7225..ac645d96285da 100644
--- a/tools/testing/selftests/mm/khugepaged.c
+++ b/tools/testing/selftests/mm/khugepaged.c
@@ -399,6 +399,7 @@ static void *file_setup_area_common(int nr_hpages, bool read_only)
exit(EXIT_FAILURE);
}
fill_memory(p, 0, size);
+ msync(p, size, MS_SYNC);
close(fd);
munmap(p, size);
success("OK");
--
2.53.0
Best Regards,
Yan, Zi
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH v4] selftests/mm: khugepaged: initialize file contents via mmap
2026-04-28 20:17 ` Zi Yan
@ 2026-04-28 20:19 ` David Hildenbrand (Arm)
2026-04-28 20:22 ` Zi Yan
0 siblings, 1 reply; 9+ messages in thread
From: David Hildenbrand (Arm) @ 2026-04-28 20:19 UTC (permalink / raw)
To: Zi Yan
Cc: Vineet Agarwal, akpm, ljs, shuah, linux-mm, linux-kselftest,
linux-kernel
On 4/28/26 22:17, Zi Yan wrote:
> On 28 Apr 2026, at 16:07, David Hildenbrand (Arm) wrote:
>
>> On 4/28/26 21:56, Zi Yan wrote:
>>>
>>>
>>> This patch breaks the khugepaged test for READ_ONLY_THP_FOR_FS.
>>>
>>> When I ran sudo ./khugepaged all:file ~/ on ext4,
>>>
>>> collapse_max_ptes_none (khugepaged:file) fails.
>>
>> madvise() still works? Is it maybe because of dirty folios? (but that should
>> also be the case on write ...)
>
> I asked codex instead.
>
> Basically, mmap(MMAP_SHARED) makes the written folio dirty and the folio
> survives the later drop_caches. Adding msync() fixes the issue.
But why doesn't the write() make the folios dirty? Or are we running into some
race condition where the old code just worked by chance?
--
Cheers,
David
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v4] selftests/mm: khugepaged: initialize file contents via mmap
2026-04-28 20:19 ` David Hildenbrand (Arm)
@ 2026-04-28 20:22 ` Zi Yan
2026-04-28 20:23 ` Zi Yan
0 siblings, 1 reply; 9+ messages in thread
From: Zi Yan @ 2026-04-28 20:22 UTC (permalink / raw)
To: David Hildenbrand (Arm)
Cc: Vineet Agarwal, akpm, ljs, shuah, linux-mm, linux-kselftest,
linux-kernel
On 28 Apr 2026, at 16:19, David Hildenbrand (Arm) wrote:
> On 4/28/26 22:17, Zi Yan wrote:
>> On 28 Apr 2026, at 16:07, David Hildenbrand (Arm) wrote:
>>
>>> On 4/28/26 21:56, Zi Yan wrote:
>>>>
>>>>
>>>> This patch breaks the khugepaged test for READ_ONLY_THP_FOR_FS.
>>>>
>>>> When I ran sudo ./khugepaged all:file ~/ on ext4,
>>>>
>>>> collapse_max_ptes_none (khugepaged:file) fails.
>>>
>>> madvise() still works? Is it maybe because of dirty folios? (but that should
>>> also be the case on write ...)
>>
>> I asked codex instead.
>>
>> Basically, mmap(MMAP_SHARED) makes the written folio dirty and the folio
>> survives the later drop_caches. Adding msync() fixes the issue.
>
> But why doesn't the write() make the folios dirty? Or are we running into some
> race condition where the old code just worked by chance?
>
The fd is opened with O_DSYNC, so the data from write() is transferred to
disk when write() returns.
Best Regards,
Yan, Zi
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v4] selftests/mm: khugepaged: initialize file contents via mmap
2026-04-28 20:22 ` Zi Yan
@ 2026-04-28 20:23 ` Zi Yan
2026-04-29 6:24 ` David Hildenbrand (Arm)
0 siblings, 1 reply; 9+ messages in thread
From: Zi Yan @ 2026-04-28 20:23 UTC (permalink / raw)
To: David Hildenbrand (Arm)
Cc: Vineet Agarwal, akpm, ljs, shuah, linux-mm, linux-kselftest,
linux-kernel
On 28 Apr 2026, at 16:22, Zi Yan wrote:
> On 28 Apr 2026, at 16:19, David Hildenbrand (Arm) wrote:
>
>> On 4/28/26 22:17, Zi Yan wrote:
>>> On 28 Apr 2026, at 16:07, David Hildenbrand (Arm) wrote:
>>>
>>>> On 4/28/26 21:56, Zi Yan wrote:
>>>>>
>>>>>
>>>>> This patch breaks the khugepaged test for READ_ONLY_THP_FOR_FS.
>>>>>
>>>>> When I ran sudo ./khugepaged all:file ~/ on ext4,
>>>>>
>>>>> collapse_max_ptes_none (khugepaged:file) fails.
>>>>
>>>> madvise() still works? Is it maybe because of dirty folios? (but that should
>>>> also be the case on write ...)
>>>
>>> I asked codex instead.
>>>
>>> Basically, mmap(MMAP_SHARED) makes the written folio dirty and the folio
>>> survives the later drop_caches. Adding msync() fixes the issue.
>>
>> But why doesn't the write() make the folios dirty? Or are we running into some
>> race condition where the old code just worked by chance?
>>
>
> The fd is opened with O_DSYNC, so the data from write() is transferred to
> disk when write() returns.
And the folio is clean.
Best Regards,
Yan, Zi
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v4] selftests/mm: khugepaged: initialize file contents via mmap
2026-04-28 20:23 ` Zi Yan
@ 2026-04-29 6:24 ` David Hildenbrand (Arm)
0 siblings, 0 replies; 9+ messages in thread
From: David Hildenbrand (Arm) @ 2026-04-29 6:24 UTC (permalink / raw)
To: Zi Yan
Cc: Vineet Agarwal, akpm, ljs, shuah, linux-mm, linux-kselftest,
linux-kernel
On 4/28/26 22:23, Zi Yan wrote:
> On 28 Apr 2026, at 16:22, Zi Yan wrote:
>
>> On 28 Apr 2026, at 16:19, David Hildenbrand (Arm) wrote:
>>
>>>
>>> But why doesn't the write() make the folios dirty? Or are we running into some
>>> race condition where the old code just worked by chance?
>>>
>>
>> The fd is opened with O_DSYNC, so the data from write() is transferred to
>> disk when write() returns.
>
> And the folio is clean.
Ah, I missed the O_DSYNC. That makes sense, thanks.
v2 actually contained the msync. So I assume we could then drop the O_DSYNC.
Note: there is no need to close the file or munmap before the exit on the error
path.
The following works for me
diff --git a/tools/testing/selftests/mm/khugepaged.c
b/tools/testing/selftests/mm/khugepaged.c
index 3fe7ef04ac62..5862a3213840 100644
--- a/tools/testing/selftests/mm/khugepaged.c
+++ b/tools/testing/selftests/mm/khugepaged.c
@@ -373,7 +373,7 @@ static void *file_setup_area(int nr_hpages)
unlink(finfo.path); /* Cleanup from previous failed tests */
printf("Creating %s for collapse%s...", finfo.path,
finfo.type == VMA_SHMEM ? " (tmpfs)" : "");
- fd = open(finfo.path, O_DSYNC | O_CREAT | O_RDWR | O_TRUNC | O_EXCL,
+ fd = open(finfo.path, O_CREAT | O_RDWR | O_TRUNC | O_EXCL,
777);
if (fd < 0) {
perror("open()");
@@ -381,9 +381,21 @@ static void *file_setup_area(int nr_hpages)
}
size = nr_hpages * hpage_pmd_size;
- p = alloc_mapping(nr_hpages);
+ if (ftruncate(fd, size)) {
+ perror("ftruncate()");
+ exit(EXIT_FAILURE);
+ }
+ p = mmap(BASE_ADDR, size, PROT_READ | PROT_WRITE,
+ MAP_SHARED, fd, 0);
+ if (p != BASE_ADDR) {
+ perror("mmap()");
+ exit(EXIT_FAILURE);
+ }
fill_memory(p, 0, size);
- write(fd, p, size);
+ if (msync(p, size, MS_SYNC)) {
+ perror("msync()");
+ exit(EXIT_FAILURE);
+ }
close(fd);
munmap(p, size);
success("OK");
--
Cheers,
David
^ permalink raw reply related [flat|nested] 9+ messages in thread
end of thread, other threads:[~2026-04-29 6:24 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-04-28 13:31 [PATCH v4] selftests/mm: khugepaged: initialize file contents via mmap Vineet Agarwal
2026-04-28 13:49 ` David Hildenbrand (Arm)
2026-04-28 19:56 ` Zi Yan
2026-04-28 20:07 ` David Hildenbrand (Arm)
2026-04-28 20:17 ` Zi Yan
2026-04-28 20:19 ` David Hildenbrand (Arm)
2026-04-28 20:22 ` Zi Yan
2026-04-28 20:23 ` Zi Yan
2026-04-29 6:24 ` David Hildenbrand (Arm)
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox