1 /*
2 * Copyright (c) International Business Machines Corp., 2001
3 * Author: Rajeev Tiwari: rajeevti@in.ibm.com
4 * Copyright (c) 2004 Gernot Payer <gpayer@suse.de>
5 * Copyright (c) 2013 Cyril Hrubis <chrubis@suse.cz>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
15 * the GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22 /*
23 * This test case provides a functional validation for mincore system call.
24 * We mmap a file of known size (multiple of page size) and lock it in
25 * memory. Then we obtain page location information via mincore and compare
26 * the result with the expected value.
27 */
28
29 #include <sys/mman.h>
30 #include <sys/types.h>
31 #include <sys/stat.h>
32 #include <sys/wait.h>
33 #include <fcntl.h>
34 #include <unistd.h>
35 #include <signal.h>
36 #include <errno.h>
37
38 #include "test.h"
39
40 char *TCID = "mincore02";
41 int TST_TOTAL = 1;
42
43 static int fd = 0;
44 static void *addr = NULL;
45 static int page_size;
46 static int num_pages = 4;
47 static unsigned char *vec = NULL;
48
cleanup(void)49 static void cleanup(void)
50 {
51 free(vec);
52 munlock(addr, page_size * num_pages);
53 munmap(addr, page_size * num_pages);
54 close(fd);
55 tst_rmdir();
56 }
57
setup(void)58 static void setup(void)
59 {
60 char *buf;
61 size_t size;
62
63 tst_tmpdir();
64
65 page_size = getpagesize();
66 if (page_size == -1)
67 tst_brkm(TBROK | TERRNO, cleanup, "Unable to get page size");
68
69 size = page_size * num_pages;
70 buf = malloc(size);
71
72 memset(buf, 42, size);
73 vec = malloc((size + page_size - 1) / page_size);
74
75 fd = open("mincore02", O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
76 if (fd == -1) {
77 tst_brkm(TBROK | TERRNO, cleanup,
78 "Unable to create temporary file");
79 }
80
81 /* fill the temporary file with two pages of data */
82 if (write(fd, buf, size) < 0) {
83 tst_brkm(TBROK | TERRNO, cleanup,
84 "Error in writing to the file");
85 }
86 free(buf);
87
88 addr = mmap(NULL, size, PROT_READ | PROT_WRITE | PROT_EXEC,
89 MAP_SHARED, fd, 0);
90
91 if (addr == MAP_FAILED) {
92 tst_brkm(TBROK | TERRNO, cleanup,
93 "Unable to map file for read/write");
94 }
95
96 /* lock mmapped file, so mincore returns "in core" for all pages */
97 if (mlock(addr, size) == -1)
98 tst_brkm(TBROK | TERRNO, cleanup, "Unable to lock the file");
99 }
100
main(int argc,char ** argv)101 int main(int argc, char **argv)
102 {
103 int lock_pages, counter;
104 int lc;
105
106 tst_parse_opts(argc, argv, NULL, NULL);
107
108 setup();
109
110 for (lc = 0; TEST_LOOPING(lc); lc++) {
111 tst_count = 0;
112
113 if (mincore(addr, num_pages * page_size, vec) == -1) {
114 tst_brkm(TBROK | TERRNO, cleanup,
115 "Unable to execute mincore system call");
116 }
117
118 /* check status of pages */
119 lock_pages = 0;
120
121 for (counter = 0; counter < num_pages; counter++) {
122 if (vec[counter] & 1)
123 lock_pages++;
124 }
125
126 if (lock_pages == num_pages) {
127 tst_resm(TPASS, "%d pages locked, %d pages in-core", num_pages,
128 lock_pages);
129 } else {
130 tst_resm(TFAIL,
131 "not all locked pages are in-core: no. locked: %d, no. in-core: %d",
132 num_pages, lock_pages);
133 }
134 }
135
136 cleanup();
137 tst_exit();
138 }
139