xref: /aosp_15_r20/external/ltp/testcases/kernel/syscalls/get_mempolicy/get_mempolicy01.c (revision 49cdfc7efb34551c7342be41a7384b9c40d7cab7)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (c) 2020 Petr Vorel <[email protected]>
4  * Copyright (c) Linux Test Project, 2009-2020
5  * Copyright (c) Crackerjack Project, 2007-2008, Hitachi, Ltd
6  *
7  * Authors:
8  * Takahiro Yasui <[email protected]>
9  * Yumiko Sugita <[email protected]>
10  * Satoshi Fujiwara <[email protected]>
11  * Manas Kumar Nayak <[email protected]> (original port to the legacy API)
12  */
13 
14 /*\
15  * [Description]
16  *
17  * Verify that get_mempolicy() returns a proper return value and errno for various cases.
18  */
19 
20 #include "config.h"
21 #include "tst_test.h"
22 
23 #ifdef HAVE_NUMA_V2
24 #include <numa.h>
25 #include <numaif.h>
26 #include <errno.h>
27 #include "tst_numa.h"
28 
29 #define MEM_LENGTH	(4 * 1024 * 1024)
30 #define PAGES_ALLOCATED 16u
31 
32 #define POLICY_DESC(x) .policy = x, .desc = "policy: "#x
33 #define POLICY_DESC_NO_TARGET(x) .policy = x, .desc = "policy: "#x", no target"
34 #define POLICY_DESC_FLAGS(x, y) .policy = x, .flags = y, .desc = "policy: "#x", flags: "#y
35 #define POLICY_DESC_FLAGS_NO_TARGET(x, y) .policy = x, .flags = y, .desc = "policy: "#x", flags: "#y", no target"
36 
37 static struct tst_nodemap *node;
38 static struct bitmask *nodemask, *getnodemask, *empty_nodemask;
39 
40 struct test_case {
41 	int policy;
42 	const char *desc;
43 	unsigned int flags;
44 	char *addr;
45 	int (*pre_test)(struct test_case *tc);
46 	int (*alloc)(struct test_case *tc);
47 	struct bitmask **exp_nodemask;
48 };
49 
50 static int test_set_mempolicy_default(struct test_case *tc);
51 static int test_set_mempolicy_none(struct test_case *tc);
52 static int test_mbind_none(struct test_case *tc);
53 static int test_mbind_default(struct test_case *tc);
54 
55 static struct test_case tcase[] = {
56 	{
57 		POLICY_DESC_NO_TARGET(MPOL_DEFAULT),
58 		.alloc = test_set_mempolicy_none,
59 		.exp_nodemask = &nodemask,
60 	},
61 	{
62 		POLICY_DESC(MPOL_BIND),
63 		.alloc = test_set_mempolicy_default,
64 		.exp_nodemask = &nodemask,
65 	},
66 	{
67 		POLICY_DESC(MPOL_INTERLEAVE),
68 		.alloc = test_set_mempolicy_default,
69 		.exp_nodemask = &nodemask,
70 	},
71 	{
72 		POLICY_DESC_NO_TARGET(MPOL_PREFERRED),
73 		.alloc = test_set_mempolicy_none,
74 		.exp_nodemask = &nodemask,
75 	},
76 	{
77 		POLICY_DESC(MPOL_PREFERRED),
78 		.alloc = test_set_mempolicy_default,
79 		.exp_nodemask = &nodemask,
80 	},
81 	{
82 		POLICY_DESC_FLAGS_NO_TARGET(MPOL_DEFAULT, MPOL_F_ADDR),
83 		.pre_test = test_mbind_none,
84 		.alloc = test_set_mempolicy_none,
85 		.exp_nodemask = &empty_nodemask,
86 	},
87 	{
88 		POLICY_DESC_FLAGS(MPOL_BIND, MPOL_F_ADDR),
89 		.pre_test = test_mbind_default,
90 		.exp_nodemask = &nodemask,
91 	},
92 	{
93 		POLICY_DESC_FLAGS(MPOL_INTERLEAVE, MPOL_F_ADDR),
94 		.pre_test = test_mbind_default,
95 		.alloc = test_set_mempolicy_default,
96 		.exp_nodemask = &nodemask,
97 	},
98 	{
99 		POLICY_DESC_FLAGS_NO_TARGET(MPOL_PREFERRED, MPOL_F_ADDR),
100 		.pre_test = test_mbind_none,
101 		.alloc = test_set_mempolicy_none,
102 		.exp_nodemask = &empty_nodemask,
103 	},
104 	{
105 		POLICY_DESC_FLAGS(MPOL_PREFERRED, MPOL_F_ADDR),
106 		.pre_test = test_mbind_default,
107 		.alloc = test_set_mempolicy_default,
108 		.exp_nodemask = &nodemask,
109 	},
110 };
111 
test_set_mempolicy_default(struct test_case * tc)112 static int test_set_mempolicy_default(struct test_case *tc)
113 {
114 	TEST(set_mempolicy(tc->policy, nodemask->maskp, nodemask->size));
115 	return TST_RET;
116 }
117 
test_set_mempolicy_none(struct test_case * tc)118 static int test_set_mempolicy_none(struct test_case *tc)
119 {
120 	TEST(set_mempolicy(tc->policy, NULL, 0));
121 	return TST_RET;
122 }
123 
test_mbind(struct test_case * tc,unsigned long * maskp,unsigned long size)124 static int test_mbind(struct test_case *tc, unsigned long *maskp, unsigned long size)
125 {
126 	tc->addr = SAFE_MMAP(NULL, MEM_LENGTH, PROT_READ | PROT_WRITE,
127 			     MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
128 
129 	TEST(mbind(tc->addr, MEM_LENGTH, tc->policy, maskp, size, 0));
130 	return TST_RET;
131 }
132 
test_mbind_none(struct test_case * tc)133 static int test_mbind_none(struct test_case *tc)
134 {
135 	return test_mbind(tc, NULL, 0);
136 }
137 
test_mbind_default(struct test_case * tc)138 static int test_mbind_default(struct test_case *tc)
139 {
140 	return test_mbind(tc, nodemask->maskp, nodemask->size);
141 }
142 
setup(void)143 static void setup(void)
144 {
145 	unsigned int i;
146 
147 	node = tst_get_nodemap(TST_NUMA_MEM, PAGES_ALLOCATED * getpagesize() / 1024);
148 	if (node->cnt < 1)
149 		tst_brk(TCONF, "test requires at least one NUMA memory node");
150 
151 	nodemask = numa_allocate_nodemask();
152 	empty_nodemask = numa_allocate_nodemask();
153 	getnodemask = numa_allocate_nodemask();
154 	numa_bitmask_setbit(nodemask, node->map[0]);
155 
156 	for (i = 0; i < ARRAY_SIZE(tcase); i++) {
157 		struct test_case *tc = &tcase[i];
158 
159 		if (tc->pre_test && tc->pre_test(tc))
160 			tst_brk(TFAIL | TERRNO, "test #%d: mbind() failed", i+1);
161 
162 		if (tc->alloc && tc->alloc(tc))
163 			tst_brk(TFAIL | TERRNO, "test #%d: set_mempolicy() failed", i+1);
164 	}
165 }
166 
cleanup(void)167 static void cleanup(void)
168 {
169 	unsigned int i;
170 
171 	for (i = 0; i < ARRAY_SIZE(tcase); i++) {
172 		struct test_case *tc = &tcase[i];
173 
174 		if (tc->pre_test)
175 			SAFE_MUNMAP(tc->addr, MEM_LENGTH);
176 	}
177 
178 	numa_free_nodemask(nodemask);
179 	numa_free_nodemask(getnodemask);
180 	tst_nodemap_free(node);
181 }
182 
do_test(unsigned int i)183 static void do_test(unsigned int i)
184 {
185 	struct test_case *tc = &tcase[i];
186 	int policy;
187 
188 	tst_res(TINFO, "test #%d: %s", i+1, tc->desc);
189 
190 	TST_EXP_PASS(get_mempolicy(&policy, getnodemask->maskp, getnodemask->size,
191 			   tc->addr, tc->flags), "%s", tc->desc);
192 
193 		struct bitmask *exp_mask = *(tc->exp_nodemask);
194 
195 		if (!numa_bitmask_equal(exp_mask, getnodemask)) {
196 			tst_res(TFAIL, "masks are not equal");
197 			tst_res_hexd(TINFO, exp_mask->maskp,
198 				     exp_mask->size / 8, "expected:");
199 			tst_res_hexd(TINFO, getnodemask->maskp,
200 				     getnodemask->size / 8, "returned:");
201 		}
202 }
203 
204 static struct tst_test test = {
205 	.tcnt = ARRAY_SIZE(tcase),
206 	.test = do_test,
207 	.setup = setup,
208 	.cleanup = cleanup,
209 };
210 
211 #else
212 TST_TEST_TCONF(NUMA_ERROR_MSG);
213 #endif /* HAVE_NUMA_V2 */
214