selftests/mm: report errno when things fail in gup_longterm
authorBrendan Jackman <jackmanb@google.com>
Tue, 11 Mar 2025 13:18:12 +0000 (13:18 +0000)
committerAndrew Morton <akpm@linux-foundation.org>
Mon, 17 Mar 2025 05:06:37 +0000 (22:06 -0700)
Patch series "selftests/mm: Some cleanups from trying to run them", v4.

I never had much luck running mm selftests so I spent a few hours digging
into why.

Looks like most of the reason is missing SKIP checks, so this series is
just adding a bunch of those that I found.  I did not do anything like all
of them, just the ones I spotted in gup_longterm, gup_test, mmap,
userfaultfd and memfd_secret.

It's a bit unfortunate to have to skip those tests when ftruncate() fails,
but I don't have time to dig deep enough into it to actually make them
pass.  I have observed the issue on 9pfs and heard rumours that NFS has a
similar problem.

I'm now able to run these test groups successfully:

- mmap
- gup_test
- compaction
- migration
- page_frag
- userfaultfd
- mlock

I've never gone past "Waiting for hugetlb memory to get depleted", in the
hugetlb tests.  I don't know if they are stuck or if they would eventually
work if I was patient enough (testing on a 1G machine).  I have not
investigated further.

I had some issues with mlock tests failing due to -ENOSRCH from mlock2(),
I can no longer reproduce that though, things work OK now.

Of the remaining tests there may be others that work fine, but there's no
convenient way to survey the whole output of run_vmtests.sh so I'm just
going test by test here.

In my spare moments I am slowly chipping away at a setup to run these
tests continuously in a reasonably hermetic QEMU environment via
virtme-ng:

https://github.com/bjackman/linux/blob/5fad4b9c592290f38e0f8bc73c9abb9c99d8787c/README.md

Hopefully that will eventually offer a way to provide a "canned"
environment where the tests are known to work, which can be fairly easily
reproduced by any developer.

This patch (of 12):

Just reporting failure doesn't tell you what went wrong.  This can fail in
different ways so report errno to help the reader get started debugging.

Link: https://lkml.kernel.org/r/20250311-mm-selftests-v4-0-dec210a658f5@google.com
Link: https://lkml.kernel.org/r/20250311-mm-selftests-v4-1-dec210a658f5@google.com
Signed-off-by: Brendan Jackman <jackmanb@google.com>
Reviewed-by: Dev Jain <dev.jain@arm.com>
Cc: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
Cc: Mateusz Guzik <mjguzik@gmail.com>
Cc: Shuah Khan <shuah@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
tools/testing/selftests/mm/gup_longterm.c

