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