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