selftests/mm: unpoison pages in memory-failure teardown

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.

Link: https://lore.kernel.org/20260729091127.1001179-1-usama.anjum@arm.com
Fixes: ff4ef2fbd1 ("selftests/mm: add memory failure anonymous page test")
Signed-off-by: Muhammad Usama Anjum <usama.anjum@arm.com>
Reviewed-by: David Hildenbrand (Arm) <david@kernel.org>
Acked-by: Miaohe Lin <linmiaohe@huawei.com>
Cc: Liam R. Howlett <liam@infradead.org>
Cc: Lorenzo Stoakes <ljs@kernel.org>
Cc: Michal Hocko <mhocko@suse.com>
Cc: Mike Rapoport <rppt@kernel.org>
Cc: Naoya Horiguchi <nao.horiguchi@gmail.com>
Cc: Shuah Khan <shuah@kernel.org>
Cc: Suren Baghdasaryan <surenb@google.com>
Cc: Vlastimil Babka <vbabka@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
This commit is contained in:
Muhammad Usama Anjum
2026-07-29 10:11:26 +01:00
committed by Andrew Morton
parent 1d3897b024
commit 288058d8db

View File

@@ -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);
}
@@ -296,8 +300,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);
}
@@ -307,8 +311,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);
@@ -337,8 +339,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);
}
@@ -348,8 +350,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);