[PATCH v4 7/7] selftests: prctl: introduce tests for disabling THPs except for madvise

Usama Arif posted 7 patches 1 month, 2 weeks ago
There is a newer version of this series
[PATCH v4 7/7] selftests: prctl: introduce tests for disabling THPs except for madvise
Posted by Usama Arif 1 month, 2 weeks ago
The test will set the global system THP setting to never, madvise
or always depending on the fixture variant and the 2M setting to
inherit before it starts (and reset to original at teardown).
The fixture setup will also test if PR_SET_THP_DISABLE prctl call can
be made with PR_THP_DISABLE_EXCEPT_ADVISED and skip if it fails.

This tests if the process can:
- successfully get the policy to disable THPs expect for madvise.
- get hugepages only on MADV_HUGE and MADV_COLLAPSE if the global policy
  is madvise/always and only with MADV_COLLAPSE if the global policy is
  never.
- successfully reset the policy of the process.
- after reset, only get hugepages with:
  - MADV_COLLAPSE when policy is set to never.
  - MADV_HUGE and MADV_COLLAPSE when policy is set to madvise.
  - always when policy is set to "always".
- repeat the above tests in a forked process to make sure  the policy is
  carried across forks.

Test results:
./prctl_thp_disable
TAP version 13
1..12
ok 1 prctl_thp_disable_completely.never.nofork
ok 2 prctl_thp_disable_completely.never.fork
ok 3 prctl_thp_disable_completely.madvise.nofork
ok 4 prctl_thp_disable_completely.madvise.fork
ok 5 prctl_thp_disable_completely.always.nofork
ok 6 prctl_thp_disable_completely.always.fork
ok 7 prctl_thp_disable_except_madvise.never.nofork
ok 8 prctl_thp_disable_except_madvise.never.fork
ok 9 prctl_thp_disable_except_madvise.madvise.nofork
ok 10 prctl_thp_disable_except_madvise.madvise.fork
ok 11 prctl_thp_disable_except_madvise.always.nofork
ok 12 prctl_thp_disable_except_madvise.always.fork

Signed-off-by: Usama Arif <usamaarif642@gmail.com>
---
 .../testing/selftests/mm/prctl_thp_disable.c  | 107 ++++++++++++++++++
 1 file changed, 107 insertions(+)

diff --git a/tools/testing/selftests/mm/prctl_thp_disable.c b/tools/testing/selftests/mm/prctl_thp_disable.c
index 8845e9f414560..9bfed4598a1a6 100644
--- a/tools/testing/selftests/mm/prctl_thp_disable.c
+++ b/tools/testing/selftests/mm/prctl_thp_disable.c
@@ -16,6 +16,10 @@
 #include "thp_settings.h"
 #include "vm_util.h"
 
+#ifndef PR_THP_DISABLE_EXCEPT_ADVISED
+#define PR_THP_DISABLE_EXCEPT_ADVISED (1 << 1)
+#endif
+
 enum thp_collapse_type {
 	THP_COLLAPSE_NONE,
 	THP_COLLAPSE_MADV_HUGEPAGE,	/* MADV_HUGEPAGE before access */
@@ -165,4 +169,107 @@ TEST_F(prctl_thp_disable_completely, fork)
 	ASSERT_EQ(ret, 0);
 }
 
+static void prctl_thp_disable_except_madvise_test(struct __test_metadata *const _metadata,
+						  size_t pmdsize,
+						  enum thp_enabled thp_policy)
+{
+	ASSERT_EQ(prctl(PR_GET_THP_DISABLE, NULL, NULL, NULL, NULL), 3);
+
+	/* tests after prctl overrides global policy */
+	ASSERT_EQ(test_mmap_thp(THP_COLLAPSE_NONE, pmdsize), 0);
+
+	ASSERT_EQ(test_mmap_thp(THP_COLLAPSE_MADV_HUGEPAGE, pmdsize),
+		  thp_policy == THP_NEVER ? 0 : 1);
+
+	ASSERT_EQ(test_mmap_thp(THP_COLLAPSE_MADV_COLLAPSE, pmdsize), 1);
+
+	/* Reset to global policy */
+	ASSERT_EQ(prctl(PR_SET_THP_DISABLE, 0, NULL, NULL, NULL), 0);
+
+	/* tests after prctl is cleared, and only global policy is effective */
+	ASSERT_EQ(test_mmap_thp(THP_COLLAPSE_NONE, pmdsize),
+		  thp_policy == THP_ALWAYS ? 1 : 0);
+
+	ASSERT_EQ(test_mmap_thp(THP_COLLAPSE_MADV_HUGEPAGE, pmdsize),
+		  thp_policy == THP_NEVER ? 0 : 1);
+
+	ASSERT_EQ(test_mmap_thp(THP_COLLAPSE_MADV_COLLAPSE, pmdsize), 1);
+}
+
+FIXTURE(prctl_thp_disable_except_madvise)
+{
+	struct thp_settings settings;
+	size_t pmdsize;
+};
+
+FIXTURE_VARIANT(prctl_thp_disable_except_madvise)
+{
+	enum thp_enabled thp_policy;
+};
+
+FIXTURE_VARIANT_ADD(prctl_thp_disable_except_madvise, never)
+{
+	.thp_policy = THP_NEVER,
+};
+
+FIXTURE_VARIANT_ADD(prctl_thp_disable_except_madvise, madvise)
+{
+	.thp_policy = THP_MADVISE,
+};
+
+FIXTURE_VARIANT_ADD(prctl_thp_disable_except_madvise, always)
+{
+	.thp_policy = THP_ALWAYS,
+};
+
+FIXTURE_SETUP(prctl_thp_disable_except_madvise)
+{
+	if (!thp_available())
+		SKIP(return, "Transparent Hugepages not available\n");
+
+	self->pmdsize = read_pmd_pagesize();
+	if (!self->pmdsize)
+		SKIP(return, "Unable to read PMD size\n");
+
+	if (prctl(PR_SET_THP_DISABLE, 1, PR_THP_DISABLE_EXCEPT_ADVISED, NULL, NULL))
+		SKIP(return, "Unable to set PR_THP_DISABLE_EXCEPT_ADVISED\n");
+
+	thp_save_settings();
+	thp_read_settings(&self->settings);
+	self->settings.thp_enabled = variant->thp_policy;
+	self->settings.hugepages[sz2ord(self->pmdsize, getpagesize())].enabled = THP_INHERIT;
+	thp_write_settings(&self->settings);
+}
+
+FIXTURE_TEARDOWN(prctl_thp_disable_except_madvise)
+{
+	thp_restore_settings();
+}
+
+TEST_F(prctl_thp_disable_except_madvise, nofork)
+{
+	prctl_thp_disable_except_madvise_test(_metadata, self->pmdsize, variant->thp_policy);
+}
+
+TEST_F(prctl_thp_disable_except_madvise, fork)
+{
+	int ret = 0;
+	pid_t pid;
+
+	/* Make sure prctl changes are carried across fork */
+	pid = fork();
+	ASSERT_GE(pid, 0);
+
+	if (!pid)
+		prctl_thp_disable_except_madvise_test(_metadata, self->pmdsize,
+						      variant->thp_policy);
+
+	wait(&ret);
+	if (WIFEXITED(ret))
+		ret = WEXITSTATUS(ret);
+	else
+		ret = -EINVAL;
+	ASSERT_EQ(ret, 0);
+}
+
 TEST_HARNESS_MAIN
-- 
2.47.3
Re: [PATCH v4 7/7] selftests: prctl: introduce tests for disabling THPs except for madvise
Posted by Lorenzo Stoakes 1 month, 2 weeks ago
On Wed, Aug 13, 2025 at 02:55:42PM +0100, Usama Arif wrote:
> The test will set the global system THP setting to never, madvise
> or always depending on the fixture variant and the 2M setting to
> inherit before it starts (and reset to original at teardown).
> The fixture setup will also test if PR_SET_THP_DISABLE prctl call can
> be made with PR_THP_DISABLE_EXCEPT_ADVISED and skip if it fails.
>
> This tests if the process can:
> - successfully get the policy to disable THPs expect for madvise.
> - get hugepages only on MADV_HUGE and MADV_COLLAPSE if the global policy
>   is madvise/always and only with MADV_COLLAPSE if the global policy is
>   never.
> - successfully reset the policy of the process.
> - after reset, only get hugepages with:
>   - MADV_COLLAPSE when policy is set to never.
>   - MADV_HUGE and MADV_COLLAPSE when policy is set to madvise.
>   - always when policy is set to "always".
> - repeat the above tests in a forked process to make sure  the policy is
>   carried across forks.
>
> Test results:
> ./prctl_thp_disable
> TAP version 13
> 1..12
> ok 1 prctl_thp_disable_completely.never.nofork
> ok 2 prctl_thp_disable_completely.never.fork
> ok 3 prctl_thp_disable_completely.madvise.nofork
> ok 4 prctl_thp_disable_completely.madvise.fork
> ok 5 prctl_thp_disable_completely.always.nofork
> ok 6 prctl_thp_disable_completely.always.fork
> ok 7 prctl_thp_disable_except_madvise.never.nofork
> ok 8 prctl_thp_disable_except_madvise.never.fork
> ok 9 prctl_thp_disable_except_madvise.madvise.nofork
> ok 10 prctl_thp_disable_except_madvise.madvise.fork
> ok 11 prctl_thp_disable_except_madvise.always.nofork
> ok 12 prctl_thp_disable_except_madvise.always.fork
>
> Signed-off-by: Usama Arif <usamaarif642@gmail.com>

I don't see any tests asserting VM_NOHUGEPAGE behaviour could you expand
this test to add that?

Other than that this is looking good.

Thanks!