index 9423ad4..1533582 100644 (file)
@@ -96,13 +96,13 @@ static void do_test(int fd, size_t size, enum test_type type, bool shared)
        int ret;
 
        if (ftruncate(fd, size)) {
-               ksft_test_result_fail("ftruncate() failed\n");
+               ksft_test_result_fail("ftruncate() failed (%s)\n", strerror(errno));
                return;
        }
 
        if (fallocate(fd, 0, 0, size)) {
                if (size == pagesize)
-                       ksft_test_result_fail("fallocate() failed\n");
+                       ksft_test_result_fail("fallocate() failed (%s)\n", strerror(errno));
                else
                        ksft_test_result_skip("need more free huge pages\n");
                return;
@@ -112,7 +112,7 @@ static void do_test(int fd, size_t size, enum test_type type, bool shared)
                   shared ? MAP_SHARED : MAP_PRIVATE, fd, 0);
        if (mem == MAP_FAILED) {
                if (size == pagesize || shared)
-                       ksft_test_result_fail("mmap() failed\n");
+                       ksft_test_result_fail("mmap() failed (%s)\n", strerror(errno));
                else
                        ksft_test_result_skip("need more free huge pages\n");
                return;
@@ -130,7 +130,7 @@ static void do_test(int fd, size_t size, enum test_type type, bool shared)
                 */
                ret = mprotect(mem, size, PROT_READ);
                if (ret) {
-                       ksft_test_result_fail("mprotect() failed\n");
+                       ksft_test_result_fail("mprotect() failed (%s)\n", strerror(errno));
                        goto munmap;
                }
                /* FALLTHROUGH */
@@ -165,18 +165,20 @@ static void do_test(int fd, size_t size, enum test_type type, bool shared)
                args.flags |= rw ? PIN_LONGTERM_TEST_FLAG_USE_WRITE : 0;
                ret = ioctl(gup_fd, PIN_LONGTERM_TEST_START, &args);
                if (ret && errno == EINVAL) {
-                       ksft_test_result_skip("PIN_LONGTERM_TEST_START failed\n");
+                       ksft_test_result_skip("PIN_LONGTERM_TEST_START failed (EINVAL)n");
                        break;
                } else if (ret && errno == EFAULT) {
                        ksft_test_result(!should_work, "Should have failed\n");
                        break;
                } else if (ret) {
-                       ksft_test_result_fail("PIN_LONGTERM_TEST_START failed\n");
+                       ksft_test_result_fail("PIN_LONGTERM_TEST_START failed (%s)\n",
+                                             strerror(errno));
                        break;
                }
 
                if (ioctl(gup_fd, PIN_LONGTERM_TEST_STOP))
-                       ksft_print_msg("[INFO] PIN_LONGTERM_TEST_STOP failed\n");
+                       ksft_print_msg("[INFO] PIN_LONGTERM_TEST_STOP failed (%s)\n",
+                                      strerror(errno));
 
                /*
                 * TODO: if the kernel ever supports long-term R/W pinning on
@@ -202,7 +204,8 @@ static void do_test(int fd, size_t size, enum test_type type, bool shared)
                /* Skip on errors, as we might just lack kernel support. */
                ret = io_uring_queue_init(1, &ring, 0);
                if (ret < 0) {
-                       ksft_test_result_skip("io_uring_queue_init() failed\n");
+                       ksft_test_result_skip("io_uring_queue_init() failed (%s)\n",
+                                             strerror(-ret));
                        break;
                }
                /*
@@ -215,13 +218,15 @@ static void do_test(int fd, size_t size, enum test_type type, bool shared)
                /* Only new kernels return EFAULT. */
                if (ret && (errno == ENOSPC || errno == EOPNOTSUPP ||
                            errno == EFAULT)) {
-                       ksft_test_result(!should_work, "Should have failed\n");
+                       ksft_test_result(!should_work, "Should have failed (%s)\n",
+                                        strerror(errno));
                } else if (ret) {
                        /*
                         * We might just lack support or have insufficient
                         * MEMLOCK limits.
                         */
-                       ksft_test_result_skip("io_uring_register_buffers() failed\n");
+                       ksft_test_result_skip("io_uring_register_buffers() failed (%s)\n",
+                                             strerror(-ret));
                } else {
                        ksft_test_result(should_work, "Should have worked\n");
                        io_uring_unregister_buffers(&ring);
@@ -249,7 +254,7 @@ static void run_with_memfd(test_fn fn, const char *desc)
 
        fd = memfd_create("test", 0);
        if (fd < 0) {
-               ksft_test_result_fail("memfd_create() failed\n");
+               ksft_test_result_fail("memfd_create() failed (%s)\n", strerror(errno));
                return;
        }
 
@@ -266,13 +271,13 @@ static void run_with_tmpfile(test_fn fn, const char *desc)
 
        file = tmpfile();
        if (!file) {
-               ksft_test_result_fail("tmpfile() failed\n");
+               ksft_test_result_fail("tmpfile() failed (%s)\n", strerror(errno));
                return;
        }
 
        fd = fileno(file);
        if (fd < 0) {
-               ksft_test_result_fail("fileno() failed\n");
+               ksft_test_result_fail("fileno() failed (%s)\n", strerror(errno));
                goto close;
        }
 
@@ -290,12 +295,12 @@ static void run_with_local_tmpfile(test_fn fn, const char *desc)
 
        fd = mkstemp(filename);
        if (fd < 0) {
-               ksft_test_result_fail("mkstemp() failed\n");
+               ksft_test_result_fail("mkstemp() failed (%s)\n", strerror(errno));
                return;
        }
 
        if (unlink(filename)) {
-               ksft_test_result_fail("unlink() failed\n");
+               ksft_test_result_fail("unlink() failed (%s)\n", strerror(errno));
                goto close;
        }
 
@@ -317,7 +322,7 @@ static void run_with_memfd_hugetlb(test_fn fn, const char *desc,
 
        fd = memfd_create("test", flags);
        if (fd < 0) {
-               ksft_test_result_skip("memfd_create() failed\n");
+               ksft_test_result_skip("memfd_create() failed (%s)\n", strerror(errno));
                return;
        }