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