• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

systemd / systemd / 16545232189

27 Jul 2025 12:03AM UTC coverage: 72.173% (-0.03%) from 72.199%
16545232189

push

github

bluca
pcrlock: Return positive exit status

Follow-up for 89e83aada.

`is-supported` expects to return a positive exit status.
To achieve that, verb_make_policy() needs to return 0 on success.

Finishes the fix for #38019.

Co-authored-by: Yu Watanabe <watanabe.yu+github@gmail.com>

5 of 5 new or added lines in 1 file covered. (100.0%)

836 existing lines in 51 files now uncovered.

302569 of 419228 relevant lines covered (72.17%)

731883.14 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

91.49
/src/shared/cpu-set-util.c
1
/* SPDX-License-Identifier: LGPL-2.1-or-later */
2

3
#include <stdio.h>
4
#include <syslog.h>
5
#include <unistd.h>
6

7
#include "alloc-util.h"
8
#include "bitfield.h"
9
#include "cpu-set-util.h"
10
#include "extract-word.h"
11
#include "hexdecoct.h"
12
#include "log.h"
13
#include "parse-util.h"
14
#include "string-util.h"
15

16
/* As of kernel 5.1, CONFIG_NR_CPUS can be set to 8192 on PowerPC */
17
#define CPU_SET_MAX_NCPU 8192
18

19
char* cpu_set_to_string(const CPUSet *c) {
17✔
20
        _cleanup_free_ char *str = NULL;
17✔
21

22
        assert(c);
17✔
23

24
        for (size_t i = 0; i < c->allocated * 8; i++) {
9,425✔
25
                if (!CPU_ISSET_S(i, c->allocated, c->set))
9,408✔
26
                        continue;
9,020✔
27

28
                if (strextendf_with_separator(&str, " ", "%zu", i) < 0)
388✔
29
                        return NULL;
30
        }
31

32
        return TAKE_PTR(str) ?: strdup("");
17✔
33
}
34

35
static int add_range(char **str, size_t start, size_t end) {
40✔
36
        assert(str);
40✔
37
        assert(start <= end);
40✔
38

39
        if (start == end)
40✔
40
                return strextendf_with_separator(str, " ", "%zu", start);
20✔
41

42
        return strextendf_with_separator(str, " ", "%zu-%zu", start, end);
20✔
43
}
44

45
char* cpu_set_to_range_string(const CPUSet *c) {
9,900✔
46
        _cleanup_free_ char *str = NULL;
9,900✔
47
        size_t start = 0, end;
9,900✔
48
        bool in_range = false;
9,900✔
49

50
        assert(c);
9,900✔
51

52
        for (size_t i = 0; i < c->allocated * 8; i++) {
19,948✔
53
                if (CPU_ISSET_S(i, c->allocated, c->set)) {
10,048✔
54
                        if (in_range)
399✔
55
                                end++;
359✔
56
                        else {
57
                                start = end = i;
58
                                in_range = true;
59
                        }
60
                        continue;
399✔
61
                }
62

63
                if (in_range && add_range(&str, start, end) < 0)
9,649✔
64
                        return NULL;
65

66
                in_range = false;
67
        }
68

69
        if (in_range && add_range(&str, start, end) < 0)
9,900✔
70
                return NULL;
71

72
        return TAKE_PTR(str) ?: strdup("");
9,900✔
73
}
74