> ---
>  .../testing/selftests/mm/prctl_thp_disable.c  | 107 ++++++++++++++++++
>  1 file changed, 107 insertions(+)
>
> diff --git a/tools/testing/selftests/mm/prctl_thp_disable.c b/tools/testing/selftests/mm/prctl_thp_disable.c
> index 8845e9f414560..9bfed4598a1a6 100644
> --- a/tools/testing/selftests/mm/prctl_thp_disable.c
> +++ b/tools/testing/selftests/mm/prctl_thp_disable.c
> @@ -16,6 +16,10 @@
>  #include "thp_settings.h"
>  #include "vm_util.h"
>
> +#ifndef PR_THP_DISABLE_EXCEPT_ADVISED
> +#define PR_THP_DISABLE_EXCEPT_ADVISED (1 << 1)
> +#endif
> +
>  enum thp_collapse_type {
>  	THP_COLLAPSE_NONE,
>  	THP_COLLAPSE_MADV_HUGEPAGE,	/* MADV_HUGEPAGE before access */
> @@ -165,4 +169,107 @@ TEST_F(prctl_thp_disable_completely, fork)
>  	ASSERT_EQ(ret, 0);
>  }
>
> +static void prctl_thp_disable_except_madvise_test(struct __test_metadata *const _metadata,
> +						  size_t pmdsize,
> +						  enum thp_enabled thp_policy)
> +{
> +	ASSERT_EQ(prctl(PR_GET_THP_DISABLE, NULL, NULL, NULL, NULL), 3);
> +
> +	/* tests after prctl overrides global policy */
> +	ASSERT_EQ(test_mmap_thp(THP_COLLAPSE_NONE, pmdsize), 0);
> +
> +	ASSERT_EQ(test_mmap_thp(THP_COLLAPSE_MADV_HUGEPAGE, pmdsize),
> +		  thp_policy == THP_NEVER ? 0 : 1);
> +
> +	ASSERT_EQ(test_mmap_thp(THP_COLLAPSE_MADV_COLLAPSE, pmdsize), 1);
> +
> +	/* Reset to global policy */
> +	ASSERT_EQ(prctl(PR_SET_THP_DISABLE, 0, NULL, NULL, NULL), 0);
> +
> +	/* tests after prctl is cleared, and only global policy is effective */
> +	ASSERT_EQ(test_mmap_thp(THP_COLLAPSE_NONE, pmdsize),
> +		  thp_policy == THP_ALWAYS ? 1 : 0);
> +
> +	ASSERT_EQ(test_mmap_thp(THP_COLLAPSE_MADV_HUGEPAGE, pmdsize),
> +		  thp_policy == THP_NEVER ? 0 : 1);
> +
> +	ASSERT_EQ(test_mmap_thp(THP_COLLAPSE_MADV_COLLAPSE, pmdsize), 1);
> +}
> +
> +FIXTURE(prctl_thp_disable_except_madvise)
> +{
> +	struct thp_settings settings;
> +	size_t pmdsize;
> +};
> +
> +FIXTURE_VARIANT(prctl_thp_disable_except_madvise)
> +{
> +	enum thp_enabled thp_policy;
> +};
> +
> +FIXTURE_VARIANT_ADD(prctl_thp_disable_except_madvise, never)
> +{
> +	.thp_policy = THP_NEVER,
> +};
> +
> +FIXTURE_VARIANT_ADD(prctl_thp_disable_except_madvise, madvise)
> +{
> +	.thp_policy = THP_MADVISE,
> +};
> +
> +FIXTURE_VARIANT_ADD(prctl_thp_disable_except_madvise, always)
> +{
> +	.thp_policy = THP_ALWAYS,
> +};

again the kselftest_harness stuff is really useful!

