mirror of
https://github.com/systemd/systemd.git
synced 2024-10-30 14:55:37 +03:00
Merge pull request #21503 from poettering/ioprio-fix
work around linux 5.15 ioprio API breakage
This commit is contained in:
commit
c8e16339f1
@ -1140,10 +1140,11 @@ CapabilityBoundingSet=~CAP_B CAP_C</programlisting>
|
||||
<varlistentry>
|
||||
<term><varname>IOSchedulingClass=</varname></term>
|
||||
|
||||
<listitem><para>Sets the I/O scheduling class for executed processes. Takes an integer between 0 and 3 or one
|
||||
of the strings <option>none</option>, <option>realtime</option>, <option>best-effort</option> or
|
||||
<option>idle</option>. If the empty string is assigned to this option, all prior assignments to both
|
||||
<varname>IOSchedulingClass=</varname> and <varname>IOSchedulingPriority=</varname> have no effect. See
|
||||
<listitem><para>Sets the I/O scheduling class for executed processes. Takes one of the strings
|
||||
<option>realtime</option>, <option>best-effort</option> or <option>idle</option>. The kernel's
|
||||
default scheduling class is <option>best-effort</option> at a priority of 4. If the empty string is
|
||||
assigned to this option, all prior assignments to both <varname>IOSchedulingClass=</varname> and
|
||||
<varname>IOSchedulingPriority=</varname> have no effect. See
|
||||
<citerefentry><refentrytitle>ioprio_set</refentrytitle><manvolnum>2</manvolnum></citerefentry> for
|
||||
details.</para></listitem>
|
||||
</varlistentry>
|
||||
@ -1156,7 +1157,8 @@ CapabilityBoundingSet=~CAP_B CAP_C</programlisting>
|
||||
bandwidth is made available to the unit's processes, larger values mean less bandwidth. The available
|
||||
priorities depend on the selected I/O scheduling class (see above). If the empty string is assigned
|
||||
to this option, all prior assignments to both <varname>IOSchedulingClass=</varname> and
|
||||
<varname>IOSchedulingPriority=</varname> have no effect. See
|
||||
<varname>IOSchedulingPriority=</varname> have no effect. For the kernel's default scheduling class
|
||||
(<option>best-effort</option>) this defaults to 4. See
|
||||
<citerefentry><refentrytitle>ioprio_set</refentrytitle><manvolnum>2</manvolnum></citerefentry> for
|
||||
details.</para></listitem>
|
||||
</varlistentry>
|
||||
|
31
src/basic/ioprio-util.c
Normal file
31
src/basic/ioprio-util.c
Normal file
@ -0,0 +1,31 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include "ioprio-util.h"
|
||||
#include "parse-util.h"
|
||||
#include "string-table.h"
|
||||
|
||||
int ioprio_parse_priority(const char *s, int *ret) {
|
||||
int i, r;
|
||||
|
||||
assert(s);
|
||||
assert(ret);
|
||||
|
||||
r = safe_atoi(s, &i);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!ioprio_priority_is_valid(i))
|
||||
return -EINVAL;
|
||||
|
||||
*ret = i;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char *const ioprio_class_table[] = {
|
||||
[IOPRIO_CLASS_NONE] = "none",
|
||||
[IOPRIO_CLASS_RT] = "realtime",
|
||||
[IOPRIO_CLASS_BE] = "best-effort",
|
||||
[IOPRIO_CLASS_IDLE] = "idle",
|
||||
};
|
||||
|
||||
DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ioprio_class, int, IOPRIO_N_CLASSES);
|
27
src/basic/ioprio-util.h
Normal file
27
src/basic/ioprio-util.h
Normal file
@ -0,0 +1,27 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
#include "macro.h"
|
||||
#include "missing_ioprio.h"
|
||||
|
||||
int ioprio_class_to_string_alloc(int i, char **s);
|
||||
int ioprio_class_from_string(const char *s);
|
||||
|
||||
static inline bool ioprio_class_is_valid(int i) {
|
||||
return IN_SET(i, IOPRIO_CLASS_NONE, IOPRIO_CLASS_RT, IOPRIO_CLASS_BE, IOPRIO_CLASS_IDLE);
|
||||
}
|
||||
|
||||
static inline bool ioprio_priority_is_valid(int i) {
|
||||
return i >= 0 && i < IOPRIO_BE_NR;
|
||||
}
|
||||
|
||||
int ioprio_parse_priority(const char *s, int *ret);
|
||||
|
||||
/* IOPRIO_CLASS_NONE with any prio value is another way to say IOPRIO_CLASS_BE with level 4. Encode that in a
|
||||
* proper macro. */
|
||||
#define IOPRIO_DEFAULT_CLASS_AND_PRIO ioprio_prio_value(IOPRIO_CLASS_BE, 4)
|
||||
|
||||
static inline int ioprio_normalize(int v) {
|
||||
/* Converts IOPRIO_CLASS_NONE to what it actually means */
|
||||
return ioprio_prio_class(v) == IOPRIO_CLASS_NONE ? IOPRIO_DEFAULT_CLASS_AND_PRIO : v;
|
||||
}
|
@ -82,6 +82,8 @@ basic_sources = files('''
|
||||
inotify-util.h
|
||||
io-util.c
|
||||
io-util.h
|
||||
ioprio-util.c
|
||||
ioprio-util.h
|
||||
limits-util.c
|
||||
limits-util.h
|
||||
linux/btrfs.h
|
||||
|
@ -1132,23 +1132,6 @@ int pid_compare_func(const pid_t *a, const pid_t *b) {
|
||||
return CMP(*a, *b);
|
||||
}
|
||||
|
||||
int ioprio_parse_priority(const char *s, int *ret) {
|
||||
int i, r;
|
||||
|
||||
assert(s);
|
||||
assert(ret);
|
||||
|
||||
r = safe_atoi(s, &i);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!ioprio_priority_is_valid(i))
|
||||
return -EINVAL;
|
||||
|
||||
*ret = i;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* The cached PID, possible values:
|
||||
*
|
||||
* == UNSET [0] → cache not initialized yet
|
||||
@ -1627,14 +1610,6 @@ _noreturn_ void freeze(void) {
|
||||
pause();
|
||||
}
|
||||
|
||||
static const char *const ioprio_class_table[] = {
|
||||
[IOPRIO_CLASS_NONE] = "none",
|
||||
[IOPRIO_CLASS_RT] = "realtime",
|
||||
[IOPRIO_CLASS_BE] = "best-effort",
|
||||
[IOPRIO_CLASS_IDLE] = "idle",
|
||||
};
|
||||
|
||||
DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ioprio_class, int, IOPRIO_N_CLASSES);
|
||||
|
||||
static const char *const sigchld_code_table[] = {
|
||||
[CLD_EXITED] = "exited",
|
||||
|
@ -14,7 +14,6 @@
|
||||
#include "alloc-util.h"
|
||||
#include "format-util.h"
|
||||
#include "macro.h"
|
||||
#include "missing_ioprio.h"
|
||||
#include "time-util.h"
|
||||
|
||||
#define procfs_file_alloca(pid, field) \
|
||||
@ -97,9 +96,6 @@ const char *personality_to_string(unsigned long);
|
||||
int safe_personality(unsigned long p);
|
||||
int opinionated_personality(unsigned long *ret);
|
||||
|
||||
int ioprio_class_to_string_alloc(int i, char **s);
|
||||
int ioprio_class_from_string(const char *s);
|
||||
|
||||
const char *sigchld_code_to_string(int i) _const_;
|
||||
int sigchld_code_from_string(const char *s) _pure_;
|
||||
|
||||
@ -130,20 +126,10 @@ static inline bool sched_priority_is_valid(int i) {
|
||||
return i >= 0 && i <= sched_get_priority_max(SCHED_RR);
|
||||
}
|
||||
|
||||
static inline bool ioprio_class_is_valid(int i) {
|
||||
return IN_SET(i, IOPRIO_CLASS_NONE, IOPRIO_CLASS_RT, IOPRIO_CLASS_BE, IOPRIO_CLASS_IDLE);
|
||||
}
|
||||
|
||||
static inline bool ioprio_priority_is_valid(int i) {
|
||||
return i >= 0 && i < IOPRIO_BE_NR;
|
||||
}
|
||||
|
||||
static inline bool pid_is_valid(pid_t p) {
|
||||
return p > 0;
|
||||
}
|
||||
|
||||
int ioprio_parse_priority(const char *s, int *ret);
|
||||
|
||||
pid_t getpid_cached(void);
|
||||
void reset_cached_pid(void);
|
||||
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "fileio.h"
|
||||
#include "hexdecoct.h"
|
||||
#include "io-util.h"
|
||||
#include "ioprio-util.h"
|
||||
#include "journal-file.h"
|
||||
#include "missing_ioprio.h"
|
||||
#include "mountpoint-util.h"
|
||||
@ -2810,7 +2811,7 @@ int bus_exec_context_set_transient_property(
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
c->ioprio = ioprio_prio_value(q, ioprio_prio_data(c->ioprio));
|
||||
c->ioprio = ioprio_normalize(ioprio_prio_value(q, ioprio_prio_data(c->ioprio)));
|
||||
c->ioprio_set = true;
|
||||
|
||||
unit_write_settingf(u, flags, name, "IOSchedulingClass=%s", s);
|
||||
@ -2829,7 +2830,7 @@ int bus_exec_context_set_transient_property(
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid IO scheduling priority: %i", p);
|
||||
|
||||
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
|
||||
c->ioprio = ioprio_prio_value(ioprio_prio_class(c->ioprio), p);
|
||||
c->ioprio = ioprio_normalize(ioprio_prio_value(ioprio_prio_class(c->ioprio), p));
|
||||
c->ioprio_set = true;
|
||||
|
||||
unit_write_settingf(u, flags, name, "IOSchedulingPriority=%i", p);
|
||||
|
@ -63,6 +63,7 @@
|
||||
#include "glob-util.h"
|
||||
#include "hexdecoct.h"
|
||||
#include "io-util.h"
|
||||
#include "ioprio-util.h"
|
||||
#include "label.h"
|
||||
#include "log.h"
|
||||
#include "macro.h"
|
||||
@ -5068,7 +5069,7 @@ void exec_context_init(ExecContext *c) {
|
||||
assert(c);
|
||||
|
||||
c->umask = 0022;
|
||||
c->ioprio = ioprio_prio_value(IOPRIO_CLASS_BE, 0);
|
||||
c->ioprio = IOPRIO_DEFAULT_CLASS_AND_PRIO;
|
||||
c->cpu_sched_policy = SCHED_OTHER;
|
||||
c->syslog_priority = LOG_DAEMON|LOG_INFO;
|
||||
c->syslog_level_prefix = true;
|
||||
@ -6020,9 +6021,9 @@ int exec_context_get_effective_ioprio(const ExecContext *c) {
|
||||
|
||||
p = ioprio_get(IOPRIO_WHO_PROCESS, 0);
|
||||
if (p < 0)
|
||||
return ioprio_prio_value(IOPRIO_CLASS_BE, 4);
|
||||
return IOPRIO_DEFAULT_CLASS_AND_PRIO;
|
||||
|
||||
return p;
|
||||
return ioprio_normalize(p);
|
||||
}
|
||||
|
||||
bool exec_context_get_effective_mount_apivfs(const ExecContext *c) {
|
||||
|
@ -40,6 +40,7 @@
|
||||
#include "fs-util.h"
|
||||
#include "hexdecoct.h"
|
||||
#include "io-util.h"
|
||||
#include "ioprio-util.h"
|
||||
#include "ip-protocol-list.h"
|
||||
#include "journal-file.h"
|
||||
#include "limits-util.h"
|
||||
@ -1416,7 +1417,7 @@ int config_parse_exec_io_class(const char *unit,
|
||||
|
||||
if (isempty(rvalue)) {
|
||||
c->ioprio_set = false;
|
||||
c->ioprio = ioprio_prio_value(IOPRIO_CLASS_BE, 0);
|
||||
c->ioprio = IOPRIO_DEFAULT_CLASS_AND_PRIO;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1426,7 +1427,7 @@ int config_parse_exec_io_class(const char *unit,
|
||||
return 0;
|
||||
}
|
||||
|
||||
c->ioprio = ioprio_prio_value(x, ioprio_prio_data(c->ioprio));
|
||||
c->ioprio = ioprio_normalize(ioprio_prio_value(x, ioprio_prio_data(c->ioprio)));
|
||||
c->ioprio_set = true;
|
||||
|
||||
return 0;
|
||||
@ -1453,7 +1454,7 @@ int config_parse_exec_io_priority(const char *unit,
|
||||
|
||||
if (isempty(rvalue)) {
|
||||
c->ioprio_set = false;
|
||||
c->ioprio = ioprio_prio_value(IOPRIO_CLASS_BE, 0);
|
||||
c->ioprio = IOPRIO_DEFAULT_CLASS_AND_PRIO;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1463,7 +1464,7 @@ int config_parse_exec_io_priority(const char *unit,
|
||||
return 0;
|
||||
}
|
||||
|
||||
c->ioprio = ioprio_prio_value(ioprio_prio_class(c->ioprio), i);
|
||||
c->ioprio = ioprio_normalize(ioprio_prio_value(ioprio_prio_class(c->ioprio), i));
|
||||
c->ioprio_set = true;
|
||||
|
||||
return 0;
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "hexdecoct.h"
|
||||
#include "hostname-util.h"
|
||||
#include "in-addr-util.h"
|
||||
#include "ioprio-util.h"
|
||||
#include "ip-protocol-list.h"
|
||||
#include "libmount-util.h"
|
||||
#include "locale-util.h"
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "errno-list.h"
|
||||
#include "errno-util.h"
|
||||
#include "fd-util.h"
|
||||
#include "ioprio-util.h"
|
||||
#include "log.h"
|
||||
#include "macro.h"
|
||||
#include "missing_sched.h"
|
||||
@ -725,32 +726,38 @@ static void test_pid_to_ptr(void) {
|
||||
assert_se(PTR_TO_PID(PID_TO_PTR(INT32_MIN)) == INT32_MIN);
|
||||
}
|
||||
|
||||
static void test_ioprio_class_from_to_string_one(const char *val, int expected) {
|
||||
static void test_ioprio_class_from_to_string_one(const char *val, int expected, int normalized) {
|
||||
assert_se(ioprio_class_from_string(val) == expected);
|
||||
if (expected >= 0) {
|
||||
_cleanup_free_ char *s = NULL;
|
||||
unsigned ret;
|
||||
int combined;
|
||||
|
||||
assert_se(ioprio_class_to_string_alloc(expected, &s) == 0);
|
||||
/* We sometimes get a class number and sometimes a number back */
|
||||
/* We sometimes get a class number and sometimes a name back */
|
||||
assert_se(streq(s, val) ||
|
||||
safe_atou(val, &ret) == 0);
|
||||
|
||||
/* Make sure normalization works, i.e. NONE → BE gets normalized */
|
||||
combined = ioprio_normalize(ioprio_prio_value(expected, 0));
|
||||
assert_se(ioprio_prio_class(combined) == normalized);
|
||||
assert_se(expected != IOPRIO_CLASS_NONE || ioprio_prio_data(combined) == 4);
|
||||
}
|
||||
}
|
||||
|
||||
static void test_ioprio_class_from_to_string(void) {
|
||||
log_info("/* %s */", __func__);
|
||||
|
||||
test_ioprio_class_from_to_string_one("none", IOPRIO_CLASS_NONE);
|
||||
test_ioprio_class_from_to_string_one("realtime", IOPRIO_CLASS_RT);
|
||||
test_ioprio_class_from_to_string_one("best-effort", IOPRIO_CLASS_BE);
|
||||
test_ioprio_class_from_to_string_one("idle", IOPRIO_CLASS_IDLE);
|
||||
test_ioprio_class_from_to_string_one("0", 0);
|
||||
test_ioprio_class_from_to_string_one("1", 1);
|
||||
test_ioprio_class_from_to_string_one("7", 7);
|
||||
test_ioprio_class_from_to_string_one("8", 8);
|
||||
test_ioprio_class_from_to_string_one("9", -EINVAL);
|
||||
test_ioprio_class_from_to_string_one("-1", -EINVAL);
|
||||
test_ioprio_class_from_to_string_one("none", IOPRIO_CLASS_NONE, IOPRIO_CLASS_BE);
|
||||
test_ioprio_class_from_to_string_one("realtime", IOPRIO_CLASS_RT, IOPRIO_CLASS_RT);
|
||||
test_ioprio_class_from_to_string_one("best-effort", IOPRIO_CLASS_BE, IOPRIO_CLASS_BE);
|
||||
test_ioprio_class_from_to_string_one("idle", IOPRIO_CLASS_IDLE, IOPRIO_CLASS_IDLE);
|
||||
test_ioprio_class_from_to_string_one("0", IOPRIO_CLASS_NONE, IOPRIO_CLASS_BE);
|
||||
test_ioprio_class_from_to_string_one("1", 1, 1);
|
||||
test_ioprio_class_from_to_string_one("7", 7, 7);
|
||||
test_ioprio_class_from_to_string_one("8", 8, 8);
|
||||
test_ioprio_class_from_to_string_one("9", -EINVAL, -EINVAL);
|
||||
test_ioprio_class_from_to_string_one("-1", -EINVAL, -EINVAL);
|
||||
}
|
||||
|
||||
static void test_setpriority_closest(void) {
|
||||
|
@ -3,6 +3,7 @@
|
||||
Description=Test for IOSchedulingClass=none
|
||||
|
||||
[Service]
|
||||
ExecStart=/bin/sh -x -c 'c=$$(LC_ALL=C ionice); test "$${c%%:*}" = "none"'
|
||||
# Old kernels might report "none" here, new kernels "best-effort".
|
||||
ExecStart=/bin/sh -x -c 'c=$$(LC_ALL=C ionice); test "$${c%%:*}" = "none" -o "$${c%%:*}" = "best-effort"'
|
||||
Type=oneshot
|
||||
IOSchedulingClass=none
|
||||
|
Loading…
Reference in New Issue
Block a user