1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Copyright (C) 2024 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
4 */
5
6 /*\
7 * [Description]
8 *
9 * This test verifies that cachestat() syscall is properly counting cached pages
10 * written inside a shared memory.
11 *
12 * [Algorithm]
13 *
14 * - create a shared memory with a specific amount of pages
15 * - monitor file with cachestat()
16 * - check if the right amount of pages have been moved into cache
17 */
18
19 #include <stdlib.h>
20 #include "cachestat.h"
21
22 #define FILENAME "myfile.bin"
23
24 static int page_size;
25 static char *page_data;
26 static struct cachestat *cs;
27 static struct cachestat_range *cs_range;
28
test_cached_pages(const int num_pages)29 static void test_cached_pages(const int num_pages)
30 {
31 int fd, file_size;
32
33 tst_res(TINFO, "Number of pages: %d", num_pages);
34
35 memset(cs, 0, sizeof(struct cachestat));
36
37 fd = shm_open(FILENAME, O_RDWR | O_CREAT, 0600);
38 if (fd < 0)
39 tst_brk(TBROK | TERRNO, "shm_open error");
40
41 file_size = page_size * num_pages;
42
43 cs_range->off = 0;
44 cs_range->len = file_size;
45
46 SAFE_FTRUNCATE(fd, file_size);
47 for (int i = 0; i < num_pages; i++)
48 SAFE_WRITE(0, fd, page_data, page_size);
49
50 memset(cs, 0xff, sizeof(*cs));
51
52 TST_EXP_PASS(cachestat(fd, cs_range, cs, 0));
53 print_cachestat(cs);
54
55 TST_EXP_EQ_LI(cs->nr_cache + cs->nr_evicted, num_pages);
56
57 SAFE_CLOSE(fd);
58 shm_unlink(FILENAME);
59 }
60
run(void)61 static void run(void)
62 {
63 for (int i = 0; i < 10; i++)
64 test_cached_pages(1 << i);
65 }
66
setup(void)67 static void setup(void)
68 {
69 page_size = (int)sysconf(_SC_PAGESIZE);
70
71 page_data = SAFE_MALLOC(page_size);
72 memset(page_data, 'a', page_size);
73 }
74
cleanup(void)75 static void cleanup(void)
76 {
77 free(page_data);
78 }
79
80 static struct tst_test test = {
81 .test_all = run,
82 .setup = setup,
83 .cleanup = cleanup,
84 .needs_tmpdir = 1,
85 .bufs = (struct tst_buffers []) {
86 {&cs, .size = sizeof(struct cachestat)},
87 {&cs_range, .size = sizeof(struct cachestat_range)},
88 {}
89 },
90 };
91