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