* [PATCH v3 0/2] fix MAP_DROPPABLE not supported errno
@ 2026-04-09 23:49 Anthony Yznaga
2026-04-09 23:49 ` [PATCH v3 1/2] mm: fix mmap errno value when MAP_DROPPABLE is not supported Anthony Yznaga
2026-04-09 23:49 ` [PATCH v3 2/2] selftests/mm: verify droppable mappings cannot be locked Anthony Yznaga
0 siblings, 2 replies; 7+ messages in thread
From: Anthony Yznaga @ 2026-04-09 23:49 UTC (permalink / raw)
To: linux-mm, linux-kernel, linux-kselftest
Cc: akpm, david, ljs, Liam.Howlett, vbabka, rppt, surenb, mhocko,
jannh, pfalcato, Jason, shuah
Mark Brown reported seeing a regression in -next on 32 bit arm with the
mlock selftests. Before exiting and marking the tests failed, the following
message was logged after an attempt to create a MAP_DROPPABLE mapping:
Bail out! mmap error: Unknown error 524
It turns out error 524 is ENOTSUPP which is an error that userspace is not
supposed to see, but it indicates in this instance that MAP_DROPPABLE is
not supported.
The first patch changes the errno returned to EOPNOTSUPP. The second patch
is a second version of a prior patch to introduce selftests to verify
locking behavior with droppable mappings with the additional change to skip
the tests when MAP_DROPPABLE is not supported.
v3:
- Added acked-by's and reviewed-by's to patch 1
- Addressed sashiko AI reviewbot questions:
- Call munlockall() if test_mlockall_future_droppable() returns early
- Skip the tests if they are compiled for an older kernel without
MAP_DROPPABLE.
v2:
- Remove unnecessary mlock() call from selftest (DavidH)
- Change tests to not exit on failure (DavidH)
Anthony Yznaga (2):
mm: fix mmap errno value when MAP_DROPPABLE is not supported
selftests/mm: verify droppable mappings cannot be locked
mm/mmap.c | 2 +-
tools/testing/selftests/mm/mlock2-tests.c | 100 ++++++++++++++++++++--
2 files changed, 92 insertions(+), 10 deletions(-)
--
2.47.3
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v3 1/2] mm: fix mmap errno value when MAP_DROPPABLE is not supported
2026-04-09 23:49 [PATCH v3 0/2] fix MAP_DROPPABLE not supported errno Anthony Yznaga
@ 2026-04-09 23:49 ` Anthony Yznaga
2026-04-09 23:49 ` [PATCH v3 2/2] selftests/mm: verify droppable mappings cannot be locked Anthony Yznaga
1 sibling, 0 replies; 7+ messages in thread
From: Anthony Yznaga @ 2026-04-09 23:49 UTC (permalink / raw)
To: linux-mm, linux-kernel, linux-kselftest
Cc: akpm, david, ljs, Liam.Howlett, vbabka, rppt, surenb, mhocko,
jannh, pfalcato, Jason, shuah
On configs where MAP_DROPPABLE is not supported (currently any 32-bit
config except for PPC32), mmap fails with errno set to ENOTSUPP.
However, ENOTSUPP is not a standard error value that userspace knows
about. The acceptable userspace-visible errno to use is EOPNOTSUPP.
checkpatch.pl has a warning to this effect.
Fixes: 9651fcedf7b9 ("mm: add MAP_DROPPABLE for designating always lazily freeable mappings")
Cc: <stable@vger.kernel.org>
Signed-off-by: Anthony Yznaga <anthony.yznaga@oracle.com>
Acked-by: David Hildenbrand <david@kernel.org>
Acked-by: Vlastimil Babka (SUSE) <vbabka@kernel.org>
Reported-by: Mark Brown <broonie@kernel.org>
Reviewed-by: Pedro Falcato <pfalcato@suse.de>
Reviewed-by: Lorenzo Stoakes (Oracle) <ljs@kernel.org>
---
mm/mmap.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/mm/mmap.c b/mm/mmap.c
index 5754d1c36462..2311ae7c2ff4 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -504,7 +504,7 @@ unsigned long do_mmap(struct file *file, unsigned long addr,
break;
case MAP_DROPPABLE:
if (VM_DROPPABLE == VM_NONE)
- return -ENOTSUPP;
+ return -EOPNOTSUPP;
/*
* A locked or stack area makes no sense to be droppable.
*
--
2.47.3
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v3 2/2] selftests/mm: verify droppable mappings cannot be locked
2026-04-09 23:49 [PATCH v3 0/2] fix MAP_DROPPABLE not supported errno Anthony Yznaga
2026-04-09 23:49 ` [PATCH v3 1/2] mm: fix mmap errno value when MAP_DROPPABLE is not supported Anthony Yznaga
@ 2026-04-09 23:49 ` Anthony Yznaga
2026-04-10 7:57 ` David Hildenbrand (Arm)
1 sibling, 1 reply; 7+ messages in thread
From: Anthony Yznaga @ 2026-04-09 23:49 UTC (permalink / raw)
To: linux-mm, linux-kernel, linux-kselftest
Cc: akpm, david, ljs, Liam.Howlett, vbabka, rppt, surenb, mhocko,
jannh, pfalcato, Jason, shuah
For configs that support MAP_DROPPABLE verify that a mapping created
with MAP_DROPPABLE cannot be locked via mlock(), and that it will not
be locked if it's created after mlockall(MCL_FUTURE).
Signed-off-by: Anthony Yznaga <anthony.yznaga@oracle.com>
---
tools/testing/selftests/mm/mlock2-tests.c | 100 ++++++++++++++++++++--
1 file changed, 91 insertions(+), 9 deletions(-)
diff --git a/tools/testing/selftests/mm/mlock2-tests.c b/tools/testing/selftests/mm/mlock2-tests.c
index b474f2b20def..47da1a05c243 100644
--- a/tools/testing/selftests/mm/mlock2-tests.c
+++ b/tools/testing/selftests/mm/mlock2-tests.c
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
#define _GNU_SOURCE
#include <sys/mman.h>
+#include <linux/mman.h>
#include <stdint.h>
#include <unistd.h>
#include <string.h>
@@ -163,14 +164,17 @@ static int lock_check(unsigned long addr)
return (vma_rss == vma_size);
}
-static int unlock_lock_check(char *map)
+static int unlock_lock_check(char *map, bool mlock_supported)
{
- if (is_vmflag_set((unsigned long)map, LOCKED)) {
+ if (!is_vmflag_set((unsigned long)map, LOCKED))
+ return 0;
+
+ if (mlock_supported)
ksft_print_msg("VMA flag %s is present on page 1 after unlock\n", LOCKED);
- return 1;
- }
+ else
+ ksft_print_msg("VMA flag %s is present on an unsupported VMA\n", LOCKED);
- return 0;
+ return 1;
}
static void test_mlock_lock(void)
@@ -196,7 +200,7 @@ static void test_mlock_lock(void)
ksft_exit_fail_msg("munlock(): %s\n", strerror(errno));
}
- ksft_test_result(!unlock_lock_check(map), "%s: Unlocked\n", __func__);
+ ksft_test_result(!unlock_lock_check(map, true), "%s: Unlocked\n", __func__);
munmap(map, 2 * page_size);
}
@@ -296,7 +300,7 @@ static void test_munlockall0(void)
ksft_exit_fail_msg("munlockall(): %s\n", strerror(errno));
}
- ksft_test_result(!unlock_lock_check(map), "%s: No locked memory\n", __func__);
+ ksft_test_result(!unlock_lock_check(map, true), "%s: No locked memory\n", __func__);
munmap(map, 2 * page_size);
}
@@ -336,9 +340,85 @@ static void test_munlockall1(void)
ksft_exit_fail_msg("munlockall() %s\n", strerror(errno));
}
- ksft_test_result(!unlock_lock_check(map), "%s: No locked memory\n", __func__);
+ ksft_test_result(!unlock_lock_check(map, true), "%s: No locked memory\n", __func__);
+ munmap(map, 2 * page_size);
+}
+
+#ifdef MAP_DROPPABLE
+/*
+ * Droppable memory should not be lockable.
+ */
+static void test_mlock_droppable(void)
+{
+ char *map;
+ unsigned long page_size = getpagesize();
+
+ /*
+ * Ensure MCL_FUTURE is not set.
+ */
+ if (munlockall()) {
+ ksft_test_result_fail("munlockall() %s\n", strerror(errno));
+ return;
+ }
+
+ map = mmap(NULL, 2 * page_size, PROT_READ | PROT_WRITE,
+ MAP_ANONYMOUS | MAP_DROPPABLE, -1, 0);
+ if (map == MAP_FAILED) {
+ if (errno == EOPNOTSUPP)
+ ksft_test_result_skip("%s: MAP_DROPPABLE not supported\n", __func__);
+ else
+ ksft_test_result_fail("mmap error: %s\n", strerror(errno));
+ return;
+ }
+
+ if (mlock2_(map, 2 * page_size, 0))
+ ksft_test_result_fail("mlock2(0): %s\n", strerror(errno));
+ else
+ ksft_test_result(!unlock_lock_check(map, false),
+ "%s: droppable memory not locked\n", __func__);
+
+ munmap(map, 2 * page_size);
+}
+
+static void test_mlockall_future_droppable(void)
+{
+ char *map;
+ unsigned long page_size = getpagesize();
+
+ if (mlockall(MCL_CURRENT | MCL_FUTURE)) {
+ ksft_test_result_fail("mlockall(MCL_CURRENT | MCL_FUTURE): %s\n", strerror(errno));
+ return;
+ }
+
+ map = mmap(NULL, 2 * page_size, PROT_READ | PROT_WRITE,
+ MAP_ANONYMOUS | MAP_DROPPABLE, -1, 0);
+
+ if (map == MAP_FAILED) {
+ if (errno == EOPNOTSUPP)
+ ksft_test_result_skip("%s: MAP_DROPPABLE not supported\n", __func__);
+ else
+ ksft_test_result_fail("mmap error: %s\n", strerror(errno));
+ munlockall();
+ return;
+ }
+
+ ksft_test_result(!unlock_lock_check(map, false), "%s: droppable memory not locked\n",
+ __func__);
+
+ munlockall();
munmap(map, 2 * page_size);
}
+#else
+static void test_mlock_droppable(void)
+{
+ ksft_test_result_skip("%s: MAP_DROPPABLE not supported\n", __func__);
+}
+
+static void test_mlockall_future_droppable(void)
+{
+ ksft_test_result_skip("%s: MAP_DROPPABLE not supported\n", __func__);
+}
+#endif /* MAP_DROPPABLE */
static void test_vma_management(bool call_mlock)
{
@@ -442,7 +522,7 @@ int main(int argc, char **argv)
munmap(map, size);
- ksft_set_plan(13);
+ ksft_set_plan(15);
test_mlock_lock();
test_mlock_onfault();
@@ -451,6 +531,8 @@ int main(int argc, char **argv)
test_lock_onfault_of_present();
test_vma_management(true);
test_mlockall();
+ test_mlock_droppable();
+ test_mlockall_future_droppable();
ksft_finished();
}
--
2.47.3
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v3 2/2] selftests/mm: verify droppable mappings cannot be locked
2026-04-09 23:49 ` [PATCH v3 2/2] selftests/mm: verify droppable mappings cannot be locked Anthony Yznaga
@ 2026-04-10 7:57 ` David Hildenbrand (Arm)
2026-04-10 19:06 ` anthony.yznaga
0 siblings, 1 reply; 7+ messages in thread
From: David Hildenbrand (Arm) @ 2026-04-10 7:57 UTC (permalink / raw)
To: Anthony Yznaga, linux-mm, linux-kernel, linux-kselftest
Cc: akpm, ljs, Liam.Howlett, vbabka, rppt, surenb, mhocko, jannh,
pfalcato, Jason, shuah
On 4/10/26 01:49, Anthony Yznaga wrote:
> For configs that support MAP_DROPPABLE verify that a mapping created
> with MAP_DROPPABLE cannot be locked via mlock(), and that it will not
> be locked if it's created after mlockall(MCL_FUTURE).
>
> Signed-off-by: Anthony Yznaga <anthony.yznaga@oracle.com>
> ---
[...]
> +
> +#ifdef MAP_DROPPABLE
> +/*
> + * Droppable memory should not be lockable.
> + */
Single-line comment.
> +static void test_mlock_droppable(void)
> +{
> + char *map;
> + unsigned long page_size = getpagesize();
We could store that in a static global and query it once during main().
Feel free to keep it as is.
> +
> + /*
> + * Ensure MCL_FUTURE is not set.
> + */
Dito.
> + if (munlockall()) {
> + ksft_test_result_fail("munlockall() %s\n", strerror(errno));
> + return;
> + }
> +
> + map = mmap(NULL, 2 * page_size, PROT_READ | PROT_WRITE,
> + MAP_ANONYMOUS | MAP_DROPPABLE, -1, 0);
> + if (map == MAP_FAILED) {
> + if (errno == EOPNOTSUPP)
> + ksft_test_result_skip("%s: MAP_DROPPABLE not supported\n", __func__);
> + else
> + ksft_test_result_fail("mmap error: %s\n", strerror(errno));
> + return;
> + }
> +
> + if (mlock2_(map, 2 * page_size, 0))
Weird, is "mlock2_" actually correct? (not "mlock2") ?
> + ksft_test_result_fail("mlock2(0): %s\n", strerror(errno));
> + else
> + ksft_test_result(!unlock_lock_check(map, false),
> + "%s: droppable memory not locked\n", __func__);
> +
> + munmap(map, 2 * page_size);
> +}
> +
> +static void test_mlockall_future_droppable(void)
> +{
> + char *map;
> + unsigned long page_size = getpagesize();
> +
> + if (mlockall(MCL_CURRENT | MCL_FUTURE)) {
> + ksft_test_result_fail("mlockall(MCL_CURRENT | MCL_FUTURE): %s\n", strerror(errno));
> + return;
> + }
> +
> + map = mmap(NULL, 2 * page_size, PROT_READ | PROT_WRITE,
> + MAP_ANONYMOUS | MAP_DROPPABLE, -1, 0);
> +
> + if (map == MAP_FAILED) {
> + if (errno == EOPNOTSUPP)
> + ksft_test_result_skip("%s: MAP_DROPPABLE not supported\n", __func__);
> + else
> + ksft_test_result_fail("mmap error: %s\n", strerror(errno));
> + munlockall();
> + return;
> + }
> +
> + ksft_test_result(!unlock_lock_check(map, false), "%s: droppable memory not locked\n",
> + __func__);
> +
> + munlockall();
> munmap(map, 2 * page_size);
> }
> +#else
> +static void test_mlock_droppable(void)
> +{
> + ksft_test_result_skip("%s: MAP_DROPPABLE not supported\n", __func__);
> +}
> +
> +static void test_mlockall_future_droppable(void)
> +{
> + ksft_test_result_skip("%s: MAP_DROPPABLE not supported\n", __func__);
> +}
> +#endif /* MAP_DROPPABLE */
>
Why not a above a
#ifndef MAP_DROPPABLE
#define MAP_DROPPABLE 0x08
#endif
instead?
> static void test_vma_management(bool call_mlock)
> {
> @@ -442,7 +522,7 @@ int main(int argc, char **argv)
>
> munmap(map, size);
>
> - ksft_set_plan(13);
> + ksft_set_plan(15);
>
> test_mlock_lock();
> test_mlock_onfault();
> @@ -451,6 +531,8 @@ int main(int argc, char **argv)
> test_lock_onfault_of_present();
> test_vma_management(true);
> test_mlockall();
> + test_mlock_droppable();
> + test_mlockall_future_droppable();
>
> ksft_finished();
> }
Feel free to add
Acked-by: David Hildenbrand (Arm) <david@kernel.org>
--
Cheers,
David
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v3 2/2] selftests/mm: verify droppable mappings cannot be locked
2026-04-10 7:57 ` David Hildenbrand (Arm)
@ 2026-04-10 19:06 ` anthony.yznaga
2026-04-13 19:46 ` David Hildenbrand (Arm)
0 siblings, 1 reply; 7+ messages in thread
From: anthony.yznaga @ 2026-04-10 19:06 UTC (permalink / raw)
To: David Hildenbrand (Arm), linux-mm, linux-kernel, linux-kselftest
Cc: akpm, ljs, Liam.Howlett, vbabka, rppt, surenb, mhocko, jannh,
pfalcato, Jason, shuah
On 4/10/26 12:57 AM, David Hildenbrand (Arm) wrote:
> On 4/10/26 01:49, Anthony Yznaga wrote:
>> For configs that support MAP_DROPPABLE verify that a mapping created
>> with MAP_DROPPABLE cannot be locked via mlock(), and that it will not
>> be locked if it's created after mlockall(MCL_FUTURE).
>>
>> Signed-off-by: Anthony Yznaga <anthony.yznaga@oracle.com>
>> ---
>
> [...]
>
>> +
>> +#ifdef MAP_DROPPABLE
>> +/*
>> + * Droppable memory should not be lockable.
>> + */
> Single-line comment.
Okay.
>
>> +static void test_mlock_droppable(void)
>> +{
>> + char *map;
>> + unsigned long page_size = getpagesize();
> We could store that in a static global and query it once during main().
> Feel free to keep it as is.
>
>> +
>> + /*
>> + * Ensure MCL_FUTURE is not set.
>> + */
> Dito.
>
>> + if (munlockall()) {
>> + ksft_test_result_fail("munlockall() %s\n", strerror(errno));
>> + return;
>> + }
>> +
>> + map = mmap(NULL, 2 * page_size, PROT_READ | PROT_WRITE,
>> + MAP_ANONYMOUS | MAP_DROPPABLE, -1, 0);
>> + if (map == MAP_FAILED) {
>> + if (errno == EOPNOTSUPP)
>> + ksft_test_result_skip("%s: MAP_DROPPABLE not supported\n", __func__);
>> + else
>> + ksft_test_result_fail("mmap error: %s\n", strerror(errno));
>> + return;
>> + }
>> +
>> + if (mlock2_(map, 2 * page_size, 0))
> Weird, is "mlock2_" actually correct? (not "mlock2") ?
It's correct though mlock2 would also work since it's been in glibc for
several years now. I just matched the existing tests. mlock2_ is a
simple wrapper around syscall in tools/testing/selftests/mm/mlock2.h,
and it was introduced when the mlock2 syscall was introduced. A trailing
rather than a preceding underscore is...unfortunate.
>
>> + ksft_test_result_fail("mlock2(0): %s\n", strerror(errno));
>> + else
>> + ksft_test_result(!unlock_lock_check(map, false),
>> + "%s: droppable memory not locked\n", __func__);
>> +
>> + munmap(map, 2 * page_size);
>> +}
>> +
>> +static void test_mlockall_future_droppable(void)
>> +{
>> + char *map;
>> + unsigned long page_size = getpagesize();
>> +
>> + if (mlockall(MCL_CURRENT | MCL_FUTURE)) {
>> + ksft_test_result_fail("mlockall(MCL_CURRENT | MCL_FUTURE): %s\n", strerror(errno));
>> + return;
>> + }
>> +
>> + map = mmap(NULL, 2 * page_size, PROT_READ | PROT_WRITE,
>> + MAP_ANONYMOUS | MAP_DROPPABLE, -1, 0);
>> +
>> + if (map == MAP_FAILED) {
>> + if (errno == EOPNOTSUPP)
>> + ksft_test_result_skip("%s: MAP_DROPPABLE not supported\n", __func__);
>> + else
>> + ksft_test_result_fail("mmap error: %s\n", strerror(errno));
>> + munlockall();
>> + return;
>> + }
>> +
>> + ksft_test_result(!unlock_lock_check(map, false), "%s: droppable memory not locked\n",
>> + __func__);
>> +
>> + munlockall();
>> munmap(map, 2 * page_size);
>> }
>> +#else
>> +static void test_mlock_droppable(void)
>> +{
>> + ksft_test_result_skip("%s: MAP_DROPPABLE not supported\n", __func__);
>> +}
>> +
>> +static void test_mlockall_future_droppable(void)
>> +{
>> + ksft_test_result_skip("%s: MAP_DROPPABLE not supported\n", __func__);
>> +}
>> +#endif /* MAP_DROPPABLE */
>>
> Why not a above a
>
> #ifndef MAP_DROPPABLE
> #define MAP_DROPPABLE 0x08
> #endif
>
> instead?
The intent was to skip the tests if compiled with headers where
MAP_DROPPABLE isn't defined rather than force the value and get EINVAL
because the kernel doesn't know about it. This way EINVAL can be flagged
as a test failure and not skipped since it would likely indicate a test
or kernel bug.
>
>> static void test_vma_management(bool call_mlock)
>> {
>> @@ -442,7 +522,7 @@ int main(int argc, char **argv)
>>
>> munmap(map, size);
>>
>> - ksft_set_plan(13);
>> + ksft_set_plan(15);
>>
>> test_mlock_lock();
>> test_mlock_onfault();
>> @@ -451,6 +531,8 @@ int main(int argc, char **argv)
>> test_lock_onfault_of_present();
>> test_vma_management(true);
>> test_mlockall();
>> + test_mlock_droppable();
>> + test_mlockall_future_droppable();
>>
>> ksft_finished();
>> }
> Feel free to add
>
> Acked-by: David Hildenbrand (Arm) <david@kernel.org>
>
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v3 2/2] selftests/mm: verify droppable mappings cannot be locked
2026-04-10 19:06 ` anthony.yznaga
@ 2026-04-13 19:46 ` David Hildenbrand (Arm)
2026-04-13 21:54 ` anthony.yznaga
0 siblings, 1 reply; 7+ messages in thread
From: David Hildenbrand (Arm) @ 2026-04-13 19:46 UTC (permalink / raw)
To: anthony.yznaga, linux-mm, linux-kernel, linux-kselftest
Cc: akpm, ljs, Liam.Howlett, vbabka, rppt, surenb, mhocko, jannh,
pfalcato, Jason, shuah
>>
>>> + if (munlockall()) {
>>> + ksft_test_result_fail("munlockall() %s\n", strerror(errno));
>>> + return;
>>> + }
>>> +
>>> + map = mmap(NULL, 2 * page_size, PROT_READ | PROT_WRITE,
>>> + MAP_ANONYMOUS | MAP_DROPPABLE, -1, 0);
>>> + if (map == MAP_FAILED) {
>>> + if (errno == EOPNOTSUPP)
>>> + ksft_test_result_skip("%s: MAP_DROPPABLE not
>>> supported\n", __func__);
>>> + else
>>> + ksft_test_result_fail("mmap error: %s\n", strerror(errno));
>>> + return;
>>> + }
>>> +
>>> + if (mlock2_(map, 2 * page_size, 0))
>> Weird, is "mlock2_" actually correct? (not "mlock2") ?
>
> It's correct though mlock2 would also work since it's been in glibc for
> several years now. I just matched the existing tests. mlock2_ is a
> simple wrapper around syscall in tools/testing/selftests/mm/mlock2.h,
> and it was introduced when the mlock2 syscall was introduced. A trailing
> rather than a preceding underscore is...unfortunate.
Interesting ... and confusing :)
>
>
>>
>>> + ksft_test_result_fail("mlock2(0): %s\n", strerror(errno));
>>> + else
>>> + ksft_test_result(!unlock_lock_check(map, false),
>>> + "%s: droppable memory not locked\n", __func__);
>>> +
>>> + munmap(map, 2 * page_size);
>>> +}
>>> +
>>> +static void test_mlockall_future_droppable(void)
>>> +{
>>> + char *map;
>>> + unsigned long page_size = getpagesize();
>>> +
>>> + if (mlockall(MCL_CURRENT | MCL_FUTURE)) {
>>> + ksft_test_result_fail("mlockall(MCL_CURRENT | MCL_FUTURE):
>>> %s\n", strerror(errno));
>>> + return;
>>> + }
>>> +
>>> + map = mmap(NULL, 2 * page_size, PROT_READ | PROT_WRITE,
>>> + MAP_ANONYMOUS | MAP_DROPPABLE, -1, 0);
>>> +
>>> + if (map == MAP_FAILED) {
>>> + if (errno == EOPNOTSUPP)
>>> + ksft_test_result_skip("%s: MAP_DROPPABLE not
>>> supported\n", __func__);
>>> + else
>>> + ksft_test_result_fail("mmap error: %s\n", strerror(errno));
>>> + munlockall();
>>> + return;
>>> + }
>>> +
>>> + ksft_test_result(!unlock_lock_check(map, false), "%s: droppable
>>> memory not locked\n",
>>> + __func__);
>>> +
>>> + munlockall();
>>> munmap(map, 2 * page_size);
>>> }
>>> +#else
>>> +static void test_mlock_droppable(void)
>>> +{
>>> + ksft_test_result_skip("%s: MAP_DROPPABLE not supported\n",
>>> __func__);
>>> +}
>>> +
>>> +static void test_mlockall_future_droppable(void)
>>> +{
>>> + ksft_test_result_skip("%s: MAP_DROPPABLE not supported\n",
>>> __func__);
>>> +}
>>> +#endif /* MAP_DROPPABLE */
>>>
>> Why not a above a
>>
>> #ifndef MAP_DROPPABLE
>> #define MAP_DROPPABLE 0x08
>> #endif
>>
>> instead?
>
> The intent was to skip the tests if compiled with headers where
> MAP_DROPPABLE isn't defined rather than force the value and get EINVAL
> because the kernel doesn't know about it. This way EINVAL can be flagged
> as a test failure and not skipped since it would likely indicate a test
> or kernel bug.
Note that the kernel headers you are compiling against don't imply
anything about the kernel that is actually running! So the argument
regarding EINVAL doesn't really hold.
But note that we, in general, try to compile against the in-tree headers.
See
commit 75d60eb30daafb966db0e45f38e4cdeb5e5ed79c
Author: Lorenzo Stoakes <ljs@kernel.org>
Date: Mon Oct 28 14:13:30 2024 +0000
tools: testing: update tools UAPI header for mman-common.h
Import the new MADV_GUARD_INSTALL/REMOVE madvise flags.
And looking into it, I already see MAP_DROPPABLE there as well, so is
any special handling here even needed?
--
Cheers,
David
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v3 2/2] selftests/mm: verify droppable mappings cannot be locked
2026-04-13 19:46 ` David Hildenbrand (Arm)
@ 2026-04-13 21:54 ` anthony.yznaga
0 siblings, 0 replies; 7+ messages in thread
From: anthony.yznaga @ 2026-04-13 21:54 UTC (permalink / raw)
To: David Hildenbrand (Arm), linux-mm, linux-kernel, linux-kselftest
Cc: akpm, ljs, Liam.Howlett, vbabka, rppt, surenb, mhocko, jannh,
pfalcato, Jason, shuah
On 4/13/26 12:46 PM, David Hildenbrand (Arm) wrote:
>>>> + if (munlockall()) {
>>>> + ksft_test_result_fail("munlockall() %s\n", strerror(errno));
>>>> + return;
>>>> + }
>>>> +
>>>> + map = mmap(NULL, 2 * page_size, PROT_READ | PROT_WRITE,
>>>> + MAP_ANONYMOUS | MAP_DROPPABLE, -1, 0);
>>>> + if (map == MAP_FAILED) {
>>>> + if (errno == EOPNOTSUPP)
>>>> + ksft_test_result_skip("%s: MAP_DROPPABLE not
>>>> supported\n", __func__);
>>>> + else
>>>> + ksft_test_result_fail("mmap error: %s\n", strerror(errno));
>>>> + return;
>>>> + }
>>>> +
>>>> + if (mlock2_(map, 2 * page_size, 0))
>>> Weird, is "mlock2_" actually correct? (not "mlock2") ?
>> It's correct though mlock2 would also work since it's been in glibc for
>> several years now. I just matched the existing tests. mlock2_ is a
>> simple wrapper around syscall in tools/testing/selftests/mm/mlock2.h,
>> and it was introduced when the mlock2 syscall was introduced. A trailing
>> rather than a preceding underscore is...unfortunate.
> Interesting ... and confusing :)
>
>>
>>>> + ksft_test_result_fail("mlock2(0): %s\n", strerror(errno));
>>>> + else
>>>> + ksft_test_result(!unlock_lock_check(map, false),
>>>> + "%s: droppable memory not locked\n", __func__);
>>>> +
>>>> + munmap(map, 2 * page_size);
>>>> +}
>>>> +
>>>> +static void test_mlockall_future_droppable(void)
>>>> +{
>>>> + char *map;
>>>> + unsigned long page_size = getpagesize();
>>>> +
>>>> + if (mlockall(MCL_CURRENT | MCL_FUTURE)) {
>>>> + ksft_test_result_fail("mlockall(MCL_CURRENT | MCL_FUTURE):
>>>> %s\n", strerror(errno));
>>>> + return;
>>>> + }
>>>> +
>>>> + map = mmap(NULL, 2 * page_size, PROT_READ | PROT_WRITE,
>>>> + MAP_ANONYMOUS | MAP_DROPPABLE, -1, 0);
>>>> +
>>>> + if (map == MAP_FAILED) {
>>>> + if (errno == EOPNOTSUPP)
>>>> + ksft_test_result_skip("%s: MAP_DROPPABLE not
>>>> supported\n", __func__);
>>>> + else
>>>> + ksft_test_result_fail("mmap error: %s\n", strerror(errno));
>>>> + munlockall();
>>>> + return;
>>>> + }
>>>> +
>>>> + ksft_test_result(!unlock_lock_check(map, false), "%s: droppable
>>>> memory not locked\n",
>>>> + __func__);
>>>> +
>>>> + munlockall();
>>>> munmap(map, 2 * page_size);
>>>> }
>>>> +#else
>>>> +static void test_mlock_droppable(void)
>>>> +{
>>>> + ksft_test_result_skip("%s: MAP_DROPPABLE not supported\n",
>>>> __func__);
>>>> +}
>>>> +
>>>> +static void test_mlockall_future_droppable(void)
>>>> +{
>>>> + ksft_test_result_skip("%s: MAP_DROPPABLE not supported\n",
>>>> __func__);
>>>> +}
>>>> +#endif /* MAP_DROPPABLE */
>>>>
>>> Why not a above a
>>>
>>> #ifndef MAP_DROPPABLE
>>> #define MAP_DROPPABLE 0x08
>>> #endif
>>>
>>> instead?
>> The intent was to skip the tests if compiled with headers where
>> MAP_DROPPABLE isn't defined rather than force the value and get EINVAL
>> because the kernel doesn't know about it. This way EINVAL can be flagged
>> as a test failure and not skipped since it would likely indicate a test
>> or kernel bug.
> Note that the kernel headers you are compiling against don't imply
> anything about the kernel that is actually running! So the argument
> regarding EINVAL doesn't really hold.
Yes, I see that now.
>
> But note that we, in general, try to compile against the in-tree headers.
>
> See
>
> commit 75d60eb30daafb966db0e45f38e4cdeb5e5ed79c
> Author: Lorenzo Stoakes <ljs@kernel.org>
> Date: Mon Oct 28 14:13:30 2024 +0000
>
> tools: testing: update tools UAPI header for mman-common.h
>
> Import the new MADV_GUARD_INSTALL/REMOVE madvise flags.
>
> And looking into it, I already see MAP_DROPPABLE there as well, so is
> any special handling here even needed?
>
I'd say no special handling is needed. If this test is compiled on with
a kernel that has MAP_DROPPABLE but run on an older kernel without
MAP_DROPPABLE, should it fail? Or should it interpret the EINVAL as a
sufficient reason to assume MAP_DROPPABLE is not supported and to skip
the result? My current thinking is it should fail because the EINVAL
could have another cause.
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2026-04-13 21:54 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-04-09 23:49 [PATCH v3 0/2] fix MAP_DROPPABLE not supported errno Anthony Yznaga
2026-04-09 23:49 ` [PATCH v3 1/2] mm: fix mmap errno value when MAP_DROPPABLE is not supported Anthony Yznaga
2026-04-09 23:49 ` [PATCH v3 2/2] selftests/mm: verify droppable mappings cannot be locked Anthony Yznaga
2026-04-10 7:57 ` David Hildenbrand (Arm)
2026-04-10 19:06 ` anthony.yznaga
2026-04-13 19:46 ` David Hildenbrand (Arm)
2026-04-13 21:54 ` anthony.yznaga
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox