1 /* 2 * Copyright (c) Linux Test Project, 2014 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation; either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 12 * the GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write to the Free Software 16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 17 * 02110-1301 USA 18 */ 19 20 /* 21 * DESCRIPTION 22 * hugeshmat04 - test for hugepage leak inspection. 23 * 24 * It is a regression test for shared hugepage leak, when over 1GB 25 * shered memory was alocated in hugepage, the hugepage is not released 26 * though process finished. 27 * 28 * You need more than 2GB memory in test job 29 * 30 * HISTORY 31 * 05/2014 - Written by Fujistu Corp. 32 * 12/2014 - Port to LTP by Li Wang. 33 * 34 * RESTRICTIONS 35 * test must be run at root 36 */ 37 38 #include <stdio.h> 39 #include <stdlib.h> 40 #include <unistd.h> 41 #include <fcntl.h> 42 #include <string.h> 43 #include <sys/mman.h> 44 #include <sys/types.h> 45 #include <sys/shm.h> 46 #include <sys/wait.h> 47 48 #include "test.h" 49 #include "mem.h" 50 #include "hugetlb.h" 51 52 #define SIZE (1024 * 1024 * 1024) 53 #define BOUNDARY (1024 * 1024 * 1024) 54 55 char *TCID = "hugeshmat04"; 56 int TST_TOTAL = 3; 57 58 static long huge_free; 59 static long huge_free2; 60 static long hugepages; 61 static long orig_shmmax, new_shmmax; 62 63 static void shared_hugepage(void); 64 65 int main(int ac, char **av) 66 { 67 int lc, i; 68 69 tst_parse_opts(ac, av, NULL, NULL); 70 71 setup(); 72 73 for (lc = 0; TEST_LOOPING(lc); lc++) { 74 tst_count = 0; 75 76 for (i = 0; i < TST_TOTAL; i++) { 77 78 huge_free = read_meminfo("HugePages_Free:"); 79 shared_hugepage(); 80 huge_free2 = read_meminfo("HugePages_Free:"); 81 82 if (huge_free2 != huge_free) 83 tst_brkm(TFAIL, cleanup, 84 "Test failed. Hugepage leak inspection."); 85 else 86 tst_resm(TPASS, "No regression found."); 87 } 88 } 89 90 cleanup(); 91 tst_exit(); 92 } 93 94 void shared_hugepage(void) 95 { 96 pid_t pid; 97 int status, shmid; 98 size_t size = (size_t)SIZE; 99 void *buf; 100 101 shmid = shmget(IPC_PRIVATE, size, SHM_HUGETLB | IPC_CREAT | 0777); 102 if (shmid < 0) 103 tst_brkm(TBROK | TERRNO, cleanup, "shmget"); 104 105 buf = shmat(shmid, (void *)BOUNDARY, SHM_RND | 0777); 106 if (buf == (void *)-1) { 107 shmctl(shmid, IPC_RMID, NULL); 108 tst_brkm(TBROK | TERRNO, cleanup, "shmat"); 109 } 110 111 memset(buf, 2, size); 112 pid = fork(); 113 114 if (pid == 0) 115 exit(1); 116 else if (pid < 0) 117 tst_brkm(TBROK | TERRNO, cleanup, "fork"); 118 119 wait(&status); 120 shmdt(buf); 121 shmctl(shmid, IPC_RMID, NULL); 122 } 123 124 void setup(void) 125 { 126 long mem_total, hpage_size; 127 128 tst_require_root(); 129 check_hugepage(); 130 131 mem_total = read_meminfo("MemTotal:"); 132 SAFE_FILE_SCANF(NULL, PATH_SHMMAX, "%ld", &orig_shmmax); 133 SAFE_FILE_PRINTF(NULL, PATH_SHMMAX, "%ld", (long)SIZE); 134 SAFE_FILE_SCANF(NULL, PATH_SHMMAX, "%ld", &new_shmmax); 135 136 if (mem_total < 2L*1024*1024) 137 tst_brkm(TCONF, NULL, "Needed > 2GB RAM, have: %ld", mem_total); 138 139 if (new_shmmax < SIZE) 140 tst_brkm(TCONF, NULL, "shmmax too low, have: %ld", new_shmmax); 141 142 orig_hugepages = get_sys_tune("nr_hugepages"); 143 hpage_size = read_meminfo("Hugepagesize:") * 1024; 144 145 hugepages = (orig_hugepages * hpage_size + SIZE) / hpage_size; 146 set_sys_tune("nr_hugepages", hugepages, 1); 147 148 TEST_PAUSE; 149 } 150 151 void cleanup(void) 152 { 153 set_sys_tune("nr_hugepages", orig_hugepages, 0); 154 SAFE_FILE_PRINTF(NULL, PATH_SHMMAX, "%ld", orig_shmmax); 155 } 156