core: always enable CPU accounting; cgtop: drop cgv1 handling (#37448)

This commit is contained in:
Mike Yuan
2025-05-15 14:41:07 +02:00
committed by GitHub
34 changed files with 298 additions and 472 deletions

View File

@@ -802,11 +802,10 @@
<variablelist>
<varlistentry>
<term>systemd 252</term>
<listitem><para>Kernel command-line arguments <varname>systemd.unified_cgroup_hierarchy</varname>
and <varname>systemd.legacy_systemd_cgroup_controller</varname> were deprecated. Please switch to
the unified cgroup hierarchy.</para>
<xi:include href="version-info.xml" xpointer="v252"/></listitem>
the unified cgroup hierarchy.</para></listitem>
</varlistentry>
</variablelist>
</refsect1>

View File

@@ -469,8 +469,6 @@ node /org/freedesktop/systemd1 {
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly u DefaultStartLimitBurst = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b DefaultCPUAccounting = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b DefaultIOAccounting = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b DefaultIPAccounting = ...;
@@ -707,8 +705,6 @@ node /org/freedesktop/systemd1 {
<!--property DefaultStartLimitBurst is not documented!-->
<!--property DefaultCPUAccounting is not documented!-->
<!--property DefaultIOAccounting is not documented!-->
<!--property DefaultIPAccounting is not documented!-->
@@ -1151,8 +1147,6 @@ node /org/freedesktop/systemd1 {
<variablelist class="dbus-property" generated="True" extra-ref="DefaultStartLimitBurst"/>
<variablelist class="dbus-property" generated="True" extra-ref="DefaultCPUAccounting"/>
<variablelist class="dbus-property" generated="True" extra-ref="DefaultIOAccounting"/>
<variablelist class="dbus-property" generated="True" extra-ref="DefaultIPAccounting"/>
@@ -2884,8 +2878,6 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s DelegateSubgroup = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly b CPUAccounting = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t CPUWeight = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t StartupCPUWeight = ...;
@@ -3525,8 +3517,6 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
<!--property DelegateControllers is not documented!-->
<!--property CPUAccounting is not documented!-->
<!--property CPUWeight is not documented!-->
<!--property StartupCPUWeight is not documented!-->
@@ -4179,8 +4169,6 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
<variablelist class="dbus-property" generated="True" extra-ref="DelegateSubgroup"/>
<variablelist class="dbus-property" generated="True" extra-ref="CPUAccounting"/>
<variablelist class="dbus-property" generated="True" extra-ref="CPUWeight"/>
<variablelist class="dbus-property" generated="True" extra-ref="StartupCPUWeight"/>
@@ -5037,8 +5025,6 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket {
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s DelegateSubgroup = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly b CPUAccounting = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t CPUWeight = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t StartupCPUWeight = ...;
@@ -5690,8 +5676,6 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket {
<!--property DelegateControllers is not documented!-->
<!--property CPUAccounting is not documented!-->
<!--property CPUWeight is not documented!-->
<!--property StartupCPUWeight is not documented!-->
@@ -6316,8 +6300,6 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket {
<variablelist class="dbus-property" generated="True" extra-ref="DelegateSubgroup"/>
<variablelist class="dbus-property" generated="True" extra-ref="CPUAccounting"/>
<variablelist class="dbus-property" generated="True" extra-ref="CPUWeight"/>
<variablelist class="dbus-property" generated="True" extra-ref="StartupCPUWeight"/>
@@ -7006,8 +6988,6 @@ node /org/freedesktop/systemd1/unit/home_2emount {
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s DelegateSubgroup = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly b CPUAccounting = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t CPUWeight = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t StartupCPUWeight = ...;
@@ -7589,8 +7569,6 @@ node /org/freedesktop/systemd1/unit/home_2emount {
<!--property DelegateControllers is not documented!-->
<!--property CPUAccounting is not documented!-->
<!--property CPUWeight is not documented!-->
<!--property StartupCPUWeight is not documented!-->
@@ -8131,8 +8109,6 @@ node /org/freedesktop/systemd1/unit/home_2emount {
<variablelist class="dbus-property" generated="True" extra-ref="DelegateSubgroup"/>
<variablelist class="dbus-property" generated="True" extra-ref="CPUAccounting"/>
<variablelist class="dbus-property" generated="True" extra-ref="CPUWeight"/>
<variablelist class="dbus-property" generated="True" extra-ref="StartupCPUWeight"/>
@@ -8948,8 +8924,6 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap {
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s DelegateSubgroup = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly b CPUAccounting = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t CPUWeight = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t StartupCPUWeight = ...;
@@ -9513,8 +9487,6 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap {
<!--property DelegateControllers is not documented!-->
<!--property CPUAccounting is not documented!-->
<!--property CPUWeight is not documented!-->
<!--property StartupCPUWeight is not documented!-->
@@ -10037,8 +10009,6 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap {
<variablelist class="dbus-property" generated="True" extra-ref="DelegateSubgroup"/>
<variablelist class="dbus-property" generated="True" extra-ref="CPUAccounting"/>
<variablelist class="dbus-property" generated="True" extra-ref="CPUWeight"/>
<variablelist class="dbus-property" generated="True" extra-ref="StartupCPUWeight"/>
@@ -10713,8 +10683,6 @@ node /org/freedesktop/systemd1/unit/system_2eslice {
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s DelegateSubgroup = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly b CPUAccounting = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t CPUWeight = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t StartupCPUWeight = ...;
@@ -10894,8 +10862,6 @@ node /org/freedesktop/systemd1/unit/system_2eslice {
<!--property DelegateControllers is not documented!-->
<!--property CPUAccounting is not documented!-->
<!--property CPUWeight is not documented!-->
<!--property StartupCPUWeight is not documented!-->
@@ -11082,8 +11048,6 @@ node /org/freedesktop/systemd1/unit/system_2eslice {
<variablelist class="dbus-property" generated="True" extra-ref="DelegateSubgroup"/>
<variablelist class="dbus-property" generated="True" extra-ref="CPUAccounting"/>
<variablelist class="dbus-property" generated="True" extra-ref="CPUWeight"/>
<variablelist class="dbus-property" generated="True" extra-ref="StartupCPUWeight"/>
@@ -11295,8 +11259,6 @@ node /org/freedesktop/systemd1/unit/session_2d1_2escope {
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s DelegateSubgroup = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly b CPUAccounting = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t CPUWeight = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t StartupCPUWeight = ...;
@@ -11490,8 +11452,6 @@ node /org/freedesktop/systemd1/unit/session_2d1_2escope {
<!--property DelegateControllers is not documented!-->
<!--property CPUAccounting is not documented!-->
<!--property CPUWeight is not documented!-->
<!--property StartupCPUWeight is not documented!-->
@@ -11702,8 +11662,6 @@ node /org/freedesktop/systemd1/unit/session_2d1_2escope {
<variablelist class="dbus-property" generated="True" extra-ref="DelegateSubgroup"/>
<variablelist class="dbus-property" generated="True" extra-ref="CPUAccounting"/>
<variablelist class="dbus-property" generated="True" extra-ref="CPUWeight"/>
<variablelist class="dbus-property" generated="True" extra-ref="StartupCPUWeight"/>

View File

@@ -46,11 +46,9 @@
given, is honored. This mode is suitable for scripting.</para>
<para>Resource usage is only accounted for control groups with the appropriate controllers turned on:
<literal>cpu</literal> controller for CPU usage, <literal>memory</literal> controller for memory usage,
and <literal>io</literal> controller for disk I/O consumption. If resource monitoring for these resources
is required, it is recommended to add the <varname>CPUAccounting=1</varname>,
<varname>MemoryAccounting=1</varname> and <varname>IOAccounting=1</varname> settings in the unit files in
question. See
<literal>memory</literal> controller for memory usage and <literal>io</literal> controller for disk I/O consumption.
If resource monitoring for these resources is required, it is recommended to add the <varname>MemoryAccounting=1</varname>
and <varname>IOAccounting=1</varname> settings in the unit files in question. See
<citerefentry><refentrytitle>systemd.resource-control</refentrytitle><manvolnum>5</manvolnum></citerefentry>
for details.</para>
@@ -59,10 +57,9 @@
the CPU load value is going to be between 0% and 800%. The number of
processors can be found in <literal>/proc/cpuinfo</literal>.</para>
<para>To emphasize: unless <literal>CPUAccounting=1</literal>, <literal>MemoryAccounting=1</literal>, and
<literal>IOAccounting=1</literal> are enabled for the services in question, no resource accounting will
be available for system services and the data shown by <command>systemd-cgtop</command> will be
incomplete.</para>
<para>To emphasize: unless <literal>MemoryAccounting=1</literal> and <literal>IOAccounting=1</literal>
are enabled for the services in question, no resource accounting will be available for system services
and the data shown by <command>systemd-cgtop</command> will be incomplete.</para>
</refsect1>
<refsect1>

View File

@@ -485,9 +485,10 @@
start request for the transient unit is verified, enqueued, and waited for. Subsequently the invoked unit is
monitored, and it is waited until it is deactivated again (most likely because the specified command
completed). On exit, terse information about the unit's runtime is shown, including total runtime (as well as
CPU usage, if <option>--property=CPUAccounting=1</option> was set) and the exit code and status of the main
process. This output may be suppressed with <option>--quiet</option>. This option may not be combined with
<option>--no-block</option>, <option>--scope</option> or the various path, socket, or timer options.</para>
CPU, memory, IO, and IP accounting data, if the corresponding cgroup accounting settings are enabled)
and the exit code and status of the main process. This output may be suppressed with <option>--quiet</option>.
This option may not be combined with <option>--no-block</option>, <option>--scope</option> or the various
path, socket, or timer options.</para>
<xi:include href="version-info.xml" xpointer="v232"/></listitem>
</varlistentry>

View File

@@ -201,7 +201,6 @@
</varlistentry>
<varlistentry>
<term><varname>DefaultCPUAccounting=</varname></term>
<term><varname>DefaultMemoryAccounting=</varname></term>
<term><varname>DefaultTasksAccounting=</varname></term>
<term><varname>DefaultIOAccounting=</varname></term>
@@ -209,14 +208,12 @@
<listitem>
<para>Configure the default resource accounting settings, as configured per-unit by
<varname>CPUAccounting=</varname>, <varname>MemoryAccounting=</varname>,
<varname>TasksAccounting=</varname>, <varname>IOAccounting=</varname> and
<varname>IPAccounting=</varname>. See
<varname>MemoryAccounting=</varname>, <varname>TasksAccounting=</varname>, <varname>IOAccounting=</varname>,
and <varname>IPAccounting=</varname>. See
<citerefentry><refentrytitle>systemd.resource-control</refentrytitle><manvolnum>5</manvolnum></citerefentry>
for details on the per-unit settings.</para>
<para><varname>DefaultCPUAccounting=</varname> defaults to yes when running on kernel ≥4.15, and no on older versions.
<varname>DefaultMemoryAccounting=</varname> defaults to &MEMORY_ACCOUNTING_DEFAULT;.
<para><varname>DefaultMemoryAccounting=</varname> defaults to &MEMORY_ACCOUNTING_DEFAULT;.
<varname>DefaultTasksAccounting=</varname> defaults to yes.
The other settings default to no.</para>
@@ -754,10 +751,18 @@
<variablelist>
<varlistentry>
<term>systemd 252</term>
<listitem><para>Option <varname>DefaultBlockIOAccounting=</varname> was deprecated. Please switch
to the unified cgroup hierarchy.</para>
<xi:include href="version-info.xml" xpointer="v252"/></listitem>
<listitem><para>Option <varname>DefaultBlockIOAccounting=</varname> was deprecated. Please switch
to the unified cgroup hierarchy.</para></listitem>
</varlistentry>
</variablelist>
<variablelist>
<varlistentry>
<term>systemd 258</term>
<listitem><para><varname>DefaultCPUAccounting=</varname> setting is deprecated, because CPU accounting
is always available on the unified cgroup hierarchy and such setting has no effect.</para></listitem>
</varlistentry>
</variablelist>
</refsect1>

View File

@@ -179,30 +179,10 @@ CPUWeight=20 DisableControllers=cpu / \
<para>Units of the types listed above can have settings for resource control configuration:</para>
<refsect2><title>CPU Accounting and Control</title>
<refsect2><title>CPU Control</title>
<variablelist class='unit-directives'>
<varlistentry>
<term><varname>CPUAccounting=</varname></term>
<listitem>
<para>Turn on CPU usage accounting for this unit. Takes a
boolean argument. Note that turning on CPU accounting for
one unit will also implicitly turn it on for all units
contained in the same slice and for all its parent slices
and the units contained therein. The system default for this
setting may be controlled with
<varname>DefaultCPUAccounting=</varname> in
<citerefentry><refentrytitle>systemd-system.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para>
<para>Under the unified cgroup hierarchy, CPU accounting is available for all units and this
setting has no effect.</para>
<xi:include href="version-info.xml" xpointer="v208"/>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>CPUWeight=<replaceable>weight</replaceable></varname></term>
<term><varname>StartupCPUWeight=<replaceable>weight</replaceable></varname></term>
@@ -1689,7 +1669,8 @@ DeviceAllow=/dev/loop-control
<variablelist>
<varlistentry>
<term>systemd 252</term>
<listitem><para> Options for controlling the Legacy Control Group Hierarchy (<ulink
<listitem><para>Options for controlling the Legacy Control Group Hierarchy (<ulink
url="https://docs.kernel.org/admin-guide/cgroup-v1/index.html">Control Groups version 1</ulink>)
are now fully deprecated:
<varname>CPUShares=<replaceable>weight</replaceable></varname>,
@@ -1703,9 +1684,16 @@ DeviceAllow=/dev/loop-control
<varname>BlockIOReadBandwidth=<replaceable>device</replaceable>
<replaceable>bytes</replaceable></varname>,
<varname>BlockIOWriteBandwidth=<replaceable>device</replaceable> <replaceable>bytes</replaceable></varname>.
Please switch to the unified cgroup hierarchy.</para>
Please switch to the unified cgroup hierarchy.</para></listitem>
</varlistentry>
</variablelist>
<xi:include href="version-info.xml" xpointer="v252"/></listitem>
<variablelist>
<varlistentry>
<term>systemd 258</term>
<listitem><para><varname>CPUAccounting=</varname> setting is deprecated, because it is always available
on the unified cgroup hierarchy and such setting has no effect.</para></listitem>
</varlistentry>
</variablelist>
</refsect1>

View File

@@ -1507,11 +1507,10 @@
<variablelist>
<varlistentry>
<term>systemd 252</term>
<listitem><para>Kernel command-line arguments <varname>systemd.unified_cgroup_hierarchy</varname>
and <varname>systemd.legacy_systemd_cgroup_controller</varname> were deprecated. Please switch to
the unified cgroup hierarchy.</para>
<xi:include href="version-info.xml" xpointer="v252"/></listitem>
the unified cgroup hierarchy.</para></listitem>
</varlistentry>
</variablelist>
</refsect1>

View File

@@ -2181,57 +2181,6 @@ static const char *const cgroup_controller_table[_CGROUP_CONTROLLER_MAX] = {
DEFINE_STRING_TABLE_LOOKUP(cgroup_controller, CGroupController);
CGroupMask get_cpu_accounting_mask(void) {
static CGroupMask needed_mask = (CGroupMask) -1;
/* On kernel ≥4.15 with unified hierarchy, cpu.stat's usage_usec is
* provided externally from the CPU controller, which means we don't
* need to enable the CPU controller just to get metrics. This is good,
* because enabling the CPU controller comes at a minor performance
* hit, especially when it's propagated deep into large hierarchies.
* There's also no separate CPU accounting controller available within
* a unified hierarchy.
*
* This combination of factors results in the desired cgroup mask to
* enable for CPU accounting varying as follows:
*
* ╔═════════════════════╤═════════════════════╗
* ║ Linux ≥4.15 │ Linux <4.15 ║
* ╔═══════════════╬═════════════════════╪═════════════════════╣
* ║ Unified ║ nothing │ CGROUP_MASK_CPU ║
* ╟───────────────╫─────────────────────┼─────────────────────╢
* ║ Hybrid/Legacy ║ CGROUP_MASK_CPUACCT │ CGROUP_MASK_CPUACCT ║
* ╚═══════════════╩═════════════════════╧═════════════════════╝
*
* We check kernel version here instead of manually checking whether
* cpu.stat is present for every cgroup, as that check in itself would
* already be fairly expensive.
*
* Kernels where this patch has been backported will therefore have the
* CPU controller enabled unnecessarily. This is more expensive than
* necessary, but harmless. ☺️
*/
if (needed_mask == (CGroupMask) -1) {
if (cg_all_unified()) {
struct utsname u;
assert_se(uname(&u) >= 0);
if (strverscmp_improved(u.release, "4.15") < 0)
needed_mask = CGROUP_MASK_CPU;
else
needed_mask = 0;
} else
needed_mask = CGROUP_MASK_CPUACCT;
}
return needed_mask;
}
bool cpu_accounting_is_cheap(void) {
return get_cpu_accounting_mask() == 0;
}
static const char* const managed_oom_mode_table[_MANAGED_OOM_MODE_MAX] = {
[MANAGED_OOM_AUTO] = "auto",
[MANAGED_OOM_KILL] = "kill",

View File

@@ -86,9 +86,6 @@ static inline CGroupMask CGROUP_MASK_EXTEND_JOINED(CGroupMask mask) {
return mask;
}
CGroupMask get_cpu_accounting_mask(void);
bool cpu_accounting_is_cheap(void);
/* Special values for all weight knobs on unified hierarchy */
#define CGROUP_WEIGHT_INVALID UINT64_MAX
#define CGROUP_WEIGHT_IDLE UINT64_C(0)

View File

@@ -140,8 +140,167 @@ static bool is_root_cgroup(const char *path) {
return empty_or_root(path);
}
static int process_memory(Group *g) {
int r;
assert(g);
if (is_root_cgroup(g->path))
r = procfs_memory_get_used(&g->memory);
else {
_cleanup_free_ char *p = NULL, *v = NULL;
r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, g->path, "memory.current", &p);
if (r < 0)
return r;
r = read_one_line_file(p, &v);
if (r == -ENOENT)
return 0;
if (r < 0)
return r;
r = safe_atou64(v, &g->memory);
}
if (r < 0)
return r;
if (g->memory > 0)
g->memory_valid = true;
return 0;
}
static int process_io(Group *g, unsigned iteration) {
_cleanup_fclose_ FILE *f = NULL;
_cleanup_free_ char *p = NULL;
uint64_t wr = 0, rd = 0;
nsec_t timestamp;
int r;
assert(g);
r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, g->path, "io.stat", &p);
if (r < 0)
return r;
f = fopen(p, "re");
if (!f) {
if (errno == ENOENT)
return 0;
return -errno;
}
for (;;) {
_cleanup_free_ char *line = NULL;
uint64_t k;
char *l;
r = read_stripped_line(f, LONG_LINE_MAX, &line);
if (r < 0)
return r;
if (r == 0)
break;
/* Skip the device */
l = line + strcspn(line, WHITESPACE);
l += strspn(l, WHITESPACE);
while (!isempty(l)) {
if (sscanf(l, "rbytes=%" SCNu64, &k) == 1)
rd += k;
else if (sscanf(l, "wbytes=%" SCNu64, &k) == 1)
wr += k;
l += strcspn(l, WHITESPACE);
l += strspn(l, WHITESPACE);
}
}
timestamp = now_nsec(CLOCK_MONOTONIC);
if (g->io_iteration == iteration - 1) {
uint64_t x, yr, yw;
x = (uint64_t) (timestamp - g->io_timestamp);
if (x < 1)
x = 1;
if (rd > g->io_input)
yr = rd - g->io_input;
else
yr = 0;
if (wr > g->io_output)
yw = wr - g->io_output;
else
yw = 0;
if (yr > 0 || yw > 0) {
g->io_input_bps = (yr * 1000000000ULL) / x;
g->io_output_bps = (yw * 1000000000ULL) / x;
g->io_valid = true;
}
}
g->io_input = rd;
g->io_output = wr;
g->io_timestamp = timestamp;
g->io_iteration = iteration;
return 0;
}
static int process_cpu(Group *g, unsigned iteration) {
nsec_t new_usage, timestamp;
int r;
assert(g);
if (is_root_cgroup(g->path)) {
r = procfs_cpu_get_usage(&new_usage);
if (r < 0)
return r;
} else {
_cleanup_free_ char *val = NULL;
uint64_t u;
r = cg_get_keyed_attribute(SYSTEMD_CGROUP_CONTROLLER, g->path, "cpu.stat", STRV_MAKE("usage_usec"), &val);
if (IN_SET(r, -ENOENT, -ENXIO))
return 0;
if (r < 0)
return r;
r = safe_atou64(val, &u);
if (r < 0)
return r;
new_usage = u * NSEC_PER_USEC;
}
timestamp = now_nsec(CLOCK_MONOTONIC);
if (g->cpu_iteration == iteration - 1 && new_usage > g->cpu_usage) {
nsec_t x, y;
x = timestamp - g->cpu_timestamp;
if (x < 1)
x = 1;
y = new_usage - g->cpu_usage;
g->cpu_fraction = (double) y / (double) x;
g->cpu_valid = true;
}
g->cpu_usage = new_usage;
g->cpu_timestamp = timestamp;
g->cpu_iteration = iteration;
return 0;
}
static int process(
const char *controller,
const char *path,
Hashmap *a,
Hashmap *b,
@@ -149,16 +308,11 @@ static int process(
Group **ret) {
Group *g;
int r, all_unified;
int r;
assert(controller);
assert(path);
assert(a);
all_unified = cg_all_unified();
if (all_unified < 0)
return all_unified;
g = hashmap_get(a, path);
if (!g) {
g = hashmap_get(b, path);
@@ -187,253 +341,77 @@ static int process(
}
}
if (streq(controller, SYSTEMD_CGROUP_CONTROLLER) &&
IN_SET(arg_count, COUNT_ALL_PROCESSES, COUNT_USERSPACE_PROCESSES)) {
if (IN_SET(arg_count, COUNT_ALL_PROCESSES, COUNT_USERSPACE_PROCESSES)) {
_cleanup_fclose_ FILE *f = NULL;
pid_t pid;
r = cg_enumerate_processes(controller, path, &f);
if (r == -ENOENT)
return 0;
if (r < 0)
r = cg_enumerate_processes(SYSTEMD_CGROUP_CONTROLLER, path, &f);
if (r < 0 && r != -ENOENT)
return r;
if (r >= 0) {
g->n_tasks = 0;
while (cg_read_pid(f, &pid, CGROUP_DONT_SKIP_UNMAPPED) > 0) {
g->n_tasks = 0;
while (cg_read_pid(f, &pid, CGROUP_DONT_SKIP_UNMAPPED) > 0) {
if (arg_count == COUNT_USERSPACE_PROCESSES && pid_is_kernel_thread(pid) > 0)
continue;
if (arg_count == COUNT_USERSPACE_PROCESSES && pid_is_kernel_thread(pid) > 0)
continue;
g->n_tasks++;
}
g->n_tasks++;
if (g->n_tasks > 0)
g->n_tasks_valid = true;
}
if (g->n_tasks > 0)
g->n_tasks_valid = true;
} else if (streq(controller, "pids") && arg_count == COUNT_PIDS) {
} else if (arg_count == COUNT_PIDS) {
if (is_root_cgroup(path)) {
r = procfs_tasks_get_current(&g->n_tasks);
if (r < 0)
return r;
} else {
_cleanup_free_ char *p = NULL, *v = NULL;
r = cg_get_path(controller, path, "pids.current", &p);
if (r < 0)
return r;
r = read_one_line_file(p, &v);
if (r == -ENOENT)
return 0;
if (r < 0)
return r;
r = safe_atou64(v, &g->n_tasks);
if (r < 0)
return r;
}
if (g->n_tasks > 0)
g->n_tasks_valid = true;
} else if (streq(controller, "memory")) {
if (is_root_cgroup(path)) {
r = procfs_memory_get_used(&g->memory);
if (r < 0)
return r;
} else {
_cleanup_free_ char *p = NULL, *v = NULL;
if (all_unified)
r = cg_get_path(controller, path, "memory.current", &p);
else
r = cg_get_path(controller, path, "memory.usage_in_bytes", &p);
r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, path, "pids.current", &p);
if (r < 0)
return r;
r = read_one_line_file(p, &v);
if (r == -ENOENT)
return 0;
if (r < 0)
if (r < 0 && r != -ENOENT)
return r;
r = safe_atou64(v, &g->memory);
if (r < 0)
return r;
}
if (g->memory > 0)
g->memory_valid = true;
} else if ((streq(controller, "io") && all_unified) ||
(streq(controller, "blkio") && !all_unified)) {
_cleanup_fclose_ FILE *f = NULL;
_cleanup_free_ char *p = NULL;
uint64_t wr = 0, rd = 0;
nsec_t timestamp;
r = cg_get_path(controller, path, all_unified ? "io.stat" : "blkio.io_service_bytes", &p);
if (r < 0)
return r;
f = fopen(p, "re");
if (!f) {
if (errno == ENOENT)
return 0;
return -errno;
}
for (;;) {
_cleanup_free_ char *line = NULL;
uint64_t k, *q;
char *l;
r = read_stripped_line(f, LONG_LINE_MAX, &line);
if (r < 0)
return r;
if (r == 0)
break;
/* Skip the device */
l = line + strcspn(line, WHITESPACE);
l += strspn(l, WHITESPACE);
if (all_unified) {
while (!isempty(l)) {
if (sscanf(l, "rbytes=%" SCNu64, &k) == 1)
rd += k;
else if (sscanf(l, "wbytes=%" SCNu64, &k) == 1)
wr += k;
l += strcspn(l, WHITESPACE);
l += strspn(l, WHITESPACE);
}
} else {
if (first_word(l, "Read")) {
l += 4;
q = &rd;
} else if (first_word(l, "Write")) {
l += 5;
q = &wr;
} else
continue;
l += strspn(l, WHITESPACE);
r = safe_atou64(l, &k);
if (r >= 0) {
r = safe_atou64(v, &g->n_tasks);
if (r < 0)
continue;
return r;
*q += k;
if (g->n_tasks > 0)
g->n_tasks_valid = true;
}
}
timestamp = now_nsec(CLOCK_MONOTONIC);
} else
assert_not_reached();
if (g->io_iteration == iteration - 1) {
uint64_t x, yr, yw;
r = process_memory(g);
if (r < 0)
return r;
x = (uint64_t) (timestamp - g->io_timestamp);
if (x < 1)
x = 1;
r = process_io(g, iteration);
if (r < 0)
return r;
if (rd > g->io_input)
yr = rd - g->io_input;
else
yr = 0;
if (wr > g->io_output)
yw = wr - g->io_output;
else
yw = 0;
if (yr > 0 || yw > 0) {
g->io_input_bps = (yr * 1000000000ULL) / x;
g->io_output_bps = (yw * 1000000000ULL) / x;
g->io_valid = true;
}
}
g->io_input = rd;
g->io_output = wr;
g->io_timestamp = timestamp;
g->io_iteration = iteration;
} else if (STR_IN_SET(controller, "cpu", "cpuacct") || cpu_accounting_is_cheap()) {
_cleanup_free_ char *p = NULL, *v = NULL;
uint64_t new_usage;
nsec_t timestamp;
if (is_root_cgroup(path)) {
r = procfs_cpu_get_usage(&new_usage);
if (r < 0)
return r;
} else if (all_unified) {
_cleanup_free_ char *val = NULL;
if (!streq(controller, "cpu"))
return 0;
r = cg_get_keyed_attribute("cpu", path, "cpu.stat", STRV_MAKE("usage_usec"), &val);
if (IN_SET(r, -ENOENT, -ENXIO))
return 0;
if (r < 0)
return r;
r = safe_atou64(val, &new_usage);
if (r < 0)
return r;
new_usage *= NSEC_PER_USEC;
} else {
if (!streq(controller, "cpuacct"))
return 0;
r = cg_get_path(controller, path, "cpuacct.usage", &p);
if (r < 0)
return r;
r = read_one_line_file(p, &v);
if (r == -ENOENT)
return 0;
if (r < 0)
return r;
r = safe_atou64(v, &new_usage);
if (r < 0)
return r;
}
timestamp = now_nsec(CLOCK_MONOTONIC);
if (g->cpu_iteration == iteration - 1 &&
(nsec_t) new_usage > g->cpu_usage) {
nsec_t x, y;
x = timestamp - g->cpu_timestamp;
if (x < 1)
x = 1;
y = (nsec_t) new_usage - g->cpu_usage;
g->cpu_fraction = (double) y / (double) x;
g->cpu_valid = true;
}
g->cpu_usage = (nsec_t) new_usage;
g->cpu_timestamp = timestamp;
g->cpu_iteration = iteration;
}
r = process_cpu(g, iteration);
if (r < 0)
return r;
if (ret)
*ret = g;
return 0;
return 1;
}
static int refresh_one(
const char *controller,
static int refresh(
const char *path,
Hashmap *a,
Hashmap *b,
@@ -442,29 +420,34 @@ static int refresh_one(
Group **ret) {
_cleanup_closedir_ DIR *d = NULL;
Group *ours = NULL;
Group *ours;
int r;
assert(controller);
assert(path);
assert(a);
if (depth > arg_depth)
if (depth > arg_depth) {
if (ret)
*ret = NULL;
return 0;
}
r = process(controller, path, a, b, iteration, &ours);
r = process(path, a, b, iteration, &ours);
if (r < 0)
return r;
r = cg_enumerate_subgroups(controller, path, &d);
if (r == -ENOENT)
r = cg_enumerate_subgroups(SYSTEMD_CGROUP_CONTROLLER, path, &d);
if (r == -ENOENT) {
if (ret)
*ret = NULL;
return 0;
}
if (r < 0)
return r;
for (;;) {
_cleanup_free_ char *fn = NULL, *p = NULL;
Group *child = NULL;
Group *child;
r = cg_read_subgroup(d, &fn);
if (r < 0)
@@ -478,15 +461,13 @@ static int refresh_one(
path_simplify(p);
r = refresh_one(controller, p, a, b, iteration, depth + 1, &child);
r = refresh(p, a, b, iteration, depth + 1, &child);
if (r < 0)
return r;
if (arg_recursive &&
if (r > 0 &&
arg_recursive &&
IN_SET(arg_count, COUNT_ALL_PROCESSES, COUNT_USERSPACE_PROCESSES) &&
child &&
child->n_tasks_valid &&
streq(controller, SYSTEMD_CGROUP_CONTROLLER)) {
child->n_tasks_valid) {
/* Recursively sum up processes */
@@ -505,18 +486,6 @@ static int refresh_one(
return 1;
}
static int refresh(const char *root, Hashmap *a, Hashmap *b, unsigned iteration) {
int r;
FOREACH_STRING(c, SYSTEMD_CGROUP_CONTROLLER, "cpu", "cpuacct", "memory", "io", "blkio", "pids") {
r = refresh_one(c, root, a, b, iteration, 0, NULL);
if (r < 0)
return r;
}
return 0;
}
static int group_compare(Group * const *a, Group * const *b) {
const Group *x = *a, *y = *b;
int r;
@@ -923,7 +892,7 @@ static int loop(const char *root) {
if (t >= usec_add(last_refresh, arg_delay) || immediate_refresh) {
r = refresh(root, a, b, iteration++);
r = refresh(root, a, b, iteration++, /* depth = */ 0, /* ret = */ NULL);
if (r < 0)
return log_error_errno(r, "Failed to refresh: %m");

View File

@@ -477,7 +477,6 @@ void cgroup_context_dump(Unit *u, FILE* f, const char *prefix) {
startup_cpuset_mems = cpu_set_to_range_string(&c->startup_cpuset_mems);
fprintf(f,
"%sCPUAccounting: %s\n"
"%sIOAccounting: %s\n"
"%sMemoryAccounting: %s\n"
"%sTasksAccounting: %s\n"
@@ -516,7 +515,6 @@ void cgroup_context_dump(Unit *u, FILE* f, const char *prefix) {
"%sManagedOOMPreference: %s\n"
"%sMemoryPressureWatch: %s\n"
"%sCoredumpReceive: %s\n",
prefix, yes_no(c->cpu_accounting),
prefix, yes_no(c->io_accounting),
prefix, yes_no(c->memory_accounting),
prefix, yes_no(c->tasks_accounting),
@@ -1698,9 +1696,6 @@ static CGroupMask unit_get_cgroup_mask(Unit *u) {
/* Figure out which controllers we need, based on the cgroup context object */
if (c->cpu_accounting)
mask |= get_cpu_accounting_mask();
if (cgroup_context_has_cpu_weight(c) ||
c->cpu_quota_per_sec_usec != USEC_INFINITY)
mask |= CGROUP_MASK_CPU;
@@ -3628,10 +3623,6 @@ static int unit_get_cpu_usage_raw(const Unit *u, const CGroupRuntime *crt, nsec_
if (unit_has_host_root_cgroup(u))
return procfs_cpu_get_usage(ret);
/* Requisite controllers for CPU accounting are not enabled */
if ((get_cpu_accounting_mask() & ~crt->cgroup_realized_mask) != 0)
return -ENODATA;
_cleanup_free_ char *val = NULL;
uint64_t us;
@@ -3660,9 +3651,6 @@ int unit_get_cpu_usage(Unit *u, nsec_t *ret) {
* started. If the cgroup has been removed already, returns the last cached value. To cache the value, simply
* call this function with a NULL return value. */
if (!UNIT_CGROUP_BOOL(u, cpu_accounting))
return -ENODATA;
CGroupRuntime *crt = unit_get_cgroup_runtime(u);
if (!crt)
return -ENODATA;

View File

@@ -123,7 +123,6 @@ typedef enum CGroupPressureWatch {
* manager is running (except for an occasional SetProperty() configuration change), outside of reload
* cycles. */
struct CGroupContext {
bool cpu_accounting;
bool io_accounting;
bool memory_accounting;
bool tasks_accounting;

View File

@@ -384,7 +384,6 @@ const sd_bus_vtable bus_cgroup_vtable[] = {
SD_BUS_PROPERTY("Delegate", "b", bus_property_get_bool, offsetof(CGroupContext, delegate), 0),
SD_BUS_PROPERTY("DelegateControllers", "as", property_get_delegate_controllers, 0, 0),
SD_BUS_PROPERTY("DelegateSubgroup", "s", NULL, offsetof(CGroupContext, delegate_subgroup), 0),
SD_BUS_PROPERTY("CPUAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, cpu_accounting), 0),
SD_BUS_PROPERTY("CPUWeight", "t", NULL, offsetof(CGroupContext, cpu_weight), 0),
SD_BUS_PROPERTY("StartupCPUWeight", "t", NULL, offsetof(CGroupContext, startup_cpu_weight), 0),
SD_BUS_PROPERTY("CPUQuotaPerSecUSec", "t", bus_property_get_usec, offsetof(CGroupContext, cpu_quota_per_sec_usec), 0),
@@ -441,6 +440,7 @@ const sd_bus_vtable bus_cgroup_vtable[] = {
SD_BUS_PROPERTY("MemoryPressureThresholdUSec", "t", bus_property_get_usec, offsetof(CGroupContext, memory_pressure_threshold_usec), 0),
SD_BUS_PROPERTY("NFTSet", "a(iiss)", property_get_cgroup_nft_set, 0, 0),
SD_BUS_PROPERTY("CoredumpReceive", "b", bus_property_get_bool, offsetof(CGroupContext, coredump_receive), 0),
/* deprecated cgroup v1 properties */
SD_BUS_PROPERTY("MemoryLimit", "t", bus_property_get_uint64_max, 0, SD_BUS_VTABLE_DEPRECATED|SD_BUS_VTABLE_HIDDEN),
SD_BUS_PROPERTY("CPUShares", "t", bus_property_get_uint64_max, 0, SD_BUS_VTABLE_DEPRECATED|SD_BUS_VTABLE_HIDDEN),
@@ -451,6 +451,9 @@ const sd_bus_vtable bus_cgroup_vtable[] = {
SD_BUS_PROPERTY("BlockIODeviceWeight", "a(st)", property_get_blockio_ast, 0, SD_BUS_VTABLE_DEPRECATED|SD_BUS_VTABLE_HIDDEN),
SD_BUS_PROPERTY("BlockIOReadBandwidth", "a(st)", property_get_blockio_ast, 0, SD_BUS_VTABLE_DEPRECATED|SD_BUS_VTABLE_HIDDEN),
SD_BUS_PROPERTY("BlockIOWriteBandwidth", "a(st)", property_get_blockio_ast, 0, SD_BUS_VTABLE_DEPRECATED|SD_BUS_VTABLE_HIDDEN),
/* since kernel v4.15 CPU accounting requires no controller, i.e. is available everywhere */
SD_BUS_PROPERTY("CPUAccounting", "b", bus_property_get_bool_true, 0, SD_BUS_VTABLE_DEPRECATED|SD_BUS_VTABLE_HIDDEN),
SD_BUS_VTABLE_END
};
@@ -1038,9 +1041,6 @@ int bus_cgroup_set_property(
flags |= UNIT_PRIVATE;
if (streq(name, "CPUAccounting"))
return bus_cgroup_set_boolean(u, name, &c->cpu_accounting, get_cpu_accounting_mask(), message, flags, error);
if (streq(name, "CPUWeight"))
return bus_cgroup_set_cpu_weight(u, name, &c->cpu_weight, message, flags, error);
@@ -2038,7 +2038,8 @@ int bus_cgroup_set_property(
"StartupBlockIOWeight",
"BlockIODeviceWeight",
"BlockIOReadBandwidth",
"BlockIOWriteBandwidth")) {
"BlockIOWriteBandwidth",
"CPUAccounting")) { /* see comment in bus_cgroup_vtable */
r = sd_bus_message_skip(message, NULL);
if (r < 0)

View File

@@ -2887,7 +2887,6 @@ const sd_bus_vtable bus_manager_vtable[] = {
SD_BUS_PROPERTY("DefaultStartLimitIntervalSec", "t", bus_property_get_usec, offsetof(Manager, defaults.start_limit.interval), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
SD_BUS_PROPERTY("DefaultStartLimitInterval", "t", bus_property_get_usec, offsetof(Manager, defaults.start_limit.interval), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
SD_BUS_PROPERTY("DefaultStartLimitBurst", "u", bus_property_get_unsigned, offsetof(Manager, defaults.start_limit.burst), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("DefaultCPUAccounting", "b", bus_property_get_bool, offsetof(Manager, defaults.cpu_accounting), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("DefaultIOAccounting", "b", bus_property_get_bool, offsetof(Manager, defaults.io_accounting), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("DefaultIPAccounting", "b", bus_property_get_bool, offsetof(Manager, defaults.ip_accounting), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("DefaultMemoryAccounting", "b", bus_property_get_bool, offsetof(Manager, defaults.memory_accounting), SD_BUS_VTABLE_PROPERTY_CONST),
@@ -2932,8 +2931,11 @@ const sd_bus_vtable bus_manager_vtable[] = {
SD_BUS_PROPERTY("DefaultOOMScoreAdjust", "i", property_get_oom_score_adjust, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("CtrlAltDelBurstAction", "s", bus_property_get_emergency_action, offsetof(Manager, cad_burst_action), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("SoftRebootsCount", "u", bus_property_get_unsigned, offsetof(Manager, soft_reboots_count), SD_BUS_VTABLE_PROPERTY_CONST),
/* deprecated cgroup v1 property */
SD_BUS_PROPERTY("DefaultBlockIOAccounting", "b", bus_property_get_bool_false, 0, SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_DEPRECATED|SD_BUS_VTABLE_HIDDEN),
/* see comment in bus_cgroup_vtable */
SD_BUS_PROPERTY("DefaultCPUAccounting", "b", bus_property_get_bool_true, 0, SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_DEPRECATED|SD_BUS_VTABLE_HIDDEN),
SD_BUS_METHOD_WITH_ARGS("GetUnit",
SD_BUS_ARGS("s", name),

View File

@@ -34,10 +34,6 @@ static int exec_cgroup_context_serialize(const CGroupContext *c, FILE *f) {
if (!c)
return 0;
r = serialize_bool_elide(f, "exec-cgroup-context-cpu-accounting", c->cpu_accounting);
if (r < 0)
return r;
r = serialize_bool_elide(f, "exec-cgroup-context-io-accounting", c->io_accounting);
if (r < 0)
return r;
@@ -445,12 +441,7 @@ static int exec_cgroup_context_deserialize(CGroupContext *c, FILE *f) {
if (r == 0) /* eof or end marker */
break;
if ((val = startswith(l, "exec-cgroup-context-cpu-accounting="))) {
r = parse_boolean(val);
if (r < 0)
return r;
c->cpu_accounting = r;
} else if ((val = startswith(l, "exec-cgroup-context-io-accounting="))) {
if ((val = startswith(l, "exec-cgroup-context-io-accounting="))) {
r = parse_boolean(val);
if (r < 0)
return r;

View File

@@ -201,7 +201,7 @@
{{type}}.StartupAllowedCPUs, config_parse_allowed_cpuset, 0, offsetof({{type}}, cgroup_context.startup_cpuset_cpus)
{{type}}.AllowedMemoryNodes, config_parse_allowed_cpuset, 0, offsetof({{type}}, cgroup_context.cpuset_mems)
{{type}}.StartupAllowedMemoryNodes, config_parse_allowed_cpuset, 0, offsetof({{type}}, cgroup_context.startup_cpuset_mems)
{{type}}.CPUAccounting, config_parse_bool, 0, offsetof({{type}}, cgroup_context.cpu_accounting)
{{type}}.CPUAccounting, config_parse_warn_compat, DISABLED_LEGACY, 0
{{type}}.CPUWeight, config_parse_cg_cpu_weight, 0, offsetof({{type}}, cgroup_context.cpu_weight)
{{type}}.StartupCPUWeight, config_parse_cg_cpu_weight, 0, offsetof({{type}}, cgroup_context.startup_cpu_weight)
{{type}}.CPUShares, config_parse_warn_compat, DISABLED_LEGACY, 0

View File

@@ -791,7 +791,7 @@ static int parse_config_file(void) {
{ "Manager", "DefaultLimitNICE", config_parse_rlimit, RLIMIT_NICE, arg_defaults.rlimit },
{ "Manager", "DefaultLimitRTPRIO", config_parse_rlimit, RLIMIT_RTPRIO, arg_defaults.rlimit },
{ "Manager", "DefaultLimitRTTIME", config_parse_rlimit, RLIMIT_RTTIME, arg_defaults.rlimit },
{ "Manager", "DefaultCPUAccounting", config_parse_bool, 0, &arg_defaults.cpu_accounting },
{ "Manager", "DefaultCPUAccounting", config_parse_warn_compat, DISABLED_LEGACY, NULL },
{ "Manager", "DefaultIOAccounting", config_parse_bool, 0, &arg_defaults.io_accounting },
{ "Manager", "DefaultIPAccounting", config_parse_bool, 0, &arg_defaults.ip_accounting },
{ "Manager", "DefaultBlockIOAccounting", config_parse_warn_compat, DISABLED_LEGACY, NULL },

View File

@@ -58,8 +58,6 @@ static int manager_context_build_json(sd_json_variant **ret, const char *name, v
JSON_BUILD_PAIR_FINITE_USEC("DefaultDeviceTimeoutUSec", m->defaults.device_timeout_usec),
JSON_BUILD_PAIR_FINITE_USEC("DefaultRestartUSec", m->defaults.restart_usec),
JSON_BUILD_PAIR_RATELIMIT("DefaultStartLimit", &m->defaults.start_limit),
SD_JSON_BUILD_PAIR_BOOLEAN("DefaultCPUAccounting", m->defaults.cpu_accounting),
SD_JSON_BUILD_PAIR_BOOLEAN("DefaultBlockIOAccounting", m->defaults.blockio_accounting),
SD_JSON_BUILD_PAIR_BOOLEAN("DefaultIOAccounting", m->defaults.io_accounting),
SD_JSON_BUILD_PAIR_BOOLEAN("DefaultIPAccounting", m->defaults.ip_accounting),
SD_JSON_BUILD_PAIR_BOOLEAN("DefaultMemoryAccounting", m->defaults.memory_accounting),

View File

@@ -4197,10 +4197,8 @@ int manager_set_unit_defaults(Manager *m, const UnitDefaults *defaults) {
m->defaults.start_limit = defaults->start_limit;
m->defaults.cpu_accounting = defaults->cpu_accounting;
m->defaults.memory_accounting = defaults->memory_accounting;
m->defaults.io_accounting = defaults->io_accounting;
m->defaults.blockio_accounting = defaults->blockio_accounting;
m->defaults.tasks_accounting = defaults->tasks_accounting;
m->defaults.ip_accounting = defaults->ip_accounting;
@@ -5096,12 +5094,8 @@ void unit_defaults_init(UnitDefaults *defaults, RuntimeScope scope) {
.device_timeout_usec = manager_default_timeout(scope),
.start_limit = { DEFAULT_START_LIMIT_INTERVAL, DEFAULT_START_LIMIT_BURST },
/* On 4.15+ with unified hierarchy, CPU accounting is essentially free as it doesn't require the CPU
* controller to be enabled, so the default is to enable it unless we got told otherwise. */
.cpu_accounting = cpu_accounting_is_cheap(),
.memory_accounting = MEMORY_ACCOUNTING_DEFAULT,
.io_accounting = false,
.blockio_accounting = false,
.tasks_accounting = true,
.ip_accounting = false,

View File

@@ -149,10 +149,8 @@ typedef struct UnitDefaults {
RateLimit start_limit;
bool cpu_accounting;
bool memory_accounting;
bool io_accounting;
bool blockio_accounting;
bool tasks_accounting;
bool ip_accounting;

View File

@@ -334,7 +334,6 @@ static void slice_enumerate_perpetual(Manager *m) {
* means the kernel will track CPU/tasks/memory for us anyway, and it is all available in /proc. Let's
* hence turn accounting on here, so that our APIs to query this data are available. */
s->cgroup_context.cpu_accounting = true;
s->cgroup_context.tasks_accounting = true;
s->cgroup_context.memory_accounting = true;
}

View File

@@ -54,7 +54,6 @@
#DefaultStartLimitIntervalSec=10s
#DefaultStartLimitBurst=5
#DefaultEnvironment=
#DefaultCPUAccounting=yes
#DefaultIOAccounting=no
#DefaultIPAccounting=no
#DefaultMemoryAccounting={{ 'yes' if MEMORY_ACCOUNTING_DEFAULT else 'no' }}

View File

@@ -173,7 +173,6 @@ static void unit_init(Unit *u) {
* context, _before_ the rest of the settings have
* been initialized */
cc->cpu_accounting = u->manager->defaults.cpu_accounting;
cc->io_accounting = u->manager->defaults.io_accounting;
cc->memory_accounting = u->manager->defaults.memory_accounting;
cc->tasks_accounting = u->manager->defaults.tasks_accounting;

View File

@@ -8,6 +8,7 @@
#include "string-util.h"
BUS_DEFINE_PROPERTY_GET_GLOBAL(bus_property_get_bool_false, "b", 0);
BUS_DEFINE_PROPERTY_GET_GLOBAL(bus_property_get_bool_true, "b", 1);
BUS_DEFINE_PROPERTY_GET_GLOBAL(bus_property_get_uint64_max, "t", UINT64_MAX);
int bus_property_get_bool(

View File

@@ -5,10 +5,6 @@
#include "macro.h"
/* For deprecated properties. */
int bus_property_get_bool_false(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error);
int bus_property_get_uint64_max(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error);
int bus_property_get_bool(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error);
int bus_property_set_bool(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *value, void *userdata, sd_bus_error *error);
int bus_property_get_tristate(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error);
@@ -105,3 +101,8 @@ int bus_property_get_string_set(sd_bus *bus, const char *path, const char *inter
#define BUS_PROPERTY_DUAL_TIMESTAMP(name, offset, flags) \
SD_BUS_PROPERTY(name, "t", bus_property_get_usec, (offset) + offsetof(struct dual_timestamp, realtime), (flags)), \
SD_BUS_PROPERTY(name "Monotonic", "t", bus_property_get_usec, (offset) + offsetof(struct dual_timestamp, monotonic), (flags))
/* For deprecated properties. */
int bus_property_get_bool_false(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error);
int bus_property_get_bool_true(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error);
int bus_property_get_uint64_max(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error);

View File

@@ -164,7 +164,6 @@ static int bus_print_property(const char *name, const char *expected_value, sd_b
else if ((STR_IN_SET(name, "CPUWeight", "StartupCPUWeight", "IOWeight", "StartupIOWeight") && u == CGROUP_WEIGHT_INVALID) ||
(STR_IN_SET(name, "CPUShares", "StartupCPUShares") && u == CGROUP_CPU_SHARES_INVALID) ||
(STR_IN_SET(name, "BlockIOWeight", "StartupBlockIOWeight") && u == CGROUP_BLKIO_WEIGHT_INVALID) ||
(STR_IN_SET(name, "MemoryCurrent", "MemoryAvailable", "TasksCurrent") && u == UINT64_MAX) ||
(startswith(name, "Memory") && ENDSWITH_SET(name, "Current", "Peak") && u == CGROUP_LIMIT_MAX) ||
(startswith(name, "IO") && ENDSWITH_SET(name, "Bytes", "Operations") && u == UINT64_MAX) ||

View File

@@ -53,10 +53,6 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE(
SD_VARLINK_DEFINE_FIELD(DefaultRestartUSec, SD_VARLINK_INT, 0),
SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man/"PROJECT_VERSION_STR"/systemd-system.conf.html#DefaultStartLimit="),
SD_VARLINK_DEFINE_FIELD_BY_TYPE(DefaultStartLimit, RateLimit, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man/"PROJECT_VERSION_STR"/systemd-system.conf.html#DefaultCPUAccounting="),
SD_VARLINK_DEFINE_FIELD(DefaultCPUAccounting, SD_VARLINK_BOOL, 0),
SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man/"PROJECT_VERSION_STR"/systemd-system.conf.html#DefaultBlockIOAccounting="),
SD_VARLINK_DEFINE_FIELD(DefaultBlockIOAccounting, SD_VARLINK_BOOL, 0),
SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man/"PROJECT_VERSION_STR"/systemd-system.conf.html#DefaultIOAccounting="),
SD_VARLINK_DEFINE_FIELD(DefaultIOAccounting, SD_VARLINK_BOOL, 0),
SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man/"PROJECT_VERSION_STR"/systemd-system.conf.html#DefaultIPAccounting="),

View File

@@ -1505,8 +1505,7 @@ static int print_property(const char *name, const char *expected_value, sd_bus_m
return 1;
} else if (contents[0] == SD_BUS_TYPE_STRUCT_BEGIN &&
STR_IN_SET(name, "IODeviceWeight", "BlockIODeviceWeight")) {
} else if (contents[0] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "IODeviceWeight")) {
const char *path;
uint64_t weight;
@@ -1526,8 +1525,7 @@ static int print_property(const char *name, const char *expected_value, sd_bus_m
return 1;
} else if (contents[0] == SD_BUS_TYPE_STRUCT_BEGIN &&
(cgroup_io_limit_type_from_string(name) >= 0 ||
STR_IN_SET(name, "BlockIOReadBandwidth", "BlockIOWriteBandwidth"))) {
cgroup_io_limit_type_from_string(name) >= 0) {
const char *path;
uint64_t bandwidth;

View File

@@ -31,7 +31,6 @@ TEST_RET(cgroup_mask, .sd_booted = true) {
_cleanup_(manager_freep) Manager *m = NULL;
Unit *son, *daughter, *parent, *root, *grandchild, *parent_deep, *nomem_parent, *nomem_leaf;
int r;
CGroupMask cpu_accounting_mask = get_cpu_accounting_mask();
r = enter_cgroup_subroot(NULL);
if (r == -ENOMEDIUM)
@@ -53,9 +52,7 @@ TEST_RET(cgroup_mask, .sd_booted = true) {
/* Turn off all kinds of default accounting, so that we can
* verify the masks resulting of our configuration and nothing
* else. */
m->defaults.cpu_accounting =
m->defaults.memory_accounting =
m->defaults.blockio_accounting =
m->defaults.memory_accounting =
m->defaults.io_accounting =
m->defaults.tasks_accounting = false;
m->defaults.tasks_max = CGROUP_TASKS_MAX_UNSET;
@@ -80,7 +77,6 @@ TEST_RET(cgroup_mask, .sd_booted = true) {
/* Verify per-unit cgroups settings. */
ASSERT_CGROUP_MASK_JOINED(unit_get_own_mask(son), CGROUP_MASK_CPU);
ASSERT_CGROUP_MASK_JOINED(unit_get_own_mask(daughter), cpu_accounting_mask);
ASSERT_CGROUP_MASK_JOINED(unit_get_own_mask(grandchild), 0);
ASSERT_CGROUP_MASK_JOINED(unit_get_own_mask(parent_deep), CGROUP_MASK_MEMORY);
ASSERT_CGROUP_MASK_JOINED(unit_get_own_mask(parent), (CGROUP_MASK_IO | CGROUP_MASK_BLKIO));
@@ -93,40 +89,40 @@ TEST_RET(cgroup_mask, .sd_booted = true) {
ASSERT_CGROUP_MASK_JOINED(unit_get_members_mask(daughter), 0);
ASSERT_CGROUP_MASK_JOINED(unit_get_members_mask(grandchild), 0);
ASSERT_CGROUP_MASK_JOINED(unit_get_members_mask(parent_deep), 0);
ASSERT_CGROUP_MASK_JOINED(unit_get_members_mask(parent), (CGROUP_MASK_CPU | cpu_accounting_mask | CGROUP_MASK_MEMORY));
ASSERT_CGROUP_MASK_JOINED(unit_get_members_mask(parent), (CGROUP_MASK_CPU | CGROUP_MASK_MEMORY));
ASSERT_CGROUP_MASK_JOINED(unit_get_members_mask(nomem_parent), (CGROUP_MASK_IO | CGROUP_MASK_BLKIO | CGROUP_MASK_MEMORY));
ASSERT_CGROUP_MASK_JOINED(unit_get_members_mask(nomem_leaf), 0);
ASSERT_CGROUP_MASK_JOINED(unit_get_members_mask(root), (CGROUP_MASK_CPU | cpu_accounting_mask | CGROUP_MASK_IO | CGROUP_MASK_BLKIO | CGROUP_MASK_MEMORY));
ASSERT_CGROUP_MASK_JOINED(unit_get_members_mask(root), (CGROUP_MASK_CPU | CGROUP_MASK_IO | CGROUP_MASK_BLKIO | CGROUP_MASK_MEMORY));
/* Verify aggregation of sibling masks. */
ASSERT_CGROUP_MASK_JOINED(unit_get_siblings_mask(son), (CGROUP_MASK_CPU | cpu_accounting_mask | CGROUP_MASK_MEMORY));
ASSERT_CGROUP_MASK_JOINED(unit_get_siblings_mask(daughter), (CGROUP_MASK_CPU | cpu_accounting_mask | CGROUP_MASK_MEMORY));
ASSERT_CGROUP_MASK_JOINED(unit_get_siblings_mask(son), (CGROUP_MASK_CPU | CGROUP_MASK_MEMORY));
ASSERT_CGROUP_MASK_JOINED(unit_get_siblings_mask(daughter), (CGROUP_MASK_CPU | CGROUP_MASK_MEMORY));
ASSERT_CGROUP_MASK_JOINED(unit_get_siblings_mask(grandchild), 0);
ASSERT_CGROUP_MASK_JOINED(unit_get_siblings_mask(parent_deep), (CGROUP_MASK_CPU | cpu_accounting_mask | CGROUP_MASK_MEMORY));
ASSERT_CGROUP_MASK_JOINED(unit_get_siblings_mask(parent), (CGROUP_MASK_CPU | cpu_accounting_mask | CGROUP_MASK_IO | CGROUP_MASK_BLKIO | CGROUP_MASK_MEMORY));
ASSERT_CGROUP_MASK_JOINED(unit_get_siblings_mask(parent_deep), (CGROUP_MASK_CPU | CGROUP_MASK_MEMORY));
ASSERT_CGROUP_MASK_JOINED(unit_get_siblings_mask(parent), (CGROUP_MASK_CPU | CGROUP_MASK_IO | CGROUP_MASK_BLKIO | CGROUP_MASK_MEMORY));
ASSERT_CGROUP_MASK_JOINED(unit_get_siblings_mask(nomem_parent), (CGROUP_MASK_CPU | CGROUP_MASK_CPUACCT | CGROUP_MASK_IO | CGROUP_MASK_BLKIO | CGROUP_MASK_MEMORY));
ASSERT_CGROUP_MASK_JOINED(unit_get_siblings_mask(nomem_leaf), (CGROUP_MASK_IO | CGROUP_MASK_BLKIO | CGROUP_MASK_MEMORY));
ASSERT_CGROUP_MASK_JOINED(unit_get_siblings_mask(root), (CGROUP_MASK_CPU | cpu_accounting_mask | CGROUP_MASK_IO | CGROUP_MASK_BLKIO | CGROUP_MASK_MEMORY));
ASSERT_CGROUP_MASK_JOINED(unit_get_siblings_mask(root), (CGROUP_MASK_CPU | CGROUP_MASK_IO | CGROUP_MASK_BLKIO | CGROUP_MASK_MEMORY));
/* Verify aggregation of target masks. */
ASSERT_CGROUP_MASK(unit_get_target_mask(son), (CGROUP_MASK_EXTEND_JOINED(CGROUP_MASK_CPU | cpu_accounting_mask | CGROUP_MASK_MEMORY) & m->cgroup_supported));
ASSERT_CGROUP_MASK(unit_get_target_mask(daughter), (CGROUP_MASK_EXTEND_JOINED(CGROUP_MASK_CPU | cpu_accounting_mask | CGROUP_MASK_MEMORY) & m->cgroup_supported));
ASSERT_CGROUP_MASK(unit_get_target_mask(son), (CGROUP_MASK_EXTEND_JOINED(CGROUP_MASK_CPU | CGROUP_MASK_MEMORY) & m->cgroup_supported));
ASSERT_CGROUP_MASK(unit_get_target_mask(daughter), (CGROUP_MASK_EXTEND_JOINED(CGROUP_MASK_CPU | CGROUP_MASK_MEMORY) & m->cgroup_supported));
ASSERT_CGROUP_MASK(unit_get_target_mask(grandchild), 0);
ASSERT_CGROUP_MASK(unit_get_target_mask(parent_deep), (CGROUP_MASK_EXTEND_JOINED(CGROUP_MASK_CPU | cpu_accounting_mask | CGROUP_MASK_MEMORY) & m->cgroup_supported));
ASSERT_CGROUP_MASK(unit_get_target_mask(parent), (CGROUP_MASK_EXTEND_JOINED(CGROUP_MASK_CPU | cpu_accounting_mask | CGROUP_MASK_IO | CGROUP_MASK_BLKIO | CGROUP_MASK_MEMORY) & m->cgroup_supported));
ASSERT_CGROUP_MASK(unit_get_target_mask(parent_deep), (CGROUP_MASK_EXTEND_JOINED(CGROUP_MASK_CPU | CGROUP_MASK_MEMORY) & m->cgroup_supported));
ASSERT_CGROUP_MASK(unit_get_target_mask(parent), (CGROUP_MASK_EXTEND_JOINED(CGROUP_MASK_CPU | CGROUP_MASK_IO | CGROUP_MASK_BLKIO | CGROUP_MASK_MEMORY) & m->cgroup_supported));
ASSERT_CGROUP_MASK(unit_get_target_mask(nomem_parent), (CGROUP_MASK_EXTEND_JOINED(CGROUP_MASK_CPU | CGROUP_MASK_CPUACCT | CGROUP_MASK_IO | CGROUP_MASK_BLKIO) & m->cgroup_supported));
ASSERT_CGROUP_MASK(unit_get_target_mask(nomem_leaf), (CGROUP_MASK_EXTEND_JOINED(CGROUP_MASK_IO | CGROUP_MASK_BLKIO) & m->cgroup_supported));
ASSERT_CGROUP_MASK(unit_get_target_mask(root), (CGROUP_MASK_EXTEND_JOINED(CGROUP_MASK_CPU | cpu_accounting_mask | CGROUP_MASK_IO | CGROUP_MASK_BLKIO | CGROUP_MASK_MEMORY) & m->cgroup_supported));
ASSERT_CGROUP_MASK(unit_get_target_mask(root), (CGROUP_MASK_EXTEND_JOINED(CGROUP_MASK_CPU | CGROUP_MASK_IO | CGROUP_MASK_BLKIO | CGROUP_MASK_MEMORY) & m->cgroup_supported));
/* Verify aggregation of enable masks. */
ASSERT_CGROUP_MASK(unit_get_enable_mask(son), 0);
ASSERT_CGROUP_MASK(unit_get_enable_mask(daughter), 0);
ASSERT_CGROUP_MASK(unit_get_enable_mask(grandchild), 0);
ASSERT_CGROUP_MASK(unit_get_enable_mask(parent_deep), 0);
ASSERT_CGROUP_MASK(unit_get_enable_mask(parent), (CGROUP_MASK_EXTEND_JOINED(CGROUP_MASK_CPU | cpu_accounting_mask | CGROUP_MASK_MEMORY) & m->cgroup_supported));
ASSERT_CGROUP_MASK(unit_get_enable_mask(parent), (CGROUP_MASK_EXTEND_JOINED(CGROUP_MASK_CPU | CGROUP_MASK_MEMORY) & m->cgroup_supported));
ASSERT_CGROUP_MASK(unit_get_enable_mask(nomem_parent), (CGROUP_MASK_EXTEND_JOINED(CGROUP_MASK_IO | CGROUP_MASK_BLKIO) & m->cgroup_supported));
ASSERT_CGROUP_MASK(unit_get_enable_mask(nomem_leaf), 0);
ASSERT_CGROUP_MASK(unit_get_enable_mask(root), (CGROUP_MASK_EXTEND_JOINED(CGROUP_MASK_CPU | cpu_accounting_mask | CGROUP_MASK_IO | CGROUP_MASK_BLKIO | CGROUP_MASK_MEMORY) & m->cgroup_supported));
ASSERT_CGROUP_MASK(unit_get_enable_mask(root), (CGROUP_MASK_EXTEND_JOINED(CGROUP_MASK_CPU | CGROUP_MASK_IO | CGROUP_MASK_BLKIO | CGROUP_MASK_MEMORY) & m->cgroup_supported));
return 0;
}

View File

@@ -249,12 +249,12 @@ systemctl revert "$UNIT_NAME"
(! grep -r "IPAccounting=" "/etc/systemd/system.control/${UNIT_NAME}.d/")
(! grep -r "MemoryMax=" "/etc/systemd/system.control/${UNIT_NAME}.d/")
# Same stuff, but with --runtime, which should use /run
systemctl set-property --runtime "$UNIT_NAME" CPUAccounting=no CPUQuota=10%
systemctl set-property --runtime "$UNIT_NAME" IOAccounting=no CPUQuota=10%
systemctl cat "$UNIT_NAME"
grep -r "CPUAccounting=no" "/run/systemd/system.control/${UNIT_NAME}.d/"
grep -r "IOAccounting=no" "/run/systemd/system.control/${UNIT_NAME}.d/"
grep -r "CPUQuota=10.00%" "/run/systemd/system.control/${UNIT_NAME}.d/"
systemctl revert "$UNIT_NAME"
(! grep -r "CPUAccounting=" "/run/systemd/system.control/${UNIT_NAME}.d/")
(! grep -r "IOAccounting=" "/run/systemd/system.control/${UNIT_NAME}.d/")
(! grep -r "CPUQuota=" "/run/systemd/system.control/${UNIT_NAME}.d/")
# Failed-unit related tests

View File

@@ -3,7 +3,6 @@
Description=Test slice for memory pressure kills
[Slice]
CPUAccounting=true
MemoryAccounting=true
IOAccounting=true
TasksAccounting=true

View File

@@ -6,4 +6,3 @@ Description=Daughter Service
Slice=parent.slice
Type=oneshot
ExecStart=true
CPUAccounting=true

View File

@@ -75,9 +75,12 @@ def find_undocumented_commands(pages, ignorelist):
parent = listitem if listitem is not None else varlistentry
rev = parent.getchildren()[-1]
if rev.get("href") != "version-info.xml":
if (filename, path) not in ignorelist:
if (
rev.get("href") != "version-info.xml" and
not path.startswith(tuple(entry[1] for entry in ignorelist if entry[0] == filename))
):
undocumented.append((filename, path))
return undocumented

View File

@@ -14,6 +14,7 @@ journald.conf.xml ./refsect1[title="Options"]/variablelist/varlistentry[term="Co
journald.conf.xml ./refsect1[title="Options"]/variablelist/varlistentry[term="RateLimitIntervalSec="]
journald.conf.xml ./refsect1[title="Options"]/variablelist/varlistentry[term="SystemMaxUse="]
journald.conf.xml ./refsect1[title="Options"]/variablelist/varlistentry[term="ForwardToSyslog="]
kernel-command-line.xml ./refsect1[title="History"]/
kernel-install.xml ./refsect1[title="Commands"]/variablelist/varlistentry[term="add [[[KERNEL-VERSION] KERNEL-IMAGE] [INITRD-FILE ...]]"]/listitem/variablelist/varlistentry[term="50-depmod.install"]
kernel-install.xml ./refsect1[title="Commands"]/variablelist/varlistentry[term="add [[[KERNEL-VERSION] KERNEL-IMAGE] [INITRD-FILE ...]]"]/listitem/variablelist/varlistentry[term="90-loaderentry.install"]
kernel-install.xml ./refsect1[title="Commands"]/variablelist/varlistentry[term="add [[[KERNEL-VERSION] KERNEL-IMAGE] [INITRD-FILE ...]]"]/listitem/variablelist/varlistentry[term="90-uki-copy.install"]
@@ -129,6 +130,7 @@ systemctl.xml ./refsect1[title="Commands"]/refsect2[title="System Commands"]/var
systemctl.xml ./refsect1[title="Commands"]/refsect2[title="System Commands"]/variablelist/varlistentry[term="suspend"]
systemctl.xml ./refsect1[title="Commands"]/refsect2[title="System Commands"]/variablelist/varlistentry[term="hibernate"]
systemctl.xml ./refsect1[title="Commands"]/refsect2[title="System Commands"]/variablelist/varlistentry[term="switch-root ROOT INIT"]
systemd.xml ./refsect1[title="History"]/
systemd-ask-password.xml ./refsect1[title="Options"]/variablelist/varlistentry[term="--icon="]
systemd-ask-password.xml ./refsect1[title="Options"]/variablelist/varlistentry[term="--timeout="]
systemd-ask-password.xml ./refsect1[title="Options"]/variablelist/varlistentry[term="--no-tty"]
@@ -175,6 +177,7 @@ systemd-nspawn.xml ./refsect1[title="Options"]/refsect2[title="Execution Options
systemd-nspawn.xml ./refsect1[title="Options"]/refsect2[title="System Identity Options"]/variablelist/varlistentry[term="--uuid="]
systemd-nspawn.xml ./refsect1[title="Options"]/refsect2[title="Networking Options"]/variablelist/varlistentry[term="--private-network"]
systemd-nspawn.xml ./refsect1[title="Options"]/refsect2[title="Image Options"]/variablelist/varlistentry[term="--read-only"]
systemd-system.conf.xml ./refsect1[title="History"]/
systemd-tmpfiles.xml ./refsect1[title="Commands and options"]/variablelist/varlistentry[term="--create"]
systemd-tmpfiles.xml ./refsect1[title="Commands and options"]/variablelist/varlistentry[term="--clean"]
systemd-tmpfiles.xml ./refsect1[title="Commands and options"]/variablelist/varlistentry[term="--remove"]
@@ -249,6 +252,7 @@ systemd.path.xml ./refsect1[title="Options"]/variablelist/varlistentry[term="Pat
systemd.path.xml ./refsect1[title="Options"]/variablelist/varlistentry[term="Unit="]
systemd.path.xml ./refsect1[title="Options"]/variablelist/varlistentry[term="MakeDirectory="]
systemd.path.xml ./refsect1[title="Options"]/variablelist/varlistentry[term="DirectoryMode="]
systemd.resource-control.xml ./refsect1[title="History"]/
systemd.service.xml ./refsect1[title="Options"]/variablelist/varlistentry[term="Type="]
systemd.service.xml ./refsect1[title="Options"]/variablelist/varlistentry[term="RemainAfterExit="]
systemd.service.xml ./refsect1[title="Options"]/variablelist/varlistentry[term="GuessMainPID="]