xref: /aosp_15_r20/external/ltp/testcases/kernel/mem/hugetlb/hugeshmat/hugeshmat04.c (revision 49cdfc7efb34551c7342be41a7384b9c40d7cab7)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (c) Linux Test Project, 2014-2017
4  *
5  * DESCRIPTION
6  *	hugeshmat04 - test for hugepage leak inspection.
7  *
8  *	It is a regression test for shared hugepage leak, when over 1GB
9  *	shared memory was alocated in hugepage, the hugepage is not released
10  *	though process finished.
11  *
12  *	You need more than 2GB memory in test job
13  *
14  * HISTORY
15  * 	05/2014 - Written by Fujistu Corp.
16  *	12/2014 - Port to LTP by Li Wang.
17  *
18  * RESTRICTIONS
19  * 	test must be run at root
20  */
21 
22 #include "hugetlb.h"
23 
24 #define SIZE	(1024 * 1024 * 1024)
25 #define BOUNDARY (1024 * 1024 * 1024)
26 #define BOUNDARY_MAX (3U * 1024 * 1024 * 1024)
27 
28 static long huge_free;
29 static long huge_free2;
30 
31 static void shared_hugepage(void);
32 
test_hugeshmat(unsigned int i LTP_ATTRIBUTE_UNUSED)33 static void test_hugeshmat(unsigned int i LTP_ATTRIBUTE_UNUSED)
34 {
35 	huge_free = SAFE_READ_MEMINFO("HugePages_Free:");
36 	shared_hugepage();
37 	huge_free2 = SAFE_READ_MEMINFO("HugePages_Free:");
38 
39 	if (huge_free2 != huge_free)
40 		tst_brk(TFAIL, "Test failed. Hugepage leak inspection.");
41 	else
42 		tst_res(TPASS, "No regression found.");
43 }
44 
shared_hugepage(void)45 static void shared_hugepage(void)
46 {
47 	pid_t pid;
48 	int status, shmid;
49 	size_t size = (size_t)SIZE;
50 	void *buf;
51 	unsigned long boundary = BOUNDARY;
52 
53 	shmid = shmget(IPC_PRIVATE, size, SHM_HUGETLB | IPC_CREAT | 0777);
54 	if (shmid < 0)
55 		tst_brk(TBROK | TERRNO, "shmget");
56 
57 	while (boundary <= BOUNDARY_MAX
58 		&& range_is_mapped(boundary, boundary+SIZE))
59 		boundary += 128*1024*1024;
60 	if (boundary > BOUNDARY_MAX)
61 		tst_brk(TCONF, "failed to find free unmapped range");
62 
63 	tst_res(TINFO, "attaching at 0x%lx", boundary);
64 	buf = shmat(shmid, (void *)boundary, SHM_RND | 0777);
65 	if (buf == (void *)-1) {
66 		shmctl(shmid, IPC_RMID, NULL);
67 		tst_brk(TBROK | TERRNO, "shmat");
68 	}
69 
70 	memset(buf, 2, size);
71 	pid = SAFE_FORK();
72 	if (pid == 0)
73 		exit(1);
74 
75 	wait(&status);
76 	shmdt(buf);
77 	shmctl(shmid, IPC_RMID, NULL);
78 }
79 
setup(void)80 static void setup(void)
81 {
82 	long hpage_size, orig_hugepages;
83 	unsigned long new_shmmax;
84 
85 	orig_hugepages = get_sys_tune("nr_hugepages");
86 	SAFE_FILE_SCANF(PATH_SHMMAX, "%lu", &new_shmmax);
87 
88 	if (new_shmmax < SIZE)
89 		tst_brk(TCONF,	"shmmax too low, have: %lu", new_shmmax);
90 
91 	hpage_size = SAFE_READ_MEMINFO("Hugepagesize:") * 1024;
92 
93 	struct tst_hugepage hp = { orig_hugepages + SIZE / hpage_size, TST_NEEDS };
94 	tst_reserve_hugepages(&hp);
95 }
96 
97 static struct tst_test test = {
98 	.tags = (const struct tst_tag[]) {
99 		{"linux-git", "c5c99429fa57"},
100 		{}
101 	},
102 	.needs_root = 1,
103 	.forks_child = 1,
104 	.needs_tmpdir = 1,
105 	.tcnt = 3,
106 	.test = test_hugeshmat,
107 	.min_mem_avail = 2048,
108 	.setup = setup,
109 	.hugepages = {1, TST_NEEDS},
110 	.save_restore = (const struct tst_path_val[]) {
111 		{PATH_SHMMAX, "1073741824", TST_SR_TCONF_MISSING | TST_SR_TBROK_RO},
112 		{}
113 	},
114 };
115