1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * Copyright (c) International Business Machines Corp., 2004 4 * Copyright (c) Linux Test Project, 2004-2017 5 * 6 * Test Name: hugemmap04 7 * 8 * Test Description: 9 * Verify that, a hugetlb mmap() succeeds when used to map the largest 10 * size possible. 11 * 12 * Expected Result: 13 * mmap() should succeed returning the address of the hugetlb mapped region. 14 * The number of free huge pages should decrease. 15 * 16 * Test: 17 * Loop if the proper options are given. 18 * Execute system call 19 * Check return code, if system call failed (return=-1) 20 * Log the errno and Issue a FAIL message. 21 * 22 * HISTORY 23 * 04/2004 Written by Robbie Williamson 24 */ 25 26#include <sys/mount.h> 27#include <stdio.h> 28#include <limits.h> 29#include <sys/param.h> 30#include "lapi/abisize.h" 31#include "hugetlb.h" 32 33static char TEMPFILE[MAXPATHLEN]; 34 35static long *addr; 36static long long mapsize; 37static int fildes; 38static long freepages; 39static long beforetest; 40static long aftertest; 41static long hugepagesmapped; 42 43static void test_hugemmap(void) 44{ 45 int huge_pagesize = 0; 46 47 /* Creat a temporary file used for huge mapping */ 48 fildes = SAFE_OPEN(TEMPFILE, O_RDWR | O_CREAT, 0666); 49 50 freepages = SAFE_READ_MEMINFO("HugePages_Free:"); 51 beforetest = freepages; 52 53 huge_pagesize = SAFE_READ_MEMINFO("Hugepagesize:"); 54 tst_res(TINFO, "Size of huge pages is %d KB", huge_pagesize); 55 56#ifdef TST_ABI32 57 tst_res(TINFO, "Total amount of free huge pages is %ld", 58 freepages); 59 tst_res(TINFO, "Max number allowed for 1 mmap file in" 60 " 32-bits is 128"); 61 if (freepages > 128) 62 freepages = 128; 63#endif 64 mapsize = (long long)freepages * huge_pagesize * 1024; 65 addr = mmap(NULL, mapsize, PROT_READ | PROT_WRITE, 66 MAP_SHARED, fildes, 0); 67 if (addr == MAP_FAILED) { 68 tst_res(TFAIL | TERRNO, "mmap() Failed on %s", 69 TEMPFILE); 70 } else { 71 tst_res(TPASS, 72 "Succeeded mapping file using %ld pages", 73 freepages); 74 75 /* force to allocate page and change HugePages_Free */ 76 *(int *)addr = 0; 77 /* Make sure the number of free huge pages AFTER testing decreased */ 78 aftertest = SAFE_READ_MEMINFO("HugePages_Free:"); 79 hugepagesmapped = beforetest - aftertest; 80 if (hugepagesmapped < 1) 81 tst_res(TWARN, "Number of HUGEPAGES_FREE stayed the" 82 " same. Okay if multiple copies running due" 83 " to test collision."); 84 } 85 86 munmap(addr, mapsize); 87 close(fildes); 88} 89 90void setup(void) 91{ 92 if (tst_hugepages == 0) 93 tst_brk(TCONF, "Not enough hugepages for testing!"); 94 95 if (!Hopt) 96 Hopt = tst_get_tmpdir(); 97 SAFE_MOUNT("none", Hopt, "hugetlbfs", 0, NULL); 98 99 snprintf(TEMPFILE, sizeof(TEMPFILE), "%s/mmapfile%d", Hopt, getpid()); 100} 101 102void cleanup(void) 103{ 104 unlink(TEMPFILE); 105 umount(Hopt); 106} 107 108static struct tst_test test = { 109 .needs_root = 1, 110 .needs_tmpdir = 1, 111 .options = (struct tst_option[]) { 112 {"H:", &Hopt, "Location of hugetlbfs, i.e. -H /var/hugetlbfs"}, 113 {"s:", &nr_opt, "Set the number of the been allocated hugepages"}, 114 {} 115 }, 116 .setup = setup, 117 .cleanup = cleanup, 118 .test_all = test_hugemmap, 119 .hugepages = {128, TST_REQUEST}, 120}; 121