]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
nspawn: add a new --cpu-affinity= switch
authorLennart Poettering <lennart@poettering.net>
Mon, 7 May 2018 19:47:15 +0000 (21:47 +0200)
committerLennart Poettering <lennart@poettering.net>
Thu, 17 May 2018 18:48:54 +0000 (20:48 +0200)
Similar as the other options added before, this is primarily useful to
provide comprehensive OCI runtime compatbility, but might be useful
otherwise, too.

man/systemd-nspawn.xml
man/systemd.nspawn.xml
src/nspawn/nspawn-gperf.gperf
src/nspawn/nspawn-settings.c
src/nspawn/nspawn-settings.h
src/nspawn/nspawn.c

index 22bb3b705b2b4b4c3227ab9e32982414632987ac..9a0e02187f7abc4a80cbe5b5c977664dcf4b51f1 100644 (file)
         integer in the range -1000…1000.</para></listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term><option>--cpu-affinity=</option></term>
+
+        <listitem><para>Controls the CPU affinity of the container payload. Takes a comma separated list of CPU numbers
+        or number ranges (the latter's start and end value separated by dashes). See <citerefentry
+        project='man-pages'><refentrytitle>sched_setaffinity</refentrytitle><manvolnum>2</manvolnum></citerefentry> for
+        details.</para></listitem>
+      </varlistentry>
+
       <varlistentry>
         <term><option>--kill-signal=</option></term>
 
index 748a633a3378c2e2e44dd75114483dfed2aa380a..1780bfd79a2277815637ef2a83bed647f3768454 100644 (file)
         details.</para></listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term><varname>CPUAffinity=</varname></term>
+
+        <listitem><para>Configures the CPU affinity. This is equivalent to the <option>--cpu-affinity=</option> command
+        line switch, and takes the same argument. See
+        <citerefentry><refentrytitle>systemd-nspawn</refentrytitle><manvolnum>1</manvolnum></citerefentry> for
+        details.</para></listitem>
+      </varlistentry>
+
       <varlistentry>
         <term><varname>Hostname=</varname></term>
 
index de00dbc243f8520a478c110304037d842849b899..f8234e75d489ed24f431bda542820326a026ec22 100644 (file)
@@ -52,6 +52,7 @@ Exec.LimitRTTIME,             config_parse_rlimit,         RLIMIT_RTTIME,     of
 Exec.Hostname,                config_parse_hostname,       0,                 offsetof(Settings, hostname)
 Exec.NoNewPrivileges,         config_parse_tristate,       0,                 offsetof(Settings, no_new_privileges)
 Exec.OOMScoreAdjust,          config_parse_oom_score_adjust, 0,               0
+Exec.CPUAffinity,             config_parse_cpu_affinity,   0,                 0
 Files.ReadOnly,               config_parse_tristate,       0,                 offsetof(Settings, read_only)
 Files.Volatile,               config_parse_volatile_mode,  0,                 offsetof(Settings, volatile_mode)
 Files.Bind,                   config_parse_bind,           0,                 0
index c91ac73e2e7ce4779d377cc48986ce5712d1bc0f..0acf718456b66f2c05ac2149b2bd1b60e3a4bdb6 100644 (file)
@@ -8,6 +8,7 @@
 #include "alloc-util.h"
 #include "cap-list.h"
 #include "conf-parser.h"
+#include "cpu-set-util.h"
 #include "hostname-util.h"
 #include "nspawn-network.h"
 #include "nspawn-settings.h"
@@ -85,6 +86,7 @@ Settings* settings_free(Settings *s) {
         strv_free(s->syscall_blacklist);
         rlimit_free_all(s->rlimit);
         free(s->hostname);
+        s->cpuset = cpu_set_mfree(s->cpuset);
 
         strv_free(s->network_interfaces);
         strv_free(s->network_macvlan);
@@ -673,3 +675,52 @@ int config_parse_oom_score_adjust(
 
         return 0;
 }
+
+int config_parse_cpu_affinity(
+                const char *unit,
+                const char *filename,
+                unsigned line,
+                const char *section,
+                unsigned section_line,
+                const char *lvalue,
+                int ltype,
+                const char *rvalue,
+                void *data,
+                void *userdata) {
+
+        _cleanup_cpu_free_ cpu_set_t *cpuset = NULL;
+        Settings *settings = data;
+        int ncpus;
+
+        assert(rvalue);
+        assert(settings);
+
+        ncpus = parse_cpu_set_and_warn(rvalue, &cpuset, unit, filename, line, lvalue);
+        if (ncpus < 0)
+                return ncpus;
+
+        if (ncpus == 0) {
+                /* An empty assignment resets the CPU list */
+                settings->cpuset = cpu_set_mfree(settings->cpuset);
+                settings->cpuset_ncpus = 0;
+                return 0;
+        }
+
+        if (!settings->cpuset) {
+                settings->cpuset = TAKE_PTR(cpuset);
+                settings->cpuset_ncpus = (unsigned) ncpus;
+                return 0;
+        }
+
+        if (settings->cpuset_ncpus < (unsigned) ncpus) {
+                CPU_OR_S(CPU_ALLOC_SIZE(settings->cpuset_ncpus), cpuset, settings->cpuset, cpuset);
+                CPU_FREE(settings->cpuset);
+                settings->cpuset = TAKE_PTR(cpuset);
+                settings->cpuset_ncpus = (unsigned) ncpus;
+                return 0;
+        }
+
+        CPU_OR_S(CPU_ALLOC_SIZE((unsigned) ncpus), settings->cpuset, settings->cpuset, cpuset);
+
+        return 0;
+}
index 7cf5be625b56b33bc2f8c728859d58452dcb353a..c786bf8c86b66572af8cb6ce7643a9a1ef2259e8 100644 (file)
@@ -7,6 +7,7 @@
   Copyright 2015 Lennart Poettering
 ***/
 
+#include <sched.h>
 #include <stdio.h>
 
 #include "sd-id128.h"
@@ -52,9 +53,10 @@ typedef enum SettingsMask {
         SETTING_HOSTNAME          = UINT64_C(1) << 17,
         SETTING_NO_NEW_PRIVILEGES = UINT64_C(1) << 18,
         SETTING_OOM_SCORE_ADJUST  = UINT64_C(1) << 19,
-        SETTING_RLIMIT_FIRST      = UINT64_C(1) << 20, /* we define one bit per resource limit here */
-        SETTING_RLIMIT_LAST       = UINT64_C(1) << (20 + _RLIMIT_MAX - 1),
-        _SETTINGS_MASK_ALL        = (UINT64_C(1) << (20 + _RLIMIT_MAX)) - 1
+        SETTING_CPU_AFFINITY      = UINT64_C(1) << 20,
+        SETTING_RLIMIT_FIRST      = UINT64_C(1) << 21, /* we define one bit per resource limit here */
+        SETTING_RLIMIT_LAST       = UINT64_C(1) << (21 + _RLIMIT_MAX - 1),
+        _SETTINGS_MASK_ALL        = (UINT64_C(1) << (21 + _RLIMIT_MAX)) - 1
 } SettingsMask;
 
 typedef struct Settings {
@@ -81,6 +83,8 @@ typedef struct Settings {
         int no_new_privileges;
         int oom_score_adjust;
         bool oom_score_adjust_set;
+        cpu_set_t *cpuset;
+        unsigned cpuset_ncpus;
 
         /* [Image] */
         int read_only;
@@ -127,3 +131,4 @@ int config_parse_private_users(const char *unit, const char *filename, unsigned
 int config_parse_syscall_filter(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
 int config_parse_hostname(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
 int config_parse_oom_score_adjust(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+int config_parse_cpu_affinity(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
index 517c750eca61717c91648adfbb822864ce97e5d4..460f1096562fd0ef8ba30433849dbf450ca3eede 100644 (file)
@@ -43,6 +43,7 @@
 #include "capability-util.h"
 #include "cgroup-util.h"
 #include "copy.h"
+#include "cpu-set-util.h"
 #include "dev-setup.h"
 #include "dissect-image.h"
 #include "env-util.h"
@@ -207,6 +208,8 @@ static struct rlimit *arg_rlimit[_RLIMIT_MAX] = {};
 static bool arg_no_new_privileges = false;
 static int arg_oom_score_adjust = 0;
 static bool arg_oom_score_adjust_set = false;
+static cpu_set_t *arg_cpuset = NULL;
+static unsigned arg_cpuset_ncpus = 0;
 
 static void help(void) {
 
@@ -278,6 +281,7 @@ static void help(void) {
                "     --rlimit=NAME=LIMIT    Set a resource limit for the payload\n"
                "     --oom-score-adjust=VALUE\n"
                "                            Adjust the OOM score value for the payload\n"
+               "     --cpu-affinity=CPUS    Adjust the CPU affinity of the container\n"
                "     --kill-signal=SIGNAL   Select signal to use for shutting down PID 1\n"
                "     --link-journal=MODE    Link up guest journal, one of no, auto, guest, \n"
                "                            host, try-guest, try-host\n"
@@ -457,6 +461,7 @@ static int parse_argv(int argc, char *argv[]) {
                 ARG_HOSTNAME,
                 ARG_NO_NEW_PRIVILEGES,
                 ARG_OOM_SCORE_ADJUST,
+                ARG_CPU_AFFINITY,
         };
 
         static const struct option options[] = {
@@ -514,6 +519,7 @@ static int parse_argv(int argc, char *argv[]) {
                 { "system-call-filter",     required_argument, NULL, ARG_SYSTEM_CALL_FILTER     },
                 { "rlimit",                 required_argument, NULL, ARG_RLIMIT                 },
                 { "oom-score-adjust",       required_argument, NULL, ARG_OOM_SCORE_ADJUST       },
+                { "cpu-affinity",           required_argument, NULL, ARG_CPU_AFFINITY           },
                 {}
         };
 
@@ -1186,6 +1192,22 @@ static int parse_argv(int argc, char *argv[]) {
                         arg_settings_mask |= SETTING_OOM_SCORE_ADJUST;
                         break;
 
+                case ARG_CPU_AFFINITY: {
+                        _cleanup_cpu_free_ cpu_set_t *cpuset = NULL;
+
+                        r = parse_cpu_set(optarg, &cpuset);
+                        if (r < 0)
+                                return log_error_errno(r, "Failed to parse CPU affinity mask: %s", optarg);
+
+                        if (arg_cpuset)
+                                CPU_FREE(arg_cpuset);
+
+                        arg_cpuset = TAKE_PTR(cpuset);
+                        arg_cpuset_ncpus = r;
+                        arg_settings_mask |= SETTING_CPU_AFFINITY;
+                        break;
+                }
+
                 case '?':
                         return -EINVAL;
 
@@ -2476,6 +2498,10 @@ static int inner_child(
                         return log_error_errno(r, "Failed to adjust OOM score: %m");
         }
 
+        if (arg_cpuset)
+                if (sched_setaffinity(0, CPU_ALLOC_SIZE(arg_cpuset_ncpus), arg_cpuset) < 0)
+                        return log_error_errno(errno, "Failed to set CPU affinity: %m");
+
         r = drop_capabilities();
         if (r < 0)
                 return log_error_errno(r, "drop_capabilities() failed: %m");
@@ -3397,6 +3423,19 @@ static int load_settings(void) {
                 }
         }
 
+        if ((arg_settings_mask & SETTING_CPU_AFFINITY) == 0 &&
+            settings->cpuset) {
+
+                if (!arg_settings_trusted)
+                        log_warning("Ignoring CPUAffinity= setting, file '%s' is not trusted.", p);
+                else {
+                        if (arg_cpuset)
+                                CPU_FREE(arg_cpuset);
+                        arg_cpuset = TAKE_PTR(settings->cpuset);
+                        arg_cpuset_ncpus = settings->cpuset_ncpus;
+                }
+        }
+
         return 0;
 }
 
@@ -4375,6 +4414,7 @@ finish:
         expose_port_free_all(arg_expose_ports);
         free(arg_root_hash);
         rlimit_free_all(arg_rlimit);
+        arg_cpuset = cpu_set_mfree(arg_cpuset);
 
         return r < 0 ? EXIT_FAILURE : ret;
 }