• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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