mirror of
https://github.com/systemd/systemd-stable.git
synced 2025-02-03 13:47:04 +03:00
core: make parsing of RLIMIT_NICE aware of actual nice levels
This commit is contained in:
parent
3e7a1f50e4
commit
2985700185
@ -629,27 +629,23 @@
|
||||
<term><varname>LimitNICE=</varname></term>
|
||||
<term><varname>LimitRTPRIO=</varname></term>
|
||||
<term><varname>LimitRTTIME=</varname></term>
|
||||
<listitem><para>These settings set both soft and hard limits
|
||||
of various resources for executed processes. See
|
||||
<citerefentry><refentrytitle>setrlimit</refentrytitle><manvolnum>2</manvolnum></citerefentry>
|
||||
for details. The resource limit is possible to specify in two formats,
|
||||
<option>value</option> to set soft and hard limits to the same value,
|
||||
or <option>soft:hard</option> to set both limits individually (e.g. LimitAS=4G:16G).
|
||||
Use the string <varname>infinity</varname> to
|
||||
configure no limit on a specific resource. The multiplicative
|
||||
suffixes K (=1024), M (=1024*1024) and so on for G, T, P and E
|
||||
may be used for resource limits measured in bytes
|
||||
(e.g. LimitAS=16G). For the limits referring to time values,
|
||||
the usual time units ms, s, min, h and so on may be used (see
|
||||
<citerefentry><refentrytitle>systemd.time</refentrytitle><manvolnum>7</manvolnum></citerefentry>
|
||||
for details). Note that if no time unit is specified for
|
||||
<varname>LimitCPU=</varname> the default unit of seconds is
|
||||
implied, while for <varname>LimitRTTIME=</varname> the default
|
||||
unit of microseconds is implied. Also, note that the effective
|
||||
granularity of the limits might influence their
|
||||
enforcement. For example, time limits specified for
|
||||
<varname>LimitCPU=</varname> will be rounded up implicitly to
|
||||
multiples of 1s.</para>
|
||||
<listitem><para>Set soft and hard limits on various resources for executed processes. See
|
||||
<citerefentry><refentrytitle>setrlimit</refentrytitle><manvolnum>2</manvolnum></citerefentry> for details on
|
||||
the resource limit concept. Resource limits may be specified in two formats: either as single value to set a
|
||||
specific soft and hard limit to the same value, or as colon-separated pair <option>soft:hard</option> to set
|
||||
both limits individually (e.g. <literal>LimitAS=4G:16G</literal>). Use the string <varname>infinity</varname>
|
||||
to configure no limit on a specific resource. The multiplicative suffixes K, M, G, T, P and E (to the base
|
||||
1024) may be used for resource limits measured in bytes (e.g. LimitAS=16G). For the limits referring to time
|
||||
values, the usual time units ms, s, min, h and so on may be used (see
|
||||
<citerefentry><refentrytitle>systemd.time</refentrytitle><manvolnum>7</manvolnum></citerefentry> for
|
||||
details). Note that if no time unit is specified for <varname>LimitCPU=</varname> the default unit of seconds
|
||||
is implied, while for <varname>LimitRTTIME=</varname> the default unit of microseconds is implied. Also, note
|
||||
that the effective granularity of the limits might influence their enforcement. For example, time limits
|
||||
specified for <varname>LimitCPU=</varname> will be rounded up implicitly to multiples of 1s. For
|
||||
<varname>LimitNICE=</varname> the value may be specified in two syntaxes: if prefixed with <literal>+</literal>
|
||||
or <literal>-</literal>, the value is understood as regular Linux nice value in the range -20..19. If not
|
||||
prefixed like this the value is understood as raw resource limit parameter in the range 0..40 (with 0 being
|
||||
equivalent to 1).</para>
|
||||
|
||||
<para>Note that most process resource limits configured with
|
||||
these options are per-process, and processes may fork in order
|
||||
|
@ -153,6 +153,56 @@ static int rlimit_parse_usec(const char *val, rlim_t *ret) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rlimit_parse_nice(const char *val, rlim_t *ret) {
|
||||
uint64_t rl;
|
||||
int r;
|
||||
|
||||
/* So, Linux is weird. The range for RLIMIT_NICE is 40..1, mapping to the nice levels -20..19. However, the
|
||||
* RLIMIT_NICE limit defaults to 0 by the kernel, i.e. a value that maps to nice level 20, which of course is
|
||||
* bogus and does not exist. In order to permit parsing the RLIMIT_NICE of 0 here we hence implement a slight
|
||||
* asymmetry: when parsing as positive nice level we permit 0..19. When parsing as negative nice level, we
|
||||
* permit -20..0. But when parsing as raw resource limit value then we also allow the special value 0.
|
||||
*
|
||||
* Yeah, Linux is quality engineering sometimes... */
|
||||
|
||||
if (val[0] == '+') {
|
||||
|
||||
/* Prefixed with "+": Parse as positive user-friendly nice value */
|
||||
r = safe_atou64(val + 1, &rl);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (rl >= PRIO_MAX)
|
||||
return -ERANGE;
|
||||
|
||||
rl = 20 - rl;
|
||||
|
||||
} else if (val[0] == '-') {
|
||||
|
||||
/* Prefixed with "-": Parse as negative user-friendly nice value */
|
||||
r = safe_atou64(val + 1, &rl);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (rl > (uint64_t) (-PRIO_MIN))
|
||||
return -ERANGE;
|
||||
|
||||
rl = 20 + rl;
|
||||
} else {
|
||||
|
||||
/* Not prefixed: parse as raw resource limit value */
|
||||
r = safe_atou64(val, &rl);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (rl > (uint64_t) (20 - PRIO_MIN))
|
||||
return -ERANGE;
|
||||
}
|
||||
|
||||
*ret = (rlim_t) rl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int (*const rlimit_parse_table[_RLIMIT_MAX])(const char *val, rlim_t *ret) = {
|
||||
[RLIMIT_CPU] = rlimit_parse_sec,
|
||||
[RLIMIT_FSIZE] = rlimit_parse_size,
|
||||
@ -167,7 +217,7 @@ static int (*const rlimit_parse_table[_RLIMIT_MAX])(const char *val, rlim_t *ret
|
||||
[RLIMIT_LOCKS] = rlimit_parse_u64,
|
||||
[RLIMIT_SIGPENDING] = rlimit_parse_u64,
|
||||
[RLIMIT_MSGQUEUE] = rlimit_parse_size,
|
||||
[RLIMIT_NICE] = rlimit_parse_u64,
|
||||
[RLIMIT_NICE] = rlimit_parse_nice,
|
||||
[RLIMIT_RTPRIO] = rlimit_parse_u64,
|
||||
[RLIMIT_RTTIME] = rlimit_parse_usec,
|
||||
};
|
||||
|
@ -99,6 +99,18 @@ int main(int argc, char *argv[]) {
|
||||
test_rlimit_parse_format(RLIMIT_NOFILE, "", 0, 0, -EINVAL, NULL);
|
||||
test_rlimit_parse_format(RLIMIT_NOFILE, "5:4", 0, 0, -EILSEQ, NULL);
|
||||
test_rlimit_parse_format(RLIMIT_NOFILE, "5:4:3", 0, 0, -EINVAL, NULL);
|
||||
test_rlimit_parse_format(RLIMIT_NICE, "20", 20, 20, 0, "20");
|
||||
test_rlimit_parse_format(RLIMIT_NICE, "40", 40, 40, 0, "40");
|
||||
test_rlimit_parse_format(RLIMIT_NICE, "41", 41, 41, -ERANGE, "41");
|
||||
test_rlimit_parse_format(RLIMIT_NICE, "0", 0, 0, 0, "0");
|
||||
test_rlimit_parse_format(RLIMIT_NICE, "-7", 27, 27, 0, "27");
|
||||
test_rlimit_parse_format(RLIMIT_NICE, "-20", 40, 40, 0, "40");
|
||||
test_rlimit_parse_format(RLIMIT_NICE, "-21", 41, 41, -ERANGE, "41");
|
||||
test_rlimit_parse_format(RLIMIT_NICE, "-0", 20, 20, 0, "20");
|
||||
test_rlimit_parse_format(RLIMIT_NICE, "+7", 13, 13, 0, "13");
|
||||
test_rlimit_parse_format(RLIMIT_NICE, "+19", 1, 1, 0, "1");
|
||||
test_rlimit_parse_format(RLIMIT_NICE, "+20", 0, 0, -ERANGE, "0");
|
||||
test_rlimit_parse_format(RLIMIT_NICE, "+0", 20, 20, 0, "20");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user