Some MM selftests attempt to configure the amount of HugeTLB pages of different sizes by writing to nr_hugepages. PowerPC hash MMU pSeries systems advertise gigantic hugepage sizes but do not support runtime allocation of such pages, writes to the corresponding nr_hugepages file fail with -EINVAL. This causes the test to bail out even though the failure is due to a platform limitation rather than the functionality being tested. Ignore -EINVAL when configuring nr_hugepages so that tests continue to run on systems where gigantic hugepage allocation is unsupported. Before patch: ------------------------- running ./hugetlb-madvise ------------------------- TAP version 13 1..1 [INFO] detected hugetlb page size: 16777216 KiB [INFO] detected hugetlb page size: 16384 KiB ok 1 MADV_DONTNEED and MADV_REMOVE on hugetlb Totals: pass:1 fail:0 xfail:0 xpass:0 skip:0 error:0 Bail out! /sys/kernel/mm/hugepages/hugepages-16777216kB/nr_hugepages write(0) failed: Invalid argument Totals: pass:0 fail:0 xfail:0 xpass:0 skip:0 error:0 [FAIL] After patch: ------------------------- running ./hugetlb-madvise ------------------------- TAP version 13 1..1 [INFO] detected hugetlb page size: 16777216 KiB [INFO] detected hugetlb page size: 16384 KiB ok 1 MADV_DONTNEED and MADV_REMOVE on hugetlb Totals: pass:1 fail:0 xfail:0 xpass:0 skip:0 error:0 [PASS] Fixes: 27477b28b74f ("selftests/mm: hugepage_settings: add APIs to get and set nr_hugepages") Co-developed-by: David Hildenbrand (Arm) Signed-off-by: David Hildenbrand (Arm) Signed-off-by: Sayali Patil --- .../testing/selftests/mm/hugepage_settings.c | 2 +- tools/testing/selftests/mm/vm_util.c | 26 ++++++++++++++++--- tools/testing/selftests/mm/vm_util.h | 1 + 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/tools/testing/selftests/mm/hugepage_settings.c b/tools/testing/selftests/mm/hugepage_settings.c index 2eab2110ac6a..d7917dce3aba 100644 --- a/tools/testing/selftests/mm/hugepage_settings.c +++ b/tools/testing/selftests/mm/hugepage_settings.c @@ -437,7 +437,7 @@ void hugetlb_set_nr_pages(unsigned long size, unsigned long nr) hugetlb_sysfs_path(path, sizeof(path), size, "nr_hugepages"); - write_num(path, nr); + write_num_ignore_einval(path, nr); } unsigned long hugetlb_free_pages(unsigned long size) diff --git a/tools/testing/selftests/mm/vm_util.c b/tools/testing/selftests/mm/vm_util.c index 311fc5b4513e..ef1ea11981a7 100644 --- a/tools/testing/selftests/mm/vm_util.c +++ b/tools/testing/selftests/mm/vm_util.c @@ -719,7 +719,7 @@ int read_file(const char *path, char *buf, size_t buflen) return (unsigned int) numread; } -void write_file(const char *path, const char *buf, size_t buflen) +static void __write_file(const char *path, const char *buf, size_t buflen, bool ignore_einval) { int fd, saved_errno; ssize_t numwritten; @@ -735,14 +735,22 @@ void write_file(const char *path, const char *buf, size_t buflen) saved_errno = errno; close(fd); errno = saved_errno; - if (numwritten < 0) + if (numwritten < 0) { + if (ignore_einval && errno == EINVAL) + return; ksft_exit_fail_msg("%s write(%.*s) failed: %s\n", path, (int)(buflen - 1), buf, strerror(errno)); + } if (numwritten != buflen - 1) ksft_exit_fail_msg("%s write(%.*s) is truncated, expected %zu bytes, got %zd bytes\n", path, (int)(buflen - 1), buf, buflen - 1, numwritten); } +void write_file(const char *path, const char *buf, size_t buflen) +{ + __write_file(path, buf, buflen, /* ignore_einval = */ false); +} + unsigned long read_num(const char *path) { char buf[21]; @@ -753,12 +761,22 @@ unsigned long read_num(const char *path) return strtoul(buf, NULL, 10); } -void write_num(const char *path, unsigned long num) +static void __write_num(const char *path, unsigned long num, bool ignore_einval) { char buf[21]; sprintf(buf, "%lu", num); - write_file(path, buf, strlen(buf) + 1); + __write_file(path, buf, strlen(buf) + 1, ignore_einval); +} + +void write_num(const char *path, unsigned long num) +{ + return __write_num(path, num, /* ignore_einval = */ false); +} + +void write_num_ignore_einval(const char *path, unsigned long num) +{ + return __write_num(path, num, /* ignore_einval = */ true); } static unsigned long shmall, shmmax; diff --git a/tools/testing/selftests/mm/vm_util.h b/tools/testing/selftests/mm/vm_util.h index ea8fc8fdf0eb..7799154b67ee 100644 --- a/tools/testing/selftests/mm/vm_util.h +++ b/tools/testing/selftests/mm/vm_util.h @@ -168,6 +168,7 @@ void write_file(const char *path, const char *buf, size_t buflen); int read_file(const char *path, char *buf, size_t buflen); unsigned long read_num(const char *path); void write_num(const char *path, unsigned long num); +void write_num_ignore_einval(const char *path, unsigned long num); void shm_limits_prepare(unsigned long length); void __shm_limits_restore(void); -- 2.52.0