xref: /aosp_15_r20/external/ltp/testcases/kernel/syscalls/mbind/mbind01.c (revision 49cdfc7efb34551c7342be41a7384b9c40d7cab7)
1*49cdfc7eSAndroid Build Coastguard Worker // SPDX-License-Identifier: GPL-2.0-or-later
2*49cdfc7eSAndroid Build Coastguard Worker /*
3*49cdfc7eSAndroid Build Coastguard Worker  * Copyright (c) Crackerjack Project., 2007-2008, Hitachi, Ltd
4*49cdfc7eSAndroid Build Coastguard Worker  * Copyright (c) 2017 Petr Vorel <[email protected]>
5*49cdfc7eSAndroid Build Coastguard Worker  *
6*49cdfc7eSAndroid Build Coastguard Worker  * Authors:
7*49cdfc7eSAndroid Build Coastguard Worker  * Takahiro Yasui <[email protected]>,
8*49cdfc7eSAndroid Build Coastguard Worker  * Yumiko Sugita <[email protected]>,
9*49cdfc7eSAndroid Build Coastguard Worker  * Satoshi Fujiwara <[email protected]>
10*49cdfc7eSAndroid Build Coastguard Worker  */
11*49cdfc7eSAndroid Build Coastguard Worker 
12*49cdfc7eSAndroid Build Coastguard Worker #include <errno.h>
13*49cdfc7eSAndroid Build Coastguard Worker #if HAVE_NUMA_H
14*49cdfc7eSAndroid Build Coastguard Worker #include <numa.h>
15*49cdfc7eSAndroid Build Coastguard Worker #endif
16*49cdfc7eSAndroid Build Coastguard Worker 
17*49cdfc7eSAndroid Build Coastguard Worker #include "config.h"
18*49cdfc7eSAndroid Build Coastguard Worker #include "numa_helper.h"
19*49cdfc7eSAndroid Build Coastguard Worker #include "tst_test.h"
20*49cdfc7eSAndroid Build Coastguard Worker #include "tst_numa.h"
21*49cdfc7eSAndroid Build Coastguard Worker #include "lapi/numaif.h"
22*49cdfc7eSAndroid Build Coastguard Worker 
23*49cdfc7eSAndroid Build Coastguard Worker #ifdef HAVE_NUMA_V2
24*49cdfc7eSAndroid Build Coastguard Worker 
25*49cdfc7eSAndroid Build Coastguard Worker #define MEM_LENGTH (4 * 1024 * 1024)
26*49cdfc7eSAndroid Build Coastguard Worker 
27*49cdfc7eSAndroid Build Coastguard Worker #define UNKNOWN_POLICY -1
28*49cdfc7eSAndroid Build Coastguard Worker 
29*49cdfc7eSAndroid Build Coastguard Worker #define POLICY_DESC(x) .policy = x, .desc = #x
30*49cdfc7eSAndroid Build Coastguard Worker #define POLICY_DESC_TEXT(x, y) .policy = x, .desc = #x" ("y")"
31*49cdfc7eSAndroid Build Coastguard Worker 
32*49cdfc7eSAndroid Build Coastguard Worker static struct bitmask *nodemask, *getnodemask, *empty_nodemask;
33*49cdfc7eSAndroid Build Coastguard Worker 
34*49cdfc7eSAndroid Build Coastguard Worker static void test_default(unsigned int i, char *p);
35*49cdfc7eSAndroid Build Coastguard Worker static void test_none(unsigned int i, char *p);
36*49cdfc7eSAndroid Build Coastguard Worker static void test_invalid_nodemask(unsigned int i, char *p);
37*49cdfc7eSAndroid Build Coastguard Worker static void check_policy_pref_or_local(int);
38*49cdfc7eSAndroid Build Coastguard Worker 
39*49cdfc7eSAndroid Build Coastguard Worker struct test_case {
40*49cdfc7eSAndroid Build Coastguard Worker 	int policy;
41*49cdfc7eSAndroid Build Coastguard Worker 	const char *desc;
42*49cdfc7eSAndroid Build Coastguard Worker 	unsigned flags;
43*49cdfc7eSAndroid Build Coastguard Worker 	int ret;
44*49cdfc7eSAndroid Build Coastguard Worker 	int err;
45*49cdfc7eSAndroid Build Coastguard Worker 	void (*check_policy)(int);
46*49cdfc7eSAndroid Build Coastguard Worker 	void (*test)(unsigned int, char *);
47*49cdfc7eSAndroid Build Coastguard Worker 	struct bitmask **exp_nodemask;
48*49cdfc7eSAndroid Build Coastguard Worker };
49*49cdfc7eSAndroid Build Coastguard Worker 
50*49cdfc7eSAndroid Build Coastguard Worker static struct test_case tcase[] = {
51*49cdfc7eSAndroid Build Coastguard Worker 	{
52*49cdfc7eSAndroid Build Coastguard Worker 		POLICY_DESC(MPOL_DEFAULT),
53*49cdfc7eSAndroid Build Coastguard Worker 		.ret = 0,
54*49cdfc7eSAndroid Build Coastguard Worker 		.err = 0,
55*49cdfc7eSAndroid Build Coastguard Worker 		.test = test_none,
56*49cdfc7eSAndroid Build Coastguard Worker 		.exp_nodemask = &empty_nodemask,
57*49cdfc7eSAndroid Build Coastguard Worker 	},
58*49cdfc7eSAndroid Build Coastguard Worker 	{
59*49cdfc7eSAndroid Build Coastguard Worker 		POLICY_DESC_TEXT(MPOL_DEFAULT, "target exists"),
60*49cdfc7eSAndroid Build Coastguard Worker 		.ret = -1,
61*49cdfc7eSAndroid Build Coastguard Worker 		.err = EINVAL,
62*49cdfc7eSAndroid Build Coastguard Worker 		.test = test_default,
63*49cdfc7eSAndroid Build Coastguard Worker 	},
64*49cdfc7eSAndroid Build Coastguard Worker 	{
65*49cdfc7eSAndroid Build Coastguard Worker 		POLICY_DESC_TEXT(MPOL_BIND, "no target"),
66*49cdfc7eSAndroid Build Coastguard Worker 		.ret = -1,
67*49cdfc7eSAndroid Build Coastguard Worker 		.err = EINVAL,
68*49cdfc7eSAndroid Build Coastguard Worker 		.test = test_none,
69*49cdfc7eSAndroid Build Coastguard Worker 	},
70*49cdfc7eSAndroid Build Coastguard Worker 	{
71*49cdfc7eSAndroid Build Coastguard Worker 		POLICY_DESC(MPOL_BIND),
72*49cdfc7eSAndroid Build Coastguard Worker 		.ret = 0,
73*49cdfc7eSAndroid Build Coastguard Worker 		.err = 0,
74*49cdfc7eSAndroid Build Coastguard Worker 		.test = test_default,
75*49cdfc7eSAndroid Build Coastguard Worker 		.exp_nodemask = &nodemask,
76*49cdfc7eSAndroid Build Coastguard Worker 	},
77*49cdfc7eSAndroid Build Coastguard Worker 	{
78*49cdfc7eSAndroid Build Coastguard Worker 		POLICY_DESC_TEXT(MPOL_INTERLEAVE, "no target"),
79*49cdfc7eSAndroid Build Coastguard Worker 		.ret = -1,
80*49cdfc7eSAndroid Build Coastguard Worker 		.err = EINVAL,
81*49cdfc7eSAndroid Build Coastguard Worker 		.test = test_none,
82*49cdfc7eSAndroid Build Coastguard Worker 	},
83*49cdfc7eSAndroid Build Coastguard Worker 	{
84*49cdfc7eSAndroid Build Coastguard Worker 		POLICY_DESC(MPOL_INTERLEAVE),
85*49cdfc7eSAndroid Build Coastguard Worker 		.ret = 0,
86*49cdfc7eSAndroid Build Coastguard Worker 		.err = 0,
87*49cdfc7eSAndroid Build Coastguard Worker 		.test = test_default,
88*49cdfc7eSAndroid Build Coastguard Worker 		.exp_nodemask = &nodemask,
89*49cdfc7eSAndroid Build Coastguard Worker 	},
90*49cdfc7eSAndroid Build Coastguard Worker 	{
91*49cdfc7eSAndroid Build Coastguard Worker 		POLICY_DESC_TEXT(MPOL_PREFERRED, "no target"),
92*49cdfc7eSAndroid Build Coastguard Worker 		.ret = 0,
93*49cdfc7eSAndroid Build Coastguard Worker 		.err = 0,
94*49cdfc7eSAndroid Build Coastguard Worker 		.test = test_none,
95*49cdfc7eSAndroid Build Coastguard Worker 		.check_policy = check_policy_pref_or_local,
96*49cdfc7eSAndroid Build Coastguard Worker 	},
97*49cdfc7eSAndroid Build Coastguard Worker 	{
98*49cdfc7eSAndroid Build Coastguard Worker 		POLICY_DESC(MPOL_PREFERRED),
99*49cdfc7eSAndroid Build Coastguard Worker 		.ret = 0,
100*49cdfc7eSAndroid Build Coastguard Worker 		.err = 0,
101*49cdfc7eSAndroid Build Coastguard Worker 		.test = test_default,
102*49cdfc7eSAndroid Build Coastguard Worker 		.exp_nodemask = &nodemask,
103*49cdfc7eSAndroid Build Coastguard Worker 	},
104*49cdfc7eSAndroid Build Coastguard Worker 	{
105*49cdfc7eSAndroid Build Coastguard Worker 		POLICY_DESC(MPOL_LOCAL),
106*49cdfc7eSAndroid Build Coastguard Worker 		.ret = 0,
107*49cdfc7eSAndroid Build Coastguard Worker 		.err = 0,
108*49cdfc7eSAndroid Build Coastguard Worker 		.test = test_none,
109*49cdfc7eSAndroid Build Coastguard Worker 		.exp_nodemask = &empty_nodemask,
110*49cdfc7eSAndroid Build Coastguard Worker 		.check_policy = check_policy_pref_or_local,
111*49cdfc7eSAndroid Build Coastguard Worker 	},
112*49cdfc7eSAndroid Build Coastguard Worker 	{
113*49cdfc7eSAndroid Build Coastguard Worker 		POLICY_DESC_TEXT(MPOL_LOCAL, "target exists"),
114*49cdfc7eSAndroid Build Coastguard Worker 		.ret = -1,
115*49cdfc7eSAndroid Build Coastguard Worker 		.err = EINVAL,
116*49cdfc7eSAndroid Build Coastguard Worker 		.test = test_default,
117*49cdfc7eSAndroid Build Coastguard Worker 	},
118*49cdfc7eSAndroid Build Coastguard Worker 	{
119*49cdfc7eSAndroid Build Coastguard Worker 		POLICY_DESC(UNKNOWN_POLICY),
120*49cdfc7eSAndroid Build Coastguard Worker 		.ret = -1,
121*49cdfc7eSAndroid Build Coastguard Worker 		.err = EINVAL,
122*49cdfc7eSAndroid Build Coastguard Worker 		.test = test_none,
123*49cdfc7eSAndroid Build Coastguard Worker 	},
124*49cdfc7eSAndroid Build Coastguard Worker 	{
125*49cdfc7eSAndroid Build Coastguard Worker 		POLICY_DESC_TEXT(MPOL_DEFAULT, "invalid flags"),
126*49cdfc7eSAndroid Build Coastguard Worker 		.flags = -1,
127*49cdfc7eSAndroid Build Coastguard Worker 		.ret = -1,
128*49cdfc7eSAndroid Build Coastguard Worker 		.err = EINVAL,
129*49cdfc7eSAndroid Build Coastguard Worker 		.test = test_none,
130*49cdfc7eSAndroid Build Coastguard Worker 	},
131*49cdfc7eSAndroid Build Coastguard Worker 	{
132*49cdfc7eSAndroid Build Coastguard Worker 		POLICY_DESC_TEXT(MPOL_PREFERRED, "invalid nodemask"),
133*49cdfc7eSAndroid Build Coastguard Worker 		.ret = -1,
134*49cdfc7eSAndroid Build Coastguard Worker 		.err = EFAULT,
135*49cdfc7eSAndroid Build Coastguard Worker 		.test = test_invalid_nodemask,
136*49cdfc7eSAndroid Build Coastguard Worker 	},
137*49cdfc7eSAndroid Build Coastguard Worker };
138*49cdfc7eSAndroid Build Coastguard Worker 
check_policy_pref_or_local(int policy)139*49cdfc7eSAndroid Build Coastguard Worker static void check_policy_pref_or_local(int policy)
140*49cdfc7eSAndroid Build Coastguard Worker {
141*49cdfc7eSAndroid Build Coastguard Worker 	if (policy != MPOL_PREFERRED && policy != MPOL_LOCAL) {
142*49cdfc7eSAndroid Build Coastguard Worker 		tst_res(TFAIL, "Wrong policy: %s(%d), "
143*49cdfc7eSAndroid Build Coastguard Worker 			"expected MPOL_PREFERRED or MPOL_LOCAL",
144*49cdfc7eSAndroid Build Coastguard Worker 			tst_mempolicy_mode_name(policy), policy);
145*49cdfc7eSAndroid Build Coastguard Worker 	}
146*49cdfc7eSAndroid Build Coastguard Worker }
147*49cdfc7eSAndroid Build Coastguard Worker 
test_default(unsigned int i,char * p)148*49cdfc7eSAndroid Build Coastguard Worker static void test_default(unsigned int i, char *p)
149*49cdfc7eSAndroid Build Coastguard Worker {
150*49cdfc7eSAndroid Build Coastguard Worker 	struct test_case *tc = &tcase[i];
151*49cdfc7eSAndroid Build Coastguard Worker 
152*49cdfc7eSAndroid Build Coastguard Worker 	TEST(mbind(p, MEM_LENGTH, tc->policy, nodemask->maskp,
153*49cdfc7eSAndroid Build Coastguard Worker 		   nodemask->size, tc->flags));
154*49cdfc7eSAndroid Build Coastguard Worker }
155*49cdfc7eSAndroid Build Coastguard Worker 
test_none(unsigned int i,char * p)156*49cdfc7eSAndroid Build Coastguard Worker static void test_none(unsigned int i, char *p)
157*49cdfc7eSAndroid Build Coastguard Worker {
158*49cdfc7eSAndroid Build Coastguard Worker 	struct test_case *tc = &tcase[i];
159*49cdfc7eSAndroid Build Coastguard Worker 
160*49cdfc7eSAndroid Build Coastguard Worker 	TEST(mbind(p, MEM_LENGTH, tc->policy, NULL, 0, tc->flags));
161*49cdfc7eSAndroid Build Coastguard Worker }
162*49cdfc7eSAndroid Build Coastguard Worker 
test_invalid_nodemask(unsigned int i,char * p)163*49cdfc7eSAndroid Build Coastguard Worker static void test_invalid_nodemask(unsigned int i, char *p)
164*49cdfc7eSAndroid Build Coastguard Worker {
165*49cdfc7eSAndroid Build Coastguard Worker 	struct test_case *tc = &tcase[i];
166*49cdfc7eSAndroid Build Coastguard Worker 
167*49cdfc7eSAndroid Build Coastguard Worker 	/* use invalid nodemask (64 MiB after heap) */
168*49cdfc7eSAndroid Build Coastguard Worker 	TEST(mbind(p, MEM_LENGTH, tc->policy, sbrk(0) + 64*1024*1024,
169*49cdfc7eSAndroid Build Coastguard Worker 		   NUMA_NUM_NODES, tc->flags));
170*49cdfc7eSAndroid Build Coastguard Worker }
171*49cdfc7eSAndroid Build Coastguard Worker 
setup(void)172*49cdfc7eSAndroid Build Coastguard Worker static void setup(void)
173*49cdfc7eSAndroid Build Coastguard Worker {
174*49cdfc7eSAndroid Build Coastguard Worker 	if (!is_numa(NULL, NH_MEMS, 1))
175*49cdfc7eSAndroid Build Coastguard Worker 		tst_brk(TCONF, "requires NUMA with at least 1 node");
176*49cdfc7eSAndroid Build Coastguard Worker 	empty_nodemask = numa_allocate_nodemask();
177*49cdfc7eSAndroid Build Coastguard Worker }
178*49cdfc7eSAndroid Build Coastguard Worker 
setup_node(void)179*49cdfc7eSAndroid Build Coastguard Worker static void setup_node(void)
180*49cdfc7eSAndroid Build Coastguard Worker {
181*49cdfc7eSAndroid Build Coastguard Worker 	int test_node = -1;
182*49cdfc7eSAndroid Build Coastguard Worker 
183*49cdfc7eSAndroid Build Coastguard Worker 	if (get_allowed_nodes(NH_MEMS, 1, &test_node) < 0)
184*49cdfc7eSAndroid Build Coastguard Worker 		tst_brk(TBROK | TERRNO, "get_allowed_nodes failed");
185*49cdfc7eSAndroid Build Coastguard Worker 
186*49cdfc7eSAndroid Build Coastguard Worker 	nodemask = numa_allocate_nodemask();
187*49cdfc7eSAndroid Build Coastguard Worker 	getnodemask = numa_allocate_nodemask();
188*49cdfc7eSAndroid Build Coastguard Worker 	numa_bitmask_setbit(nodemask, test_node);
189*49cdfc7eSAndroid Build Coastguard Worker }
190*49cdfc7eSAndroid Build Coastguard Worker 
do_test(unsigned int i)191*49cdfc7eSAndroid Build Coastguard Worker static void do_test(unsigned int i)
192*49cdfc7eSAndroid Build Coastguard Worker {
193*49cdfc7eSAndroid Build Coastguard Worker 	struct test_case *tc = &tcase[i];
194*49cdfc7eSAndroid Build Coastguard Worker 	int policy, fail = 0;
195*49cdfc7eSAndroid Build Coastguard Worker 	char *p = NULL;
196*49cdfc7eSAndroid Build Coastguard Worker 
197*49cdfc7eSAndroid Build Coastguard Worker 	tst_res(TINFO, "case %s", tc->desc);
198*49cdfc7eSAndroid Build Coastguard Worker 
199*49cdfc7eSAndroid Build Coastguard Worker 	if (tc->policy == MPOL_LOCAL) {
200*49cdfc7eSAndroid Build Coastguard Worker 		if ((tst_kvercmp(5, 14, 0)) >= 0)
201*49cdfc7eSAndroid Build Coastguard Worker 			tc->check_policy = NULL;
202*49cdfc7eSAndroid Build Coastguard Worker 	}
203*49cdfc7eSAndroid Build Coastguard Worker 
204*49cdfc7eSAndroid Build Coastguard Worker 	setup_node();
205*49cdfc7eSAndroid Build Coastguard Worker 
206*49cdfc7eSAndroid Build Coastguard Worker 	p = SAFE_MMAP(NULL, MEM_LENGTH, PROT_READ | PROT_WRITE, MAP_PRIVATE |
207*49cdfc7eSAndroid Build Coastguard Worker 			 MAP_ANONYMOUS, 0, 0);
208*49cdfc7eSAndroid Build Coastguard Worker 
209*49cdfc7eSAndroid Build Coastguard Worker 	tc->test(i, p);
210*49cdfc7eSAndroid Build Coastguard Worker 
211*49cdfc7eSAndroid Build Coastguard Worker 	if (TST_RET >= 0) {
212*49cdfc7eSAndroid Build Coastguard Worker 		/* Check policy of the allocated memory */
213*49cdfc7eSAndroid Build Coastguard Worker 		TEST(get_mempolicy(&policy, getnodemask->maskp,
214*49cdfc7eSAndroid Build Coastguard Worker 				   getnodemask->size, p, MPOL_F_ADDR));
215*49cdfc7eSAndroid Build Coastguard Worker 		if (TST_RET < 0) {
216*49cdfc7eSAndroid Build Coastguard Worker 			tst_res(TFAIL | TTERRNO, "get_mempolicy failed");
217*49cdfc7eSAndroid Build Coastguard Worker 			return;
218*49cdfc7eSAndroid Build Coastguard Worker 		}
219*49cdfc7eSAndroid Build Coastguard Worker 
220*49cdfc7eSAndroid Build Coastguard Worker 		if (tc->check_policy)
221*49cdfc7eSAndroid Build Coastguard Worker 			tc->check_policy(policy);
222*49cdfc7eSAndroid Build Coastguard Worker 		else if (tc->policy != policy) {
223*49cdfc7eSAndroid Build Coastguard Worker 			tst_res(TFAIL, "Wrong policy: %s(%d), expected: %s(%d)",
224*49cdfc7eSAndroid Build Coastguard Worker 				tst_mempolicy_mode_name(policy), policy,
225*49cdfc7eSAndroid Build Coastguard Worker 				tst_mempolicy_mode_name(tc->policy), tc->policy);
226*49cdfc7eSAndroid Build Coastguard Worker 			fail = 1;
227*49cdfc7eSAndroid Build Coastguard Worker 		}
228*49cdfc7eSAndroid Build Coastguard Worker 		if (tc->exp_nodemask) {
229*49cdfc7eSAndroid Build Coastguard Worker 			struct bitmask *exp_mask = *(tc->exp_nodemask);
230*49cdfc7eSAndroid Build Coastguard Worker 
231*49cdfc7eSAndroid Build Coastguard Worker 			if (!numa_bitmask_equal(exp_mask, getnodemask)) {
232*49cdfc7eSAndroid Build Coastguard Worker 				tst_res(TFAIL, "masks are not equal");
233*49cdfc7eSAndroid Build Coastguard Worker 				tst_res_hexd(TINFO, exp_mask->maskp,
234*49cdfc7eSAndroid Build Coastguard Worker 					exp_mask->size / 8, "exp_mask: ");
235*49cdfc7eSAndroid Build Coastguard Worker 				tst_res_hexd(TINFO, getnodemask->maskp,
236*49cdfc7eSAndroid Build Coastguard Worker 					getnodemask->size / 8, "returned: ");
237*49cdfc7eSAndroid Build Coastguard Worker 				fail = 1;
238*49cdfc7eSAndroid Build Coastguard Worker 			}
239*49cdfc7eSAndroid Build Coastguard Worker 		}
240*49cdfc7eSAndroid Build Coastguard Worker 	}
241*49cdfc7eSAndroid Build Coastguard Worker 
242*49cdfc7eSAndroid Build Coastguard Worker 	if (TST_RET != tc->ret) {
243*49cdfc7eSAndroid Build Coastguard Worker 		tst_res(TFAIL, "wrong return code: %ld, expected: %d",
244*49cdfc7eSAndroid Build Coastguard Worker 			TST_RET, tc->ret);
245*49cdfc7eSAndroid Build Coastguard Worker 		fail = 1;
246*49cdfc7eSAndroid Build Coastguard Worker 	}
247*49cdfc7eSAndroid Build Coastguard Worker 	if (TST_RET == -1 && TST_ERR != tc->err) {
248*49cdfc7eSAndroid Build Coastguard Worker 		tst_res(TFAIL | TTERRNO, "expected errno: %s, got",
249*49cdfc7eSAndroid Build Coastguard Worker 			tst_strerrno(tc->err));
250*49cdfc7eSAndroid Build Coastguard Worker 		fail = 1;
251*49cdfc7eSAndroid Build Coastguard Worker 	}
252*49cdfc7eSAndroid Build Coastguard Worker 	if (!fail)
253*49cdfc7eSAndroid Build Coastguard Worker 		tst_res(TPASS, "Test passed");
254*49cdfc7eSAndroid Build Coastguard Worker }
255*49cdfc7eSAndroid Build Coastguard Worker 
256*49cdfc7eSAndroid Build Coastguard Worker static struct tst_test test = {
257*49cdfc7eSAndroid Build Coastguard Worker 	.tcnt = ARRAY_SIZE(tcase),
258*49cdfc7eSAndroid Build Coastguard Worker 	.test = do_test,
259*49cdfc7eSAndroid Build Coastguard Worker 	.setup = setup,
260*49cdfc7eSAndroid Build Coastguard Worker };
261*49cdfc7eSAndroid Build Coastguard Worker 
262*49cdfc7eSAndroid Build Coastguard Worker #else
263*49cdfc7eSAndroid Build Coastguard Worker 	TST_TEST_TCONF(NUMA_ERROR_MSG);
264*49cdfc7eSAndroid Build Coastguard Worker #endif
265