> +
> +FIXTURE_SETUP(prctl_thp_disable_except_madvise)
> +{
> +	if (!thp_available())
> +		SKIP(return, "Transparent Hugepages not available\n");
> +
> +	self->pmdsize = read_pmd_pagesize();
> +	if (!self->pmdsize)
> +		SKIP(return, "Unable to read PMD size\n");
> +
> +	if (prctl(PR_SET_THP_DISABLE, 1, PR_THP_DISABLE_EXCEPT_ADVISED, NULL, NULL))
> +		SKIP(return, "Unable to set PR_THP_DISABLE_EXCEPT_ADVISED\n");

This should be a test fail I think, as the only ways this could fail are
invalid flags, or failure to obtain an mmap write lock.

> +
> +	thp_save_settings();
> +	thp_read_settings(&self->settings);
> +	self->settings.thp_enabled = variant->thp_policy;
> +	self->settings.hugepages[sz2ord(self->pmdsize, getpagesize())].enabled = THP_INHERIT;
> +	thp_write_settings(&self->settings);
> +}
> +
> +FIXTURE_TEARDOWN(prctl_thp_disable_except_madvise)
> +{
> +	thp_restore_settings();
> +}
> +
> +TEST_F(prctl_thp_disable_except_madvise, nofork)
> +{
> +	prctl_thp_disable_except_madvise_test(_metadata, self->pmdsize, variant->thp_policy);
> +}
> +
> +TEST_F(prctl_thp_disable_except_madvise, fork)
> +{
> +	int ret = 0;
> +	pid_t pid;
> +
> +	/* Make sure prctl changes are carried across fork */
> +	pid = fork();
> +	ASSERT_GE(pid, 0);
> +
> +	if (!pid)
> +		prctl_thp_disable_except_madvise_test(_metadata, self->pmdsize,
> +						      variant->thp_policy);
> +
> +	wait(&ret);
> +	if (WIFEXITED(ret))
> +		ret = WEXITSTATUS(ret);
> +	else
> +		ret = -EINVAL;
> +	ASSERT_EQ(ret, 0);
> +}
> +
>  TEST_HARNESS_MAIN
> --
> 2.47.3
>
Re: [PATCH v4 7/7] selftests: prctl: introduce tests for disabling THPs except for madvise
Posted by David Hildenbrand 1 month, 2 weeks ago
>> +
>> +FIXTURE_SETUP(prctl_thp_disable_except_madvise)
>> +{
>> +	if (!thp_available())
>> +		SKIP(return, "Transparent Hugepages not available\n");
>> +
>> +	self->pmdsize = read_pmd_pagesize();
>> +	if (!self->pmdsize)
>> +		SKIP(return, "Unable to read PMD size\n");
>> +
>> +	if (prctl(PR_SET_THP_DISABLE, 1, PR_THP_DISABLE_EXCEPT_ADVISED, NULL, NULL))
>> +		SKIP(return, "Unable to set PR_THP_DISABLE_EXCEPT_ADVISED\n");
> 
> This should be a test fail I think, as the only ways this could fail are
> invalid flags, or failure to obtain an mmap write lock.

Running a kernel that does not support it?

We could check the errno to distinguish I guess.

-- 
Cheers,

David / dhildenb
Re: [PATCH v4 7/7] selftests: prctl: introduce tests for disabling THPs except for madvise
Posted by Lorenzo Stoakes 1 month, 2 weeks ago
On Wed, Aug 13, 2025 at 06:24:11PM +0200, David Hildenbrand wrote:
> > > +
> > > +FIXTURE_SETUP(prctl_thp_disable_except_madvise)
> > > +{
> > > +	if (!thp_available())
> > > +		SKIP(return, "Transparent Hugepages not available\n");
> > > +
> > > +	self->pmdsize = read_pmd_pagesize();
> > > +	if (!self->pmdsize)
> > > +		SKIP(return, "Unable to read PMD size\n");
> > > +
> > > +	if (prctl(PR_SET_THP_DISABLE, 1, PR_THP_DISABLE_EXCEPT_ADVISED, NULL, NULL))
> > > +		SKIP(return, "Unable to set PR_THP_DISABLE_EXCEPT_ADVISED\n");
> >
> > This should be a test fail I think, as the only ways this could fail are
> > invalid flags, or failure to obtain an mmap write lock.
>
> Running a kernel that does not support it?

I can't see anything in the kernel to #ifdef it out so I suppose you mean
running these tests on an older kernel?

But this is an unsupported way of running self-tests, they are tied to the
kernel version in which they reside, and test that specific version.

Unless I'm missing something here?

>
> We could check the errno to distinguish I guess.

Which one? manpage says -EINVAL, but can also be due to incorrect invocation,
which would mean a typo could mean tests pass but your tests do nothing :)

>
> --
> Cheers,
>
> David / dhildenb
>
Re: [PATCH v4 7/7] selftests: prctl: introduce tests for disabling THPs except for madvise
Posted by Usama Arif 1 month, 2 weeks ago

On 13/08/2025 19:52, Lorenzo Stoakes wrote:
> On Wed, Aug 13, 2025 at 06:24:11PM +0200, David Hildenbrand wrote:
>>>> +
>>>> +FIXTURE_SETUP(prctl_thp_disable_except_madvise)
>>>> +{
>>>> +	if (!thp_available())
>>>> +		SKIP(return, "Transparent Hugepages not available\n");
>>>> +
>>>> +	self->pmdsize = read_pmd_pagesize();
>>>> +	if (!self->pmdsize)
>>>> +		SKIP(return, "Unable to read PMD size\n");
>>>> +
>>>> +	if (prctl(PR_SET_THP_DISABLE, 1, PR_THP_DISABLE_EXCEPT_ADVISED, NULL, NULL))
>>>> +		SKIP(return, "Unable to set PR_THP_DISABLE_EXCEPT_ADVISED\n");
>>>
>>> This should be a test fail I think, as the only ways this could fail are
>>> invalid flags, or failure to obtain an mmap write lock.
>>
>> Running a kernel that does not support it?
> 
> I can't see anything in the kernel to #ifdef it out so I suppose you mean
> running these tests on an older kernel?
> 

It was a fail in my previous revision
(https://lore.kernel.org/all/9bcb1dee-314e-4366-9bad-88a47d516c79@redhat.com/)

I do believe people (including me :)) get the latest kernel selftest and run it on
older kernels.
It might not be the right way to run selftests, but I do think its done.

> But this is an unsupported way of running self-tests, they are tied to the
> kernel version in which they reside, and test that specific version.
> 
> Unless I'm missing something here?
> 
>>
>> We could check the errno to distinguish I guess.
> 
> Which one? manpage says -EINVAL, but can also be due to incorrect invocation,
> which would mean a typo could mean tests pass but your tests do nothing :)
> 

Yeah I dont think we can distinguish between the prctl not being available (i.e. older kernel)
and the prctl not working as it should.

We just need to decide whether to fail or skip.

If the right way is to always run selftests from the same kernel version as the host
on which its being run on, we can just fail? I can go back to the older version of
doing things and move the failure from FIXTURE_SETUP to TEST_F?   

>>
>> --
>> Cheers,
>>
>> David / dhildenb
>>
Re: [PATCH v4 7/7] selftests: prctl: introduce tests for disabling THPs except for madvise
Posted by Lorenzo Stoakes 1 month, 2 weeks ago
On Thu, Aug 14, 2025 at 11:36:51AM +0100, Usama Arif wrote:
>
>
> On 13/08/2025 19:52, Lorenzo Stoakes wrote:
> > On Wed, Aug 13, 2025 at 06:24:11PM +0200, David Hildenbrand wrote:
> >>>> +
> >>>> +FIXTURE_SETUP(prctl_thp_disable_except_madvise)
> >>>> +{
> >>>> +	if (!thp_available())
> >>>> +		SKIP(return, "Transparent Hugepages not available\n");
> >>>> +
> >>>> +	self->pmdsize = read_pmd_pagesize();
> >>>> +	if (!self->pmdsize)
> >>>> +		SKIP(return, "Unable to read PMD size\n");
> >>>> +
> >>>> +	if (prctl(PR_SET_THP_DISABLE, 1, PR_THP_DISABLE_EXCEPT_ADVISED, NULL, NULL))
> >>>> +		SKIP(return, "Unable to set PR_THP_DISABLE_EXCEPT_ADVISED\n");
> >>>
> >>> This should be a test fail I think, as the only ways this could fail are
> >>> invalid flags, or failure to obtain an mmap write lock.
> >>
> >> Running a kernel that does not support it?
> >
> > I can't see anything in the kernel to #ifdef it out so I suppose you mean
> > running these tests on an older kernel?
> >
>
> It was a fail in my previous revision
> (https://lore.kernel.org/all/9bcb1dee-314e-4366-9bad-88a47d516c79@redhat.com/)

Well it seems it's a debate between me and David then haha :P sorry.

This is a bit of a trivial thing I'm just keen that bugs don't get accidentally
missed because of skips, that's the most important thing I think.

>
> I do believe people (including me :)) get the latest kernel selftest and run it on
> older kernels.
> It might not be the right way to run selftests, but I do think its done.

People can do unsupported things, but then if it breaks that's on them to live
with :)

>
> > But this is an unsupported way of running self-tests, they are tied to the
> > kernel version in which they reside, and test that specific version.
> >
> > Unless I'm missing something here?
> >
> >>
> >> We could check the errno to distinguish I guess.
> >
> > Which one? manpage says -EINVAL, but can also be due to incorrect invocation,
> > which would mean a typo could mean tests pass but your tests do nothing :)
> >
>
> Yeah I dont think we can distinguish between the prctl not being available (i.e. older kernel)
> and the prctl not working as it should.
>
> We just need to decide whether to fail or skip.

