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 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 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 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 194 static void help(void) 195 { 196 printf(" -H /.. Location of hugetlbfs, i.e. -H /var/hugetlbfs\n"); 197 } 198