xref: /aosp_15_r20/external/ltp/testcases/kernel/mem/hugetlb/hugemmap/hugemmap32.c (revision 49cdfc7efb34551c7342be41a7384b9c40d7cab7)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (C) 2023, IBM Corporation.
4  * Author: Tarun Sahu
5  */
6 
7 /*\
8  * [Description]
9  *
10  * Before kernel version 5.10-rc7, there was a bug that resulted in a "Bad Page
11  * State" error when freeing gigantic hugepages. This happened because the
12  * struct page entry compound_nr, which overlapped with page->mapping in the
13  * first tail page, was not cleared, causing the error. To ensure that this
14  * issue does not reoccur as struct page keeps changing and some fields are
15  * managed by folio, this test checks that freeing gigantic hugepages does not
16  * produce the above-mentioned error.
17  */
18 
19 #define _GNU_SOURCE
20 #include <dirent.h>
21 
22 #include <stdio.h>
23 
24 #include "hugetlb.h"
25 
26 #define PATH_HUGEPAGE "/sys/kernel/mm/hugepages"
27 #define GIGANTIC_MIN_ORDER 10
28 
29 static int org_g_hpages;
30 static char g_hpage_path[4096];
31 
run_test(void)32 static void run_test(void)
33 {
34 	if (FILE_PRINTF(g_hpage_path, "%d", 1))
35 		tst_brk(TCONF, "Can't update the gigantic hugepages.");
36 	SAFE_FILE_PRINTF(g_hpage_path, "%d", 0);
37 
38 	if (tst_taint_check())
39 		tst_res(TFAIL, "Freeing Gigantic pages resulted in Bad Page State bug.");
40 	else
41 		tst_res(TPASS, "Successfully freed the gigantic hugepages");
42 }
43 
setup(void)44 static void setup(void)
45 {
46 	DIR *dir;
47 	struct dirent *ent;
48 	unsigned long hpage_size;
49 
50 	if (access(PATH_HUGEPAGE, F_OK))
51 		tst_brk(TCONF, "hugetlbfs is not supported");
52 
53 	dir = SAFE_OPENDIR(PATH_HUGEPAGE);
54 	while ((ent = SAFE_READDIR(dir))) {
55 		if ((sscanf(ent->d_name, "hugepages-%lukB", &hpage_size) == 1) &&
56 			is_hugetlb_gigantic(hpage_size * 1024)) {
57 			sprintf(g_hpage_path, "%s/%s/%s", PATH_HUGEPAGE,
58 					ent->d_name, "nr_hugepages");
59 			break;
60 		}
61 	}
62 	if (!g_hpage_path[0])
63 		tst_brk(TCONF, "Gigantic hugepages not supported");
64 
65 	SAFE_CLOSEDIR(dir);
66 
67 	SAFE_FILE_PRINTF("/proc/sys/vm/drop_caches", "3");
68 	SAFE_FILE_PRINTF("/proc/sys/vm/compact_memory", "1");
69 
70 	if (tst_available_mem() < (long long)hpage_size) {
71 		g_hpage_path[0] = '\0';
72 		tst_brk(TCONF, "No enough memory for gigantic hugepage reservation");
73 	}
74 
75 	SAFE_FILE_LINES_SCANF(g_hpage_path, "%d", &org_g_hpages);
76 }
77 
cleanup(void)78 static void cleanup(void)
79 {
80 	if (g_hpage_path[0])
81 		SAFE_FILE_PRINTF(g_hpage_path, "%d", org_g_hpages);
82 }
83 
84 static struct tst_test test = {
85 	.tags = (struct tst_tag[]) {
86 	    {"linux-git", "ba9c1201beaa"},
87 	    {"linux-git", "a01f43901cfb"},
88 	    {}
89 	},
90 	.needs_root = 1,
91 	.setup = setup,
92 	.cleanup = cleanup,
93 	.test_all = run_test,
94 	.taint_check = TST_TAINT_B,
95 };
96