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: hugemmap04
22 *
23 * Test Description:
24 * Verify that, a hugetlb mmap() succeeds when used to map the largest
25 * size possible.
26 *
27 * Expected Result:
28 * mmap() should succeed returning the address of the hugetlb mapped region.
29 * The number of free huge pages should decrease.
30 *
31 * Algorithm:
32 * Setup:
33 * Setup signal handling.
34 * Pause for SIGUSR1 if option specified.
35 * Create temporary directory.
36 *
37 * Test:
38 * Loop if the proper options are given.
39 * Execute system call
40 * Check return code, if system call failed (return=-1)
41 * Log the errno and Issue a FAIL message.
42 * Cleanup:
43 * Print timing stats if options given
44 * Delete the temporary directory created.
45 *
46 * HISTORY
47 * 04/2004 Written by Robbie Williamson
48 */
49
50 #include <sys/types.h>
51 #include <sys/mman.h>
52 #include <sys/mount.h>
53 #include <sys/stat.h>
54 #include <errno.h>
55 #include <fcntl.h>
56 #include <signal.h>
57 #include <stdint.h>
58 #include <stdio.h>
59 #include <stdlib.h>
60 #include <string.h>
61 #include <unistd.h>
62
63 #include "test.h"
64 #include "safe_macros.h"
65 #include "mem.h"
66 #include "hugetlb.h"
67
68 static char TEMPFILE[MAXPATHLEN];
69
70 char *TCID = "hugemmap04";
71 int TST_TOTAL = 1;
72 static long *addr;
73 static long long mapsize;
74 static int fildes;
75 static long freepages;
76 static long beforetest;
77 static long aftertest;
78 static long hugepagesmapped;
79 static long hugepages = 128;
80 static char *Hopt;
81
82 static void help(void);
83
main(int ac,char ** av)84 int main(int ac, char **av)
85 {
86 int lc;
87 int Hflag = 0;
88 int sflag = 0;
89 int huge_pagesize = 0;
90
91 option_t options[] = {
92 {"H:", &Hflag, &Hopt},
93 {"s:", &sflag, &nr_opt},
94 {NULL, NULL, NULL}
95 };
96
97 tst_parse_opts(ac, av, options, &help);
98
99 if (!Hflag) {
100 tst_tmpdir();
101 Hopt = tst_get_tmpdir();
102 }
103 if (sflag)
104 hugepages = SAFE_STRTOL(NULL, nr_opt, 0, LONG_MAX);
105
106 setup();
107
108 for (lc = 0; TEST_LOOPING(lc); lc++) {
109 /* Creat a temporary file used for huge mapping */
110 fildes = open(TEMPFILE, O_RDWR | O_CREAT, 0666);
111 if (fildes < 0)
112 tst_brkm(TFAIL | TERRNO, cleanup, "open %s failed",
113 TEMPFILE);
114
115 tst_count = 0;
116
117 /* Note the number of free huge pages BEFORE testing */
118 freepages = read_meminfo("HugePages_Free:");
119 beforetest = freepages;
120
121 /* Note the size of huge page size BEFORE testing */
122 huge_pagesize = read_meminfo("Hugepagesize:");
123 tst_resm(TINFO, "Size of huge pages is %d KB", huge_pagesize);
124
125 #if __WORDSIZE == 32
126 tst_resm(TINFO, "Total amount of free huge pages is %d",
127 freepages);
128 tst_resm(TINFO, "Max number allowed for 1 mmap file in"
129 " 32-bits is 128");
130 if (freepages > 128)
131 freepages = 128;
132 #endif
133 mapsize = (long long)freepages *huge_pagesize * 1024;
134 addr = mmap(NULL, mapsize, PROT_READ | PROT_WRITE,
135 MAP_SHARED, fildes, 0);
136 sleep(2);
137 if (addr == MAP_FAILED) {
138 tst_resm(TFAIL | TERRNO, "mmap() Failed on %s",
139 TEMPFILE);
140 close(fildes);
141 continue;
142 } else {
143 tst_resm(TPASS,
144 "Succeeded mapping file using %ld pages",
145 freepages);
146 /* force to allocate page and change HugePages_Free */
147 *(int *)addr = 0;
148 }
149
150 /*
151 * Make sure the number of free huge pages
152 * AFTER testing decreased
153 */
154 aftertest = read_meminfo("HugePages_Free:");
155 hugepagesmapped = beforetest - aftertest;
156 if (hugepagesmapped < 1)
157 tst_resm(TWARN, "Number of HUGEPAGES_FREE stayed the"
158 " same. Okay if multiple copies running due"
159 " to test collision.");
160
161 /* Clean up things in case we are looping */
162 /* Unmap the mapped memory */
163 if (munmap(addr, mapsize) != 0)
164 tst_brkm(TFAIL | TERRNO, NULL, "munmap failed");
165
166 close(fildes);
167 }
168
169 cleanup();
170 tst_exit();
171 }
172
setup(void)173 void setup(void)
174 {
175 TEST_PAUSE;
176 tst_require_root();
177 check_hugepage();
178 if (mount("none", Hopt, "hugetlbfs", 0, NULL) < 0)
179 tst_brkm(TBROK | TERRNO, NULL, "mount failed on %s", Hopt);
180 orig_hugepages = get_sys_tune("nr_hugepages");
181 set_sys_tune("nr_hugepages", hugepages, 1);
182 snprintf(TEMPFILE, sizeof(TEMPFILE), "%s/mmapfile%d", Hopt, getpid());
183 }
184
cleanup(void)185 void cleanup(void)
186 {
187 unlink(TEMPFILE);
188 set_sys_tune("nr_hugepages", orig_hugepages, 0);
189
190 umount(Hopt);
191 tst_rmdir();
192 }
193
help(void)194 static void help(void)
195 {
196 printf(" -H /.. Location of hugetlbfs, i.e. -H /var/hugetlbfs\n");
197 }
198