xref: /aosp_15_r20/external/ltp/testcases/kernel/syscalls/mincore/mincore04.c (revision 49cdfc7efb34551c7342be41a7384b9c40d7cab7)
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