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
27 static long huge_free;
28 static long huge_free2;
29 static long hugepages;
30 static long orig_shmmax = -1, new_shmmax;
31
32 static void shared_hugepage(void);
33
test_hugeshmat(unsigned int i LTP_ATTRIBUTE_UNUSED)34 static void test_hugeshmat(unsigned int i LTP_ATTRIBUTE_UNUSED)
35 {
36 huge_free = SAFE_READ_MEMINFO("HugePages_Free:");
37 shared_hugepage();
38 huge_free2 = SAFE_READ_MEMINFO("HugePages_Free:");
39
40 if (huge_free2 != huge_free)
41 tst_brk(TFAIL, "Test failed. Hugepage leak inspection.");
42 else
43 tst_res(TPASS, "No regression found.");
44 }
45
shared_hugepage(void)46 static void shared_hugepage(void)
47 {
48 pid_t pid;
49 int status, shmid;
50 size_t size = (size_t)SIZE;
51 void *buf;
52
53 shmid = shmget(IPC_PRIVATE, size, SHM_HUGETLB | IPC_CREAT | 0777);
54 if (shmid < 0)
55 tst_brk(TBROK | TERRNO, "shmget");
56
57 buf = shmat(shmid, (void *)BOUNDARY, SHM_RND | 0777);
58 if (buf == (void *)-1) {
59 shmctl(shmid, IPC_RMID, NULL);
60 tst_brk(TBROK | TERRNO, "shmat");
61 }
62
63 memset(buf, 2, size);
64 pid = SAFE_FORK();
65 if (pid == 0)
66 exit(1);
67
68 wait(&status);
69 shmdt(buf);
70 shmctl(shmid, IPC_RMID, NULL);
71 }
72
setup(void)73 static void setup(void)
74 {
75 long mem_total, hpage_size, orig_hugepages;
76
77 if (tst_hugepages == 0)
78 tst_brk(TCONF, "Not enough hugepages for testing.");
79
80 orig_hugepages = get_sys_tune("nr_hugepages");
81 mem_total = SAFE_READ_MEMINFO("MemTotal:");
82 SAFE_FILE_SCANF(PATH_SHMMAX, "%ld", &orig_shmmax);
83 SAFE_FILE_PRINTF(PATH_SHMMAX, "%ld", (long)SIZE);
84 SAFE_FILE_SCANF(PATH_SHMMAX, "%ld", &new_shmmax);
85
86 if (mem_total < 2L*1024*1024)
87 tst_brk(TCONF, "Needed > 2GB RAM, have: %ld", mem_total);
88
89 if (new_shmmax < SIZE)
90 tst_brk(TCONF, "shmmax too low, have: %ld", new_shmmax);
91
92 hpage_size = SAFE_READ_MEMINFO("Hugepagesize:") * 1024;
93
94 hugepages = orig_hugepages + SIZE / hpage_size;
95 tst_request_hugepages(hugepages);
96 if (tst_hugepages != (unsigned long)hugepages)
97 tst_brk(TCONF, "No enough hugepages for testing.");
98 }
99
cleanup(void)100 static void cleanup(void)
101 {
102 if (orig_shmmax != -1)
103 SAFE_FILE_PRINTF(PATH_SHMMAX, "%ld", orig_shmmax);
104 }
105
106 static struct tst_test test = {
107 .needs_root = 1,
108 .forks_child = 1,
109 .needs_tmpdir = 1,
110 .tcnt = 3,
111 .test = test_hugeshmat,
112 .setup = setup,
113 .cleanup = cleanup,
114 .request_hugepages = 1,
115 };
116