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

systemd / systemd / 23774132158

30 Mar 2026 09:35PM UTC coverage: 72.398% (+0.2%) from 72.208%
23774132158

push

github

daandemeyer
Only enable `NoAuto=true` for supported partitions

When `Format=empty` is set we need to check for `NoAuto` support for
the partition type, else we print a warning later in the build.

Followup for 381304a

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

7091 existing lines in 92 files now uncovered.

318474 of 439892 relevant lines covered (72.4%)

1151474.34 hits per line

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

78.38
/src/basic/limits-util.c
1
/* SPDX-License-Identifier: LGPL-2.1-or-later */
2

3
#include <unistd.h>
4

5
#include "alloc-util.h"
6
#include "cgroup-util.h"
7
#include "limits-util.h"
8
#include "log.h"
9
#include "memory-util.h"
10
#include "parse-util.h"
11
#include "process-util.h"
12
#include "procfs-util.h"
13

14
uint64_t physical_memory(void) {
9,430✔
15
        _cleanup_free_ char *root = NULL, *value = NULL;
9,430✔
16
        uint64_t mem, lim;
9,430✔
17
        size_t ps;
9,430✔
18
        long sc;
9,430✔
19
        int r;
9,430✔
20

21
        /* We return this as uint64_t in case we are running as 32-bit process on a 64-bit kernel with huge amounts of
22
         * memory.
23
         *
24
         * In order to support containers nicely that have a configured memory limit we'll take the minimum of the
25
         * physically reported amount of memory and the limit configured for the root cgroup, if there is any. */
26

27
        sc = sysconf(_SC_PHYS_PAGES);
9,430✔
28
        assert(sc > 0);
9,430✔
29

30
        ps = page_size();
9,430✔
31
        /* Silence static analyzers */
32
        assert((uint64_t) sc <= UINT64_MAX / (uint64_t) ps);
9,430✔
33
        mem = (uint64_t) sc * (uint64_t) ps;
9,430✔
34

35
        r = cg_get_root_path(&root);
9,430✔
36
        if (r < 0) {
9,430✔
UNCOV
37
                log_debug_errno(r, "Failed to determine root cgroup, ignoring cgroup memory limit: %m");
×
UNCOV
38
                return mem;
×
39
        }
40

41
        r = cg_get_attribute(root, "memory.max", &value);
9,430✔
42
        if (r == -ENOENT) /* Field does not exist on the system's top-level cgroup, hence don't
9,430✔
43
                           * complain. (Note that it might exist on our own root though, if we live
44
                           * in a cgroup namespace, hence check anyway instead of not even
45
                           * trying.) */
46
                return mem;
47
        if (r < 0) {
8,552✔
UNCOV
48
                log_debug_errno(r, "Failed to read memory.max cgroup attribute, ignoring cgroup memory limit: %m");
×
UNCOV
49
                return mem;
×
50
        }
51

52
        if (streq(value, "max"))
8,552✔
53
                return mem;
54

55
        r = safe_atou64(value, &lim);
×
56
        if (r < 0) {
×
UNCOV
57
                log_debug_errno(r, "Failed to parse cgroup memory limit '%s', ignoring: %m", value);
×
58
                return mem;
×
59
        }
UNCOV
60
        if (lim == UINT64_MAX)
×
61
                return mem;
62

63
        /* Make sure the limit is a multiple of our own page size */
UNCOV
64
        lim /= ps;
×
65
        lim *= ps;
×
66

UNCOV
67
        return MIN(mem, lim);
×
68
}
69

70
uint64_t physical_memory_scale(uint64_t v, uint64_t max) {
369✔
71
        uint64_t p, m, ps;
369✔
72

73
        /* Shortcut two special cases */
74
        if (v == 0)
369✔
75
                return 0;
76
        if (v == max)
365✔
77
                return physical_memory();
4✔
78

79
        assert(max > 0);
361✔
80

81
        /* Returns the physical memory size, multiplied by v divided by max. Returns UINT64_MAX on overflow. On success
82
         * the result is a multiple of the page size (rounds down). */
83

84
        ps = page_size();
361✔
85
        assert(ps > 0);
361✔
86

87
        p = physical_memory() / ps;
361✔
88
        assert(p > 0);
361✔
89

90
        if (v > UINT64_MAX / p)
361✔
91
                return UINT64_MAX;
92

93
        m = p * v;
360✔
94
        m /= max;
360✔
95

96
        if (m > UINT64_MAX / ps)
360✔
97
                return UINT64_MAX;
98

99
        return m * ps;
360✔
100
}
101

