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 <[email protected]>
---
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


Reply via email to