Blame SOURCES/0276-pid1-parse-CPUAffinity-in-incremental-fashion.patch

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