The memory-failure tests call cleanup() only after all result checks. A failed ASSERT_* invokes fixture teardown and aborts the test, so it skips cleanup() and leaves the injected page hardware-poisoned. Invoke cleanup() from FIXTURE_TEARDOWN() instead. Guard it with self->injection_attempted so tests that exit before injection do not try to unpoison a page when no injection was attempted. Injection can poison a page before returning an error or delivering SIGBUS, so teardown must clean up after every injection attempt. This runs the existing HWPoison and HardwareCorrupted checks on both normal and assertion-failure paths. Fixes: ff4ef2fbd101 ("selftests/mm: add memory failure anonymous page test") Signed-off-by: Muhammad Usama Anjum --- Changes since v1: - Rename triggered to injection_attempted. - Document why teardown cleans up after every injection attempt. --- tools/testing/selftests/mm/memory-failure.c | 44 ++++++++++----------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/tools/testing/selftests/mm/memory-failure.c b/tools/testing/selftests/mm/memory-failure.c index 5d00aab31f9b5..f3cb578b16096 100644 --- a/tools/testing/selftests/mm/memory-failure.c +++ b/tools/testing/selftests/mm/memory-failure.c @@ -46,7 +46,7 @@ FIXTURE(memory_failure) unsigned long pfn; int pagemap_fd; int kpageflags_fd; - bool triggered; + bool injection_attempted; }; FIXTURE_VARIANT(memory_failure) @@ -122,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) { @@ -200,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; @@ -217,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; @@ -231,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); } @@ -242,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); } @@ -298,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); } @@ -309,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); @@ -347,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); } @@ -358,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); -- 2.47.3