1 /*
2 *
3 * Copyright (c) International Business Machines Corp., 2004
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
13 * the GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20 /*
21 * Test Name: hugemmap01
22 *
23 * Test Description:
24 * Verify that, mmap() succeeds when used to map a file in a hugetlbfs.
25 *
26 * Expected Result:
27 * mmap() should succeed returning the address of the hugetlb mapped region.
28 * The number of free huge pages should decrease.
29 *
30 * Algorithm:
31 * Setup:
32 * Setup signal handling.
33 * Pause for SIGUSR1 if option specified.
34 * Create temporary directory.
35 *
36 * Test:
37 * Loop if the proper options are given.
38 * Execute system call
39 * Check return code, if system call failed (return=-1)
40 * Log the errno and Issue a FAIL message.
41 * Cleanup:
42 * Print timing stats if options given
43 * Delete the temporary directory created.
44 *
45 * HISTORY
46 * 04/2004 Written by Robbie Williamson
47 */
48
49 #include <sys/types.h>
50 #include <sys/mman.h>
51 #include <sys/mount.h>
52 #include <sys/stat.h>
53 #include <errno.h>
54 #include <fcntl.h>
55 #include <signal.h>
56 #include <stdint.h>
57 #include <stdio.h>
58 #include <stdlib.h>
59 #include <string.h>
60 #include <unistd.h>
61
62 #include "test.h"
63 #include "hugetlb.h"
64 #include "safe_macros.h"
65 #include "mem.h"
66
67 static char TEMPFILE[MAXPATHLEN];
68
69 char *TCID = "hugemmap01";
70 int TST_TOTAL = 1;
71 static long *addr;
72 static int fildes;
73 static char *Hopt;
74 static long beforetest;
75 static long aftertest;
76 static long hugepagesmapped;
77 static long hugepages = 128;
78
79 static void help(void);
80
main(int ac,char ** av)81 int main(int ac, char **av)
82 {
83 int lc;
84 int Hflag = 0;
85 long page_sz = 0;
86 int sflag = 0;
87
88 option_t options[] = {
89 {"H:", &Hflag, &Hopt},
90 {"s:", &sflag, &nr_opt},
91 {NULL, NULL, NULL}
92 };
93
94 tst_parse_opts(ac, av, options, &help);
95
96 if (!Hflag) {
97 tst_tmpdir();
98 Hopt = tst_get_tmpdir();
99 }
100 if (sflag)
101 hugepages = SAFE_STRTOL(NULL, nr_opt, 0, LONG_MAX);
102
103 setup();
104
105 for (lc = 0; TEST_LOOPING(lc); lc++) {
106 /* Creat a temporary file used for mapping */
107 fildes = open(TEMPFILE, O_RDWR | O_CREAT, 0666);
108 if (fildes < 0)
109 tst_brkm(TFAIL | TERRNO, cleanup, "open %s failed",
110 TEMPFILE);
111
112 tst_count = 0;
113
114 /* Note the number of free huge pages BEFORE testing */
115 beforetest = read_meminfo("HugePages_Free:");
116
117 /* Note the size of huge page size BEFORE testing */
118 page_sz = read_meminfo("Hugepagesize:") * 1024;
119
120 addr = mmap(NULL, page_sz, PROT_READ | PROT_WRITE,
121 MAP_SHARED, fildes, 0);
122 if (addr == MAP_FAILED) {
123 tst_resm(TFAIL | TERRNO, "mmap() Failed on %s",
124 TEMPFILE);
125 close(fildes);
126 continue;
127 } else {
128 close(fildes);
129 tst_resm(TPASS, "call succeeded");
130 /* force to allocate page and change HugePages_Free */
131 *(int *)addr = 0;
132 }
133
134 /*
135 * Make sure the number of free huge pages
136 * AFTER testing decreased
137 */
138 aftertest = read_meminfo("HugePages_Free:");
139 hugepagesmapped = beforetest - aftertest;
140 if (hugepagesmapped < 1)
141 tst_resm(TWARN, "Number of HUGEPAGES_FREE stayed the"
142 " same. Okay if multiple copies running due"
143 " to test collision.");
144
145 /* Clean up things in case we are looping */
146 /* Unmap the mapped memory */
147 if (munmap(addr, page_sz) != 0)
148 tst_brkm(TFAIL | TERRNO, NULL, "munmap failed");
149
150 close(fildes);
151 }
152
153 cleanup();
154 tst_exit();
155 }
156
setup(void)157 void setup(void)
158 {
159 TEST_PAUSE;
160 tst_require_root();
161 check_hugepage();
162 if (mount("none", Hopt, "hugetlbfs", 0, NULL) < 0)
163 tst_brkm(TBROK | TERRNO, NULL, "mount failed on %s", Hopt);
164
165 orig_hugepages = get_sys_tune("nr_hugepages");
166 set_sys_tune("nr_hugepages", hugepages, 1);
167 snprintf(TEMPFILE, sizeof(TEMPFILE), "%s/mmapfile%d", Hopt, getpid());
168 }
169
cleanup(void)170 void cleanup(void)
171 {
172 unlink(TEMPFILE);
173 set_sys_tune("nr_hugepages", orig_hugepages, 0);
174
175 umount(Hopt);
176 tst_rmdir();
177 }
178
help(void)179 static void help(void)
180 {
181 printf(" -H /.. Location of hugetlbfs, i.e. -H /var/hugetlbfs\n");
182 printf(" -s num Set the number of the been allocated hugepages\n");
183 }
184