pid1: parse CPUAffinity= in incremental fashion

This makes the handling of this option match what we do in unit files. I think
consistency is important here. (As it happens, it is the only option in
system.conf that is "non-atomic", i.e. where there's a list of things which can
be split over multiple assignments. All other options are single-valued, so
there's no issue of how to handle multiple assignments.)
This commit is contained in:
Zbigniew Jędrzejewski-Szmek 2019-05-24 08:35:51 +02:00
parent b54d7241f2
commit 61fbbac1d5
3 changed files with 35 additions and 15 deletions

View file

@ -96,10 +96,13 @@
<varlistentry>
<term><varname>CPUAffinity=</varname></term>
<listitem><para>Configures the CPU affinity for the service manager as well as the default CPU affinity for all
forked off processes. Takes a list of CPU indices or ranges separated by either whitespace or commas. CPU
ranges are specified by the lower and upper CPU indices separated by a dash. Individual services may override
the CPU affinity for their processes with the <varname>CPUAffinity=</varname> setting in unit files, see
<listitem><para>Configures the CPU affinity for the service manager as well as the default CPU
affinity for all forked off processes. Takes a list of CPU indices or ranges separated by either
whitespace or commas. CPU ranges are specified by the lower and upper CPU indices separated by a
dash. This option may be specified more than once, in which case the specified CPU affinity masks are
merged. If the empty string is assigned, the mask is reset, all assignments prior to this will have
no effect. Individual services may override the CPU affinity for their processes with the
<varname>CPUAffinity=</varname> setting in unit files, see
<citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para></listitem>
</varlistentry>

View file

@ -754,7 +754,7 @@ CapabilityBoundingSet=~CAP_B CAP_C</programlisting>
<listitem><para>Controls the CPU affinity of the executed processes. Takes a list of CPU indices or ranges
separated by either whitespace or commas. CPU ranges are specified by the lower and upper CPU indices separated
by a dash. This option may be specified more than once, in which case the specified CPU affinity masks are
by a dash. This option may be specified more than once, in which case the specified CPU affinity masks are
merged. If the empty string is assigned, the mask is reset, all assignments prior to this will have no
effect. See
<citerefentry><refentrytitle>sched_setaffinity</refentrytitle><manvolnum>2</manvolnum></citerefentry> for

View file

@ -139,6 +139,8 @@ static sd_id128_t arg_machine_id = {};
static EmergencyAction arg_cad_burst_action = EMERGENCY_ACTION_REBOOT_FORCE;
static OOMPolicy arg_default_oom_policy = OOM_STOP;
static CPUSet arg_cpu_affinity = {};
_noreturn_ static void freeze_or_exit_or_reboot(void) {
/* If we are running in a container, let's prefer exiting, after all we can propagate an exit code to
@ -567,17 +569,11 @@ static int config_parse_cpu_affinity2(
void *data,
void *userdata) {
_cleanup_(cpu_set_reset) CPUSet c = {};
int r;
CPUSet *affinity = data;
r = parse_cpu_set_full(rvalue, &c, true, unit, filename, line, lvalue);
if (r < 0)
return r;
assert(affinity);
if (sched_setaffinity(0, c.allocated, c.set) < 0)
log_warning_errno(errno, "Failed to set CPU affinity: %m");
// FIXME: parsing and execution should be seperated.
(void) parse_cpu_set_extend(rvalue, affinity, true, unit, filename, line, lvalue);
return 0;
}
@ -719,7 +715,7 @@ static int parse_config_file(void) {
{ "Manager", "CrashShell", config_parse_bool, 0, &arg_crash_shell },
{ "Manager", "CrashReboot", config_parse_bool, 0, &arg_crash_reboot },
{ "Manager", "ShowStatus", config_parse_show_status, 0, &arg_show_status },
{ "Manager", "CPUAffinity", config_parse_cpu_affinity2, 0, NULL },
{ "Manager", "CPUAffinity", config_parse_cpu_affinity2, 0, &arg_cpu_affinity },
{ "Manager", "JoinControllers", config_parse_warn_compat, DISABLED_CONFIGURATION, NULL },
{ "Manager", "RuntimeWatchdogSec", config_parse_sec, 0, &arg_runtime_watchdog },
{ "Manager", "ShutdownWatchdogSec", config_parse_sec, 0, &arg_shutdown_watchdog },
@ -1733,6 +1729,21 @@ static void initialize_core_pattern(bool skip_setup) {
log_warning_errno(r, "Failed to write '%s' to /proc/sys/kernel/core_pattern, ignoring: %m", arg_early_core_pattern);
}
static void update_cpu_affinity(bool skip_setup) {
_cleanup_free_ char *mask = NULL;
if (skip_setup || !arg_cpu_affinity.set)
return;
assert(arg_cpu_affinity.allocated > 0);
mask = cpu_set_to_string(&arg_cpu_affinity);
log_debug("Setting CPU affinity to %s.", strnull(mask));
if (sched_setaffinity(0, arg_cpu_affinity.allocated, arg_cpu_affinity.set) < 0)
log_warning_errno(errno, "Failed to set CPU affinity: %m");
}
static void do_reexecute(
int argc,
char *argv[],
@ -1905,6 +1916,8 @@ static int invoke_main_loop(
set_manager_defaults(m);
update_cpu_affinity(false);
if (saved_log_level >= 0)
manager_override_log_level(m, saved_log_level);
if (saved_log_target >= 0)
@ -2063,6 +2076,8 @@ static int initialize_runtime(
if (arg_action != ACTION_RUN)
return 0;
update_cpu_affinity(skip_setup);
if (arg_system) {
/* Make sure we leave a core dump without panicking the kernel. */
install_crash_handler();
@ -2195,6 +2210,8 @@ static void free_arguments(void) {
arg_confirm_spawn = mfree(arg_confirm_spawn);
arg_default_environment = strv_free(arg_default_environment);
arg_syscall_archs = set_free(arg_syscall_archs);
cpu_set_reset(&arg_cpu_affinity);
}
static int load_configuration(int argc, char **argv, const char **ret_error_message) {