I really think it's far worse to miss a bug in the code (or testing) than to
account for people running with different kernels.

>
> If the right way is to always run selftests from the same kernel version as the host
> on which its being run on, we can just fail? I can go back to the older version of
> doing things and move the failure from FIXTURE_SETUP to TEST_F?

Yeah I think it simply should just be a fail.

Why would you move things around though? Think it's fine as-is, if something on
setup fails then all tests should fail.

Cheers, Lorenzo
Re: [PATCH v4 7/7] selftests: prctl: introduce tests for disabling THPs except for madvise
Posted by Usama Arif 1 month, 2 weeks ago

> 
> Why would you move things around though? Think it's fine as-is, if something on
> setup fails then all tests should fail.

If its a "test" itself and not a check, I think its better if it belongs in TEST_F and
not FIXTURE_SETUP.
But yeah this is ofcourse going to be the first test, so if it fails the entire thing
is marked as a failure and we dont proceed.

> 
> Cheers, Lorenzo
Re: [PATCH v4 7/7] selftests: prctl: introduce tests for disabling THPs except for madvise
Posted by David Hildenbrand 1 month, 2 weeks ago
On 13.08.25 20:52, Lorenzo Stoakes wrote:
> On Wed, Aug 13, 2025 at 06:24:11PM +0200, David Hildenbrand wrote:
>>>> +
>>>> +FIXTURE_SETUP(prctl_thp_disable_except_madvise)
>>>> +{
>>>> +	if (!thp_available())
>>>> +		SKIP(return, "Transparent Hugepages not available\n");
>>>> +
>>>> +	self->pmdsize = read_pmd_pagesize();
>>>> +	if (!self->pmdsize)
>>>> +		SKIP(return, "Unable to read PMD size\n");
>>>> +
>>>> +	if (prctl(PR_SET_THP_DISABLE, 1, PR_THP_DISABLE_EXCEPT_ADVISED, NULL, NULL))
>>>> +		SKIP(return, "Unable to set PR_THP_DISABLE_EXCEPT_ADVISED\n");
>>>
>>> This should be a test fail I think, as the only ways this could fail are
>>> invalid flags, or failure to obtain an mmap write lock.
>>
>> Running a kernel that does not support it?
> 
> I can't see anything in the kernel to #ifdef it out so I suppose you mean
> running these tests on an older kernel?

Yes.

> 
> But this is an unsupported way of running self-tests, they are tied to the
> kernel version in which they reside, and test that specific version.
> 
> Unless I'm missing something here?

I remember we allow for a bit of flexibility when it is simple to handle.

Is that documented somewhere?

> 
>>
>> We could check the errno to distinguish I guess.
> 
> Which one? manpage says -EINVAL, but can also be due to incorrect invocation,
> which would mean a typo could mean tests pass but your tests do nothing :)

Right, no ENOSYS in that case to distinguish :(

-- 
Cheers

David / dhildenb
Re: [PATCH v4 7/7] selftests: prctl: introduce tests for disabling THPs except for madvise
Posted by Lorenzo Stoakes 1 month, 2 weeks ago
+cc Mark who might have insights here

On Thu, Aug 14, 2025 at 11:32:55AM +0200, David Hildenbrand wrote:
> On 13.08.25 20:52, Lorenzo Stoakes wrote:
> > On Wed, Aug 13, 2025 at 06:24:11PM +0200, David Hildenbrand wrote:
> > > > > +
> > > > > +FIXTURE_SETUP(prctl_thp_disable_except_madvise)
> > > > > +{
> > > > > +	if (!thp_available())
> > > > > +		SKIP(return, "Transparent Hugepages not available\n");
> > > > > +
> > > > > +	self->pmdsize = read_pmd_pagesize();
> > > > > +	if (!self->pmdsize)
> > > > > +		SKIP(return, "Unable to read PMD size\n");
> > > > > +
> > > > > +	if (prctl(PR_SET_THP_DISABLE, 1, PR_THP_DISABLE_EXCEPT_ADVISED, NULL, NULL))
> > > > > +		SKIP(return, "Unable to set PR_THP_DISABLE_EXCEPT_ADVISED\n");
> > > >
> > > > This should be a test fail I think, as the only ways this could fail are
> > > > invalid flags, or failure to obtain an mmap write lock.
> > >
> > > Running a kernel that does not support it?
> >
> > I can't see anything in the kernel to #ifdef it out so I suppose you mean
> > running these tests on an older kernel?
>
> Yes.
>
> >
> > But this is an unsupported way of running self-tests, they are tied to the
> > kernel version in which they reside, and test that specific version.
> >
> > Unless I'm missing something here?
>
> I remember we allow for a bit of flexibility when it is simple to handle.
>
> Is that documented somewhere?

Not sure if it's documented, but it'd make testing extremely egregious if
you had to consider all of the possible kernels and interactions and etc.

I think it's 'if it happens to work then fine' but otherwise it is expected
that the tests match the kernel.

It's also very neat that with a revision you get a set of (hopefully)
working tests for that revision :)

>
> >
> > >
> > > We could check the errno to distinguish I guess.
> >
> > Which one? manpage says -EINVAL, but can also be due to incorrect invocation,
> > which would mean a typo could mean tests pass but your tests do nothing :)
>
> Right, no ENOSYS in that case to distinguish :(

Yup sadly

>
> --
> Cheers
>
> David / dhildenb
>
Re: [PATCH v4 7/7] selftests: prctl: introduce tests for disabling THPs except for madvise
Posted by Mark Brown 1 month, 2 weeks ago
On Thu, Aug 14, 2025 at 11:49:15AM +0100, Lorenzo Stoakes wrote:
> On Thu, Aug 14, 2025 at 11:32:55AM +0200, David Hildenbrand wrote:
> > On 13.08.25 20:52, Lorenzo Stoakes wrote:

> > > I can't see anything in the kernel to #ifdef it out so I suppose you mean
> > > running these tests on an older kernel?

...

> > > But this is an unsupported way of running self-tests, they are tied to the
> > > kernel version in which they reside, and test that specific version.

> > > Unless I'm missing something here?

> > I remember we allow for a bit of flexibility when it is simple to handle.

> > Is that documented somewhere?

> Not sure if it's documented, but it'd make testing extremely egregious if
> you had to consider all of the possible kernels and interactions and etc.

> I think it's 'if it happens to work then fine' but otherwise it is expected
> that the tests match the kernel.

> It's also very neat that with a revision you get a set of (hopefully)
> working tests for that revision :)

