On Thu, 11 Jun 2026 12:01:55 +0200 "David Hildenbrand (Arm)" <[email protected]> wrote:
> The droppable test currently relies on creating memory pressure in a > child process to trigger dropping the droppable pages. > > That not only takes a long time on some machines (allocating and filling > all that memory), on large machines this will not work as we hardcode the > area size to 134217728 bytes. > > ... further, we rely on timeouts to detect that memory was not dropped, > which is really suboptimal. > > Instead, let's just use MADV_PAGEOUT on a 2 MiB region. MADV_PAGEOUT works > with droppable memory even without swap. > > There is the low chance of MADV_PAGEOUT failing to drop a page because > of speculative references. We'll wait 1s and retry 10 times to > rule that unlikely case out as best as we can. > > On a machine without swap: > > $ ./droppable > TAP version 13 > 1..1 > ok 1 madvise(MADV_PAGEOUT) behavior > # Totals: pass:1 fail:0 xfail:0 xpass:0 skip:0 error:0 > > Reported-by: Aishwarya TCV <[email protected]> > Fixes: 9651fcedf7b9 ("mm: add MAP_DROPPABLE for designating always lazily > freeable mappings") Because this is a fix for a test, I think not Cc-ing stable@ is ok. Further, arguably this is not a fix but an improvement? No strong opinion, just thinking loud. > Signed-off-by: David Hildenbrand (Arm) <[email protected]> Reviewed-by: SeongJae Park <[email protected]> > --- > tools/testing/selftests/mm/droppable.c | 46 > +++++++++++++++++++--------------- > 1 file changed, 26 insertions(+), 20 deletions(-) > > diff --git a/tools/testing/selftests/mm/droppable.c > b/tools/testing/selftests/mm/droppable.c > index 30c8be37fcb9..57e1b6fc5569 100644 > --- a/tools/testing/selftests/mm/droppable.c > +++ b/tools/testing/selftests/mm/droppable.c > @@ -17,10 +17,10 @@ > > int main(int argc, char *argv[]) > { > - size_t alloc_size = 134217728; > - size_t page_size = getpagesize(); > + const size_t alloc_size = 2 * 1024 * 1024; > + int retry_count = 10; > + bool dropped; > void *alloc; > - pid_t child; > > ksft_print_header(); > ksft_set_plan(1); > @@ -35,26 +35,32 @@ int main(int argc, char *argv[]) > exit(KSFT_FAIL); > } > memset(alloc, 'A', alloc_size); > - for (size_t i = 0; i < alloc_size; i += page_size) > - assert(*(uint8_t *)(alloc + i)); > - > - child = fork(); > - assert(child >= 0); > - if (!child) { > - for (;;) > - *(char *)malloc(page_size) = 'B'; > - } > > - for (bool done = false; !done;) { > - for (size_t i = 0; i < alloc_size; i += page_size) { > - if (!*(uint8_t *)(alloc + i)) { > - done = true; > - break; > + while (retry_count--) { > + if (madvise(alloc, alloc_size, MADV_PAGEOUT)) { > + if (errno == EINVAL) { > + ksft_test_result_skip("madvise(MADV_PAGEOUT) > not supported\n"); > + exit(KSFT_SKIP); This check is for a case that this test is running against an old kernel that doesn't have MADV_PAGEOUT? Assuming so, I was first thinking this check might not really needed, assuming the test runner would pick the kselftest code from the running kernel's source code. But I recalled some people do get kselftest code from random place. So this check seems nice to me. Just thinking loud. Thanks, SJ [...]

