Home | History | Annotate | Download | only in hugemmap
      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