• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
main(int ac,char ** av)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 
shared_hugepage(void)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 
setup(void)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 
cleanup(void)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