75
char* cpu_set_to_mask_string(const CPUSet *c) {
25✔
76
        _cleanup_free_ char *str = NULL;
25✔
77
        bool found_nonzero = false;
25✔
78
        int r;
25✔
79

80
        assert(c);
25✔
81

82
        /* Return CPU set in hexadecimal bitmap mask, e.g.
83
         *   CPU   0 ->  "1"
84
         *   CPU   1 ->  "2"
85
         *   CPU 0,1 ->  "3"
86
         *   CPU 0-3 ->  "f"
87
         *   CPU 0-7 -> "ff"
88
         *   CPU 4-7 -> "f0"
89
         *   CPU   7 -> "80"
90
         *   None    ->  "0"
91
         *
92
         * When there are more than 32 CPUs, separate every 32 CPUs by comma, e.g.
93
         *  CPU 0-47 -> "ffff,ffffffff"
94
         *  CPU 0-63 -> "ffffffff,ffffffff"
95
         *  CPU 0-71 -> "ff,ffffffff,ffffffff" */
96

97
        for (size_t i = c->allocated * 8; i > 0; ) {
335✔
98
                uint32_t m = 0;
310✔
99

100
                for (int j = (i % 32 ?: 32) - 1; j >= 0; j--)
10,540✔
101
                        if (CPU_ISSET_S(--i, c->allocated, c->set))
9,920✔
102
                                SET_BIT(m, j);
399✔
103

104
                if (!found_nonzero) {
310✔
105
                        if (m == 0)
45✔
106
                                continue;
22✔
107

108
                        r = strextendf_with_separator(&str, ",", "%" PRIx32, m);
23✔
109
                } else
110
                        r = strextendf_with_separator(&str, ",", "%08" PRIx32, m);
265✔
111
                if (r < 0)
288✔
112
                        return NULL;
113

114
                found_nonzero = true;
115
        }
116

117
        return TAKE_PTR(str) ?: strdup("0");
25✔
118
}
119

120
void cpu_set_done(CPUSet *c) {
439,372✔
121
        assert(c);
439,372✔
122

123
        if (c->set)
439,372✔
124
                CPU_FREE(c->set);
67✔
125

126
        *c = (CPUSet) {};
439,372✔
127
}
439,372✔
128

129
int cpu_set_realloc(CPUSet *c, size_t n) {
8,371✔
130
        assert(c);
8,371✔
131

132
        if (n > CPU_SET_MAX_NCPU)
8,371✔
133
                return -ERANGE;
134

135
        n = CPU_ALLOC_SIZE(n);
8,371✔
136
        if (n <= c->allocated) {
8,371✔
137
                assert(c->set || n == 0);
8,284✔
138
                return 0;
139
        }
140

141
        if (!GREEDY_REALLOC0(c->set, DIV_ROUND_UP(n, sizeof(cpu_set_t))))
87✔
142
                return -ENOMEM;
143

144
        c->allocated = n;
87✔
145
        return 0;
87✔
146
}
147

148
int cpu_set_add(CPUSet *c, size_t i) {
8,194✔
149
        int r;
8,194✔
150

151
        assert(c);
8,194✔
152

153
        /* cpu_set_realloc() has similar check, but for avoiding overflow. */
154
        if (i >= CPU_SET_MAX_NCPU)
8,194✔
155
                return -ERANGE;
156

157
        r = cpu_set_realloc(c, i + 1);
8,192✔
158
        if (r < 0)
8,192✔
159
                return r;
160

161
        CPU_SET_S(i, c->allocated, c->set);
8,192✔
162
        return 0;
163
}
164

165
int cpu_set_add_set(CPUSet *c, const CPUSet *src) {
4✔
166
        int r;
4✔
167

168
        assert(c);
4✔
169
        assert(src);
4✔
170

171
        r = cpu_set_realloc(c, src->allocated * 8);
4✔
172
        if (r < 0)
4✔
173
                return r;
174

175
        for (size_t i = 0; i < src->allocated * 8; i++)
196✔
176
                if (CPU_ISSET_S(i, src->allocated, src->set))
192✔
177
                        CPU_SET_S(i, c->allocated, c->set);
5✔
178

179
        return 1;
180
}
181

182
int cpu_set_add_range(CPUSet *c, size_t start, size_t end) {
149✔
183
        int r;
149✔
184

185
        assert(c);
149✔
186
        assert(start <= end);
149✔
187

188
        /* cpu_set_realloc() has similar check, but for avoiding overflow. */
189
        if (end >= CPU_SET_MAX_NCPU)
149✔
190
                return -ERANGE;
191

192
        r = cpu_set_realloc(c, end + 1);
147✔
193
        if (r < 0)
147✔
194
                return r;
195

196
        for (size_t i = start; i <= end; i++)
8,915✔
197
                CPU_SET_S(i, c->allocated, c->set);
8,768✔
198

199
        return 0;
200
}
201