102
uint64_t system_tasks_max(void) {
13,246✔
103
        uint64_t a = TASKS_MAX, b = TASKS_MAX, c = TASKS_MAX;
13,246✔
104
        _cleanup_free_ char *root = NULL;
13,246✔
105
        int r;
13,246✔
106

107
        /* Determine the maximum number of tasks that may run on this system. We check three sources to
108
         * determine this limit:
109
         *
110
         * a) kernel.threads-max sysctl: the maximum number of tasks (threads) the kernel allows.
111
         *
112
         *    This puts a direct limit on the number of concurrent tasks.
113
         *
114
         * b) kernel.pid_max sysctl: the maximum PID value.
115
         *
116
         *    This limits the numeric range PIDs can take, and thus indirectly also limits the number of
117
         *    concurrent threads. It's primarily a compatibility concept: some crappy old code used a signed
118
         *    16-bit type for PIDs, hence the kernel provides a way to ensure the PIDs never go beyond
119
         *    INT16_MAX by default.
120
         *
121
         *    Also note the weird definition: PIDs assigned will be kept below this value, which means
122
         *    the number of tasks that can be created is one lower, as PID 0 is not a valid process ID.
123
         *
124
         * c) pids.max on the root cgroup: the kernel's configured maximum number of tasks.
125
         *
126
         * and then pick the smallest of the three.
127
         *
128
         * By default pid_max is set to much lower values than threads-max, hence the limit people come into
129
         * contact with first, as it's the lowest boundary they need to bump when they want higher number of
130
         * processes.
131
         */
132

133
        r = procfs_get_threads_max(&a);
13,246✔
134
        if (r < 0)
13,246✔
UNCOV
135
                log_debug_errno(r, "Failed to read kernel.threads-max, ignoring: %m");
×
136

137
        r = procfs_get_pid_max(&b);
13,246✔
138
        if (r < 0)
13,246✔
UNCOV
139
                log_debug_errno(r, "Failed to read kernel.pid_max, ignoring: %m");
×
140
        else if (b > 0)
13,246✔
141
                /* Subtract one from pid_max, since PID 0 is not a valid PID */
142
                b--;
13,246✔
143

144
        r = cg_get_root_path(&root);
13,246✔
145
        if (r < 0)
13,246✔
UNCOV
146
                log_debug_errno(r, "Failed to determine cgroup root path, ignoring: %m");
×
147
        else {
148
                /* We'll have the "pids.max" attribute on the our root cgroup only if we are in a
149
                 * CLONE_NEWCGROUP namespace. On the top-level namespace this attribute is missing, hence
150
                 * suppress any message about that */
151
                r = cg_get_attribute_as_uint64(root, "pids.max", &c);
13,246✔
152
                if (r < 0 && r != -ENODATA)
13,246✔
UNCOV
153
                        log_debug_errno(r, "Failed to read pids.max attribute of root cgroup, ignoring: %m");
×
154
        }
155

156
        return MIN3(a, b, c);
13,246✔
157
}
158

159
uint64_t system_tasks_max_scale(uint64_t v, uint64_t max) {
10,256✔
160
        uint64_t t, m;
10,256✔
161

162
        /* Shortcut two special cases */
163
        if (v == 0)
10,256✔
164
                return 0;
165
        if (v == max)
10,252✔
166
                return system_tasks_max();
4✔
167

168
        assert(max > 0);
10,248✔
169

170
        /* Multiply the system's task value by the fraction v/max. Hence, if max==100 this calculates percentages
171
         * relative to the system's maximum number of tasks. Returns UINT64_MAX on overflow. */
172

173
        t = system_tasks_max();
10,248✔
174
        assert(t > 0);
10,248✔
175

176
        if (v > UINT64_MAX / t) /* overflow? */
10,248✔
177
                return UINT64_MAX;
178

179
        m = t * v;
10,247✔
180
        return m / max;
10,247✔
181
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc