Skip to content

Commit 12e8a2f

Browse files
MiaoheLinakpm00
authored andcommitted
selftests/mm: add memory failure clean pagecache test
This patch adds a new testcase to validate memory failure handling for clean pagecache. This test performs similar operations as anonymous pages except allocating memory using mmap() with a file fd. This test helps ensure that memory failure handling for clean pagecache works correctly, including unchanged page content, page isolation, and recovery paths. Link: https://lkml.kernel.org/r/20260206031639.2707102-3-linmiaohe@huawei.com Signed-off-by: Miaohe Lin <linmiaohe@huawei.com> Reported-by: kernel test robot <lkp@intel.com> Closes: https://lore.kernel.org/oe-kbuild-all/202601221142.mDWA1ucw-lkp@intel.com/ Cc: David Hildenbrand <david@kernel.org> Cc: Liam Howlett <liam.howlett@oracle.com> Cc: Lorenzo Stoakes <lorenzo.stoakes@oracle.com> Cc: Mark Brown <broonie@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@suse.cz> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
1 parent ff4ef2f commit 12e8a2f

1 file changed

Lines changed: 66 additions & 0 deletions

File tree

tools/testing/selftests/mm/memory-failure.c

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,14 @@
1010
#include <sys/mman.h>
1111
#include <linux/mman.h>
1212
#include <linux/string.h>
13+
#include <unistd.h>
1314
#include <signal.h>
1415
#include <setjmp.h>
1516
#include <unistd.h>
1617
#include <fcntl.h>
18+
#include <sys/vfs.h>
19+
#include <linux/magic.h>
20+
#include <errno.h>
1721

1822
#include "vm_util.h"
1923

@@ -24,7 +28,9 @@ enum inject_type {
2428

2529
enum result_type {
2630
MADV_HARD_ANON,
31+
MADV_HARD_CLEAN_PAGECACHE,
2732
MADV_SOFT_ANON,
33+
MADV_SOFT_CLEAN_PAGECACHE,
2834
};
2935

3036
static jmp_buf signal_jmp_buf;
@@ -154,6 +160,8 @@ static void check(struct __test_metadata *_metadata, FIXTURE_DATA(memory_failure
154160

155161
switch (type) {
156162
case MADV_SOFT_ANON:
163+
case MADV_HARD_CLEAN_PAGECACHE:
164+
case MADV_SOFT_CLEAN_PAGECACHE:
157165
/* It is not expected to receive a SIGBUS signal. */
158166
ASSERT_EQ(setjmp, 0);
159167

@@ -236,4 +244,62 @@ TEST_F(memory_failure, anon)
236244
ASSERT_EQ(munmap(addr, self->page_size), 0);
237245
}
238246

247+
/* Borrowed from mm/gup_longterm.c. */
248+
static int get_fs_type(int fd)
249+
{
250+
struct statfs fs;
251+
int ret;
252+
253+
do {
254+
ret = fstatfs(fd, &fs);
255+
} while (ret && errno == EINTR);
256+
257+
return ret ? 0 : (int)fs.f_type;
258+
}
259+
260+
TEST_F(memory_failure, clean_pagecache)
261+
{
262+
const char *fname = "./clean-page-cache-test-file";
263+
int fd;
264+
char *addr;
265+
int ret;
266+
int fs_type;
267+
268+
fd = open(fname, O_RDWR | O_CREAT, 0664);
269+
if (fd < 0)
270+
SKIP(return, "failed to open test file.\n");
271+
unlink(fname);
272+
ftruncate(fd, self->page_size);
273+
fs_type = get_fs_type(fd);
274+
if (!fs_type || fs_type == TMPFS_MAGIC)
275+
SKIP(return, "unsupported filesystem :%x\n", fs_type);
276+
277+
addr = mmap(0, self->page_size, PROT_READ | PROT_WRITE,
278+
MAP_SHARED, fd, 0);
279+
if (addr == MAP_FAILED)
280+
SKIP(return, "mmap failed, not enough memory.\n");
281+
memset(addr, 0xce, self->page_size);
282+
fsync(fd);
283+
284+
prepare(_metadata, self, addr);
285+
286+
ret = sigsetjmp(signal_jmp_buf, 1);
287+
if (!self->triggered) {
288+
self->triggered = true;
289+
ASSERT_EQ(variant->inject(self, addr), 0);
290+
FORCE_READ(*addr);
291+
}
292+
293+
if (variant->type == MADV_HARD)
294+
check(_metadata, self, addr, MADV_HARD_CLEAN_PAGECACHE, ret);
295+
else
296+
check(_metadata, self, addr, MADV_SOFT_CLEAN_PAGECACHE, ret);
297+
298+
cleanup(_metadata, self, addr);
299+
300+
ASSERT_EQ(munmap(addr, self->page_size), 0);
301+
302+
ASSERT_EQ(close(fd), 0);
303+
}
304+
239305
TEST_HARNESS_MAIN

0 commit comments

Comments
 (0)