202
int cpu_set_add_all(CPUSet *c) {
2✔
203
        assert(c);
2✔
204

205
        long m = sysconf(_SC_NPROCESSORS_ONLN);
2✔
206
        if (m < 0)
2✔
UNCOV
207
                return -errno;
×
208
        if (m == 0)
2✔
209
                return -ENXIO;
210

211
        return cpu_set_add_range(c, 0, m - 1);
2✔
212
}
213

214
int config_parse_cpu_set(
47,944✔
215
                const char *unit,
216
                const char *filename,
217
                unsigned line,
218
                const char *section,
219
                unsigned section_line,
220
                const char *lvalue,
221
                int ltype, /* 0 when used as conf parser, 1 when used as usual parser */
222
                const char *rvalue,
223
                void *data,
224
                void *userdata) {
225

226
        CPUSet *c = ASSERT_PTR(data);
47,944✔
227
        int r, level = ltype ? LOG_DEBUG : LOG_ERR;
47,944✔
228
        bool critical = ltype;
47,944✔
229

230
        assert(critical || lvalue);
47,944✔
231

232
        if (isempty(rvalue)) {
47,944✔
233
                cpu_set_done(c);
47,875✔
234
                return 1;
47,944✔
235
        }
236

237
        _cleanup_(cpu_set_done) CPUSet cpuset = {};
69✔
238
        for (const char *p = rvalue;;) {
69✔
239
                _cleanup_free_ char *word = NULL;
149✔
240

241
                r = extract_first_word(&p, &word, WHITESPACE ",", EXTRACT_UNQUOTE);
214✔
242
                if (r == -ENOMEM)
214✔
UNCOV
243
                        return log_oom_full(level);
×
244
                if (r < 0) {
214✔
245
                        if (critical)
1✔
246
                                return log_debug_errno(r, "Failed to parse CPU set: %s", rvalue);
1✔
247

248
                        log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse %s= setting, ignoring assignment: %s",
×
249
                                   lvalue, rvalue);
UNCOV
250
                        return 0;
×
251
                }
252
                if (r == 0)
213✔
253
                        break;
254

255
                unsigned lower, upper;
148✔
256
                r = parse_range(word, &lower, &upper);
148✔
257
                if (r < 0) {
148✔
258
                        if (critical)
4✔
259
                                return log_debug_errno(r, "Failed to parse CPU range: %s", word);
2✔
260

261
                        log_syntax(unit, LOG_WARNING, filename, line, r,
2✔
262
                                   "Failed to parse CPU range, ignoring assignment: %s", word);
263
                        continue;
2✔
264
                }
265

266
                if (lower > upper) {
144✔
267
                        if (critical)
1✔
268
                                return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
1✔
269
                                                       "Invalid CPU range (%u > %u): %s",
270
                                                       lower, upper, word);
271

UNCOV
272
                        log_syntax(unit, LOG_WARNING, filename, line, r,
×
273
                                   "Invalid CPU range (%u > %u), ignoring assignment: %s",
274
                                   lower, upper, word);
UNCOV
275
                        continue;
×
276
                }
277

278
                r = cpu_set_add_range(&cpuset, lower, upper);
143✔
279
                if (r == -ENOMEM)
143✔
280
                        return log_oom_full(level);
×
281
                if (r < 0) {
143✔
UNCOV
282
                        if (critical)
×
283
                                return log_debug_errno(r, "Failed to set CPU(s) '%s': %m", word);
×
284

UNCOV
285
                        log_syntax(unit, LOG_WARNING, filename, line, r,
×
286
                                   "Failed to set CPU(s), ignoring assignment: %s", word);
287
                }
288
        }
289