Some people do try to run the selftests with older kernels, they're
trying to get better coverage for the stables.  For a lot of areas the
skipping falls out natually since there's some optionality (so even with
the same kernel version you might not have the feature in the running
kernel) or it's a new API which has a discovery mechanism in the ABI
anyway.  OTOH some areas have been actively hostile to the idea of
running on older kernels so there are things that do break when you try.
TBH so long as the tests don't crash the system or something people are
probably just going to ignore any tests that have never passed.
Re: [PATCH v4 7/7] selftests: prctl: introduce tests for disabling THPs except for madvise
Posted by David Hildenbrand 1 month, 2 weeks ago
On 14.08.25 13:45, Mark Brown wrote:
> On Thu, Aug 14, 2025 at 11:49:15AM +0100, Lorenzo Stoakes wrote:
>> On Thu, Aug 14, 2025 at 11:32:55AM +0200, David Hildenbrand wrote:
>>> On 13.08.25 20:52, Lorenzo Stoakes wrote:
> 
>>>> I can't see anything in the kernel to #ifdef it out so I suppose you mean
>>>> running these tests on an older kernel?
> 
> ...
> 
>>>> But this is an unsupported way of running self-tests, they are tied to the
>>>> kernel version in which they reside, and test that specific version.
> 
>>>> Unless I'm missing something here?
> 
>>> I remember we allow for a bit of flexibility when it is simple to handle.
> 
>>> Is that documented somewhere?
> 
>> Not sure if it's documented, but it'd make testing extremely egregious if
>> you had to consider all of the possible kernels and interactions and etc.
> 
>> I think it's 'if it happens to work then fine' but otherwise it is expected
>> that the tests match the kernel.
> 
>> It's also very neat that with a revision you get a set of (hopefully)
>> working tests for that revision :)
> 
> Some people do try to run the selftests with older kernels, they're
> trying to get better coverage for the stables.  For a lot of areas the
> skipping falls out natually since there's some optionality (so even with
> the same kernel version you might not have the feature in the running
> kernel) or it's a new API which has a discovery mechanism in the ABI
> anyway.  OTOH some areas have been actively hostile to the idea of
> running on older kernels so there are things that do break when you try.
> TBH so long as the tests don't crash the system or something people are
> probably just going to ignore any tests that have never passed.

