1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Copyright (c) 2018 Cyril Hrubis <chrubis@suse.cz>
4 */
5
6 /*
7 * We are testing set_mempolicy() with MPOL_BIND and MPOL_PREFERRED.
8 *
9 * For each node with memory we set its bit in nodemask with set_mempolicy()
10 * and verify that memory has been allocated accordingly.
11 */
12
13 #include <errno.h>
14 #include "config.h"
15 #ifdef HAVE_NUMA_V2
16 # include <numa.h>
17 # include <numaif.h>
18 #endif
19 #include "tst_test.h"
20 #include "tst_numa.h"
21
22 #ifdef HAVE_NUMA_V2
23
24 #include "set_mempolicy.h"
25
26 static size_t page_size;
27 static struct tst_nodemap *nodes;
28
29 #define PAGES_ALLOCATED 16u
30
setup(void)31 static void setup(void)
32 {
33 page_size = getpagesize();
34
35 nodes = tst_get_nodemap(TST_NUMA_MEM, 2 * PAGES_ALLOCATED * page_size / 1024);
36 if (nodes->cnt <= 1)
37 tst_brk(TCONF, "Test requires at least two NUMA memory nodes");
38 }
39
cleanup(void)40 static void cleanup(void)
41 {
42 tst_nodemap_free(nodes);
43 }
44
verify_mempolicy(unsigned int node,int mode)45 static void verify_mempolicy(unsigned int node, int mode)
46 {
47 struct bitmask *bm = numa_allocate_nodemask();
48 unsigned int i;
49
50 numa_bitmask_setbit(bm, node);
51
52 TEST(set_mempolicy(mode, bm->maskp, bm->size+1));
53
54 if (TST_RET) {
55 tst_res(TFAIL | TTERRNO,
56 "set_mempolicy(%s) node %u",
57 tst_mempolicy_mode_name(mode), node);
58 return;
59 }
60
61 tst_res(TPASS, "set_mempolicy(%s) node %u",
62 tst_mempolicy_mode_name(mode), node);
63
64 numa_free_nodemask(bm);
65
66 const char *prefix = "child: ";
67
68 if (SAFE_FORK()) {
69 prefix = "parent: ";
70 tst_reap_children();
71 }
72
73 tst_nodemap_reset_counters(nodes);
74 alloc_fault_count(nodes, NULL, PAGES_ALLOCATED * page_size);
75 tst_nodemap_print_counters(nodes);
76
77 for (i = 0; i < nodes->cnt; i++) {
78 if (nodes->map[i] == node) {
79 if (nodes->counters[i] == PAGES_ALLOCATED) {
80 tst_res(TPASS, "%sNode %u allocated %u",
81 prefix, node, PAGES_ALLOCATED);
82 } else {
83 tst_res(TFAIL, "%sNode %u allocated %u, expected %u",
84 prefix, node, nodes->counters[i],
85 PAGES_ALLOCATED);
86 }
87 continue;
88 }
89
90 if (nodes->counters[i]) {
91 tst_res(TFAIL, "%sNode %u allocated %u, expected 0",
92 prefix, i, nodes->counters[i]);
93 }
94 }
95 }
96
verify_set_mempolicy(unsigned int n)97 static void verify_set_mempolicy(unsigned int n)
98 {
99 unsigned int i;
100 int mode = n ? MPOL_PREFERRED : MPOL_BIND;
101
102 for (i = 0; i < nodes->cnt; i++)
103 verify_mempolicy(nodes->map[i], mode);
104 }
105
106 static struct tst_test test = {
107 .setup = setup,
108 .cleanup = cleanup,
109 .test = verify_set_mempolicy,
110 .tcnt = 2,
111 .forks_child = 1,
112 .needs_checkpoints = 1,
113 };
114
115 #else
116
117 TST_TEST_TCONF(NUMA_ERROR_MSG);
118
119 #endif /* HAVE_NUMA_V2 */
120