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) <[email protected]>
Signed-off-by: David Hildenbrand (Arm) <[email protected]>
Signed-off-by: Sayali Patil <[email protected]>
---
.../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