diff options
Diffstat (limited to 'tools/testing/selftests/mm/memory-failure.c')
| -rw-r--r-- | tools/testing/selftests/mm/memory-failure.c | 59 |
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); |
