• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) Linux Test Project, 2014-2017
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 
15 /*
16  * DESCRIPTION
17  *	hugeshmat04 - test for hugepage leak inspection.
18  *
19  *	It is a regression test for shared hugepage leak, when over 1GB
20  *	shered memory was alocated in hugepage, the hugepage is not released
21  *	though process finished.
22  *
23  *	You need more than 2GB memory in test job
24  *
25  * HISTORY
26  * 	05/2014 - Written by Fujistu Corp.
27  *	12/2014 - Port to LTP by Li Wang.
28  *
29  * RESTRICTIONS
30  * 	test must be run at root
31  */
32 
33 #include "hugetlb.h"
34 
35 #define SIZE	(1024 * 1024 * 1024)
36 #define BOUNDARY (1024 * 1024 * 1024)
37 
38 static long huge_free;
39 static long huge_free2;
40 static long hugepages;
41 static long orig_shmmax, new_shmmax;
42 
43 static void shared_hugepage(void);
44 
test_hugeshmat(unsigned int i LTP_ATTRIBUTE_UNUSED)45 static void test_hugeshmat(unsigned int i LTP_ATTRIBUTE_UNUSED)
46 {
47 	huge_free = SAFE_READ_MEMINFO("HugePages_Free:");
48 	shared_hugepage();
49 	huge_free2 = SAFE_READ_MEMINFO("HugePages_Free:");
50 
51 	if (huge_free2 != huge_free)
52 		tst_brk(TFAIL, "Test failed. Hugepage leak inspection.");
53 	else
54 		tst_res(TPASS, "No regression found.");
55 }
56 
shared_hugepage(void)57 static void shared_hugepage(void)
58 {
59 	pid_t pid;
60 	int status, shmid;
61 	size_t size = (size_t)SIZE;
62 	void *buf;
63 
64 	shmid = shmget(IPC_PRIVATE, size, SHM_HUGETLB | IPC_CREAT | 0777);
65 	if (shmid < 0)
66 		tst_brk(TBROK | TERRNO, "shmget");
67 
68 	buf = shmat(shmid, (void *)BOUNDARY, SHM_RND | 0777);
69 	if (buf == (void *)-1) {
70 		shmctl(shmid, IPC_RMID, NULL);
71 		tst_brk(TBROK | TERRNO, "shmat");
72 	}
73 
74 	memset(buf, 2, size);
75 	pid = SAFE_FORK();
76 	if (pid == 0)
77 		exit(1);
78 
79 	wait(&status);
80 	shmdt(buf);
81 	shmctl(shmid, IPC_RMID, NULL);
82 }
83 
setup(void)84 static void setup(void)
85 {
86 	long mem_total, hpage_size, orig_hugepages;
87 
88 	orig_hugepages = save_nr_hugepages();
89 	mem_total = SAFE_READ_MEMINFO("MemTotal:");
90 	SAFE_FILE_SCANF(PATH_SHMMAX, "%ld", &orig_shmmax);
91 	SAFE_FILE_PRINTF(PATH_SHMMAX, "%ld", (long)SIZE);
92 	SAFE_FILE_SCANF(PATH_SHMMAX, "%ld", &new_shmmax);
93 
94 	if (mem_total < 2L*1024*1024)
95 		tst_brk(TCONF,	"Needed > 2GB RAM, have: %ld", mem_total);
96 
97 	if (new_shmmax < SIZE)
98 		tst_brk(TCONF,	"shmmax too low, have: %ld", new_shmmax);
99 
100 	hpage_size = SAFE_READ_MEMINFO("Hugepagesize:") * 1024;
101 
102 	hugepages = (orig_hugepages * hpage_size + SIZE) / hpage_size;
103 	set_sys_tune("nr_hugepages", hugepages, 1);
104 }
105 
cleanup(void)106 static void cleanup(void)
107 {
108 	restore_nr_hugepages();
109 	SAFE_FILE_PRINTF(PATH_SHMMAX, "%ld", orig_shmmax);
110 }
111 
112 static struct tst_test test = {
113 	.needs_root = 1,
114 	.forks_child = 1,
115 	.needs_tmpdir = 1,
116 	.tcnt = 3,
117 	.test = test_hugeshmat,
118 	.setup = setup,
119 	.cleanup = cleanup,
120 };
121