1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Copyright (c) Zilogic Systems Pvt. Ltd., 2020
4 * Email: [email protected]
5 */
6
7 /*
8 * mincore04
9 * Test shows that pages mapped in one process(parent) and
10 * faulted in another(child) results in mincore(in parent) reporting
11 * that all mapped pages are resident.
12 */
13
14 #include <unistd.h>
15 #include <sys/types.h>
16 #include <sys/mman.h>
17 #include <sys/types.h>
18 #include <sys/stat.h>
19 #include <sys/wait.h>
20 #include <fcntl.h>
21 #include <stdlib.h>
22 #include "tst_test.h"
23 #include "pgsize_helpers.h"
24
25 #define NUM_PAGES 3
26
27 static int fd;
28 static int size;
29 static void *ptr;
30
cleanup(void)31 static void cleanup(void)
32 {
33 if (fd > 0)
34 SAFE_CLOSE(fd);
35 if (ptr) {
36 SAFE_MUNLOCK(ptr, size);
37 SAFE_MUNMAP(ptr, size);
38 }
39 }
40
setup(void)41 static void setup(void)
42 {
43 int page_size, ret;
44
45 page_size = getpagesize();
46 size = page_size * NUM_PAGES;
47 fd = SAFE_OPEN("FILE", O_CREAT | O_RDWR, 0600);
48 SAFE_FTRUNCATE(fd, size);
49
50 /* File pages from file creation are cleared from cache. */
51 SAFE_FSYNC(fd);
52 ret = posix_fadvise(fd, 0, size, POSIX_FADV_DONTNEED);
53 if (ret == -1)
54 tst_brk(TBROK | TERRNO, "fadvise failed");
55 }
56
lock_file(void)57 static void lock_file(void)
58 {
59 SAFE_MLOCK(ptr, size);
60 TST_CHECKPOINT_WAKE(0);
61 TST_CHECKPOINT_WAIT(1);
62 }
63
count_pages_in_cache(void)64 static int count_pages_in_cache(void)
65 {
66 int locked_pages = 0;
67 int count, ret;
68 DECLARE_MINCORE_VECTOR(vec, NUM_PAGES);
69
70 TST_CHECKPOINT_WAIT(0);
71
72 ret = mincore(ptr, size, vec);
73 if (ret == -1)
74 tst_brk(TBROK | TERRNO, "mincore failed");
75 for (count = 0; count < nr_pgs_to_nr_kernel_pgs(NUM_PAGES); count++) {
76 if (vec[count] & 1)
77 locked_pages++;
78 }
79 locked_pages = nr_kernel_pgs_to_nr_pgs(locked_pages);
80
81 TST_CHECKPOINT_WAKE(1);
82 return locked_pages;
83 }
84
test_mincore(void)85 static void test_mincore(void)
86 {
87 int locked_pages;
88
89 ptr = SAFE_MMAP(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
90 pid_t child_pid = SAFE_FORK();
91
92 if (child_pid == 0) {
93 lock_file();
94 exit(0);
95 }
96
97 locked_pages = count_pages_in_cache();
98 tst_reap_children();
99
100 if (locked_pages == NUM_PAGES)
101 tst_res(TPASS, "mincore reports all %d pages locked by child process "
102 "are resident", locked_pages);
103 else
104 tst_res(TFAIL, "mincore reports %d pages resident but %d pages "
105 "locked by child process", locked_pages, NUM_PAGES);
106 }
107
108 static struct tst_test test = {
109 .setup = setup,
110 .cleanup = cleanup,
111 .forks_child = 1,
112 .test_all = test_mincore,
113 .needs_checkpoints = 1,
114 };
115