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