1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Copyright (c) Zilogic Systems Pvt. Ltd., 2020
4 * Email: code@zilogic.com
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
24 #define NUM_PAGES 3
25
26 static int fd;
27 static int size;
28 static void *ptr;
29
cleanup(void)30 static void cleanup(void)
31 {
32 if (fd > 0)
33 SAFE_CLOSE(fd);
34 if (ptr) {
35 SAFE_MUNLOCK(ptr, size);
36 SAFE_MUNMAP(ptr, size);
37 }
38 }
39
setup(void)40 static void setup(void)
41 {
42 int page_size, ret;
43
44 page_size = getpagesize();
45 size = page_size * NUM_PAGES;
46 fd = SAFE_OPEN("FILE", O_CREAT | O_RDWR, 0600);
47 SAFE_FTRUNCATE(fd, size);
48
49 /* File pages from file creation are cleared from cache. */
50 SAFE_FSYNC(fd);
51 ret = posix_fadvise(fd, 0, size, POSIX_FADV_DONTNEED);
52 if (ret == -1)
53 tst_brk(TBROK | TERRNO, "fadvise failed");
54 }
55
lock_file(void)56 static void lock_file(void)
57 {
58 SAFE_MLOCK(ptr, size);
59 TST_CHECKPOINT_WAKE(0);
60 TST_CHECKPOINT_WAIT(1);
61 }
62
count_pages_in_cache(void)63 static int count_pages_in_cache(void)
64 {
65 int locked_pages = 0;
66 int count, ret;
67 unsigned char vec[NUM_PAGES];
68
69 TST_CHECKPOINT_WAIT(0);
70
71 ret = mincore(ptr, size, vec);
72 if (ret == -1)
73 tst_brk(TBROK | TERRNO, "mincore failed");
74 for (count = 0; count < NUM_PAGES; count++) {
75 if (vec[count] & 1)
76 locked_pages++;
77 }
78
79 TST_CHECKPOINT_WAKE(1);
80 return locked_pages;
81 }
82
test_mincore(void)83 static void test_mincore(void)
84 {
85 int locked_pages;
86
87 ptr = SAFE_MMAP(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
88 pid_t child_pid = SAFE_FORK();
89
90 if (child_pid == 0) {
91 lock_file();
92 exit(0);
93 }
94
95 locked_pages = count_pages_in_cache();
96 tst_reap_children();
97
98 if (locked_pages == NUM_PAGES)
99 tst_res(TPASS, "mincore reports all %d pages locked by child process "
100 "are resident", locked_pages);
101 else
102 tst_res(TFAIL, "mincore reports %d pages resident but %d pages "
103 "locked by child process", locked_pages, NUM_PAGES);
104 }
105
106 static struct tst_test test = {
107 .setup = setup,
108 .cleanup = cleanup,
109 .forks_child = 1,
110 .test_all = test_mincore,
111 .needs_checkpoints = 1,
112 };
113