b9a53a
From 8bf8409c6e08f5aef35d1976e172b3f61b651c8d Mon Sep 17 00:00:00 2001
b9a53a
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
b9a53a
Date: Fri, 24 May 2019 08:35:51 +0200
b9a53a
Subject: [PATCH] pid1: parse CPUAffinity= in incremental fashion
b9a53a
b9a53a
This makes the handling of this option match what we do in unit files. I think
b9a53a
consistency is important here. (As it happens, it is the only option in
b9a53a
system.conf that is "non-atomic", i.e. where there's a list of things which can
b9a53a
be split over multiple assignments. All other options are single-valued, so
b9a53a
there's no issue of how to handle multiple assignments.)
b9a53a
b9a53a
(cherry picked from commit 61fbbac1d517a0b3498a689c736c6ca918497904)
b9a53a
b9a53a
Related: #1734787
b9a53a
---
b9a53a
 man/systemd-system.conf.xml | 13 ++++++++-----
b9a53a
 man/systemd.exec.xml        |  2 +-
b9a53a
 src/core/main.c             | 36 ++++++++++++++++++++++++++----------
b9a53a
 3 files changed, 35 insertions(+), 16 deletions(-)
b9a53a
b9a53a
diff --git a/man/systemd-system.conf.xml b/man/systemd-system.conf.xml
b9a53a
index 085086200a..ab23779ec0 100644
b9a53a
--- a/man/systemd-system.conf.xml
b9a53a
+++ b/man/systemd-system.conf.xml
b9a53a
@@ -99,11 +99,14 @@
b9a53a
       <varlistentry>
b9a53a
         <term><varname>CPUAffinity=</varname></term>
b9a53a
 
b9a53a
-        <listitem><para>Configures the initial CPU affinity for the
b9a53a
-        init process. Takes a list of CPU indices or ranges separated
b9a53a
-        by either whitespace or commas. CPU ranges are specified by
b9a53a
-        the lower and upper CPU indices separated by a
b9a53a
-        dash.</para></listitem>
b9a53a
+        <listitem><para>Configures the CPU affinity for the service manager as well as the default CPU
b9a53a
+        affinity for all forked off processes. Takes a list of CPU indices or ranges separated by either
b9a53a
+        whitespace or commas. CPU ranges are specified by the lower and upper CPU indices separated by a
b9a53a
+        dash. This option may be specified more than once, in which case the specified CPU affinity masks are
b9a53a
+        merged. If the empty string is assigned, the mask is reset, all assignments prior to this will have
b9a53a
+        no effect. Individual services may override the CPU affinity for their processes with the
b9a53a
+        <varname>CPUAffinity=</varname> setting in unit files, see
b9a53a
+        <citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para></listitem>
b9a53a
       </varlistentry>
b9a53a
 
b9a53a
       <varlistentry>
b9a53a
diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml
b9a53a
index 737c52bcc4..342b8385bc 100644
b9a53a
--- a/man/systemd.exec.xml
b9a53a
+++ b/man/systemd.exec.xml
b9a53a
@@ -703,7 +703,7 @@ CapabilityBoundingSet=~CAP_B CAP_C</programlisting>
b9a53a
 
b9a53a
         <listitem><para>Controls the CPU affinity of the executed processes. Takes a list of CPU indices or ranges
b9a53a
         separated by either whitespace or commas. CPU ranges are specified by the lower and upper CPU indices separated
b9a53a
-        by a dash.  This option may be specified more than once, in which case the specified CPU affinity masks are
b9a53a
+        by a dash. This option may be specified more than once, in which case the specified CPU affinity masks are
b9a53a
         merged. If the empty string is assigned, the mask is reset, all assignments prior to this will have no
b9a53a
         effect. See
b9a53a
         <citerefentry><refentrytitle>sched_setaffinity</refentrytitle><manvolnum>2</manvolnum></citerefentry> for
b9a53a
diff --git a/src/core/main.c b/src/core/main.c
b9a53a
index e62b2756ee..bc1db2af7b 100644
b9a53a
--- a/src/core/main.c
b9a53a
+++ b/src/core/main.c
b9a53a
@@ -127,6 +127,7 @@ static bool arg_default_tasks_accounting = true;
b9a53a
 static uint64_t arg_default_tasks_max = UINT64_MAX;
b9a53a
 static sd_id128_t arg_machine_id = {};
b9a53a
 static EmergencyAction arg_cad_burst_action = EMERGENCY_ACTION_REBOOT_FORCE;
b9a53a
+static CPUSet arg_cpu_affinity = {};
b9a53a
 
b9a53a
 _noreturn_ static void freeze_or_reboot(void) {
b9a53a
 
b9a53a
@@ -537,17 +538,11 @@ static int config_parse_cpu_affinity2(
b9a53a
                 void *data,
b9a53a
                 void *userdata) {
b9a53a
 
b9a53a
-        _cleanup_(cpu_set_reset) CPUSet c = {};
b9a53a
-        int r;
b9a53a
-
b9a53a
-        r = parse_cpu_set_full(rvalue, &c, true, unit, filename, line, lvalue);
b9a53a
-        if (r < 0)
b9a53a
-                return r;
b9a53a
+        CPUSet *affinity = data;
b9a53a
 
b9a53a
-        if (sched_setaffinity(0, c.allocated, c.set) < 0)
b9a53a
-                log_warning_errno(errno, "Failed to set CPU affinity: %m");
b9a53a
+        assert(affinity);
b9a53a
 
b9a53a
-        // FIXME: parsing and execution should be seperated.
b9a53a
+        (void) parse_cpu_set_extend(rvalue, affinity, true, unit, filename, line, lvalue);
b9a53a
 
b9a53a
         return 0;
b9a53a
 }
b9a53a
@@ -655,7 +650,7 @@ static int parse_config_file(void) {
b9a53a
                 { "Manager", "CrashShell",                config_parse_bool,             0, &arg_crash_shell                       },
b9a53a
                 { "Manager", "CrashReboot",               config_parse_bool,             0, &arg_crash_reboot                      },
b9a53a
                 { "Manager", "ShowStatus",                config_parse_show_status,      0, &arg_show_status                       },
b9a53a
-                { "Manager", "CPUAffinity",               config_parse_cpu_affinity2,    0, NULL                                   },
b9a53a
+                { "Manager", "CPUAffinity",               config_parse_cpu_affinity2,    0, &arg_cpu_affinity                      },
b9a53a
                 { "Manager", "JoinControllers",           config_parse_join_controllers, 0, &arg_join_controllers                  },
b9a53a
                 { "Manager", "RuntimeWatchdogSec",        config_parse_sec,              0, &arg_runtime_watchdog                  },
b9a53a
                 { "Manager", "ShutdownWatchdogSec",       config_parse_sec,              0, &arg_shutdown_watchdog                 },
b9a53a
@@ -1483,6 +1478,21 @@ static void initialize_coredump(bool skip_setup) {
b9a53a
 #endif
b9a53a
 }
b9a53a
 
b9a53a
+static void update_cpu_affinity(bool skip_setup) {
b9a53a
+        _cleanup_free_ char *mask = NULL;
b9a53a
+
b9a53a
+        if (skip_setup || !arg_cpu_affinity.set)
b9a53a
+                return;
b9a53a
+
b9a53a
+        assert(arg_cpu_affinity.allocated > 0);
b9a53a
+
b9a53a
+        mask = cpu_set_to_string(&arg_cpu_affinity);
b9a53a
+        log_debug("Setting CPU affinity to %s.", strnull(mask));
b9a53a
+
b9a53a
+        if (sched_setaffinity(0, arg_cpu_affinity.allocated, arg_cpu_affinity.set) < 0)
b9a53a
+                log_warning_errno(errno, "Failed to set CPU affinity: %m");
b9a53a
+}
b9a53a
+
b9a53a
 static void do_reexecute(
b9a53a
                 int argc,
b9a53a
                 char *argv[],
b9a53a
@@ -1655,6 +1665,8 @@ static int invoke_main_loop(
b9a53a
 
b9a53a
                         set_manager_defaults(m);
b9a53a
 
b9a53a
+                        update_cpu_affinity(false);
b9a53a
+
b9a53a
                         if (saved_log_level >= 0)
b9a53a
                                 manager_override_log_level(m, saved_log_level);
b9a53a
                         if (saved_log_target >= 0)
b9a53a
@@ -1813,6 +1825,8 @@ static int initialize_runtime(
b9a53a
         if (arg_action != ACTION_RUN)
b9a53a
                 return 0;
b9a53a
 
b9a53a
+        update_cpu_affinity(skip_setup);
b9a53a
+
b9a53a
         if (arg_system) {
b9a53a
                 /* Make sure we leave a core dump without panicing the kernel. */
b9a53a
                 install_crash_handler();
b9a53a
@@ -1947,6 +1961,8 @@ static void free_arguments(void) {
b9a53a
         arg_join_controllers = strv_free_free(arg_join_controllers);
b9a53a
         arg_default_environment = strv_free(arg_default_environment);
b9a53a
         arg_syscall_archs = set_free(arg_syscall_archs);
b9a53a
+
b9a53a
+        cpu_set_reset(&arg_cpu_affinity);
b9a53a
 }
b9a53a
 
b9a53a
 static int load_configuration(int argc, char **argv, const char **ret_error_message) {