summaryrefslogtreecommitdiff
path: root/tools/testing/selftests/mm/memory-failure.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/testing/selftests/mm/memory-failure.c')
-rw-r--r--tools/testing/selftests/mm/memory-failure.c59
1 files changed, 34 insertions, 25 deletions
diff --git a/tools/testing/selftests/mm/memory-failure.c b/tools/testing/selftests/mm/memory-failure.c
index 3d9e0b9ffb41..f3cb578b1609 100644
--- a/tools/testing/selftests/mm/memory-failure.c
+++ b/tools/testing/selftests/mm/memory-failure.c
@@ -13,7 +13,6 @@
#include <unistd.h>
#include <signal.h>
#include <setjmp.h>
-#include <unistd.h>
#include <fcntl.h>
#include <sys/vfs.h>
#include <linux/magic.h>
@@ -47,7 +46,7 @@ FIXTURE(memory_failure)
unsigned long pfn;
int pagemap_fd;
int kpageflags_fd;
- bool triggered;
+ bool injection_attempted;
};
FIXTURE_VARIANT(memory_failure)
@@ -123,13 +122,6 @@ static void teardown_sighandler(void)
sigaction(SIGBUS, &sa, NULL);
}
-FIXTURE_TEARDOWN(memory_failure)
-{
- close(self->kpageflags_fd);
- close(self->pagemap_fd);
- teardown_sighandler();
-}
-
static void prepare(struct __test_metadata *_metadata, FIXTURE_DATA(memory_failure) * self,
void *vaddr)
{
@@ -201,8 +193,7 @@ static void check(struct __test_metadata *_metadata, FIXTURE_DATA(memory_failure
ASSERT_EQ(pfn_flags & KPF_HWPOISON, KPF_HWPOISON);
}
-static void cleanup(struct __test_metadata *_metadata, FIXTURE_DATA(memory_failure) * self,
- void *vaddr)
+static void cleanup(struct __test_metadata *_metadata, FIXTURE_DATA(memory_failure) * self)
{
unsigned long size;
uint64_t pfn_flags;
@@ -218,6 +209,20 @@ static void cleanup(struct __test_metadata *_metadata, FIXTURE_DATA(memory_failu
ASSERT_EQ(size, self->corrupted_size);
}
+FIXTURE_TEARDOWN(memory_failure)
+{
+ /*
+ * Injection may poison the page before failing or delivering SIGBUS, so
+ * clean up after every injection attempt.
+ */
+ if (self->injection_attempted)
+ cleanup(_metadata, self);
+
+ close(self->kpageflags_fd);
+ close(self->pagemap_fd);
+ teardown_sighandler();
+}
+
TEST_F(memory_failure, anon)
{
char *addr;
@@ -232,8 +237,8 @@ TEST_F(memory_failure, anon)
prepare(_metadata, self, addr);
ret = sigsetjmp(signal_jmp_buf, 1);
- if (!self->triggered) {
- self->triggered = true;
+ if (!self->injection_attempted) {
+ self->injection_attempted = true;
ASSERT_EQ(variant->inject(self, addr), 0);
FORCE_READ(*addr);
}
@@ -243,8 +248,6 @@ TEST_F(memory_failure, anon)
else
check(_metadata, self, addr, MADV_SOFT_ANON, ret);
- cleanup(_metadata, self, addr);
-
ASSERT_EQ(munmap(addr, self->page_size), 0);
}
@@ -284,8 +287,10 @@ TEST_F(memory_failure, clean_pagecache)
if (fd < 0)
SKIP(return, "failed to open test file.\n");
fs_type = get_fs_type(fd);
- if (!fs_type || fs_type == TMPFS_MAGIC)
+ if (!fs_type || fs_type == TMPFS_MAGIC) {
+ close(fd);
SKIP(return, "unsupported filesystem :%x\n", fs_type);
+ }
addr = mmap(0, self->page_size, PROT_READ | PROT_WRITE,
MAP_SHARED, fd, 0);
@@ -297,8 +302,8 @@ TEST_F(memory_failure, clean_pagecache)
prepare(_metadata, self, addr);
ret = sigsetjmp(signal_jmp_buf, 1);
- if (!self->triggered) {
- self->triggered = true;
+ if (!self->injection_attempted) {
+ self->injection_attempted = true;
ASSERT_EQ(variant->inject(self, addr), 0);
FORCE_READ(*addr);
}
@@ -308,8 +313,6 @@ TEST_F(memory_failure, clean_pagecache)
else
check(_metadata, self, addr, MADV_SOFT_CLEAN_PAGECACHE, ret);
- cleanup(_metadata, self, addr);
-
ASSERT_EQ(munmap(addr, self->page_size), 0);
ASSERT_EQ(close(fd), 0);
@@ -326,8 +329,16 @@ TEST_F(memory_failure, dirty_pagecache)
if (fd < 0)
SKIP(return, "failed to open test file.\n");
fs_type = get_fs_type(fd);
- if (!fs_type || fs_type == TMPFS_MAGIC)
+ /*
+ * MADV_HARD poisoning of dirty page-cache data records an expected
+ * -EIO in the file mapping. NFS reports this error on close(), so
+ * skip this variant.
+ */
+ if (!fs_type || fs_type == TMPFS_MAGIC ||
+ (fs_type == NFS_SUPER_MAGIC && variant->type == MADV_HARD)) {
+ close(fd);
SKIP(return, "unsupported filesystem :%x\n", fs_type);
+ }
addr = mmap(0, self->page_size, PROT_READ | PROT_WRITE,
MAP_SHARED, fd, 0);
@@ -338,8 +349,8 @@ TEST_F(memory_failure, dirty_pagecache)
prepare(_metadata, self, addr);
ret = sigsetjmp(signal_jmp_buf, 1);
- if (!self->triggered) {
- self->triggered = true;
+ if (!self->injection_attempted) {
+ self->injection_attempted = true;
ASSERT_EQ(variant->inject(self, addr), 0);
FORCE_READ(*addr);
}
@@ -349,8 +360,6 @@ TEST_F(memory_failure, dirty_pagecache)
else
check(_metadata, self, addr, MADV_SOFT_DIRTY_PAGECACHE, ret);
- cleanup(_metadata, self, addr);
-
ASSERT_EQ(munmap(addr, self->page_size), 0);
ASSERT_EQ(close(fd), 0);