1 /*
2 * Copyright (c) Crackerjack Project., 2007-2008, Hitachi, Ltd
3 * Copyright (c) 2017 Petr Vorel <pvorel@suse.cz>
4 *
5 * Authors:
6 * Takahiro Yasui <takahiro.yasui.mp@hitachi.com>,
7 * Yumiko Sugita <yumiko.sugita.yf@hitachi.com>,
8 * Satoshi Fujiwara <sa-fuji@sdl.hitachi.co.jp>
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License as
12 * published by the Free Software Foundation; either version 2 of
13 * the License, or (at your option) any later version.
14 *
15 * This program is distributed in the hope that it would be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program. If not, see <http://www.gnu.org/licenses/>.
22 */
23
24 #include <errno.h>
25 #if HAVE_NUMA_H
26 #include <numa.h>
27 #endif
28
29 #include "config.h"
30 #include "numa_helper.h"
31 #include "tst_test.h"
32
33 #ifdef HAVE_NUMA_V2
34
35 #define MEM_LENGTH (4 * 1024 * 1024)
36
37 #define UNKNOWN_POLICY -1
38
39 #define POLICY_DESC(x) .policy = x, .desc = #x
40 #define POLICY_DESC_TEXT(x, y) .policy = x, .desc = #x" ("y")"
41
42 static struct bitmask *nodemask, *getnodemask, *empty_nodemask;
43
44 static void test_default(unsigned int i, char *p);
45 static void test_none(unsigned int i, char *p);
46 static void test_invalid_nodemask(unsigned int i, char *p);
47
48 struct test_case {
49 int policy;
50 const char *desc;
51 unsigned flags;
52 int ret;
53 int err;
54 void (*test)(unsigned int, char *);
55 struct bitmask **exp_nodemask;
56 };
57
58 static struct test_case tcase[] = {
59 {
60 POLICY_DESC(MPOL_DEFAULT),
61 .ret = 0,
62 .err = 0,
63 .test = test_none,
64 .exp_nodemask = &empty_nodemask,
65 },
66 {
67 POLICY_DESC_TEXT(MPOL_DEFAULT, "target exists"),
68 .ret = -1,
69 .err = EINVAL,
70 .test = test_default,
71 },
72 {
73 POLICY_DESC_TEXT(MPOL_BIND, "no target"),
74 .ret = -1,
75 .err = EINVAL,
76 .test = test_none,
77 },
78 {
79 POLICY_DESC(MPOL_BIND),
80 .ret = 0,
81 .err = 0,
82 .test = test_default,
83 .exp_nodemask = &nodemask,
84 },
85 {
86 POLICY_DESC_TEXT(MPOL_INTERLEAVE, "no target"),
87 .ret = -1,
88 .err = EINVAL,
89 .test = test_none,
90 },
91 {
92 POLICY_DESC(MPOL_INTERLEAVE),
93 .ret = 0,
94 .err = 0,
95 .test = test_default,
96 .exp_nodemask = &nodemask,
97 },
98 {
99 POLICY_DESC_TEXT(MPOL_PREFERRED, "no target"),
100 .ret = 0,
101 .err = 0,
102 .test = test_none,
103 },
104 {
105 POLICY_DESC(MPOL_PREFERRED),
106 .ret = 0,
107 .err = 0,
108 .test = test_default,
109 .exp_nodemask = &nodemask,
110 },
111 {
112 POLICY_DESC(UNKNOWN_POLICY),
113 .ret = -1,
114 .err = EINVAL,
115 .test = test_none,
116 },
117 {
118 POLICY_DESC_TEXT(MPOL_DEFAULT, "invalid flags"),
119 .flags = -1,
120 .ret = -1,
121 .err = EINVAL,
122 .test = test_none,
123 },
124 {
125 POLICY_DESC_TEXT(MPOL_PREFERRED, "invalid nodemask"),
126 .ret = -1,
127 .err = EFAULT,
128 .test = test_invalid_nodemask,
129 },
130 };
131
test_default(unsigned int i,char * p)132 static void test_default(unsigned int i, char *p)
133 {
134 struct test_case *tc = &tcase[i];
135
136 TEST(mbind(p, MEM_LENGTH, tc->policy, nodemask->maskp,
137 nodemask->size, tc->flags));
138 }
139
test_none(unsigned int i,char * p)140 static void test_none(unsigned int i, char *p)
141 {
142 struct test_case *tc = &tcase[i];
143
144 TEST(mbind(p, MEM_LENGTH, tc->policy, NULL, 0, tc->flags));
145 }
146
test_invalid_nodemask(unsigned int i,char * p)147 static void test_invalid_nodemask(unsigned int i, char *p)
148 {
149 struct test_case *tc = &tcase[i];
150
151 /* use invalid nodemask (64 MiB after heap) */
152 TEST(mbind(p, MEM_LENGTH, tc->policy, sbrk(0) + 64*1024*1024,
153 NUMA_NUM_NODES, tc->flags));
154 }
155
setup(void)156 static void setup(void)
157 {
158 if (!is_numa(NULL, NH_MEMS, 1))
159 tst_brk(TCONF, "requires NUMA with at least 1 node");
160 empty_nodemask = numa_allocate_nodemask();
161 }
162
setup_node(void)163 static void setup_node(void)
164 {
165 int test_node = -1;
166
167 if (get_allowed_nodes(NH_MEMS, 1, &test_node) < 0)
168 tst_brk(TBROK | TERRNO, "get_allowed_nodes failed");
169
170 nodemask = numa_allocate_nodemask();
171 getnodemask = numa_allocate_nodemask();
172 numa_bitmask_setbit(nodemask, test_node);
173 }
174
do_test(unsigned int i)175 static void do_test(unsigned int i)
176 {
177 struct test_case *tc = &tcase[i];
178 int policy, fail = 0;
179 char *p = NULL;
180
181 tst_res(TINFO, "case %s", tc->desc);
182
183 setup_node();
184
185 p = mmap(NULL, MEM_LENGTH, PROT_READ | PROT_WRITE, MAP_PRIVATE |
186 MAP_ANONYMOUS, 0, 0);
187 if (p == MAP_FAILED)
188 tst_brk(TBROK | TERRNO, "mmap");
189
190 tc->test(i, p);
191
192 if (TST_RET >= 0) {
193 /* Check policy of the allocated memory */
194 TEST(get_mempolicy(&policy, getnodemask->maskp,
195 getnodemask->size, p, MPOL_F_ADDR));
196 if (TST_RET < 0) {
197 tst_res(TFAIL | TTERRNO, "get_mempolicy failed");
198 return;
199 }
200 if (tc->policy != policy) {
201 tst_res(TFAIL, "Wrong policy: %d, expected: %d",
202 tc->policy, policy);
203 fail = 1;
204 }
205 if (tc->exp_nodemask) {
206 struct bitmask *exp_mask = *(tc->exp_nodemask);
207
208 if (!numa_bitmask_equal(exp_mask, getnodemask)) {
209 tst_res(TFAIL, "masks are not equal");
210 tst_res_hexd(TINFO, exp_mask->maskp,
211 exp_mask->size / 8, "exp_mask: ");
212 tst_res_hexd(TINFO, getnodemask->maskp,
213 getnodemask->size / 8, "returned: ");
214 fail = 1;
215 }
216 }
217 }
218
219 if (TST_RET != tc->ret) {
220 tst_res(TFAIL, "wrong return code: %ld, expected: %d",
221 TST_RET, tc->ret);
222 fail = 1;
223 }
224 if (TST_RET == -1 && TST_ERR != tc->err) {
225 tst_res(TFAIL | TTERRNO, "expected errno: %s, got",
226 tst_strerrno(tc->err));
227 fail = 1;
228 }
229 if (!fail)
230 tst_res(TPASS, "Test passed");
231 }
232
233 static struct tst_test test = {
234 .tcnt = ARRAY_SIZE(tcase),
235 .test = do_test,
236 .setup = setup,
237 };
238
239 #else
240 TST_TEST_TCONF(NUMA_ERROR_MSG);
241 #endif
242