nspawn: add a new --oom-score-adjust= command line switch
authorLennart Poettering <lennart@poettering.net>
Mon, 7 May 2018 19:17:09 +0000 (21:17 +0200)
committerLennart Poettering <lennart@poettering.net>
Thu, 17 May 2018 18:48:12 +0000 (20:48 +0200)
This is primarily useful in order to provide comprehensive OCI runtime
compatibility with nspawn, but might have uses outside of it.

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 7f2b755..22bb3b7 100644 (file)
       </varlistentry>
 
       <varlistentry>
+        <term><option>--oom-score-adjust=</option></term>
+
+        <listitem><para>Changes the OOM ("Out Of Memory") score adjustment value for the container payload. This controls
+        <filename>/proc/self/oom_score_adj</filename> which influences the preference with which this container is
+        terminated when memory becomes scarce. For details see <citerefentry
+        project='man-pages'><refentrytitle>proc</refentrytitle><manvolnum>5</manvolnum></citerefentry>. Takes an
+        integer in the range -1000…1000.</para></listitem>
+      </varlistentry>
+
+      <varlistentry>
         <term><option>--kill-signal=</option></term>
 
         <listitem><para>Specify the process signal to send to the container's PID 1 when nspawn itself receives
index 436f8cd..748a633 100644 (file)
       </varlistentry>
 
       <varlistentry>
+        <term><varname>OOMScoreAdjust=</varname></term>
+
+        <listitem><para>Configures the OOM score adjustment value. This is equivalent to the
+        <option>--oom-score-adjust=</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>
 
         <listitem><para>Configures the kernel hostname set for the container. This is equivalent to the
index a375967..de00dbc 100644 (file)
@@ -51,6 +51,7 @@ Exec.LimitRTPRIO,             config_parse_rlimit,         RLIMIT_RTPRIO,     of
 Exec.LimitRTTIME,             config_parse_rlimit,         RLIMIT_RTTIME,     offsetof(Settings, rlimit)
 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
 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 11a2f41..c91ac73 100644 (file)
@@ -634,3 +634,42 @@ int config_parse_hostname(
 
         return 0;
 }
+
+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) {
+
+        Settings *settings = data;
+        int oa, r;
+
+        assert(rvalue);
+        assert(settings);
+
+        if (isempty(rvalue)) {
+                settings->oom_score_adjust_set = false;
+                return 0;
+        }
+
+        r = parse_oom_score_adjust(rvalue, &oa);
+        if (r == -ERANGE) {
+                log_syntax(unit, LOG_ERR, filename, line, r, "OOM score adjust value out of range, ignoring: %s", rvalue);
+                return 0;
+        }
+        if (r < 0) {
+                log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse the OOM score adjust value, ignoring: %s", rvalue);
+                return 0;
+        }
+
+        settings->oom_score_adjust = oa;
+        settings->oom_score_adjust_set = true;
+
+        return 0;
+}
index 130331e..7cf5be6 100644 (file)
@@ -51,9 +51,10 @@ typedef enum SettingsMask {
         SETTING_SYSCALL_FILTER    = UINT64_C(1) << 16,
         SETTING_HOSTNAME          = UINT64_C(1) << 17,
         SETTING_NO_NEW_PRIVILEGES = UINT64_C(1) << 18,
-        SETTING_RLIMIT_FIRST      = UINT64_C(1) << 19, /* we define one bit per resource limit here */
-        SETTING_RLIMIT_LAST       = UINT64_C(1) << (19 + _RLIMIT_MAX - 1),
-        _SETTINGS_MASK_ALL        = (UINT64_C(1) << (19 + _RLIMIT_MAX)) - 1
+        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
 } SettingsMask;
 
 typedef struct Settings {
@@ -78,6 +79,8 @@ typedef struct Settings {
         struct rlimit *rlimit[_RLIMIT_MAX];
         char *hostname;
         int no_new_privileges;
+        int oom_score_adjust;
+        bool oom_score_adjust_set;
 
         /* [Image] */
         int read_only;
@@ -123,3 +126,4 @@ int config_parse_pid2(const char *unit, const char *filename, unsigned line, con
 int config_parse_private_users(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_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);
index a7b35ab..21d6398 100644 (file)
@@ -204,6 +204,8 @@ static char **arg_syscall_whitelist = NULL;
 static char **arg_syscall_blacklist = NULL;
 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 void help(void) {
         printf("%s [OPTIONS...] [PATH] [ARGUMENTS...]\n\n"
@@ -270,6 +272,8 @@ static void help(void) {
                "     --system-call-filter=LIST|~LIST\n"
                "                            Permit/prohibit specific system calls\n"
                "     --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"
                "     --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"
@@ -448,6 +452,7 @@ static int parse_argv(int argc, char *argv[]) {
                 ARG_RLIMIT,
                 ARG_HOSTNAME,
                 ARG_NO_NEW_PRIVILEGES,
+                ARG_OOM_SCORE_ADJUST,
         };
 
         static const struct option options[] = {
@@ -504,6 +509,7 @@ static int parse_argv(int argc, char *argv[]) {
                 { "root-hash",              required_argument, NULL, ARG_ROOT_HASH              },
                 { "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       },
                 {}
         };
 
@@ -1167,6 +1173,15 @@ static int parse_argv(int argc, char *argv[]) {
                         break;
                 }
 
+                case ARG_OOM_SCORE_ADJUST:
+                        r = parse_oom_score_adjust(optarg, &arg_oom_score_adjust);
+                        if (r < 0)
+                                return log_error_errno(r, "Failed to parse --oom-score-adjust= parameter: %s", optarg);
+
+                        arg_oom_score_adjust_set = true;
+                        arg_settings_mask |= SETTING_OOM_SCORE_ADJUST;
+                        break;
+
                 case '?':
                         return -EINVAL;
 
@@ -2451,6 +2466,12 @@ static int inner_child(
                 rtnl_socket = safe_close(rtnl_socket);
         }
 
+        if (arg_oom_score_adjust_set) {
+                r = set_oom_score_adjust(arg_oom_score_adjust);
+                if (r < 0)
+                        return log_error_errno(r, "Failed to adjust OOM score: %m");
+        }
+
         r = drop_capabilities();
         if (r < 0)
                 return log_error_errno(r, "drop_capabilities() failed: %m");
@@ -3361,6 +3382,17 @@ static int load_settings(void) {
             settings->no_new_privileges >= 0)
                 arg_no_new_privileges = settings->no_new_privileges;
 
+        if ((arg_settings_mask & SETTING_OOM_SCORE_ADJUST) == 0 &&
+            settings->oom_score_adjust_set) {
+
+                if (!arg_settings_trusted)
+                        log_warning("Ignoring OOMScoreAdjust= setting, file '%s' is not trusted.", p);
+                else {
+                        arg_oom_score_adjust = settings->oom_score_adjust;
+                        arg_oom_score_adjust_set = true;
+                }
+        }
+
         return 0;
 }