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: 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 
     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 
    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 
    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 
    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