Some people (hello :) ) run tests against distro kernels ... shame that 
prctl just knows one sort of "EINVAL" so we cannot distinguish :(

But yeah, maybe one has to be more careful of filtering these failures 
out then.

-- 
Cheers

David / dhildenb
Re: [PATCH v4 7/7] selftests: prctl: introduce tests for disabling THPs except for madvise
Posted by Mark Brown 1 month, 2 weeks ago
On Thu, Aug 14, 2025 at 02:00:27PM +0200, David Hildenbrand wrote:

> Some people (hello :) ) run tests against distro kernels ... shame that
> prctl just knows one sort of "EINVAL" so we cannot distinguish :(

> But yeah, maybe one has to be more careful of filtering these failures out
> then.

Perhaps this is something that needs considering in the ABI, so
userspace can reasonably figure out if it failed to configure whatever
is being configured due to a missing feature (in which case it should
fall back to not using that feature somehow) or due to it messing
something else up?  We might be happy with the tests being version
specific but general userspace should be able to be a bit more robust.
Re: [PATCH v4 7/7] selftests: prctl: introduce tests for disabling THPs except for madvise
Posted by David Hildenbrand 1 month, 2 weeks ago
On 14.08.25 14:09, Mark Brown wrote:
> On Thu, Aug 14, 2025 at 02:00:27PM +0200, David Hildenbrand wrote:
> 
>> Some people (hello :) ) run tests against distro kernels ... shame that
>> prctl just knows one sort of "EINVAL" so we cannot distinguish :(
> 
>> But yeah, maybe one has to be more careful of filtering these failures out
>> then.
> 
> Perhaps this is something that needs considering in the ABI, so
> userspace can reasonably figure out if it failed to configure whatever
> is being configured due to a missing feature (in which case it should
> fall back to not using that feature somehow) or due to it messing
> something else up?  We might be happy with the tests being version
> specific but general userspace should be able to be a bit more robust.

Yeah, the whole prctl() ship has sailed, unfortunately :(

-- 
Cheers

David / dhildenb
Re: [PATCH v4 7/7] selftests: prctl: introduce tests for disabling THPs except for madvise
Posted by Mark Brown 1 month, 2 weeks ago
On Thu, Aug 14, 2025 at 02:59:13PM +0200, David Hildenbrand wrote:
> On 14.08.25 14:09, Mark Brown wrote:

> > Perhaps this is something that needs considering in the ABI, so
> > userspace can reasonably figure out if it failed to configure whatever
> > is being configured due to a missing feature (in which case it should
> > fall back to not using that feature somehow) or due to it messing
> > something else up?  We might be happy with the tests being version
> > specific but general userspace should be able to be a bit more robust.

> Yeah, the whole prctl() ship has sailed, unfortunately :(

Perhaps a second call or sysfs file or something that returns the
supported mask?  You'd still have a boostrapping issue with existing
versions but at least at any newer stuff would be helped.
Re: [PATCH v4 7/7] selftests: prctl: introduce tests for disabling THPs except for madvise
Posted by Lorenzo Stoakes 1 month, 2 weeks ago
On Thu, Aug 14, 2025 at 02:08:57PM +0100, Mark Brown wrote:
> On Thu, Aug 14, 2025 at 02:59:13PM +0200, David Hildenbrand wrote:
> > On 14.08.25 14:09, Mark Brown wrote:
>
> > > Perhaps this is something that needs considering in the ABI, so
> > > userspace can reasonably figure out if it failed to configure whatever
> > > is being configured due to a missing feature (in which case it should
> > > fall back to not using that feature somehow) or due to it messing
> > > something else up?  We might be happy with the tests being version
> > > specific but general userspace should be able to be a bit more robust.
>
> > Yeah, the whole prctl() ship has sailed, unfortunately :(
>
> Perhaps a second call or sysfs file or something that returns the
> supported mask?  You'd still have a boostrapping issue with existing
> versions but at least at any newer stuff would be helped.

Ack yeah I do wish we had better APIs for expressing what was
available/not. Will put this sort of thing on the TODO...

Overall I don't want to hold this up unnecesarily, and I bow to the
consensus if others feel we ought not to _assume_ same kernel at least best
effort.

Usama - It's ok to leave it as is in this case since obviously only tip
kernel will have this feature.

Cheers, Lorenzo
Re: [PATCH v4 7/7] selftests: prctl: introduce tests for disabling THPs except for madvise
Posted by Usama Arif 1 month, 2 weeks ago

On 14/08/2025 16:02, Lorenzo Stoakes wrote:
> On Thu, Aug 14, 2025 at 02:08:57PM +0100, Mark Brown wrote:
>> On Thu, Aug 14, 2025 at 02:59:13PM +0200, David Hildenbrand wrote:
>>> On 14.08.25 14:09, Mark Brown wrote:
>>
>>>> Perhaps this is something that needs considering in the ABI, so
>>>> userspace can reasonably figure out if it failed to configure whatever
>>>> is being configured due to a missing feature (in which case it should
>>>> fall back to not using that feature somehow) or due to it messing
>>>> something else up?  We might be happy with the tests being version
>>>> specific but general userspace should be able to be a bit more robust.
>>
>>> Yeah, the whole prctl() ship has sailed, unfortunately :(
>>
>> Perhaps a second call or sysfs file or something that returns the
>> supported mask?  You'd still have a boostrapping issue with existing
>> versions but at least at any newer stuff would be helped.
> 
> Ack yeah I do wish we had better APIs for expressing what was
> available/not. Will put this sort of thing on the TODO...
> 
> Overall I don't want to hold this up unnecesarily, and I bow to the
> consensus if others feel we ought not to _assume_ same kernel at least best
> effort.
> 
> Usama - It's ok to leave it as is in this case since obviously only tip
> kernel will have this feature.

ah ok, so will keep it at skipping if prctl doesnt work in fixture as is
in the current v4 version.

I only have the below diff and its equivalent for patch 7 as a difference over
this version. Will wait until tomorrow morning incase there are more comments
and hopefully send out a last revision!

Thanks!



diff --git a/tools/testing/selftests/mm/prctl_thp_disable.c b/tools/testing/selftests/mm/prctl_thp_disable.c
index 8845e9f414560..e9e519c85224c 100644
--- a/tools/testing/selftests/mm/prctl_thp_disable.c
+++ b/tools/testing/selftests/mm/prctl_thp_disable.c
@@ -18,6 +18,7 @@
 
 enum thp_collapse_type {
        THP_COLLAPSE_NONE,
+       THP_COLLAPSE_MADV_NOHUGEPAGE,
        THP_COLLAPSE_MADV_HUGEPAGE,     /* MADV_HUGEPAGE before access */
        THP_COLLAPSE_MADV_COLLAPSE,     /* MADV_COLLAPSE after access */
 };
@@ -49,6 +50,8 @@ static int test_mmap_thp(enum thp_collapse_type madvise_buf, size_t pmdsize)
 
        if (madvise_buf == THP_COLLAPSE_MADV_HUGEPAGE)
                madvise(mem, pmdsize, MADV_HUGEPAGE);
+       else if (madvise_buf == THP_COLLAPSE_MADV_NOHUGEPAGE)
+               madvise(mem, pmdsize, MADV_NOHUGEPAGE);
 
        /* Ensure memory is allocated */
        memset(mem, 1, pmdsize);
@@ -73,6 +76,8 @@ static void prctl_thp_disable_completely_test(struct __test_metadata *const _met
        /* tests after prctl overrides global policy */
        ASSERT_EQ(test_mmap_thp(THP_COLLAPSE_NONE, pmdsize), 0);
 
+       ASSERT_EQ(test_mmap_thp(THP_COLLAPSE_MADV_NOHUGEPAGE, pmdsize), 0);
+
        ASSERT_EQ(test_mmap_thp(THP_COLLAPSE_MADV_HUGEPAGE, pmdsize), 0);
 
        ASSERT_EQ(test_mmap_thp(THP_COLLAPSE_MADV_COLLAPSE, pmdsize), 0);
@@ -84,6 +89,8 @@ static void prctl_thp_disable_completely_test(struct __test_metadata *const _met
        ASSERT_EQ(test_mmap_thp(THP_COLLAPSE_NONE, pmdsize),
                  thp_policy == THP_ALWAYS ? 1 : 0);
 
+       ASSERT_EQ(test_mmap_thp(THP_COLLAPSE_MADV_NOHUGEPAGE, pmdsize), 0);
+
        ASSERT_EQ(test_mmap_thp(THP_COLLAPSE_MADV_HUGEPAGE, pmdsize),
                  thp_policy == THP_NEVER ? 0 : 1);

> 
> Cheers, Lorenzo