1
0
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:
Yu Watanabe 2021-11-25 14:23:02 +09:00 committed by GitHub
commit c8e16339f1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 101 additions and 66 deletions

View File

@ -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
View 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
View 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;
}

View File

@ -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

View File

@ -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",

View File

@ -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);

View File

@ -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);

View File

@ -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) {

View File

@ -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;

View File

@ -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"

View File

@ -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) {

View File

@ -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