backport: sync patches from systemd community; Fix compilation failure with - O0 option
(cherry picked from commit 112d69b7c80bafc341b94dbc98d8efd8c288f7a3)
This commit is contained in:
parent
186cf19a70
commit
5304d4b4cc
128
backport-core-Add-trigger-limit-for-path-units.patch
Normal file
128
backport-core-Add-trigger-limit-for-path-units.patch
Normal file
@ -0,0 +1,128 @@
|
||||
From aaae822b37aa3ca39aebb516fdc6bef36d730c25 Mon Sep 17 00:00:00 2001
|
||||
From: Daan De Meyer <daan.j.demeyer@gmail.com>
|
||||
Date: Fri, 17 Dec 2021 20:01:31 +0100
|
||||
Subject: [PATCH] core: Add trigger limit for path units
|
||||
|
||||
When conditions fail on a service unit, a path unit can cause
|
||||
PID 1 to busy loop as it keeps trying to activate the service unit.
|
||||
To avoid this from happening, add a trigger limit to the path unit,
|
||||
identical to the trigger limit we have for socket units.
|
||||
|
||||
Initially, let's start with a high limit and not make it configurable.
|
||||
If needed, we can add properties to configure the rate limit similar
|
||||
to the ones we have for socket units.
|
||||
|
||||
Conflict:code context adaptation
|
||||
Reference:https://github.com/systemd/systemd-stable/commit/aaae822b37aa3ca39aebb516fdc6bef36d730c25
|
||||
---
|
||||
src/core/path.c | 10 ++++++++++
|
||||
src/core/path.h | 3 +++
|
||||
test/testsuite-63.units/test63.service | 2 +-
|
||||
test/units/testsuite-63.service | 21 +++++++++++++++++----
|
||||
4 files changed, 31 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/src/core/path.c b/src/core/path.c
|
||||
index 1b0f115dd8..f89e35a001 100644
|
||||
--- a/src/core/path.c
|
||||
+++ b/src/core/path.c
|
||||
@@ -265,6 +265,9 @@ static void path_init(Unit *u) {
|
||||
assert(u->load_state == UNIT_STUB);
|
||||
|
||||
p->directory_mode = 0755;
|
||||
+
|
||||
+ p->trigger_limit.interval = 2 * USEC_PER_SEC;
|
||||
+ p->trigger_limit.burst = 200;
|
||||
}
|
||||
|
||||
void path_free_specs(Path *p) {
|
||||
@@ -494,6 +497,12 @@ static void path_enter_running(Path *p) {
|
||||
if (unit_stop_pending(UNIT(p)))
|
||||
return;
|
||||
|
||||
+ if (!ratelimit_below(&p->trigger_limit)) {
|
||||
+ log_unit_warning(UNIT(p), "Trigger limit hit, refusing further activation.");
|
||||
+ path_enter_dead(p, PATH_FAILURE_TRIGGER_LIMIT_HIT);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
trigger = UNIT_TRIGGER(UNIT(p));
|
||||
if (!trigger) {
|
||||
log_unit_error(UNIT(p), "Unit to trigger vanished.");
|
||||
@@ -836,6 +845,7 @@ static const char* const path_result_table[_PATH_RESULT_MAX] = {
|
||||
[PATH_FAILURE_RESOURCES] = "resources",
|
||||
[PATH_FAILURE_START_LIMIT_HIT] = "start-limit-hit",
|
||||
[PATH_FAILURE_UNIT_START_LIMIT_HIT] = "unit-start-limit-hit",
|
||||
+ [PATH_FAILURE_TRIGGER_LIMIT_HIT] = "trigger-limit-hit",
|
||||
};
|
||||
|
||||
DEFINE_STRING_TABLE_LOOKUP(path_result, PathResult);
|
||||
diff --git a/src/core/path.h b/src/core/path.h
|
||||
index 66ae857dc4..d835c24166 100644
|
||||
--- a/src/core/path.h
|
||||
+++ b/src/core/path.h
|
||||
@@ -46,6 +46,7 @@ typedef enum PathResult {
|
||||
PATH_FAILURE_RESOURCES,
|
||||
PATH_FAILURE_START_LIMIT_HIT,
|
||||
PATH_FAILURE_UNIT_START_LIMIT_HIT,
|
||||
+ PATH_FAILURE_TRIGGER_LIMIT_HIT,
|
||||
_PATH_RESULT_MAX,
|
||||
_PATH_RESULT_INVALID = -EINVAL,
|
||||
} PathResult;
|
||||
@@ -61,6 +62,8 @@ struct Path {
|
||||
mode_t directory_mode;
|
||||
|
||||
PathResult result;
|
||||
+
|
||||
+ RateLimit trigger_limit;
|
||||
};
|
||||
|
||||
void path_free_specs(Path *p);
|
||||
diff --git a/test/testsuite-63.units/test63.service b/test/testsuite-63.units/test63.service
|
||||
index c838018..6292434 100644
|
||||
--- a/test/testsuite-63.units/test63.service
|
||||
+++ b/test/testsuite-63.units/test63.service
|
||||
@@ -1,5 +1,5 @@
|
||||
[Unit]
|
||||
-ConditionPathExists=!/tmp/nonexistent
|
||||
+ConditionPathExists=/tmp/nonexistent
|
||||
|
||||
[Service]
|
||||
ExecStart=true
|
||||
diff --git a/test/units/testsuite-63.service b/test/units/testsuite-63.service
|
||||
index 0a8d143be9..40422127ff 100644
|
||||
--- a/test/units/testsuite-63.service
|
||||
+++ b/test/units/testsuite-63.service
|
||||
@@ -5,13 +5,26 @@ Description=TEST-63-ISSUE-17433
|
||||
[Service]
|
||||
ExecStartPre=rm -f /failed /testok
|
||||
Type=oneshot
|
||||
+
|
||||
+# Test that a path unit continuously triggering a service that fails condition checks eventually fails with
|
||||
+# the trigger-limit-hit error.
|
||||
ExecStart=rm -f /tmp/nonexistent
|
||||
ExecStart=systemctl start test63.path
|
||||
ExecStart=touch /tmp/test63
|
||||
-# Make sure systemd has sufficient time to hit the start limit for test63.service.
|
||||
+# Make sure systemd has sufficient time to hit the trigger limit for test63.path.
|
||||
ExecStart=sleep 2
|
||||
-ExecStart=sh -x -c 'test "$(systemctl show test63.service -P ActiveState)" = failed'
|
||||
-ExecStart=sh -x -c 'test "$(systemctl show test63.service -P Result)" = start-limit-hit'
|
||||
+ExecStart=sh -x -c 'test "$(systemctl show test63.service -P ActiveState)" = inactive'
|
||||
+ExecStart=sh -x -c 'test "$(systemctl show test63.service -P Result)" = success'
|
||||
ExecStart=sh -x -c 'test "$(systemctl show test63.path -P ActiveState)" = failed'
|
||||
-ExecStart=sh -x -c 'test "$(systemctl show test63.path -P Result)" = unit-start-limit-hit'
|
||||
+ExecStart=sh -x -c 'test "$(systemctl show test63.path -P Result)" = trigger-limit-hit'
|
||||
+
|
||||
+# Test that starting the service manually doesn't affect the path unit.
|
||||
+ExecStart=rm -f /tmp/test63
|
||||
+ExecStart=systemctl reset-failed
|
||||
+ExecStart=systemctl start test63.path
|
||||
+ExecStart=systemctl start test63.service
|
||||
+ExecStart=sh -x -c 'test "$(systemctl show test63.service -P ActiveState)" = inactive'
|
||||
+ExecStart=sh -x -c 'test "$(systemctl show test63.service -P Result)" = success'
|
||||
+ExecStart=sh -x -c 'test "$(systemctl show test63.path -P ActiveState)" = active'
|
||||
+ExecStart=sh -x -c 'test "$(systemctl show test63.path -P Result)" = success'
|
||||
ExecStart=sh -x -c 'echo OK >/testok'
|
||||
--
|
||||
2.33.0
|
||||
|
||||
493
backport-core-Check-unit-start-rate-limiting-earlier.patch
Normal file
493
backport-core-Check-unit-start-rate-limiting-earlier.patch
Normal file
@ -0,0 +1,493 @@
|
||||
From 9727f2427ff6b2e1f4ab927cc57ad8e888f04e95 Mon Sep 17 00:00:00 2001
|
||||
From: Daan De Meyer <daan.j.demeyer@gmail.com>
|
||||
Date: Tue, 24 Aug 2021 16:46:47 +0100
|
||||
Subject: [PATCH] core: Check unit start rate limiting earlier
|
||||
|
||||
Fixes #17433. Currently, if any of the validations we do before we
|
||||
check start rate limiting fail, we can still enter a busy loop as
|
||||
no rate limiting gets applied. A common occurence of this scenario
|
||||
is path units triggering a service that fails a condition check.
|
||||
|
||||
To fix the issue, we simply move up start rate limiting checks to
|
||||
be the first thing we do when starting a unit. To achieve this,
|
||||
we add a new method to the unit vtable and implement it for the
|
||||
relevant unit types so that we can do the start rate limit checks
|
||||
earlier on.
|
||||
|
||||
Conflict:code context adaptation
|
||||
Reference:https://github.com/systemd/systemd-stable/commit/9727f2427ff6b2e1f4ab927cc57ad8e888f04e95
|
||||
---
|
||||
src/core/automount.c | 23 +++++++++++++++++------
|
||||
src/core/mount.c | 23 +++++++++++++++++------
|
||||
src/core/path.c | 23 +++++++++++++++++------
|
||||
src/core/service.c | 25 ++++++++++++++++++-------
|
||||
src/core/socket.c | 23 +++++++++++++++++------
|
||||
src/core/swap.c | 23 +++++++++++++++++------
|
||||
src/core/timer.c | 23 +++++++++++++++++------
|
||||
src/core/unit.c | 7 +++++++
|
||||
src/core/unit.h | 4 ++++
|
||||
test/TEST-63-ISSUE-17433/Makefile | 1 +
|
||||
test/TEST-63-ISSUE-17433/test.sh | 9 +++++++++
|
||||
test/meson.build | 2 ++
|
||||
test/testsuite-10.units/test10.service | 3 +++
|
||||
test/testsuite-63.units/test63.path | 2 ++
|
||||
test/testsuite-63.units/test63.service | 5 +++++
|
||||
test/units/testsuite-63.service | 16 ++++++++++++++++
|
||||
16 files changed, 169 insertions(+), 43 deletions(-)
|
||||
create mode 120000 test/TEST-63-ISSUE-17433/Makefile
|
||||
create mode 100755 test/TEST-63-ISSUE-17433/test.sh
|
||||
create mode 100644 test/testsuite-63.units/test63.path
|
||||
create mode 100644 test/testsuite-63.units/test63.service
|
||||
create mode 100644 test/units/testsuite-63.service
|
||||
|
||||
diff --git a/src/core/automount.c b/src/core/automount.c
|
||||
index 30226b9bde..11eb352b9b 100644
|
||||
--- a/src/core/automount.c
|
||||
+++ b/src/core/automount.c
|
||||
@@ -813,12 +813,6 @@ static int automount_start(Unit *u) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
- r = unit_test_start_limit(u);
|
||||
- if (r < 0) {
|
||||
- automount_enter_dead(a, AUTOMOUNT_FAILURE_START_LIMIT_HIT);
|
||||
- return r;
|
||||
- }
|
||||
-
|
||||
r = unit_acquire_invocation_id(u);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@@ -1064,6 +1058,21 @@ static bool automount_supported(void) {
|
||||
return supported;
|
||||
}
|
||||
|
||||
+static int automount_test_start_limit(Unit *u) {
|
||||
+ Automount *a = AUTOMOUNT(u);
|
||||
+ int r;
|
||||
+
|
||||
+ assert(a);
|
||||
+
|
||||
+ r = unit_test_start_limit(u);
|
||||
+ if (r < 0) {
|
||||
+ automount_enter_dead(a, AUTOMOUNT_FAILURE_START_LIMIT_HIT);
|
||||
+ return r;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static const char* const automount_result_table[_AUTOMOUNT_RESULT_MAX] = {
|
||||
[AUTOMOUNT_SUCCESS] = "success",
|
||||
[AUTOMOUNT_FAILURE_RESOURCES] = "resources",
|
||||
@@ -1126,4 +1135,6 @@ const UnitVTable automount_vtable = {
|
||||
[JOB_FAILED] = "Failed to unset automount %s.",
|
||||
},
|
||||
},
|
||||
+
|
||||
+ .test_start_limit = automount_test_start_limit,
|
||||
};
|
||||
diff --git a/src/core/mount.c b/src/core/mount.c
|
||||
index fb8f72e257..35b56426d4 100644
|
||||
--- a/src/core/mount.c
|
||||
+++ b/src/core/mount.c
|
||||
@@ -1167,12 +1167,6 @@ static int mount_start(Unit *u) {
|
||||
|
||||
assert(IN_SET(m->state, MOUNT_DEAD, MOUNT_FAILED));
|
||||
|
||||
- r = unit_test_start_limit(u);
|
||||
- if (r < 0) {
|
||||
- mount_enter_dead(m, MOUNT_FAILURE_START_LIMIT_HIT);
|
||||
- return r;
|
||||
- }
|
||||
-
|
||||
r = unit_acquire_invocation_id(u);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@@ -2138,6 +2132,21 @@ static int mount_can_clean(Unit *u, ExecCleanMask *ret) {
|
||||
return exec_context_get_clean_mask(&m->exec_context, ret);
|
||||
}
|
||||
|
||||
+static int mount_test_start_limit(Unit *u) {
|
||||
+ Mount *m = MOUNT(u);
|
||||
+ int r;
|
||||
+
|
||||
+ assert(m);
|
||||
+
|
||||
+ r = unit_test_start_limit(u);
|
||||
+ if (r < 0) {
|
||||
+ mount_enter_dead(m, MOUNT_FAILURE_START_LIMIT_HIT);
|
||||
+ return r;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static const char* const mount_exec_command_table[_MOUNT_EXEC_COMMAND_MAX] = {
|
||||
[MOUNT_EXEC_MOUNT] = "ExecMount",
|
||||
[MOUNT_EXEC_UNMOUNT] = "ExecUnmount",
|
||||
@@ -2235,4 +2244,6 @@ const UnitVTable mount_vtable = {
|
||||
[JOB_TIMEOUT] = "Timed out unmounting %s.",
|
||||
},
|
||||
},
|
||||
+
|
||||
+ .test_start_limit = mount_test_start_limit,
|
||||
};
|
||||
diff --git a/src/core/path.c b/src/core/path.c
|
||||
index 800524a308..693636b0ee 100644
|
||||
--- a/src/core/path.c
|
||||
+++ b/src/core/path.c
|
||||
@@ -590,12 +590,6 @@ static int path_start(Unit *u) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
- r = unit_test_start_limit(u);
|
||||
- if (r < 0) {
|
||||
- path_enter_dead(p, PATH_FAILURE_START_LIMIT_HIT);
|
||||
- return r;
|
||||
- }
|
||||
-
|
||||
r = unit_acquire_invocation_id(u);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@@ -812,6 +806,21 @@ static void path_reset_failed(Unit *u) {
|
||||
p->result = PATH_SUCCESS;
|
||||
}
|
||||
|
||||
+static int path_test_start_limit(Unit *u) {
|
||||
+ Path *p = PATH(u);
|
||||
+ int r;
|
||||
+
|
||||
+ assert(p);
|
||||
+
|
||||
+ r = unit_test_start_limit(u);
|
||||
+ if (r < 0) {
|
||||
+ path_enter_dead(p, PATH_FAILURE_START_LIMIT_HIT);
|
||||
+ return r;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static const char* const path_type_table[_PATH_TYPE_MAX] = {
|
||||
[PATH_EXISTS] = "PathExists",
|
||||
[PATH_EXISTS_GLOB] = "PathExistsGlob",
|
||||
@@ -866,4 +875,6 @@ const UnitVTable path_vtable = {
|
||||
.reset_failed = path_reset_failed,
|
||||
|
||||
.bus_set_property = bus_path_set_property,
|
||||
+
|
||||
+ .test_start_limit = path_test_start_limit,
|
||||
};
|
||||
diff --git a/src/core/service.c b/src/core/service.c
|
||||
index c55304d170..9d8eef1f74 100644
|
||||
--- a/src/core/service.c
|
||||
+++ b/src/core/service.c
|
||||
@@ -2436,13 +2436,6 @@ static int service_start(Unit *u) {
|
||||
|
||||
assert(IN_SET(s->state, SERVICE_DEAD, SERVICE_FAILED));
|
||||
|
||||
- /* Make sure we don't enter a busy loop of some kind. */
|
||||
- r = unit_test_start_limit(u);
|
||||
- if (r < 0) {
|
||||
- service_enter_dead(s, SERVICE_FAILURE_START_LIMIT_HIT, false);
|
||||
- return r;
|
||||
- }
|
||||
-
|
||||
r = unit_acquire_invocation_id(u);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@@ -4445,6 +4438,22 @@ static const char *service_finished_job(Unit *u, JobType t, JobResult result) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
+static int service_test_start_limit(Unit *u) {
|
||||
+ Service *s = SERVICE(u);
|
||||
+ int r;
|
||||
+
|
||||
+ assert(s);
|
||||
+
|
||||
+ /* Make sure we don't enter a busy loop of some kind. */
|
||||
+ r = unit_test_start_limit(u);
|
||||
+ if (r < 0) {
|
||||
+ service_enter_dead(s, SERVICE_FAILURE_START_LIMIT_HIT, false);
|
||||
+ return r;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static const char* const service_restart_table[_SERVICE_RESTART_MAX] = {
|
||||
[SERVICE_RESTART_NO] = "no",
|
||||
[SERVICE_RESTART_ON_SUCCESS] = "on-success",
|
||||
@@ -4608,4 +4617,6 @@ const UnitVTable service_vtable = {
|
||||
},
|
||||
.finished_job = service_finished_job,
|
||||
},
|
||||
+
|
||||
+ .test_start_limit = service_test_start_limit,
|
||||
};
|
||||
diff --git a/src/core/socket.c b/src/core/socket.c
|
||||
index ceaf39bdd3..177068eed4 100644
|
||||
--- a/src/core/socket.c
|
||||
+++ b/src/core/socket.c
|
||||
@@ -2513,12 +2513,6 @@ static int socket_start(Unit *u) {
|
||||
|
||||
assert(IN_SET(s->state, SOCKET_DEAD, SOCKET_FAILED));
|
||||
|
||||
- r = unit_test_start_limit(u);
|
||||
- if (r < 0) {
|
||||
- socket_enter_dead(s, SOCKET_FAILURE_START_LIMIT_HIT);
|
||||
- return r;
|
||||
- }
|
||||
-
|
||||
r = unit_acquire_invocation_id(u);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@@ -3425,6 +3419,21 @@ static int socket_can_clean(Unit *u, ExecCleanMask *ret) {
|
||||
return exec_context_get_clean_mask(&s->exec_context, ret);
|
||||
}
|
||||
|
||||
+static int socket_test_start_limit(Unit *u) {
|
||||
+ Socket *s = SOCKET(u);
|
||||
+ int r;
|
||||
+
|
||||
+ assert(s);
|
||||
+
|
||||
+ r = unit_test_start_limit(u);
|
||||
+ if (r < 0) {
|
||||
+ socket_enter_dead(s, SOCKET_FAILURE_START_LIMIT_HIT);
|
||||
+ return r;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static const char* const socket_exec_command_table[_SOCKET_EXEC_COMMAND_MAX] = {
|
||||
[SOCKET_EXEC_START_PRE] = "ExecStartPre",
|
||||
[SOCKET_EXEC_START_CHOWN] = "ExecStartChown",
|
||||
@@ -3551,4 +3560,6 @@ const UnitVTable socket_vtable = {
|
||||
[JOB_TIMEOUT] = "Timed out stopping %s.",
|
||||
},
|
||||
},
|
||||
+
|
||||
+ .test_start_limit = socket_test_start_limit,
|
||||
};
|
||||
diff --git a/src/core/swap.c b/src/core/swap.c
|
||||
index 48ba5c7664..29c63118ac 100644
|
||||
--- a/src/core/swap.c
|
||||
+++ b/src/core/swap.c
|
||||
@@ -932,12 +932,6 @@ static int swap_start(Unit *u) {
|
||||
if (UNIT(other)->job && UNIT(other)->job->state == JOB_RUNNING)
|
||||
return -EAGAIN;
|
||||
|
||||
- r = unit_test_start_limit(u);
|
||||
- if (r < 0) {
|
||||
- swap_enter_dead(s, SWAP_FAILURE_START_LIMIT_HIT);
|
||||
- return r;
|
||||
- }
|
||||
-
|
||||
r = unit_acquire_invocation_id(u);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@@ -1588,6 +1582,21 @@ static int swap_can_clean(Unit *u, ExecCleanMask *ret) {
|
||||
return exec_context_get_clean_mask(&s->exec_context, ret);
|
||||
}
|
||||
|
||||
+static int swap_test_start_limit(Unit *u) {
|
||||
+ Swap *s = SWAP(u);
|
||||
+ int r;
|
||||
+
|
||||
+ assert(s);
|
||||
+
|
||||
+ r = unit_test_start_limit(u);
|
||||
+ if (r < 0) {
|
||||
+ swap_enter_dead(s, SWAP_FAILURE_START_LIMIT_HIT);
|
||||
+ return r;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static const char* const swap_exec_command_table[_SWAP_EXEC_COMMAND_MAX] = {
|
||||
[SWAP_EXEC_ACTIVATE] = "ExecActivate",
|
||||
[SWAP_EXEC_DEACTIVATE] = "ExecDeactivate",
|
||||
@@ -1683,4 +1692,6 @@ const UnitVTable swap_vtable = {
|
||||
[JOB_TIMEOUT] = "Timed out deactivating swap %s.",
|
||||
},
|
||||
},
|
||||
+
|
||||
+ .test_start_limit = swap_test_start_limit,
|
||||
};
|
||||
diff --git a/src/core/timer.c b/src/core/timer.c
|
||||
index 12515a6a75..8853121c00 100644
|
||||
--- a/src/core/timer.c
|
||||
+++ b/src/core/timer.c
|
||||
@@ -627,12 +627,6 @@ static int timer_start(Unit *u) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
- r = unit_test_start_limit(u);
|
||||
- if (r < 0) {
|
||||
- timer_enter_dead(t, TIMER_FAILURE_START_LIMIT_HIT);
|
||||
- return r;
|
||||
- }
|
||||
-
|
||||
r = unit_acquire_invocation_id(u);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@@ -890,6 +884,21 @@ static int timer_can_clean(Unit *u, ExecCleanMask *ret) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static int timer_test_start_limit(Unit *u) {
|
||||
+ Timer *t = TIMER(u);
|
||||
+ int r;
|
||||
+
|
||||
+ assert(t);
|
||||
+
|
||||
+ r = unit_test_start_limit(u);
|
||||
+ if (r < 0) {
|
||||
+ timer_enter_dead(t, TIMER_FAILURE_START_LIMIT_HIT);
|
||||
+ return r;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static const char* const timer_base_table[_TIMER_BASE_MAX] = {
|
||||
[TIMER_ACTIVE] = "OnActiveSec",
|
||||
[TIMER_BOOT] = "OnBootSec",
|
||||
@@ -949,4 +958,6 @@ const UnitVTable timer_vtable = {
|
||||
.timezone_change = timer_timezone_change,
|
||||
|
||||
.bus_set_property = bus_timer_set_property,
|
||||
+
|
||||
+ .test_start_limit = timer_test_start_limit,
|
||||
};
|
||||
diff --git a/src/core/unit.c b/src/core/unit.c
|
||||
index 7d72dfa864..48e7b95e56 100644
|
||||
--- a/src/core/unit.c
|
||||
+++ b/src/core/unit.c
|
||||
@@ -1857,6 +1857,13 @@ int unit_start(Unit *u) {
|
||||
|
||||
assert(u);
|
||||
|
||||
+ /* Check start rate limiting early so that failure conditions don't cause us to enter a busy loop. */
|
||||
+ if (UNIT_VTABLE(u)->test_start_limit) {
|
||||
+ int r = UNIT_VTABLE(u)->test_start_limit(u);
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
+ }
|
||||
+
|
||||
/* If this is already started, then this will succeed. Note that this will even succeed if this unit
|
||||
* is not startable by the user. This is relied on to detect when we need to wait for units and when
|
||||
* waiting is finished. */
|
||||
diff --git a/src/core/unit.h b/src/core/unit.h
|
||||
index b3e9c2106f..b689f29f8f 100644
|
||||
--- a/src/core/unit.h
|
||||
+++ b/src/core/unit.h
|
||||
@@ -658,6 +658,10 @@ typedef struct UnitVTable {
|
||||
* of this type will immediately fail. */
|
||||
bool (*supported)(void);
|
||||
|
||||
+ /* If this function is set, it's invoked first as part of starting a unit to allow start rate
|
||||
+ * limiting checks to occur before we do anything else. */
|
||||
+ int (*test_start_limit)(Unit *u);
|
||||
+
|
||||
/* The strings to print in status messages */
|
||||
UnitStatusMessageFormats status_message_formats;
|
||||
|
||||
diff --git a/test/TEST-63-ISSUE-17433/Makefile b/test/TEST-63-ISSUE-17433/Makefile
|
||||
new file mode 120000
|
||||
index 0000000000..e9f93b1104
|
||||
--- /dev/null
|
||||
+++ b/test/TEST-63-ISSUE-17433/Makefile
|
||||
@@ -0,0 +1 @@
|
||||
+../TEST-01-BASIC/Makefile
|
||||
\ No newline at end of file
|
||||
diff --git a/test/TEST-63-ISSUE-17433/test.sh b/test/TEST-63-ISSUE-17433/test.sh
|
||||
new file mode 100755
|
||||
index 0000000000..c595a9f2de
|
||||
--- /dev/null
|
||||
+++ b/test/TEST-63-ISSUE-17433/test.sh
|
||||
@@ -0,0 +1,9 @@
|
||||
+#!/usr/bin/env bash
|
||||
+set -e
|
||||
+
|
||||
+TEST_DESCRIPTION="https://github.com/systemd/systemd/issues/17433"
|
||||
+
|
||||
+# shellcheck source=test/test-functions
|
||||
+. "${TEST_BASE_DIR:?}/test-functions"
|
||||
+
|
||||
+do_test "$@"
|
||||
diff --git a/test/meson.build b/test/meson.build
|
||||
index a21230a4a8..b8335fb50f 100644
|
||||
--- a/test/meson.build
|
||||
+++ b/test/meson.build
|
||||
@@ -33,6 +33,8 @@ if install_tests
|
||||
install_dir : testdata_dir)
|
||||
install_subdir('testsuite-52.units',
|
||||
install_dir : testdata_dir)
|
||||
+ install_subdir('testsuite-63.units',
|
||||
+ install_dir : testdata_dir)
|
||||
|
||||
testsuite08_dir = testdata_dir + '/testsuite-08.units'
|
||||
install_data('testsuite-08.units/-.mount',
|
||||
diff --git a/test/testsuite-10.units/test10.service b/test/testsuite-10.units/test10.service
|
||||
index d0be786b01..2fb476b986 100644
|
||||
--- a/test/testsuite-10.units/test10.service
|
||||
+++ b/test/testsuite-10.units/test10.service
|
||||
@@ -1,6 +1,9 @@
|
||||
[Unit]
|
||||
Requires=test10.socket
|
||||
ConditionPathExistsGlob=/tmp/nonexistent
|
||||
+# Make sure we hit the socket trigger limit in the test and not the service start limit.
|
||||
+StartLimitInterval=1000
|
||||
+StartLimitBurst=1000
|
||||
|
||||
[Service]
|
||||
ExecStart=true
|
||||
diff --git a/test/testsuite-63.units/test63.path b/test/testsuite-63.units/test63.path
|
||||
new file mode 100644
|
||||
index 0000000000..a6573bda0a
|
||||
--- /dev/null
|
||||
+++ b/test/testsuite-63.units/test63.path
|
||||
@@ -0,0 +1,2 @@
|
||||
+[Path]
|
||||
+PathExists=/tmp/test63
|
||||
diff --git a/test/testsuite-63.units/test63.service b/test/testsuite-63.units/test63.service
|
||||
new file mode 100644
|
||||
index 0000000000..c83801874d
|
||||
--- /dev/null
|
||||
+++ b/test/testsuite-63.units/test63.service
|
||||
@@ -0,0 +1,5 @@
|
||||
+[Unit]
|
||||
+ConditionPathExists=!/tmp/nonexistent
|
||||
+
|
||||
+[Service]
|
||||
+ExecStart=true
|
||||
diff --git a/test/units/testsuite-63.service b/test/units/testsuite-63.service
|
||||
new file mode 100644
|
||||
index 0000000000..04122723d4
|
||||
--- /dev/null
|
||||
+++ b/test/units/testsuite-63.service
|
||||
@@ -0,0 +1,16 @@
|
||||
+[Unit]
|
||||
+Description=TEST-63-ISSUE-17433
|
||||
+
|
||||
+[Service]
|
||||
+ExecStartPre=rm -f /failed /testok
|
||||
+Type=oneshot
|
||||
+ExecStart=rm -f /tmp/nonexistent
|
||||
+ExecStart=systemctl start test63.path
|
||||
+ExecStart=touch /tmp/test63
|
||||
+# Make sure systemd has sufficient time to hit the start limit for test63.service.
|
||||
+ExecStart=sleep 2
|
||||
+ExecStart=sh -x -c 'test "$(systemctl show test63.service -P ActiveState)" = failed'
|
||||
+ExecStart=sh -x -c 'test "$(systemctl show test63.service -P Result)" = start-limit-hit'
|
||||
+ExecStart=sh -x -c 'test "$(systemctl show test63.path -P ActiveState)" = failed'
|
||||
+ExecStart=sh -x -c 'test "$(systemctl show test63.path -P Result)" = unit-start-limit-hit'
|
||||
+ExecStart=sh -x -c 'echo OK >/testok'
|
||||
--
|
||||
2.33.0
|
||||
|
||||
@ -0,0 +1,51 @@
|
||||
From ce2146f5256659c7fb53a7d5b9dc551252e27e7e Mon Sep 17 00:00:00 2001
|
||||
From: Daan De Meyer <daan.j.demeyer@gmail.com>
|
||||
Date: Tue, 19 Oct 2021 10:45:48 +0100
|
||||
Subject: [PATCH] core: Delay start rate limit check when starting a unit
|
||||
|
||||
Doing start rate limit checks before doing condition checks made
|
||||
condition check failures count towards the start rate limit which
|
||||
broke existing assumptions (see #21025). Run the rate limit checks
|
||||
after the condition checks again to restore the previous behaviour.
|
||||
|
||||
Conflict:NA
|
||||
Reference:https://github.com/systemd/systemd-stable/commit/ce2146f5256659c7fb53a7d5b9dc551252e27e7e
|
||||
---
|
||||
src/core/unit.c | 14 +++++++-------
|
||||
1 file changed, 7 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/src/core/unit.c b/src/core/unit.c
|
||||
index a2944c1917..a6403002a6 100644
|
||||
--- a/src/core/unit.c
|
||||
+++ b/src/core/unit.c
|
||||
@@ -1855,13 +1855,6 @@ int unit_start(Unit *u) {
|
||||
|
||||
assert(u);
|
||||
|
||||
- /* Check start rate limiting early so that failure conditions don't cause us to enter a busy loop. */
|
||||
- if (UNIT_VTABLE(u)->test_start_limit) {
|
||||
- r = UNIT_VTABLE(u)->test_start_limit(u);
|
||||
- if (r < 0)
|
||||
- return r;
|
||||
- }
|
||||
-
|
||||
/* If this is already started, then this will succeed. Note that this will even succeed if this unit
|
||||
* is not startable by the user. This is relied on to detect when we need to wait for units and when
|
||||
* waiting is finished. */
|
||||
@@ -1911,6 +1904,13 @@ int unit_start(Unit *u) {
|
||||
return unit_start(following);
|
||||
}
|
||||
|
||||
+ /* Check start rate limiting early so that failure conditions don't cause us to enter a busy loop. */
|
||||
+ if (UNIT_VTABLE(u)->test_start_limit) {
|
||||
+ r = UNIT_VTABLE(u)->test_start_limit(u);
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
+ }
|
||||
+
|
||||
/* If it is stopped, but we cannot start it, then fail */
|
||||
if (!UNIT_VTABLE(u)->start)
|
||||
return -EBADR;
|
||||
--
|
||||
2.33.0
|
||||
|
||||
@ -0,0 +1,33 @@
|
||||
From 5f37c1a955e399756c4137d22f7f0f45a619f425 Mon Sep 17 00:00:00 2001
|
||||
From: Daan De Meyer <daan.j.demeyer@gmail.com>
|
||||
Date: Sat, 30 Oct 2021 22:12:06 +0100
|
||||
Subject: [PATCH] core: Move 'r' variable declaration to start of unit_start()
|
||||
|
||||
Conflict:NA
|
||||
Reference:https://github.com/systemd/systemd-stable/commit/5f37c1a955e399756c4137d22f7f0f45a619f425
|
||||
---
|
||||
src/core/unit.c | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/core/unit.c b/src/core/unit.c
|
||||
index 4c55827a65..a2944c1917 100644
|
||||
--- a/src/core/unit.c
|
||||
+++ b/src/core/unit.c
|
||||
@@ -1851,12 +1851,13 @@ static bool unit_verify_deps(Unit *u) {
|
||||
int unit_start(Unit *u) {
|
||||
UnitActiveState state;
|
||||
Unit *following;
|
||||
+ int r;
|
||||
|
||||
assert(u);
|
||||
|
||||
/* Check start rate limiting early so that failure conditions don't cause us to enter a busy loop. */
|
||||
if (UNIT_VTABLE(u)->test_start_limit) {
|
||||
- int r = UNIT_VTABLE(u)->test_start_limit(u);
|
||||
+ r = UNIT_VTABLE(u)->test_start_limit(u);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
--
|
||||
2.33.0
|
||||
|
||||
@ -0,0 +1,265 @@
|
||||
From 705578c3b9d794097233aa66010cf67b2a444716 Mon Sep 17 00:00:00 2001
|
||||
From: Michal Sekletar <msekleta@redhat.com>
|
||||
Date: Mon, 4 Oct 2021 17:51:52 +0200
|
||||
Subject: [PATCH] core: rename/generalize UNIT(u)->test_start_limit() hook
|
||||
|
||||
Up until now the main reason why we didn't proceed with starting the
|
||||
unit was exceed start limit burst. However, for unit types like mounts
|
||||
the other reason could be effective ratelimit on /proc/self/mountinfo
|
||||
event source. That means our mount unit state may not reflect current
|
||||
kernel state. Hence, we need to attempt to re-run the start job again
|
||||
after ratelimit on event source expires.
|
||||
|
||||
As we will be introducing another reason than start limit let's rename
|
||||
the virtual function that implements the check.
|
||||
|
||||
Conflict:NA
|
||||
Reference:https://github.com/systemd/systemd-stable/commit/705578c3b9d794097233aa66010cf67b2a444716
|
||||
---
|
||||
src/core/automount.c | 6 +++---
|
||||
src/core/mount.c | 6 +++---
|
||||
src/core/path.c | 6 +++---
|
||||
src/core/service.c | 6 +++---
|
||||
src/core/socket.c | 6 +++---
|
||||
src/core/swap.c | 6 +++---
|
||||
src/core/timer.c | 6 +++---
|
||||
src/core/unit.c | 6 +++---
|
||||
src/core/unit.h | 2 +-
|
||||
9 files changed, 25 insertions(+), 25 deletions(-)
|
||||
|
||||
diff --git a/src/core/automount.c b/src/core/automount.c
|
||||
index de470935c7..1fc3fc0f82 100644
|
||||
--- a/src/core/automount.c
|
||||
+++ b/src/core/automount.c
|
||||
@@ -1063,7 +1063,7 @@ static bool automount_supported(void) {
|
||||
return supported;
|
||||
}
|
||||
|
||||
-static int automount_test_start_limit(Unit *u) {
|
||||
+static int automount_can_start(Unit *u) {
|
||||
Automount *a = AUTOMOUNT(u);
|
||||
int r;
|
||||
|
||||
@@ -1075,7 +1075,7 @@ static int automount_test_start_limit(Unit *u) {
|
||||
return r;
|
||||
}
|
||||
|
||||
- return 0;
|
||||
+ return 1;
|
||||
}
|
||||
|
||||
static const char* const automount_result_table[_AUTOMOUNT_RESULT_MAX] = {
|
||||
@@ -1142,5 +1142,5 @@ const UnitVTable automount_vtable = {
|
||||
},
|
||||
},
|
||||
|
||||
- .test_start_limit = automount_test_start_limit,
|
||||
+ .can_start = automount_can_start,
|
||||
};
|
||||
diff --git a/src/core/mount.c b/src/core/mount.c
|
||||
index 321c7986b3..2ebae752b6 100644
|
||||
--- a/src/core/mount.c
|
||||
+++ b/src/core/mount.c
|
||||
@@ -2135,7 +2135,7 @@ static int mount_can_clean(Unit *u, ExecCleanMask *ret) {
|
||||
return exec_context_get_clean_mask(&m->exec_context, ret);
|
||||
}
|
||||
|
||||
-static int mount_test_start_limit(Unit *u) {
|
||||
+static int mount_can_start(Unit *u) {
|
||||
Mount *m = MOUNT(u);
|
||||
int r;
|
||||
|
||||
@@ -2147,7 +2147,7 @@ static int mount_test_start_limit(Unit *u) {
|
||||
return r;
|
||||
}
|
||||
|
||||
- return 0;
|
||||
+ return 1;
|
||||
}
|
||||
|
||||
static const char* const mount_exec_command_table[_MOUNT_EXEC_COMMAND_MAX] = {
|
||||
@@ -2248,5 +2248,5 @@ const UnitVTable mount_vtable = {
|
||||
},
|
||||
},
|
||||
|
||||
- .test_start_limit = mount_test_start_limit,
|
||||
+ .can_start = mount_can_start,
|
||||
};
|
||||
diff --git a/src/core/path.c b/src/core/path.c
|
||||
index 0a3d86e9db..cdab9dcf8c 100644
|
||||
--- a/src/core/path.c
|
||||
+++ b/src/core/path.c
|
||||
@@ -811,7 +811,7 @@ static void path_reset_failed(Unit *u) {
|
||||
p->result = PATH_SUCCESS;
|
||||
}
|
||||
|
||||
-static int path_test_start_limit(Unit *u) {
|
||||
+static int path_can_start(Unit *u) {
|
||||
Path *p = PATH(u);
|
||||
int r;
|
||||
|
||||
@@ -823,7 +823,7 @@ static int path_test_start_limit(Unit *u) {
|
||||
return r;
|
||||
}
|
||||
|
||||
- return 0;
|
||||
+ return 1;
|
||||
}
|
||||
|
||||
static const char* const path_type_table[_PATH_TYPE_MAX] = {
|
||||
@@ -882,5 +882,5 @@ const UnitVTable path_vtable = {
|
||||
|
||||
.bus_set_property = bus_path_set_property,
|
||||
|
||||
- .test_start_limit = path_test_start_limit,
|
||||
+ .can_start = path_can_start,
|
||||
};
|
||||
diff --git a/src/core/service.c b/src/core/service.c
|
||||
index 83cbc9f489..17c19a2c4a 100644
|
||||
--- a/src/core/service.c
|
||||
+++ b/src/core/service.c
|
||||
@@ -4482,7 +4482,7 @@ static const char *service_finished_job(Unit *u, JobType t, JobResult result) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
-static int service_test_start_limit(Unit *u) {
|
||||
+static int service_can_start(Unit *u) {
|
||||
Service *s = SERVICE(u);
|
||||
int r;
|
||||
|
||||
@@ -4495,7 +4495,7 @@ static int service_test_start_limit(Unit *u) {
|
||||
return r;
|
||||
}
|
||||
|
||||
- return 0;
|
||||
+ return 1;
|
||||
}
|
||||
|
||||
static const char* const service_restart_table[_SERVICE_RESTART_MAX] = {
|
||||
@@ -4669,5 +4669,5 @@ const UnitVTable service_vtable = {
|
||||
.finished_job = service_finished_job,
|
||||
},
|
||||
|
||||
- .test_start_limit = service_test_start_limit,
|
||||
+ .can_start = service_can_start,
|
||||
};
|
||||
diff --git a/src/core/socket.c b/src/core/socket.c
|
||||
index 6534311bef..f265aab594 100644
|
||||
--- a/src/core/socket.c
|
||||
+++ b/src/core/socket.c
|
||||
@@ -3427,7 +3427,7 @@ static int socket_can_clean(Unit *u, ExecCleanMask *ret) {
|
||||
return exec_context_get_clean_mask(&s->exec_context, ret);
|
||||
}
|
||||
|
||||
-static int socket_test_start_limit(Unit *u) {
|
||||
+static int socket_can_start(Unit *u) {
|
||||
Socket *s = SOCKET(u);
|
||||
int r;
|
||||
|
||||
@@ -3439,7 +3439,7 @@ static int socket_test_start_limit(Unit *u) {
|
||||
return r;
|
||||
}
|
||||
|
||||
- return 0;
|
||||
+ return 1;
|
||||
}
|
||||
|
||||
static const char* const socket_exec_command_table[_SOCKET_EXEC_COMMAND_MAX] = {
|
||||
@@ -3570,5 +3570,5 @@ const UnitVTable socket_vtable = {
|
||||
},
|
||||
},
|
||||
|
||||
- .test_start_limit = socket_test_start_limit,
|
||||
+ .can_start = socket_can_start,
|
||||
};
|
||||
diff --git a/src/core/swap.c b/src/core/swap.c
|
||||
index de72ac9232..3b28235194 100644
|
||||
--- a/src/core/swap.c
|
||||
+++ b/src/core/swap.c
|
||||
@@ -1581,7 +1581,7 @@ static int swap_can_clean(Unit *u, ExecCleanMask *ret) {
|
||||
return exec_context_get_clean_mask(&s->exec_context, ret);
|
||||
}
|
||||
|
||||
-static int swap_test_start_limit(Unit *u) {
|
||||
+static int swap_can_start(Unit *u) {
|
||||
Swap *s = SWAP(u);
|
||||
int r;
|
||||
|
||||
@@ -1593,7 +1593,7 @@ static int swap_test_start_limit(Unit *u) {
|
||||
return r;
|
||||
}
|
||||
|
||||
- return 0;
|
||||
+ return 1;
|
||||
}
|
||||
|
||||
static const char* const swap_exec_command_table[_SWAP_EXEC_COMMAND_MAX] = {
|
||||
@@ -1692,5 +1692,5 @@ const UnitVTable swap_vtable = {
|
||||
},
|
||||
},
|
||||
|
||||
- .test_start_limit = swap_test_start_limit,
|
||||
+ .can_start = swap_can_start,
|
||||
};
|
||||
diff --git a/src/core/timer.c b/src/core/timer.c
|
||||
index 240a2f473b..b22168fad5 100644
|
||||
--- a/src/core/timer.c
|
||||
+++ b/src/core/timer.c
|
||||
@@ -889,7 +889,7 @@ static int timer_can_clean(Unit *u, ExecCleanMask *ret) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int timer_test_start_limit(Unit *u) {
|
||||
+static int timer_can_start(Unit *u) {
|
||||
Timer *t = TIMER(u);
|
||||
int r;
|
||||
|
||||
@@ -901,7 +901,7 @@ static int timer_test_start_limit(Unit *u) {
|
||||
return r;
|
||||
}
|
||||
|
||||
- return 0;
|
||||
+ return 1;
|
||||
}
|
||||
|
||||
static const char* const timer_base_table[_TIMER_BASE_MAX] = {
|
||||
@@ -965,5 +965,5 @@ const UnitVTable timer_vtable = {
|
||||
|
||||
.bus_set_property = bus_timer_set_property,
|
||||
|
||||
- .test_start_limit = timer_test_start_limit,
|
||||
+ .can_start = timer_can_start,
|
||||
};
|
||||
diff --git a/src/core/unit.c b/src/core/unit.c
|
||||
index 77d4ceaf24..929cc85e13 100644
|
||||
--- a/src/core/unit.c
|
||||
+++ b/src/core/unit.c
|
||||
@@ -1904,9 +1904,9 @@ int unit_start(Unit *u) {
|
||||
return unit_start(following);
|
||||
}
|
||||
|
||||
- /* Check start rate limiting early so that failure conditions don't cause us to enter a busy loop. */
|
||||
- if (UNIT_VTABLE(u)->test_start_limit) {
|
||||
- r = UNIT_VTABLE(u)->test_start_limit(u);
|
||||
+ /* Check our ability to start early so that failure conditions don't cause us to enter a busy loop. */
|
||||
+ if (UNIT_VTABLE(u)->can_start) {
|
||||
+ r = UNIT_VTABLE(u)->can_start(u);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
diff --git a/src/core/unit.h b/src/core/unit.h
|
||||
index 3f3a75d33b..76701519c2 100644
|
||||
--- a/src/core/unit.h
|
||||
+++ b/src/core/unit.h
|
||||
@@ -665,7 +665,7 @@ typedef struct UnitVTable {
|
||||
|
||||
/* If this function is set, it's invoked first as part of starting a unit to allow start rate
|
||||
* limiting checks to occur before we do anything else. */
|
||||
- int (*test_start_limit)(Unit *u);
|
||||
+ int (*can_start)(Unit *u);
|
||||
|
||||
/* The strings to print in status messages */
|
||||
UnitStatusMessageFormats status_message_formats;
|
||||
--
|
||||
2.33.0
|
||||
|
||||
@ -0,0 +1,29 @@
|
||||
From a7c93dfe91e88a5a561341c523a45c7f8d71a588 Mon Sep 17 00:00:00 2001
|
||||
From: Michal Sekletar <msekleta@redhat.com>
|
||||
Date: Mon, 4 Oct 2021 19:41:34 +0200
|
||||
Subject: [PATCH] mount: make mount units start jobs not runnable if
|
||||
/p/s/mountinfo ratelimit is in effect
|
||||
|
||||
Conflict:NA
|
||||
Reference:https://github.com/systemd/systemd-stable/commit/a7c93dfe91e88a5a561341c523a45c7f8d71a588
|
||||
---
|
||||
src/core/mount.c | 3 +++
|
||||
1 file changed, 3 insertions(+)
|
||||
|
||||
diff --git a/src/core/mount.c b/src/core/mount.c
|
||||
index 2ebae752b6..88a670dc2a 100644
|
||||
--- a/src/core/mount.c
|
||||
+++ b/src/core/mount.c
|
||||
@@ -2141,6 +2141,9 @@ static int mount_can_start(Unit *u) {
|
||||
|
||||
assert(m);
|
||||
|
||||
+ if (sd_event_source_is_ratelimited(u->manager->mount_event_source))
|
||||
+ return -EAGAIN;
|
||||
+
|
||||
r = unit_test_start_limit(u);
|
||||
if (r < 0) {
|
||||
mount_enter_dead(m, MOUNT_FAILURE_START_LIMIT_HIT);
|
||||
--
|
||||
2.33.0
|
||||
|
||||
@ -0,0 +1,56 @@
|
||||
From edc027b4f1cfaa49e8ecdde763eb8c623402d464 Mon Sep 17 00:00:00 2001
|
||||
From: Michal Sekletar <msekleta@redhat.com>
|
||||
Date: Mon, 4 Oct 2021 20:31:49 +0200
|
||||
Subject: [PATCH] mount: retrigger run queue after ratelimit expired to run
|
||||
delayed mount start jobs
|
||||
|
||||
Fixes #20329
|
||||
|
||||
Conflict:NA
|
||||
Reference:https://github.com/systemd/systemd-stable/commit/edc027b4f1cfaa49e8ecdde763eb8c623402d464
|
||||
---
|
||||
src/core/mount.c | 21 +++++++++++++++++++++
|
||||
1 file changed, 21 insertions(+)
|
||||
|
||||
diff --git a/src/core/mount.c b/src/core/mount.c
|
||||
index 88a670dc2a..3463641c6c 100644
|
||||
--- a/src/core/mount.c
|
||||
+++ b/src/core/mount.c
|
||||
@@ -1838,6 +1838,21 @@ static bool mount_is_mounted(Mount *m) {
|
||||
return UNIT(m)->perpetual || FLAGS_SET(m->proc_flags, MOUNT_PROC_IS_MOUNTED);
|
||||
}
|
||||
|
||||
+static int mount_on_ratelimit_expire(sd_event_source *s, void *userdata) {
|
||||
+ Manager *m = userdata;
|
||||
+ int r;
|
||||
+
|
||||
+ assert(m);
|
||||
+
|
||||
+ /* By entering ratelimited state we made all mount start jobs not runnable, now rate limit is over so let's
|
||||
+ * make sure we dispatch them in the next iteration. */
|
||||
+ r = sd_event_source_set_enabled(m->run_queue_event_source, SD_EVENT_ONESHOT);
|
||||
+ if (r < 0)
|
||||
+ log_debug_errno(r, "Failed to enable run queue event source, ignoring: %m");
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static void mount_enumerate(Manager *m) {
|
||||
int r;
|
||||
|
||||
@@ -1891,6 +1906,12 @@ static void mount_enumerate(Manager *m) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
+ r = sd_event_source_set_ratelimit_expire_callback(m->mount_event_source, mount_on_ratelimit_expire);
|
||||
+ if (r < 0) {
|
||||
+ log_error_errno(r, "Failed to enable rate limit for mount events: %m");
|
||||
+ goto fail;
|
||||
+ }
|
||||
+
|
||||
(void) sd_event_source_set_description(m->mount_event_source, "mount-monitor-dispatch");
|
||||
}
|
||||
|
||||
--
|
||||
2.33.0
|
||||
|
||||
106
backport-pid1-add-a-manager_trigger_run_queue-helper.patch
Normal file
106
backport-pid1-add-a-manager_trigger_run_queue-helper.patch
Normal file
@ -0,0 +1,106 @@
|
||||
From b0c4b2824693fe6a27ea9439ec7a6328a0e23704 Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Fri, 12 Nov 2021 09:43:07 +0100
|
||||
Subject: [PATCH] pid1: add a manager_trigger_run_queue() helper
|
||||
|
||||
We have two different places where we re-trigger the run queue now.
|
||||
let's unify it under a common function, that is part of the Manager
|
||||
code.
|
||||
|
||||
Follow-up for #20953
|
||||
|
||||
Conflict:code context adaptation
|
||||
Reference:https://github.com/systemd/systemd-stable/commit/b0c4b2824693fe6a27ea9439ec7a6328a0e23704
|
||||
---
|
||||
src/core/job.c | 8 ++------
|
||||
src/core/manager.c | 12 ++++++++++++
|
||||
src/core/manager.h | 2 ++
|
||||
src/core/mount.c | 9 +++------
|
||||
4 files changed, 19 insertions(+), 12 deletions(-)
|
||||
|
||||
diff --git a/src/core/job.c b/src/core/job.c
|
||||
index 6dd01a6f49..b7ac75ac71 100644
|
||||
--- a/src/core/job.c
|
||||
+++ b/src/core/job.c
|
||||
@@ -1107,17 +1107,13 @@ void job_add_to_run_queue(Job *j) {
|
||||
if (j->in_run_queue)
|
||||
return;
|
||||
|
||||
- if (prioq_isempty(j->manager->run_queue)) {
|
||||
- r = sd_event_source_set_enabled(j->manager->run_queue_event_source, SD_EVENT_ONESHOT);
|
||||
- if (r < 0)
|
||||
- log_warning_errno(r, "Failed to enable job run queue event source, ignoring: %m");
|
||||
- }
|
||||
-
|
||||
r = prioq_put(j->manager->run_queue, j, &j->run_queue_idx);
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "Failed put job in run queue, ignoring: %m");
|
||||
else
|
||||
j->in_run_queue = true;
|
||||
+
|
||||
+ manager_trigger_run_queue(j->manager);
|
||||
}
|
||||
|
||||
void job_add_to_dbus_queue(Job *j) {
|
||||
diff --git a/src/core/manager.c b/src/core/manager.c
|
||||
index 61895ab092..b21747daea 100644
|
||||
--- a/src/core/manager.c
|
||||
+++ b/src/core/manager.c
|
||||
@@ -2248,6 +2248,18 @@ static int manager_dispatch_run_queue(sd_event_source *source, void *userdata) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
+void manager_trigger_run_queue(Manager *m) {
|
||||
+ int r;
|
||||
+
|
||||
+ assert(m);
|
||||
+
|
||||
+ r = sd_event_source_set_enabled(
|
||||
+ m->run_queue_event_source,
|
||||
+ prioq_isempty(m->run_queue) ? SD_EVENT_OFF : SD_EVENT_ONESHOT);
|
||||
+ if (r < 0)
|
||||
+ log_warning_errno(r, "Failed to enable job run queue event source, ignoring: %m");
|
||||
+}
|
||||
+
|
||||
static unsigned manager_dispatch_dbus_queue(Manager *m) {
|
||||
unsigned n = 0, budget;
|
||||
Unit *u;
|
||||
diff --git a/src/core/manager.h b/src/core/manager.h
|
||||
index 29ce812121..c9230cb5c4 100644
|
||||
--- a/src/core/manager.h
|
||||
+++ b/src/core/manager.h
|
||||
@@ -507,6 +507,8 @@ int manager_get_effective_environment(Manager *m, char ***ret);
|
||||
|
||||
int manager_set_default_rlimits(Manager *m, struct rlimit **default_rlimit);
|
||||
|
||||
+void manager_trigger_run_queue(Manager *m);
|
||||
+
|
||||
int manager_loop(Manager *m);
|
||||
|
||||
int manager_open_serialization(Manager *m, FILE **_f);
|
||||
diff --git a/src/core/mount.c b/src/core/mount.c
|
||||
index 3463641c6c..4f76b552c2 100644
|
||||
--- a/src/core/mount.c
|
||||
+++ b/src/core/mount.c
|
||||
@@ -1840,15 +1840,12 @@ static bool mount_is_mounted(Mount *m) {
|
||||
|
||||
static int mount_on_ratelimit_expire(sd_event_source *s, void *userdata) {
|
||||
Manager *m = userdata;
|
||||
- int r;
|
||||
|
||||
assert(m);
|
||||
|
||||
- /* By entering ratelimited state we made all mount start jobs not runnable, now rate limit is over so let's
|
||||
- * make sure we dispatch them in the next iteration. */
|
||||
- r = sd_event_source_set_enabled(m->run_queue_event_source, SD_EVENT_ONESHOT);
|
||||
- if (r < 0)
|
||||
- log_debug_errno(r, "Failed to enable run queue event source, ignoring: %m");
|
||||
+ /* By entering ratelimited state we made all mount start jobs not runnable, now rate limit is over so
|
||||
+ * let's make sure we dispatch them in the next iteration. */
|
||||
+ manager_trigger_run_queue(m);
|
||||
|
||||
return 0;
|
||||
}
|
||||
--
|
||||
2.33.0
|
||||
|
||||
@ -0,0 +1,282 @@
|
||||
From fd69f2247520b0be3190ded96d646a415edc97b7 Mon Sep 17 00:00:00 2001
|
||||
From: Michal Sekletar <msekleta@redhat.com>
|
||||
Date: Mon, 4 Oct 2021 19:44:06 +0200
|
||||
Subject: [PATCH] sd-event: introduce callback invoked when event source
|
||||
ratelimit expires
|
||||
|
||||
Conflict:code context adaptation
|
||||
Reference:https://github.com/systemd/systemd-stable/commit/fd69f2247520b0be3190ded96d646a415edc97b7
|
||||
---
|
||||
man/sd_event_source_set_ratelimit.xml | 22 +++++++---
|
||||
src/libsystemd/libsystemd.sym | 1 +
|
||||
src/libsystemd/sd-event/event-source.h | 1 +
|
||||
src/libsystemd/sd-event/sd-event.c | 61 ++++++++++++++++++++++----
|
||||
src/libsystemd/sd-event/test-event.c | 12 +++++
|
||||
src/systemd/sd-event.h | 1 +
|
||||
6 files changed, 85 insertions(+), 13 deletions(-)
|
||||
|
||||
diff --git a/man/sd_event_source_set_ratelimit.xml b/man/sd_event_source_set_ratelimit.xml
|
||||
index ac8529074a..37354a09f6 100644
|
||||
--- a/man/sd_event_source_set_ratelimit.xml
|
||||
+++ b/man/sd_event_source_set_ratelimit.xml
|
||||
@@ -19,6 +19,7 @@
|
||||
<refname>sd_event_source_set_ratelimit</refname>
|
||||
<refname>sd_event_source_get_ratelimit</refname>
|
||||
<refname>sd_event_source_is_ratelimited</refname>
|
||||
+ <refname>sd_event_source_set_ratelimit_expire_callback</refname>
|
||||
|
||||
<refpurpose>Configure rate limiting on event sources</refpurpose>
|
||||
</refnamediv>
|
||||
@@ -46,6 +47,12 @@
|
||||
<paramdef>sd_event_source *<parameter>source</parameter></paramdef>
|
||||
</funcprototype>
|
||||
|
||||
+ <funcprototype>
|
||||
+ <funcdef>int <function>sd_event_source_set_ratelimit_expire_callback</function></funcdef>
|
||||
+ <paramdef>sd_event_source *<parameter>source</parameter></paramdef>
|
||||
+ <paramdef>sd_event_handler_t<parameter>callback</parameter></paramdef>
|
||||
+ </funcprototype>
|
||||
+
|
||||
</funcsynopsis>
|
||||
</refsynopsisdiv>
|
||||
|
||||
@@ -78,6 +85,10 @@
|
||||
is currently affected by rate limiting, i.e. it has recently hit the rate limit and is currently
|
||||
temporarily disabled due to that.</para>
|
||||
|
||||
+ <para><function>sd_event_source_set_ratelimit_expire_callback</function> may be used to set a callback
|
||||
+ function that is invoked every time the event source leaves rate limited state. Note that function is
|
||||
+ called in the same event loop iteration in which state transition occured.</para>
|
||||
+
|
||||
<para>Rate limiting is currently implemented for I/O, timer, signal, defer and inotify event
|
||||
sources.</para>
|
||||
</refsect1>
|
||||
@@ -85,11 +96,12 @@
|
||||
<refsect1>
|
||||
<title>Return Value</title>
|
||||
|
||||
- <para>On success, <function>sd_event_source_set_ratelimit()</function> and
|
||||
- <function>sd_event_source_get_ratelimit()</function> return a non-negative integer. On failure, they
|
||||
- return a negative errno-style error code. <function>sd_event_source_is_ratelimited</function> returns
|
||||
- zero if rate limiting is currently not in effect and greater than zero if it is in effect; it returns a
|
||||
- negative errno-style error code on failure.</para>
|
||||
+ <para>On success, <function>sd_event_source_set_ratelimit()</function>,
|
||||
+ <function>sd_event_source_set_ratelimit_expire_callback</function> and
|
||||
+ <function>sd_event_source_get_ratelimit()</function> return a non-negative integer. On failure, they return
|
||||
+ a negative errno-style error code. <function>sd_event_source_is_ratelimited</function> returns zero if rate
|
||||
+ limiting is currently not in effect and greater than zero if it is in effect; it returns a negative
|
||||
+ errno-style error code on failure.</para>
|
||||
|
||||
<refsect2>
|
||||
<title>Errors</title>
|
||||
diff --git a/src/libsystemd/libsystemd.sym b/src/libsystemd/libsystemd.sym
|
||||
index 5e2fc9e231..2178668d11 100644
|
||||
--- a/src/libsystemd/libsystemd.sym
|
||||
+++ b/src/libsystemd/libsystemd.sym
|
||||
@@ -767,4 +767,5 @@ LIBSYSTEMD_249 {
|
||||
sd_device_get_trigger_uuid;
|
||||
sd_device_new_from_ifname;
|
||||
sd_device_new_from_ifindex;
|
||||
+ sd_event_source_set_ratelimit_expire_callback;
|
||||
} LIBSYSTEMD_248;
|
||||
diff --git a/src/libsystemd/sd-event/event-source.h b/src/libsystemd/sd-event/event-source.h
|
||||
index 41845c0bb5..74cbc26962 100644
|
||||
--- a/src/libsystemd/sd-event/event-source.h
|
||||
+++ b/src/libsystemd/sd-event/event-source.h
|
||||
@@ -71,6 +71,7 @@ struct sd_event_source {
|
||||
uint64_t prepare_iteration;
|
||||
|
||||
sd_event_destroy_t destroy_callback;
|
||||
+ sd_event_handler_t ratelimit_expire_callback;
|
||||
|
||||
LIST_FIELDS(sd_event_source, sources);
|
||||
|
||||
diff --git a/src/libsystemd/sd-event/sd-event.c b/src/libsystemd/sd-event/sd-event.c
|
||||
index 0ca0248510..d8f84d9ba7 100644
|
||||
--- a/src/libsystemd/sd-event/sd-event.c
|
||||
+++ b/src/libsystemd/sd-event/sd-event.c
|
||||
@@ -2908,7 +2908,7 @@ fail:
|
||||
return r;
|
||||
}
|
||||
|
||||
-static int event_source_leave_ratelimit(sd_event_source *s) {
|
||||
+static int event_source_leave_ratelimit(sd_event_source *s, bool run_callback) {
|
||||
int r;
|
||||
|
||||
assert(s);
|
||||
@@ -2940,6 +2940,30 @@ static int event_source_leave_ratelimit(sd_event_source *s) {
|
||||
ratelimit_reset(&s->rate_limit);
|
||||
|
||||
log_debug("Event source %p (%s) left rate limit state.", s, strna(s->description));
|
||||
+
|
||||
+ if (run_callback && s->ratelimit_expire_callback) {
|
||||
+ s->dispatching = true;
|
||||
+ r = s->ratelimit_expire_callback(s, s->userdata);
|
||||
+ s->dispatching = false;
|
||||
+
|
||||
+ if (r < 0) {
|
||||
+ log_debug_errno(r, "Ratelimit expiry callback of event source %s (type %s) returned error, %s: %m",
|
||||
+ strna(s->description),
|
||||
+ event_source_type_to_string(s->type),
|
||||
+ s->exit_on_failure ? "exiting" : "disabling");
|
||||
+
|
||||
+ if (s->exit_on_failure)
|
||||
+ (void) sd_event_exit(s->event, r);
|
||||
+ }
|
||||
+
|
||||
+ if (s->n_ref == 0)
|
||||
+ source_free(s);
|
||||
+ else if (r < 0)
|
||||
+ sd_event_source_set_enabled(s, SD_EVENT_OFF);
|
||||
+
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
@@ -3139,6 +3163,7 @@ static int process_timer(
|
||||
struct clock_data *d) {
|
||||
|
||||
sd_event_source *s;
|
||||
+ bool callback_invoked = false;
|
||||
int r;
|
||||
|
||||
assert(e);
|
||||
@@ -3156,9 +3181,11 @@ static int process_timer(
|
||||
* again. */
|
||||
assert(s->ratelimited);
|
||||
|
||||
- r = event_source_leave_ratelimit(s);
|
||||
+ r = event_source_leave_ratelimit(s, /* run_callback */ true);
|
||||
if (r < 0)
|
||||
return r;
|
||||
+ else if (r == 1)
|
||||
+ callback_invoked = true;
|
||||
|
||||
continue;
|
||||
}
|
||||
@@ -3173,7 +3200,7 @@ static int process_timer(
|
||||
event_source_time_prioq_reshuffle(s);
|
||||
}
|
||||
|
||||
- return 0;
|
||||
+ return callback_invoked;
|
||||
}
|
||||
|
||||
static int process_child(sd_event *e, int64_t threshold, int64_t *ret_min_priority) {
|
||||
@@ -4097,15 +4124,15 @@ _public_ int sd_event_wait(sd_event *e, uint64_t timeout) {
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
|
||||
- r = process_timer(e, e->timestamp.realtime, &e->realtime);
|
||||
+ r = process_inotify(e);
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
|
||||
- r = process_timer(e, e->timestamp.boottime, &e->boottime);
|
||||
+ r = process_timer(e, e->timestamp.realtime, &e->realtime);
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
|
||||
- r = process_timer(e, e->timestamp.monotonic, &e->monotonic);
|
||||
+ r = process_timer(e, e->timestamp.boottime, &e->boottime);
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
|
||||
@@ -4117,9 +4144,20 @@ _public_ int sd_event_wait(sd_event *e, uint64_t timeout) {
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
|
||||
- r = process_inotify(e);
|
||||
+ r = process_timer(e, e->timestamp.monotonic, &e->monotonic);
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
+ else if (r == 1) {
|
||||
+ /* Ratelimit expiry callback was called. Let's postpone processing pending sources and
|
||||
+ * put loop in the initial state in order to evaluate (in the next iteration) also sources
|
||||
+ * there were potentially re-enabled by the callback.
|
||||
+ *
|
||||
+ * Wondering why we treat only this invocation of process_timer() differently? Once event
|
||||
+ * source is ratelimited we essentially transform it into CLOCK_MONOTONIC timer hence
|
||||
+ * ratelimit expiry callback is never called for any other timer type. */
|
||||
+ r = 0;
|
||||
+ goto finish;
|
||||
+ }
|
||||
|
||||
if (event_next_pending(e)) {
|
||||
e->state = SD_EVENT_PENDING;
|
||||
@@ -4488,7 +4526,7 @@ _public_ int sd_event_source_set_ratelimit(sd_event_source *s, uint64_t interval
|
||||
|
||||
/* When ratelimiting is configured we'll always reset the rate limit state first and start fresh,
|
||||
* non-ratelimited. */
|
||||
- r = event_source_leave_ratelimit(s);
|
||||
+ r = event_source_leave_ratelimit(s, /* run_callback */ false);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@@ -4496,6 +4534,13 @@ _public_ int sd_event_source_set_ratelimit(sd_event_source *s, uint64_t interval
|
||||
return 0;
|
||||
}
|
||||
|
||||
+_public_ int sd_event_source_set_ratelimit_expire_callback(sd_event_source *s, sd_event_handler_t callback) {
|
||||
+ assert_return(s, -EINVAL);
|
||||
+
|
||||
+ s->ratelimit_expire_callback = callback;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
_public_ int sd_event_source_get_ratelimit(sd_event_source *s, uint64_t *ret_interval, unsigned *ret_burst) {
|
||||
assert_return(s, -EINVAL);
|
||||
|
||||
diff --git a/src/libsystemd/sd-event/test-event.c b/src/libsystemd/sd-event/test-event.c
|
||||
index b637639f26..0ac23c1118 100644
|
||||
--- a/src/libsystemd/sd-event/test-event.c
|
||||
+++ b/src/libsystemd/sd-event/test-event.c
|
||||
@@ -623,6 +623,11 @@ static int ratelimit_time_handler(sd_event_source *s, uint64_t usec, void *userd
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static int expired = -1;
|
||||
+static int ratelimit_expired(sd_event_source *s, void *userdata) {
|
||||
+ return ++expired;
|
||||
+}
|
||||
+
|
||||
static void test_ratelimit(void) {
|
||||
_cleanup_close_pair_ int p[2] = {-1, -1};
|
||||
_cleanup_(sd_event_unrefp) sd_event *e = NULL;
|
||||
@@ -686,12 +691,19 @@ static void test_ratelimit(void) {
|
||||
|
||||
assert_se(sd_event_source_set_ratelimit(s, 1 * USEC_PER_SEC, 10) >= 0);
|
||||
|
||||
+ /* Set callback that will be invoked when we leave rate limited state. */
|
||||
+ assert_se(sd_event_source_set_ratelimit_expire_callback(s, ratelimit_expired) >= 0);
|
||||
+
|
||||
do {
|
||||
assert_se(sd_event_run(e, UINT64_MAX) >= 0);
|
||||
} while (!sd_event_source_is_ratelimited(s));
|
||||
|
||||
log_info("ratelimit_time_handler: called 10 more times, event source got ratelimited");
|
||||
assert_se(count == 20);
|
||||
+
|
||||
+ /* Dispatch the event loop once more and check that ratelimit expiration callback got called */
|
||||
+ assert_se(sd_event_run(e, UINT64_MAX) >= 0);
|
||||
+ assert_se(expired == 0);
|
||||
}
|
||||
|
||||
static void test_simple_timeout(void) {
|
||||
diff --git a/src/systemd/sd-event.h b/src/systemd/sd-event.h
|
||||
index f4357aa593..63984eef15 100644
|
||||
--- a/src/systemd/sd-event.h
|
||||
+++ b/src/systemd/sd-event.h
|
||||
@@ -166,6 +166,7 @@ int sd_event_source_set_exit_on_failure(sd_event_source *s, int b);
|
||||
int sd_event_source_set_ratelimit(sd_event_source *s, uint64_t interval_usec, unsigned burst);
|
||||
int sd_event_source_get_ratelimit(sd_event_source *s, uint64_t *ret_interval_usec, unsigned *ret_burst);
|
||||
int sd_event_source_is_ratelimited(sd_event_source *s);
|
||||
+int sd_event_source_set_ratelimit_expire_callback(sd_event_source *s, sd_event_handler_t callback);
|
||||
|
||||
/* Define helpers so that __attribute__((cleanup(sd_event_unrefp))) and similar may be used. */
|
||||
_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_event, sd_event_unref);
|
||||
--
|
||||
2.33.0
|
||||
|
||||
@ -0,0 +1,47 @@
|
||||
From c29e6a9530316823b0455cd83eb6d0bb8dd664f4 Mon Sep 17 00:00:00 2001
|
||||
From: Michal Sekletar <msekleta@redhat.com>
|
||||
Date: Thu, 25 Nov 2021 18:28:25 +0100
|
||||
Subject: [PATCH] unit: add jobs that were skipped because of ratelimit back to
|
||||
run_queue
|
||||
|
||||
Assumption in edc027b was that job we first skipped because of active
|
||||
ratelimit is still in run_queue. Hence we trigger the queue and dispatch
|
||||
it in the next iteration. Actually we remove jobs from run_queue in
|
||||
job_run_and_invalidate() before we call unit_start(). Hence if we want
|
||||
to attempt to run the job again in the future we need to add it back
|
||||
to run_queue.
|
||||
|
||||
Fixes #21458
|
||||
|
||||
Conflict:NA
|
||||
Reference:https://github.com/systemd/systemd-stable/commit/c29e6a9530316823b0455cd83eb6d0bb8dd664f4
|
||||
---
|
||||
src/core/mount.c | 9 +++++++++
|
||||
1 file changed, 9 insertions(+)
|
||||
|
||||
diff --git a/src/core/mount.c b/src/core/mount.c
|
||||
index 90b11347f7..35368fe8e6 100644
|
||||
--- a/src/core/mount.c
|
||||
+++ b/src/core/mount.c
|
||||
@@ -1840,9 +1840,18 @@ static bool mount_is_mounted(Mount *m) {
|
||||
|
||||
static int mount_on_ratelimit_expire(sd_event_source *s, void *userdata) {
|
||||
Manager *m = userdata;
|
||||
+ Job *j;
|
||||
|
||||
assert(m);
|
||||
|
||||
+ /* Let's enqueue all start jobs that were previously skipped because of active ratelimit. */
|
||||
+ HASHMAP_FOREACH(j, m->jobs) {
|
||||
+ if (j->unit->type != UNIT_MOUNT)
|
||||
+ continue;
|
||||
+
|
||||
+ job_add_to_run_queue(j);
|
||||
+ }
|
||||
+
|
||||
/* By entering ratelimited state we made all mount start jobs not runnable, now rate limit is over so
|
||||
* let's make sure we dispatch them in the next iteration. */
|
||||
manager_trigger_run_queue(m);
|
||||
--
|
||||
2.33.0
|
||||
|
||||
@ -0,0 +1,54 @@
|
||||
From b161bc394b2cc8b271dda9208e310cc2af0cc29d Mon Sep 17 00:00:00 2001
|
||||
From: Michal Sekletar <msekleta@redhat.com>
|
||||
Date: Mon, 30 May 2022 11:55:41 +0200
|
||||
Subject: [PATCH] unit: check for mount rate limiting before checking active
|
||||
state
|
||||
|
||||
Having this check as part of mount_can_start() is too late because
|
||||
UNIT(u)->can_start() virtual method is called after checking the active
|
||||
state of unit in unit_start().
|
||||
|
||||
We need to hold off running mount start jobs when /p/s/mountinfo monitor
|
||||
is rate limited even when given mount unit is already active.
|
||||
|
||||
Fixes #20329
|
||||
|
||||
Conflict:NA
|
||||
Reference:https://github.com/systemd/systemd-stable/commit/b161bc394b2cc8b271dda9208e310cc2af0cc29d
|
||||
---
|
||||
src/core/mount.c | 3 ---
|
||||
src/core/unit.c | 4 ++++
|
||||
2 files changed, 4 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/src/core/mount.c b/src/core/mount.c
|
||||
index 20b4bb6d2b..a2fd9c2a99 100644
|
||||
--- a/src/core/mount.c
|
||||
+++ b/src/core/mount.c
|
||||
@@ -2170,9 +2170,6 @@ static int mount_can_start(Unit *u) {
|
||||
|
||||
assert(m);
|
||||
|
||||
- if (sd_event_source_is_ratelimited(u->manager->mount_event_source))
|
||||
- return -EAGAIN;
|
||||
-
|
||||
r = unit_test_start_limit(u);
|
||||
if (r < 0) {
|
||||
mount_enter_dead(m, MOUNT_FAILURE_START_LIMIT_HIT);
|
||||
diff --git a/src/core/unit.c b/src/core/unit.c
|
||||
index b0756bc6f4..d7f5245ca3 100644
|
||||
--- a/src/core/unit.c
|
||||
+++ b/src/core/unit.c
|
||||
@@ -1868,6 +1868,10 @@ int unit_start(Unit *u) {
|
||||
|
||||
assert(u);
|
||||
|
||||
+ /* Let's hold off running start jobs for mount units when /proc/self/mountinfo monitor is rate limited. */
|
||||
+ if (u->type == UNIT_MOUNT && sd_event_source_is_ratelimited(u->manager->mount_event_source))
|
||||
+ return -EAGAIN;
|
||||
+
|
||||
/* If this is already started, then this will succeed. Note that this will even succeed if this unit
|
||||
* is not startable by the user. This is relied on to detect when we need to wait for units and when
|
||||
* waiting is finished. */
|
||||
--
|
||||
2.33.0
|
||||
|
||||
@ -10,12 +10,13 @@ logs). Therefore, when the journal~ file is generated, delete all journal files
|
||||
except system.journal, to ensure that the sd_journal_next function meets user
|
||||
expectations.
|
||||
---
|
||||
meson.build | 2 ++
|
||||
meson.build | 3 ++-
|
||||
src/basic/dirent-util.c | 24 ++++++++++++++++
|
||||
src/basic/dirent-util.h | 2 ++
|
||||
src/libsystemd/sd-journal/journal-file.c | 35 ++++++++++++++++++++++++
|
||||
src/libsystemd/sd-journal/sd-journal.c | 22 ---------------
|
||||
5 files changed, 63 insertions(+), 22 deletions(-)
|
||||
src/test/meson.build | 2 +-
|
||||
6 files changed, 64 insertions(+), 23 deletions(-)
|
||||
|
||||
diff --git a/meson.build b/meson.build
|
||||
index 278e264..9ab40b6 100644
|
||||
@ -30,6 +31,15 @@ index 278e264..9ab40b6 100644
|
||||
'.')
|
||||
|
||||
libsystemd_includes = [basic_includes, include_directories(
|
||||
@@ -1801,7 +1801,7 @@ test_dlopen = executable(
|
||||
test_dlopen_c,
|
||||
disable_mempool_c,
|
||||
include_directories : includes,
|
||||
- link_with : [libbasic],
|
||||
+ link_with : [libbasic, libsystemd_static],
|
||||
dependencies : [libdl],
|
||||
build_by_default : want_tests != 'false')
|
||||
|
||||
diff --git a/src/basic/dirent-util.c b/src/basic/dirent-util.c
|
||||
index f6213a3..b227cae 100644
|
||||
--- a/src/basic/dirent-util.c
|
||||
@ -181,6 +191,19 @@ index 1a76bb6..56e1398 100644
|
||||
static int directory_open(sd_journal *j, const char *path, DIR **ret) {
|
||||
DIR *d;
|
||||
|
||||
diff --git a/src/test/meson.build b/src/test/meson.build
|
||||
index 7f7d8b7..9b1fb87 100644
|
||||
--- a/src/test/meson.build
|
||||
+++ b/src/test/meson.build
|
||||
@@ -364,7 +364,7 @@ tests += [
|
||||
[], [], [], '', 'timeout=90'],
|
||||
|
||||
[['src/test/test-set.c'],
|
||||
- [libbasic]],
|
||||
+ [libbasic, libsystemd_static]],
|
||||
|
||||
[['src/test/test-ordered-set.c']],
|
||||
|
||||
--
|
||||
2.23.0
|
||||
|
||||
|
||||
@ -29,7 +29,7 @@ index 053deac..de5b745 100644
|
||||
--- a/src/core/mount.c
|
||||
+++ b/src/core/mount.c
|
||||
@@ -1895,6 +1895,10 @@ static void mount_enumerate(Manager *m) {
|
||||
goto fail;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
+ r = sd_event_source_set_preempt_dispatch_count(m->mount_event_source, 5);
|
||||
@ -53,8 +53,8 @@ index d2dc214..0fa41aa 100644
|
||||
+ unsigned preempt_dispatch_count; /*Will be preempted by lower priority if dispatched count reaches to this*/
|
||||
+
|
||||
sd_event_destroy_t destroy_callback;
|
||||
sd_event_handler_t ratelimit_expire_callback;
|
||||
|
||||
LIST_FIELDS(sd_event_source, sources);
|
||||
diff --git a/src/libsystemd/sd-event/sd-event.c b/src/libsystemd/sd-event/sd-event.c
|
||||
index e9199de..46f8aff 100644
|
||||
--- a/src/libsystemd/sd-event/sd-event.c
|
||||
@ -211,10 +211,10 @@ diff --git a/src/systemd/sd-event.h b/src/systemd/sd-event.h
|
||||
index 2ae2a0d..f113aba 100644
|
||||
--- a/src/systemd/sd-event.h
|
||||
+++ b/src/systemd/sd-event.h
|
||||
@@ -165,6 +165,7 @@ int sd_event_source_set_exit_on_failure(sd_event_source *s, int b);
|
||||
int sd_event_source_set_ratelimit(sd_event_source *s, uint64_t interval_usec, unsigned burst);
|
||||
@@ -165,6 +165,7 @@ int sd_event_source_set_ratelimit(sd_event_source *s, uint64_t interval_usec, unsigned burst);
|
||||
int sd_event_source_get_ratelimit(sd_event_source *s, uint64_t *ret_interval_usec, unsigned *ret_burst);
|
||||
int sd_event_source_is_ratelimited(sd_event_source *s);
|
||||
int sd_event_source_set_ratelimit_expire_callback(sd_event_source *s, sd_event_handler_t callback);
|
||||
+int sd_event_source_set_preempt_dispatch_count(sd_event_source *s, unsigned count);
|
||||
|
||||
/* Define helpers so that __attribute__((cleanup(sd_event_unrefp))) and similar may be used. */
|
||||
|
||||
16
systemd.spec
16
systemd.spec
@ -21,7 +21,7 @@
|
||||
Name: systemd
|
||||
Url: https://www.freedesktop.org/wiki/Software/systemd
|
||||
Version: 249
|
||||
Release: 52
|
||||
Release: 53
|
||||
License: MIT and LGPLv2+ and GPLv2+
|
||||
Summary: System and Service Manager
|
||||
|
||||
@ -517,6 +517,17 @@ Patch6469: backport-core-device-verify-device-syspath-on-switching-root.pat
|
||||
Patch6470: backport-sd-lldp-use-memcpy_safe-as-the-buffer-size-may-be-ze.patch
|
||||
Patch6471: backport-shared-bootspec-avoid-crashing-on-config-without-a-v.patch
|
||||
Patch6472: backport-sysext-refuse-empty-release-ID-to-avoid-triggering-a.patch
|
||||
Patch6473: backport-core-Check-unit-start-rate-limiting-earlier.patch
|
||||
Patch6474: backport-core-Move-r-variable-declaration-to-start-of-unit_st.patch
|
||||
Patch6475: backport-core-Delay-start-rate-limit-check-when-starting-a-un.patch
|
||||
Patch6476: backport-core-Add-trigger-limit-for-path-units.patch
|
||||
Patch6477: backport-sd-event-introduce-callback-invoked-when-event-sourc.patch
|
||||
Patch6478: backport-core-rename-generalize-UNIT-u-test_start_limit-hook.patch
|
||||
Patch6479: backport-mount-make-mount-units-start-jobs-not-runnable-if-p-.patch
|
||||
Patch6480: backport-mount-retrigger-run-queue-after-ratelimit-expired-to.patch
|
||||
Patch6481: backport-pid1-add-a-manager_trigger_run_queue-helper.patch
|
||||
Patch6482: backport-unit-add-jobs-that-were-skipped-because-of-ratelimit.patch
|
||||
Patch6483: backport-unit-check-for-mount-rate-limiting-before-checking-a.patch
|
||||
|
||||
Patch9001: update-rtc-with-system-clock-when-shutdown.patch
|
||||
Patch9002: udev-add-actions-while-rename-netif-failed.patch
|
||||
@ -1988,6 +1999,9 @@ fi
|
||||
%{_libdir}/security/pam_systemd.so
|
||||
|
||||
%changelog
|
||||
* Tue Aug 15 2023 wangyuhang <wangyuhang27@huawei.com> - 249-53
|
||||
- backport: sync patches from systemd community
|
||||
|
||||
* Thu Jun 15 2023 hongjinghao <hongjinghao@huawei.com> - 249-52
|
||||
- backport: sync patches from systemd community
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user