]>
git.ipfire.org Git - thirdparty/systemd.git/blob - src/shared/numa-util.c
8c18c582270ecd077cd200a5d42f8b85cb434f46
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
5 #include "alloc-util.h"
6 #include "cpu-set-util.h"
7 #include "dirent-util.h"
11 #include "missing_syscall.h"
12 #include "numa-util.h"
13 #include "parse-util.h"
14 #include "stdio-util.h"
15 #include "string-table.h"
16 #include "string-util.h"
18 bool numa_policy_is_valid(const NUMAPolicy
*policy
) {
21 if (!mpol_is_valid(numa_policy_get_type(policy
)))
24 if (!policy
->nodes
.set
&&
25 !IN_SET(numa_policy_get_type(policy
), MPOL_DEFAULT
, MPOL_LOCAL
, MPOL_PREFERRED
))
28 if (policy
->nodes
.set
&&
29 numa_policy_get_type(policy
) == MPOL_PREFERRED
&&
30 CPU_COUNT_S(policy
->nodes
.allocated
, policy
->nodes
.set
) != 1)
36 static int numa_policy_to_mempolicy(const NUMAPolicy
*policy
, unsigned long *ret_maxnode
, unsigned long **ret_nodes
) {
37 unsigned node
, bits
= 0, ulong_bits
;
38 _cleanup_free_
unsigned long *out
= NULL
;
44 if (IN_SET(numa_policy_get_type(policy
), MPOL_DEFAULT
, MPOL_LOCAL
) ||
45 (numa_policy_get_type(policy
) == MPOL_PREFERRED
&& !policy
->nodes
.set
)) {
51 bits
= policy
->nodes
.allocated
* 8;
52 ulong_bits
= sizeof(unsigned long) * 8;
54 out
= new0(unsigned long, DIV_ROUND_UP(policy
->nodes
.allocated
, sizeof(unsigned long)));
58 /* We don't make any assumptions about internal type libc is using to store NUMA node mask.
59 Hence we need to convert the node mask to the representation expected by set_mempolicy() */
60 for (node
= 0; node
< bits
; node
++)
61 if (CPU_ISSET_S(node
, policy
->nodes
.allocated
, policy
->nodes
.set
))
62 out
[node
/ ulong_bits
] |= 1ul << (node
% ulong_bits
);
64 *ret_nodes
= TAKE_PTR(out
);
65 *ret_maxnode
= bits
+ 1;
69 int apply_numa_policy(const NUMAPolicy
*policy
) {
71 _cleanup_free_
unsigned long *nodes
= NULL
;
72 unsigned long maxnode
;
76 if (get_mempolicy(NULL
, NULL
, 0, NULL
, 0) < 0 && errno
== ENOSYS
)
79 if (!numa_policy_is_valid(policy
))
82 r
= numa_policy_to_mempolicy(policy
, &maxnode
, &nodes
);
86 r
= set_mempolicy(numa_policy_get_type(policy
), nodes
, maxnode
);
93 int numa_to_cpu_set(const NUMAPolicy
*policy
, CPUSet
*ret
) {
94 _cleanup_(cpu_set_done
) CPUSet s
= {};
100 for (size_t i
= 0; i
< policy
->nodes
.allocated
* 8; i
++) {
101 _cleanup_free_
char *l
= NULL
;
102 char p
[STRLEN("/sys/devices/system/node/node//cpulist") + DECIMAL_STR_MAX(size_t) + 1];
104 if (!CPU_ISSET_S(i
, policy
->nodes
.allocated
, policy
->nodes
.set
))
107 xsprintf(p
, "/sys/devices/system/node/node%zu/cpulist", i
);
109 r
= read_one_line_file(p
, &l
);
113 _cleanup_(cpu_set_done
) CPUSet part
= {};
114 r
= parse_cpu_set(l
, &part
);
118 r
= cpu_set_add_set(&s
, &part
);
123 *ret
= TAKE_STRUCT(s
);
128 static int numa_max_node(void) {
129 _cleanup_closedir_
DIR *d
= NULL
;
132 d
= opendir("/sys/devices/system/node");
136 FOREACH_DIRENT(de
, d
, break) {
140 if (de
->d_type
!= DT_DIR
)
143 n
= startswith(de
->d_name
, "node");
147 r
= safe_atoi(n
, &node
);
158 int numa_mask_add_all(CPUSet
*mask
) {
165 log_debug_errno(m
, "Failed to determine maximum NUMA node index, assuming 1023: %m");
166 m
= 1023; /* CONFIG_NODES_SHIFT is set to 10 on x86_64, i.e. 1024 NUMA nodes in total */
169 for (int i
= 0; i
<= m
; i
++) {
172 r
= cpu_set_add(mask
, i
);
180 static const char* const mpol_table
[] = {
181 [MPOL_DEFAULT
] = "default",
182 [MPOL_PREFERRED
] = "preferred",
183 [MPOL_BIND
] = "bind",
184 [MPOL_INTERLEAVE
] = "interleave",
185 [MPOL_LOCAL
] = "local",
188 DEFINE_STRING_TABLE_LOOKUP(mpol
, int);