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 backed by a
8 * file on each supported filesystem.
9 */
10
11#include <errno.h>
12#include "config.h"
13#ifdef HAVE_NUMA_V2
14# include <numaif.h>
15# include <numa.h>
16#endif
17#include "tst_test.h"
18#include "tst_numa.h"
19
20#define MNTPOINT "mntpoint"
21#define PAGES_ALLOCATED 16u
22
23#ifdef HAVE_NUMA_V2
24
25#include "set_mempolicy.h"
26
27static size_t page_size;
28static struct tst_nodemap *nodes;
29
30static void setup(void)
31{
32	page_size = getpagesize();
33
34	nodes = tst_get_nodemap(TST_NUMA_MEM, 2 * PAGES_ALLOCATED * page_size / 1024);
35	if (nodes->cnt <= 1)
36		tst_brk(TCONF, "Test requires at least two NUMA memory nodes");
37}
38
39static void cleanup(void)
40{
41	tst_nodemap_free(nodes);
42}
43
44static void verify_mempolicy(unsigned int node, int mode)
45{
46	struct bitmask *bm = numa_allocate_nodemask();
47	unsigned int i;
48
49	numa_bitmask_setbit(bm, node);
50
51	TEST(set_mempolicy(mode, bm->maskp, bm->size+1));
52
53	if (TST_RET) {
54		tst_res(TFAIL | TTERRNO,
55		        "set_mempolicy(%s) node %u",
56		        tst_mempolicy_mode_name(mode), node);
57		return;
58	}
59
60	tst_res(TPASS, "set_mempolicy(%s) node %u",
61	        tst_mempolicy_mode_name(mode), node);
62
63	numa_free_nodemask(bm);
64
65	tst_nodemap_reset_counters(nodes);
66	alloc_fault_count(nodes, MNTPOINT "/numa-test-file", PAGES_ALLOCATED * page_size);
67
68	for (i = 0; i < nodes->cnt; i++) {
69		if (nodes->map[i] == node) {
70			if (nodes->counters[i] == PAGES_ALLOCATED) {
71				tst_res(TPASS, "Node %u allocated %u",
72				        node, PAGES_ALLOCATED);
73			} else {
74				tst_res(TFAIL, "Node %u allocated %u, expected %u",
75				        node, nodes->counters[i], PAGES_ALLOCATED);
76			}
77			continue;
78		}
79
80		if (nodes->counters[i]) {
81			tst_res(TFAIL, "Node %u allocated %u, expected 0",
82			        node, nodes->counters[i]);
83		}
84	}
85}
86
87static void verify_set_mempolicy(unsigned int n)
88{
89	unsigned int i;
90	int mode = n ? MPOL_PREFERRED : MPOL_BIND;
91
92	for (i = 0; i < nodes->cnt; i++)
93		verify_mempolicy(nodes->map[i], mode);
94}
95
96static struct tst_test test = {
97	.setup = setup,
98	.cleanup = cleanup,
99	.test = verify_set_mempolicy,
100	.tcnt = 2,
101	.needs_root = 1,
102	.all_filesystems = 1,
103	.mntpoint = MNTPOINT,
104	.forks_child = 1,
105	.needs_checkpoints = 1,
106};
107
108#else
109
110TST_TEST_TCONF(NUMA_ERROR_MSG);
111
112#endif /* HAVE_NUMA_V2 */
113