290
        if (!c->set) {
65✔
291
                *c = TAKE_STRUCT(cpuset);
63✔
292
                return 1;
63✔
293
        }
294

295
        r = cpu_set_add_set(c, &cpuset);
2✔
296
        if (r == -ENOMEM)
2✔
UNCOV
297
                return log_oom_full(level);
×
298
        assert(r >= 0);
2✔
299

300
        return 1;
301
}
302

303
int parse_cpu_set(const char *s, CPUSet *ret) {
47,925✔
304
        _cleanup_(cpu_set_done) CPUSet c = {};
47,925✔
305
        int r;
47,925✔
306

307
        assert(s);
47,925✔
308
        assert(ret);
47,925✔
309

310
        r = config_parse_cpu_set(
47,925✔
311
                        /* unit = */ NULL,
312
                        /* filename = */ NULL,
313
                        /* line = */ 0,
314
                        /* section = */ NULL,
315
                        /* section_line = */ 0,
316
                        /* lvalue = */ NULL,
317
                        /* ltype = */ 1,
318
                        /* rvalue = */ s,
319
                        /* data = */ &c,
320
                        /* userdata = */ NULL);
321
        if (r < 0)
47,925✔
322
                return r;
323

324
        *ret = TAKE_STRUCT(c);
47,921✔
325
        return 0;
47,921✔
326
}
327

328
int cpus_in_affinity_mask(void) {
71✔
329
        size_t n = 16;
71✔
330
        int r;
71✔
331

332
        for (;;) {
71✔
333
                cpu_set_t *c;
71✔
334

335
                c = CPU_ALLOC(n);
71✔
336
                if (!c)
71✔
337
                        return -ENOMEM;
338

339
                if (sched_getaffinity(0, CPU_ALLOC_SIZE(n), c) >= 0) {
71✔
340
                        int k;
71✔
341

342
                        k = CPU_COUNT_S(CPU_ALLOC_SIZE(n), c);
71✔
343
                        CPU_FREE(c);
71✔
344

345
                        if (k <= 0)
71✔
346
                                return -EINVAL;
347

348
                        return k;
71✔
349
                }
350

UNCOV
351
                r = -errno;
×
352
                CPU_FREE(c);
×
353

354
                if (r != -EINVAL)
×
355
                        return r;
356
                if (n > SIZE_MAX/2)
×
357
                        return -ENOMEM;
UNCOV
358
                n *= 2;
×
359
        }
360
}
361

362
int cpu_set_to_dbus(const CPUSet *c, uint8_t **ret, size_t *ret_size) {
9,895✔
363
        assert(c);
9,895✔
364
        assert(ret);
9,895✔
365
        assert(ret_size);
9,895✔
366

367
        uint8_t *buf = new0(uint8_t, c->allocated);
9,895✔
368
        if (!buf)
9,895✔
369
                return -ENOMEM;
370

371
        for (size_t i = 0; i < c->allocated * 8; i++)
11,431✔
372
                if (CPU_ISSET_S(i, c->allocated, c->set))
1,536✔
373
                        SET_BIT(buf[i / 8], i % 8);
154✔
374

375
        *ret = buf;
9,895✔
376
        *ret_size = c->allocated;
9,895✔
377
        return 0;
9,895✔
378
}
379

380
int cpu_set_from_dbus(const uint8_t *bits, size_t size, CPUSet *ret) {
27✔
381
        _cleanup_(cpu_set_done) CPUSet c = {};
27✔
382
        int r;
27✔
383

384
        assert(bits || size == 0);
27✔
385
        assert(ret);
27✔
386

387
        r = cpu_set_realloc(&c, size * 8);
27✔
388
        if (r < 0)
27✔
389
                return r;
390

391
        for (size_t i = 0; i < size * 8; i++)
923✔
392
                if (BIT_SET(bits[i / 8], i % 8))
896✔
393
                        CPU_SET_S(i, c.allocated, c.set);
115✔
394

395
        *ret = TAKE_STRUCT(c);
27✔
396
        return 0;
27✔
397
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc