linux-mm.kvack.org archive mirror
 help / color / mirror / Atom feed
* [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