basebuilder_pel7x64builder0
4 years ago
20 changed files with 1832 additions and 0 deletions
@ -0,0 +1,35 @@ |
|||||||
|
From 6a0d21a508e43ca7a89b700e98fd86a08eff4fee Mon Sep 17 00:00:00 2001 |
||||||
|
From: Michal Sekletar <msekleta@redhat.com> |
||||||
|
Date: Mon, 9 Sep 2019 14:38:35 +0200 |
||||||
|
Subject: [PATCH] path: stop watching path specs once we triggered the target |
||||||
|
unit |
||||||
|
|
||||||
|
We start watching them again once we get a notification that triggered |
||||||
|
unit entered inactive or failed state. |
||||||
|
|
||||||
|
Fixes: #10503 |
||||||
|
(cherry picked from commit 8fca6944c2ee20c63d62154c8badddc77170b176) |
||||||
|
|
||||||
|
Resolves: #1641777 |
||||||
|
--- |
||||||
|
src/core/path.c | 6 ++---- |
||||||
|
1 file changed, 2 insertions(+), 4 deletions(-) |
||||||
|
|
||||||
|
diff --git a/src/core/path.c b/src/core/path.c |
||||||
|
index 0533bb4e21..a74cbf2372 100644 |
||||||
|
--- a/src/core/path.c |
||||||
|
+++ b/src/core/path.c |
||||||
|
@@ -497,11 +497,9 @@ static void path_enter_running(Path *p) { |
||||||
|
|
||||||
|
p->inotify_triggered = false; |
||||||
|
|
||||||
|
- r = path_watch(p); |
||||||
|
- if (r < 0) |
||||||
|
- goto fail; |
||||||
|
- |
||||||
|
path_set_state(p, PATH_RUNNING); |
||||||
|
+ path_unwatch(p); |
||||||
|
+ |
||||||
|
return; |
||||||
|
|
||||||
|
fail: |
@ -0,0 +1,39 @@ |
|||||||
|
From 98234ad6e16e868bd1fa3e4622c43a182fdee75c Mon Sep 17 00:00:00 2001 |
||||||
|
From: =?UTF-8?q?Renaud=20M=C3=A9trich?= <rmetrich@redhat.com> |
||||||
|
Date: Sat, 23 Nov 2019 13:37:02 +0100 |
||||||
|
Subject: [PATCH] unit: fix potential use of cgroup_path after free() when |
||||||
|
freeing unit |
||||||
|
|
||||||
|
Resolves: #1760149 |
||||||
|
--- |
||||||
|
src/core/cgroup.c | 3 +-- |
||||||
|
src/core/unit.c | 2 +- |
||||||
|
2 files changed, 2 insertions(+), 3 deletions(-) |
||||||
|
|
||||||
|
diff --git a/src/core/cgroup.c b/src/core/cgroup.c |
||||||
|
index 0ce265dbf4..9af8126957 100644 |
||||||
|
--- a/src/core/cgroup.c |
||||||
|
+++ b/src/core/cgroup.c |
||||||
|
@@ -874,8 +874,7 @@ void unit_destroy_cgroup_if_empty(Unit *u) { |
||||||
|
|
||||||
|
hashmap_remove(u->manager->cgroup_unit, u->cgroup_path); |
||||||
|
|
||||||
|
- free(u->cgroup_path); |
||||||
|
- u->cgroup_path = NULL; |
||||||
|
+ u->cgroup_path = mfree(u->cgroup_path); |
||||||
|
u->cgroup_realized = false; |
||||||
|
u->cgroup_realized_mask = 0; |
||||||
|
} |
||||||
|
diff --git a/src/core/unit.c b/src/core/unit.c |
||||||
|
index 294c9eb70f..0dc66203a4 100644 |
||||||
|
--- a/src/core/unit.c |
||||||
|
+++ b/src/core/unit.c |
||||||
|
@@ -515,7 +515,7 @@ void unit_free(Unit *u) { |
||||||
|
|
||||||
|
if (u->cgroup_path) { |
||||||
|
hashmap_remove(u->manager->cgroup_unit, u->cgroup_path); |
||||||
|
- free(u->cgroup_path); |
||||||
|
+ u->cgroup_path = mfree(u->cgroup_path); |
||||||
|
} |
||||||
|
|
||||||
|
set_remove(u->manager->failed_units, u); |
@ -0,0 +1,112 @@ |
|||||||
|
From 017d1bc2a34946336dbafcc1c9c390ea45a2a3bd Mon Sep 17 00:00:00 2001 |
||||||
|
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl> |
||||||
|
Date: Sat, 22 Oct 2016 22:16:02 -0400 |
||||||
|
Subject: [PATCH] core: when restarting services, don't close fds |
||||||
|
|
||||||
|
We would close all the stored fds in service_release_resources(), which of |
||||||
|
course broke the whole concept of storing fds over service restart. |
||||||
|
|
||||||
|
Fixes #4408. |
||||||
|
|
||||||
|
(cherry picked from commit f0bfbfac43b7faa68ef1bb2ad659c191b9ec85d2) |
||||||
|
(cherry picked from commit 4c271437cd695c31e76adb191013009689a7797c) |
||||||
|
Resolves: #1803802 |
||||||
|
--- |
||||||
|
src/core/service.c | 22 +++++++++++++++------- |
||||||
|
src/core/unit.c | 6 ++++-- |
||||||
|
src/core/unit.h | 2 +- |
||||||
|
3 files changed, 20 insertions(+), 10 deletions(-) |
||||||
|
|
||||||
|
diff --git a/src/core/service.c b/src/core/service.c |
||||||
|
index e538280bad..3c2f69a003 100644 |
||||||
|
--- a/src/core/service.c |
||||||
|
+++ b/src/core/service.c |
||||||
|
@@ -258,7 +258,17 @@ static void service_fd_store_unlink(ServiceFDStore *fs) { |
||||||
|
free(fs); |
||||||
|
} |
||||||
|
|
||||||
|
-static void service_release_resources(Unit *u) { |
||||||
|
+static void service_release_fd_store(Service *s) { |
||||||
|
+ assert(s); |
||||||
|
+ |
||||||
|
+ log_unit_debug(UNIT(s)->id, "Releasing all stored fds"); |
||||||
|
+ while (s->fd_store) |
||||||
|
+ service_fd_store_unlink(s->fd_store); |
||||||
|
+ |
||||||
|
+ assert(s->n_fd_store == 0); |
||||||
|
+} |
||||||
|
+ |
||||||
|
+static void service_release_resources(Unit *u, bool inactive) { |
||||||
|
Service *s = SERVICE(u); |
||||||
|
|
||||||
|
assert(s); |
||||||
|
@@ -266,12 +276,10 @@ static void service_release_resources(Unit *u) { |
||||||
|
if (!s->fd_store) |
||||||
|
return; |
||||||
|
|
||||||
|
- log_debug("Releasing all resources for %s", u->id); |
||||||
|
- |
||||||
|
- while (s->fd_store) |
||||||
|
- service_fd_store_unlink(s->fd_store); |
||||||
|
+ log_unit_debug(u->id, "Releasing resources."); |
||||||
|
|
||||||
|
- assert(s->n_fd_store == 0); |
||||||
|
+ if (inactive) |
||||||
|
+ service_release_fd_store(s); |
||||||
|
} |
||||||
|
|
||||||
|
static void service_done(Unit *u) { |
||||||
|
@@ -319,7 +327,7 @@ static void service_done(Unit *u) { |
||||||
|
|
||||||
|
s->timer_event_source = sd_event_source_unref(s->timer_event_source); |
||||||
|
|
||||||
|
- service_release_resources(u); |
||||||
|
+ service_release_resources(u, true); |
||||||
|
} |
||||||
|
|
||||||
|
static int on_fd_store_io(sd_event_source *e, int fd, uint32_t revents, void *userdata) { |
||||||
|
diff --git a/src/core/unit.c b/src/core/unit.c |
||||||
|
index 0dc66203a4..22e31a76b3 100644 |
||||||
|
--- a/src/core/unit.c |
||||||
|
+++ b/src/core/unit.c |
||||||
|
@@ -285,6 +285,7 @@ int unit_set_description(Unit *u, const char *description) { |
||||||
|
|
||||||
|
bool unit_may_gc(Unit *u) { |
||||||
|
UnitActiveState state; |
||||||
|
+ bool inactive; |
||||||
|
assert(u); |
||||||
|
|
||||||
|
/* Checks whether the unit is ready to be unloaded for garbage collection. |
||||||
|
@@ -302,16 +303,17 @@ bool unit_may_gc(Unit *u) { |
||||||
|
return false; |
||||||
|
|
||||||
|
state = unit_active_state(u); |
||||||
|
+ inactive = state == UNIT_INACTIVE; |
||||||
|
|
||||||
|
/* If the unit is inactive and failed and no job is queued for |
||||||
|
* it, then release its runtime resources */ |
||||||
|
if (UNIT_IS_INACTIVE_OR_FAILED(state) && |
||||||
|
UNIT_VTABLE(u)->release_resources) |
||||||
|
- UNIT_VTABLE(u)->release_resources(u); |
||||||
|
+ UNIT_VTABLE(u)->release_resources(u, inactive); |
||||||
|
|
||||||
|
/* But we keep the unit object around for longer when it is |
||||||
|
* referenced or configured to not be gc'ed */ |
||||||
|
- if (state != UNIT_INACTIVE) |
||||||
|
+ if (!inactive) |
||||||
|
return false; |
||||||
|
|
||||||
|
if (UNIT_VTABLE(u)->no_gc) |
||||||
|
diff --git a/src/core/unit.h b/src/core/unit.h |
||||||
|
index 719fc95260..232be8164f 100644 |
||||||
|
--- a/src/core/unit.h |
||||||
|
+++ b/src/core/unit.h |
||||||
|
@@ -360,7 +360,7 @@ struct UnitVTable { |
||||||
|
|
||||||
|
/* When the unit is not running and no job for it queued we |
||||||
|
* shall release its runtime resources */ |
||||||
|
- void (*release_resources)(Unit *u); |
||||||
|
+ void (*release_resources)(Unit *u, bool inactive); |
||||||
|
|
||||||
|
/* Return true when this unit is suitable for snapshotting */ |
||||||
|
bool (*check_snapshot)(Unit *u); |
@ -0,0 +1,170 @@ |
|||||||
|
From 9684908410868cb590ad74f4747bdbf9b5790abb Mon Sep 17 00:00:00 2001 |
||||||
|
From: Lennart Poettering <lennart@poettering.net> |
||||||
|
Date: Mon, 13 Nov 2017 15:08:49 +0100 |
||||||
|
Subject: [PATCH] unit: rework a bit how we keep the service fdstore from being |
||||||
|
destroyed during service restart |
||||||
|
|
||||||
|
When preparing for a restart we quickly go through the DEAD/INACTIVE |
||||||
|
service state before entering AUTO_RESTART. When doing this, we need to |
||||||
|
make sure we don't destroy the FD store. Previously this was done by |
||||||
|
checking the failure state of the unit, and keeping the FD store around |
||||||
|
when the unit failed, under the assumption that the restart logic will |
||||||
|
then get into action. |
||||||
|
|
||||||
|
This is not entirely correct howver, as there might be failure states |
||||||
|
that will no result in restarts. |
||||||
|
|
||||||
|
With this commit we slightly alter the logic: a ref counter for the fd |
||||||
|
store is added, that is increased right before we handle the restart |
||||||
|
logic, and decreased again right-after. |
||||||
|
|
||||||
|
This should ensure that the fdstore lives exactly as long as it needs. |
||||||
|
|
||||||
|
Follow-up for f0bfbfac43b7faa68ef1bb2ad659c191b9ec85d2. |
||||||
|
|
||||||
|
(cherry picked from commit 7eb2a8a1259043e107ebec94e30ed160a93f40a7) |
||||||
|
(cherry picked from commit e2636bde0f07319d0d35262dac6ff2638ba4e598) |
||||||
|
Resolves: #1803802 |
||||||
|
--- |
||||||
|
src/core/service.c | 23 ++++++++++++++++++----- |
||||||
|
src/core/service.h | 1 + |
||||||
|
src/core/unit.c | 12 ++++-------- |
||||||
|
src/core/unit.h | 5 ++--- |
||||||
|
4 files changed, 25 insertions(+), 16 deletions(-) |
||||||
|
|
||||||
|
diff --git a/src/core/service.c b/src/core/service.c |
||||||
|
index 3c2f69a003..e32cdf4594 100644 |
||||||
|
--- a/src/core/service.c |
||||||
|
+++ b/src/core/service.c |
||||||
|
@@ -261,6 +261,9 @@ static void service_fd_store_unlink(ServiceFDStore *fs) { |
||||||
|
static void service_release_fd_store(Service *s) { |
||||||
|
assert(s); |
||||||
|
|
||||||
|
+ if (s->n_keep_fd_store > 0) |
||||||
|
+ return; |
||||||
|
+ |
||||||
|
log_unit_debug(UNIT(s)->id, "Releasing all stored fds"); |
||||||
|
while (s->fd_store) |
||||||
|
service_fd_store_unlink(s->fd_store); |
||||||
|
@@ -268,7 +271,7 @@ static void service_release_fd_store(Service *s) { |
||||||
|
assert(s->n_fd_store == 0); |
||||||
|
} |
||||||
|
|
||||||
|
-static void service_release_resources(Unit *u, bool inactive) { |
||||||
|
+static void service_release_resources(Unit *u) { |
||||||
|
Service *s = SERVICE(u); |
||||||
|
|
||||||
|
assert(s); |
||||||
|
@@ -278,8 +281,7 @@ static void service_release_resources(Unit *u, bool inactive) { |
||||||
|
|
||||||
|
log_unit_debug(u->id, "Releasing resources."); |
||||||
|
|
||||||
|
- if (inactive) |
||||||
|
- service_release_fd_store(s); |
||||||
|
+ service_release_fd_store(s); |
||||||
|
} |
||||||
|
|
||||||
|
static void service_done(Unit *u) { |
||||||
|
@@ -327,7 +329,7 @@ static void service_done(Unit *u) { |
||||||
|
|
||||||
|
s->timer_event_source = sd_event_source_unref(s->timer_event_source); |
||||||
|
|
||||||
|
- service_release_resources(u, true); |
||||||
|
+ service_release_resources(u); |
||||||
|
} |
||||||
|
|
||||||
|
static int on_fd_store_io(sd_event_source *e, int fd, uint32_t revents, void *userdata) { |
||||||
|
@@ -1330,6 +1332,10 @@ static void service_enter_dead(Service *s, ServiceResult f, bool allow_restart) |
||||||
|
if (f != SERVICE_SUCCESS) |
||||||
|
s->result = f; |
||||||
|
|
||||||
|
+ /* Make sure service_release_resources() doesn't destroy our FD store, while we are changing through |
||||||
|
+ * SERVICE_FAILED/SERVICE_DEAD before entering into SERVICE_AUTO_RESTART. */ |
||||||
|
+ s->n_keep_fd_store++; |
||||||
|
+ |
||||||
|
service_set_state(s, s->result != SERVICE_SUCCESS ? SERVICE_FAILED : SERVICE_DEAD); |
||||||
|
|
||||||
|
if (s->result != SERVICE_SUCCESS) { |
||||||
|
@@ -1351,12 +1357,19 @@ static void service_enter_dead(Service *s, ServiceResult f, bool allow_restart) |
||||||
|
(!IN_SET(s->main_exec_status.code, CLD_KILLED, CLD_DUMPED) || !set_contains(s->restart_prevent_status.signal, INT_TO_PTR(s->main_exec_status.status)))) { |
||||||
|
|
||||||
|
r = service_arm_timer(s, s->restart_usec); |
||||||
|
- if (r < 0) |
||||||
|
+ if (r < 0) { |
||||||
|
+ s->n_keep_fd_store--; |
||||||
|
goto fail; |
||||||
|
+ } |
||||||
|
|
||||||
|
service_set_state(s, SERVICE_AUTO_RESTART); |
||||||
|
} |
||||||
|
|
||||||
|
+ /* The new state is in effect, let's decrease the fd store ref counter again. Let's also readd us to the GC |
||||||
|
+ * queue, so that the fd store is possibly gc'ed again */ |
||||||
|
+ s->n_keep_fd_store--; |
||||||
|
+ unit_add_to_gc_queue(UNIT(s)); |
||||||
|
+ |
||||||
|
s->forbid_restart = false; |
||||||
|
|
||||||
|
/* We want fresh tmpdirs in case service is started again immediately */ |
||||||
|
diff --git a/src/core/service.h b/src/core/service.h |
||||||
|
index 82938a1fc4..e5753f1f4c 100644 |
||||||
|
--- a/src/core/service.h |
||||||
|
+++ b/src/core/service.h |
||||||
|
@@ -215,6 +215,7 @@ struct Service { |
||||||
|
ServiceFDStore *fd_store; |
||||||
|
unsigned n_fd_store; |
||||||
|
unsigned n_fd_store_max; |
||||||
|
+ unsigned n_keep_fd_store; |
||||||
|
}; |
||||||
|
|
||||||
|
extern const UnitVTable service_vtable; |
||||||
|
diff --git a/src/core/unit.c b/src/core/unit.c |
||||||
|
index 22e31a76b3..eff9fdbe70 100644 |
||||||
|
--- a/src/core/unit.c |
||||||
|
+++ b/src/core/unit.c |
||||||
|
@@ -285,7 +285,6 @@ int unit_set_description(Unit *u, const char *description) { |
||||||
|
|
||||||
|
bool unit_may_gc(Unit *u) { |
||||||
|
UnitActiveState state; |
||||||
|
- bool inactive; |
||||||
|
assert(u); |
||||||
|
|
||||||
|
/* Checks whether the unit is ready to be unloaded for garbage collection. |
||||||
|
@@ -303,17 +302,14 @@ bool unit_may_gc(Unit *u) { |
||||||
|
return false; |
||||||
|
|
||||||
|
state = unit_active_state(u); |
||||||
|
- inactive = state == UNIT_INACTIVE; |
||||||
|
|
||||||
|
- /* If the unit is inactive and failed and no job is queued for |
||||||
|
- * it, then release its runtime resources */ |
||||||
|
+ /* If the unit is inactive and failed and no job is queued for it, then release its runtime resources */ |
||||||
|
if (UNIT_IS_INACTIVE_OR_FAILED(state) && |
||||||
|
UNIT_VTABLE(u)->release_resources) |
||||||
|
- UNIT_VTABLE(u)->release_resources(u, inactive); |
||||||
|
+ UNIT_VTABLE(u)->release_resources(u); |
||||||
|
|
||||||
|
- /* But we keep the unit object around for longer when it is |
||||||
|
- * referenced or configured to not be gc'ed */ |
||||||
|
- if (!inactive) |
||||||
|
+ /* But we keep the unit object around for longer when it is referenced or configured to not be gc'ed */ |
||||||
|
+ if (state != UNIT_INACTIVE) |
||||||
|
return false; |
||||||
|
|
||||||
|
if (UNIT_VTABLE(u)->no_gc) |
||||||
|
diff --git a/src/core/unit.h b/src/core/unit.h |
||||||
|
index 232be8164f..3b0fd8d9df 100644 |
||||||
|
--- a/src/core/unit.h |
||||||
|
+++ b/src/core/unit.h |
||||||
|
@@ -358,9 +358,8 @@ struct UnitVTable { |
||||||
|
* even though nothing references it and it isn't active in any way. */ |
||||||
|
bool (*may_gc)(Unit *u); |
||||||
|
|
||||||
|
- /* When the unit is not running and no job for it queued we |
||||||
|
- * shall release its runtime resources */ |
||||||
|
- void (*release_resources)(Unit *u, bool inactive); |
||||||
|
+ /* When the unit is not running and no job for it queued we shall release its runtime resources */ |
||||||
|
+ void (*release_resources)(Unit *u); |
||||||
|
|
||||||
|
/* Return true when this unit is suitable for snapshotting */ |
||||||
|
bool (*check_snapshot)(Unit *u); |
@ -0,0 +1,145 @@ |
|||||||
|
From c53791854050661d34417f12755837abd74d213a Mon Sep 17 00:00:00 2001 |
||||||
|
From: Evgeny Vereshchagin <evvers@ya.ru> |
||||||
|
Date: Tue, 17 Nov 2015 11:21:23 +0000 |
||||||
|
Subject: [PATCH] tests: add basic journal test |
||||||
|
|
||||||
|
(cherry picked from commit 1c36b4a73b876258fbe01fbe9bc9b750b7dcc9ce) |
||||||
|
(cherry picked from commit e974b9915ccc7bf56d23fd6fc67631990d893c89) |
||||||
|
Resolves: #1803802 |
||||||
|
--- |
||||||
|
test/TEST-04-JOURNAL/Makefile | 1 + |
||||||
|
test/TEST-04-JOURNAL/test-journal.sh | 18 +++++++ |
||||||
|
test/TEST-04-JOURNAL/test.sh | 76 ++++++++++++++++++++++++++++ |
||||||
|
test/test-functions | 2 +- |
||||||
|
4 files changed, 96 insertions(+), 1 deletion(-) |
||||||
|
create mode 120000 test/TEST-04-JOURNAL/Makefile |
||||||
|
create mode 100755 test/TEST-04-JOURNAL/test-journal.sh |
||||||
|
create mode 100755 test/TEST-04-JOURNAL/test.sh |
||||||
|
|
||||||
|
diff --git a/test/TEST-04-JOURNAL/Makefile b/test/TEST-04-JOURNAL/Makefile |
||||||
|
new file mode 120000 |
||||||
|
index 0000000000..e9f93b1104 |
||||||
|
--- /dev/null |
||||||
|
+++ b/test/TEST-04-JOURNAL/Makefile |
||||||
|
@@ -0,0 +1 @@ |
||||||
|
+../TEST-01-BASIC/Makefile |
||||||
|
\ No newline at end of file |
||||||
|
diff --git a/test/TEST-04-JOURNAL/test-journal.sh b/test/TEST-04-JOURNAL/test-journal.sh |
||||||
|
new file mode 100755 |
||||||
|
index 0000000000..c75f396ceb |
||||||
|
--- /dev/null |
||||||
|
+++ b/test/TEST-04-JOURNAL/test-journal.sh |
||||||
|
@@ -0,0 +1,18 @@ |
||||||
|
+#!/bin/bash |
||||||
|
+ |
||||||
|
+set -x |
||||||
|
+set -e |
||||||
|
+set -o pipefail |
||||||
|
+ |
||||||
|
+# Test stdout stream |
||||||
|
+ |
||||||
|
+# Skip empty lines |
||||||
|
+ID=$(journalctl --new-id128 | sed -n 2p) |
||||||
|
+>/expected |
||||||
|
+printf $'\n\n\n' | systemd-cat -t "$ID" --level-prefix false |
||||||
|
+journalctl --flush |
||||||
|
+journalctl -b -o cat -t "$ID" >/output |
||||||
|
+cmp /expected /output |
||||||
|
+ |
||||||
|
+touch /testok |
||||||
|
+exit 0 |
||||||
|
diff --git a/test/TEST-04-JOURNAL/test.sh b/test/TEST-04-JOURNAL/test.sh |
||||||
|
new file mode 100755 |
||||||
|
index 0000000000..e37cb7d412 |
||||||
|
--- /dev/null |
||||||
|
+++ b/test/TEST-04-JOURNAL/test.sh |
||||||
|
@@ -0,0 +1,76 @@ |
||||||
|
+#!/bin/bash |
||||||
|
+# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*- |
||||||
|
+# ex: ts=8 sw=4 sts=4 et filetype=sh |
||||||
|
+TEST_DESCRIPTION="Journal-related tests" |
||||||
|
+ |
||||||
|
+. $TEST_BASE_DIR/test-functions |
||||||
|
+ |
||||||
|
+check_result_qemu() { |
||||||
|
+ ret=1 |
||||||
|
+ mkdir -p $TESTDIR/root |
||||||
|
+ mount ${LOOPDEV}p1 $TESTDIR/root |
||||||
|
+ [[ -e $TESTDIR/root/testok ]] && ret=0 |
||||||
|
+ [[ -f $TESTDIR/root/failed ]] && cp -a $TESTDIR/root/failed $TESTDIR |
||||||
|
+ cp -a $TESTDIR/root/var/log/journal $TESTDIR |
||||||
|
+ umount $TESTDIR/root |
||||||
|
+ [[ -f $TESTDIR/failed ]] && cat $TESTDIR/failed |
||||||
|
+ ls -l $TESTDIR/journal/*/*.journal |
||||||
|
+ test -s $TESTDIR/failed && ret=$(($ret+1)) |
||||||
|
+ return $ret |
||||||
|
+} |
||||||
|
+ |
||||||
|
+test_run() { |
||||||
|
+ if run_qemu; then |
||||||
|
+ check_result_qemu || return 1 |
||||||
|
+ else |
||||||
|
+ dwarn "can't run QEMU, skipping" |
||||||
|
+ fi |
||||||
|
+ if check_nspawn; then |
||||||
|
+ run_nspawn |
||||||
|
+ check_result_nspawn || return 1 |
||||||
|
+ else |
||||||
|
+ dwarn "can't run systemd-nspawn, skipping" |
||||||
|
+ fi |
||||||
|
+ return 0 |
||||||
|
+} |
||||||
|
+ |
||||||
|
+test_setup() { |
||||||
|
+ create_empty_image |
||||||
|
+ mkdir -p $TESTDIR/root |
||||||
|
+ mount ${LOOPDEV}p1 $TESTDIR/root |
||||||
|
+ |
||||||
|
+ # Create what will eventually be our root filesystem onto an overlay |
||||||
|
+ ( |
||||||
|
+ LOG_LEVEL=5 |
||||||
|
+ eval $(udevadm info --export --query=env --name=${LOOPDEV}p2) |
||||||
|
+ |
||||||
|
+ setup_basic_environment |
||||||
|
+ |
||||||
|
+ # setup the testsuite service |
||||||
|
+ cat >$initdir/etc/systemd/system/testsuite.service <<EOF |
||||||
|
+[Unit] |
||||||
|
+Description=Testsuite service |
||||||
|
+After=multi-user.target |
||||||
|
+ |
||||||
|
+[Service] |
||||||
|
+ExecStart=/test-journal.sh |
||||||
|
+Type=oneshot |
||||||
|
+EOF |
||||||
|
+ |
||||||
|
+ cp test-journal.sh $initdir/ |
||||||
|
+ |
||||||
|
+ setup_testsuite |
||||||
|
+ ) |
||||||
|
+ setup_nspawn_root |
||||||
|
+ |
||||||
|
+ ddebug "umount $TESTDIR/root" |
||||||
|
+ umount $TESTDIR/root |
||||||
|
+} |
||||||
|
+ |
||||||
|
+test_cleanup() { |
||||||
|
+ umount $TESTDIR/root 2>/dev/null |
||||||
|
+ [[ $LOOPDEV ]] && losetup -d $LOOPDEV |
||||||
|
+ return 0 |
||||||
|
+} |
||||||
|
+ |
||||||
|
+do_test "$@" |
||||||
|
diff --git a/test/test-functions b/test/test-functions |
||||||
|
index e50ce556fd..d5e9650903 100644 |
||||||
|
--- a/test/test-functions |
||||||
|
+++ b/test/test-functions |
||||||
|
@@ -12,7 +12,7 @@ if ! ROOTLIBDIR=$(pkg-config --variable=systemdutildir systemd); then |
||||||
|
ROOTLIBDIR=/usr/lib/systemd |
||||||
|
fi |
||||||
|
|
||||||
|
-BASICTOOLS="test sh bash setsid loadkeys setfont login sulogin gzip sleep echo mount umount cryptsetup date dmsetup modprobe chmod chown ln" |
||||||
|
+BASICTOOLS="test sh bash setsid loadkeys setfont login sulogin gzip sleep echo mount umount cryptsetup date dmsetup modprobe chmod chown ln sed cmp tee" |
||||||
|
DEBUGTOOLS="df free ls stty cat ps ln ip route dmesg dhclient mkdir cp ping dhclient strace less grep id tty touch du sort hostname" |
||||||
|
|
||||||
|
function find_qemu_bin() { |
@ -0,0 +1,54 @@ |
|||||||
|
From e3468af46bd16e3550c25a0770f47f0bf21780f3 Mon Sep 17 00:00:00 2001 |
||||||
|
From: Evgeny Vereshchagin <evvers@ya.ru> |
||||||
|
Date: Wed, 30 Dec 2015 03:33:43 +0000 |
||||||
|
Subject: [PATCH] tests: add regression test for `systemctl restart |
||||||
|
systemd-journald` |
||||||
|
|
||||||
|
See https://github.com/systemd/systemd/issues/2236 |
||||||
|
|
||||||
|
(cherry picked from commit 3889613ec6bc54b9e02955f62b9d5c5b571c3d4b) |
||||||
|
(cherry picked from commit 4dc893c03fe9c56a3d3070fb8583f5584014aa49) |
||||||
|
Resolves: #1803802 |
||||||
|
--- |
||||||
|
test/TEST-04-JOURNAL/test-journal.sh | 8 ++++++++ |
||||||
|
test/TEST-04-JOURNAL/test.sh | 9 +++++++++ |
||||||
|
2 files changed, 17 insertions(+) |
||||||
|
|
||||||
|
diff --git a/test/TEST-04-JOURNAL/test-journal.sh b/test/TEST-04-JOURNAL/test-journal.sh |
||||||
|
index c75f396ceb..701b0cf724 100755 |
||||||
|
--- a/test/TEST-04-JOURNAL/test-journal.sh |
||||||
|
+++ b/test/TEST-04-JOURNAL/test-journal.sh |
||||||
|
@@ -14,5 +14,13 @@ journalctl --flush |
||||||
|
journalctl -b -o cat -t "$ID" >/output |
||||||
|
cmp /expected /output |
||||||
|
|
||||||
|
+# Don't lose streams on restart |
||||||
|
+systemctl start forever-print-hola |
||||||
|
+sleep 3 |
||||||
|
+systemctl restart systemd-journald |
||||||
|
+sleep 3 |
||||||
|
+systemctl stop forever-print-hola |
||||||
|
+[[ ! -f "/i-lose-my-logs" ]] |
||||||
|
+ |
||||||
|
touch /testok |
||||||
|
exit 0 |
||||||
|
diff --git a/test/TEST-04-JOURNAL/test.sh b/test/TEST-04-JOURNAL/test.sh |
||||||
|
index e37cb7d412..6aea67ba4e 100755 |
||||||
|
--- a/test/TEST-04-JOURNAL/test.sh |
||||||
|
+++ b/test/TEST-04-JOURNAL/test.sh |
||||||
|
@@ -55,6 +55,15 @@ After=multi-user.target |
||||||
|
[Service] |
||||||
|
ExecStart=/test-journal.sh |
||||||
|
Type=oneshot |
||||||
|
+EOF |
||||||
|
+ |
||||||
|
+ cat >$initdir/etc/systemd/system/forever-print-hola.service <<EOF |
||||||
|
+[Unit] |
||||||
|
+Description=ForeverPrintHola service |
||||||
|
+ |
||||||
|
+[Service] |
||||||
|
+Type=simple |
||||||
|
+ExecStart=/bin/sh -x -c 'while :; do printf "Hola\n" || touch /i-lose-my-logs; sleep 1; done' |
||||||
|
EOF |
||||||
|
|
||||||
|
cp test-journal.sh $initdir/ |
@ -0,0 +1,33 @@ |
|||||||
|
From 39ab4de70c6f2b35ec735195803f4bd1eb5892c1 Mon Sep 17 00:00:00 2001 |
||||||
|
From: Evgeny Vereshchagin <evvers@ya.ru> |
||||||
|
Date: Thu, 20 Oct 2016 13:18:12 +0000 |
||||||
|
Subject: [PATCH] tests: add test that journald keeps fds over termination by |
||||||
|
signal |
||||||
|
|
||||||
|
This test fails before previous commit, and passes with it. |
||||||
|
|
||||||
|
(cherry picked from commit bff653e3970bb79832568ae86b095ee530b62302) |
||||||
|
(cherry picked from commit ee8f69ae5ddac6f05c56ea7dbcb76fbbb2e355ee) |
||||||
|
Resolves: #1803802 |
||||||
|
--- |
||||||
|
test/TEST-04-JOURNAL/test-journal.sh | 8 ++++++++ |
||||||
|
1 file changed, 8 insertions(+) |
||||||
|
|
||||||
|
diff --git a/test/TEST-04-JOURNAL/test-journal.sh b/test/TEST-04-JOURNAL/test-journal.sh |
||||||
|
index 701b0cf724..d0b05c46d6 100755 |
||||||
|
--- a/test/TEST-04-JOURNAL/test-journal.sh |
||||||
|
+++ b/test/TEST-04-JOURNAL/test-journal.sh |
||||||
|
@@ -22,5 +22,13 @@ sleep 3 |
||||||
|
systemctl stop forever-print-hola |
||||||
|
[[ ! -f "/i-lose-my-logs" ]] |
||||||
|
|
||||||
|
+# https://github.com/systemd/systemd/issues/4408 |
||||||
|
+rm -f /i-lose-my-logs |
||||||
|
+systemctl start forever-print-hola |
||||||
|
+sleep 3 |
||||||
|
+systemctl kill --signal=SIGKILL systemd-journald |
||||||
|
+sleep 3 |
||||||
|
+[[ ! -f "/i-lose-my-logs" ]] |
||||||
|
+ |
||||||
|
touch /testok |
||||||
|
exit 0 |
@ -0,0 +1,50 @@ |
|||||||
|
From d8c33d7a4e0d9b4375159776913f5c3fd2905c21 Mon Sep 17 00:00:00 2001 |
||||||
|
From: Jan Synacek <jsynacek@redhat.com> |
||||||
|
Date: Tue, 7 Jan 2020 11:22:26 +0100 |
||||||
|
Subject: [PATCH] journal: do not trigger assertion when journal_file_close() |
||||||
|
get NULL |
||||||
|
|
||||||
|
We generally expect destructors to not complain if a NULL argument is passed. |
||||||
|
|
||||||
|
Closes #12400. |
||||||
|
|
||||||
|
(cherry picked from commit c377a6f3ad3d9bed4ce7e873e8e9ec6b1650c57d) |
||||||
|
(cherry picked from commit 248925c68092bab7ce0231449176db153f55d818) |
||||||
|
Resolves: #1807798 |
||||||
|
--- |
||||||
|
src/journal/journal-file.c | 3 ++- |
||||||
|
src/journal/journald-server.c | 7 ++----- |
||||||
|
2 files changed, 4 insertions(+), 6 deletions(-) |
||||||
|
|
||||||
|
diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c |
||||||
|
index 586f620e21..cf8dad3fcd 100644 |
||||||
|
--- a/src/journal/journal-file.c |
||||||
|
+++ b/src/journal/journal-file.c |
||||||
|
@@ -129,7 +129,8 @@ int journal_file_set_offline(JournalFile *f) { |
||||||
|
} |
||||||
|
|
||||||
|
void journal_file_close(JournalFile *f) { |
||||||
|
- assert(f); |
||||||
|
+ if (!f) |
||||||
|
+ return; |
||||||
|
|
||||||
|
#ifdef HAVE_GCRYPT |
||||||
|
/* Write the final tag */ |
||||||
|
diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c |
||||||
|
index aaabb2f7ab..ffe2daa7be 100644 |
||||||
|
--- a/src/journal/journald-server.c |
||||||
|
+++ b/src/journal/journald-server.c |
||||||
|
@@ -1933,11 +1933,8 @@ void server_done(Server *s) { |
||||||
|
while (s->stdout_streams) |
||||||
|
stdout_stream_free(s->stdout_streams); |
||||||
|
|
||||||
|
- if (s->system_journal) |
||||||
|
- journal_file_close(s->system_journal); |
||||||
|
- |
||||||
|
- if (s->runtime_journal) |
||||||
|
- journal_file_close(s->runtime_journal); |
||||||
|
+ (void) journal_file_close(s->system_journal); |
||||||
|
+ (void) journal_file_close(s->runtime_journal); |
||||||
|
|
||||||
|
while ((f = ordered_hashmap_steal_first(s->user_journals))) |
||||||
|
journal_file_close(f); |
@ -0,0 +1,53 @@ |
|||||||
|
From 5b7b538fcd268288cea8d8b7f16f839afbf74f39 Mon Sep 17 00:00:00 2001 |
||||||
|
From: Lennart Poettering <lennart@poettering.net> |
||||||
|
Date: Wed, 28 Nov 2018 12:41:44 +0100 |
||||||
|
Subject: [PATCH] mount: don't propagate errors from mount_setup_unit() further |
||||||
|
up |
||||||
|
|
||||||
|
If we can't process a specific line in /proc/self/mountinfo we should |
||||||
|
log about it (which we do), but this should not affect other lines, nor |
||||||
|
further processing of mount units. Let's keep these failures local. |
||||||
|
|
||||||
|
Fixes: #10874 |
||||||
|
(cherry picked from commit ba0d56f55f2073164799be714b5bd1aad94d059a) |
||||||
|
Resolves: #1809159 |
||||||
|
--- |
||||||
|
src/core/mount.c | 9 +++------ |
||||||
|
1 file changed, 3 insertions(+), 6 deletions(-) |
||||||
|
|
||||||
|
diff --git a/src/core/mount.c b/src/core/mount.c |
||||||
|
index 3167bd6bb1..126038c27f 100644 |
||||||
|
--- a/src/core/mount.c |
||||||
|
+++ b/src/core/mount.c |
||||||
|
@@ -1571,7 +1571,7 @@ fail: |
||||||
|
static int mount_load_proc_self_mountinfo(Manager *m, bool set_flags) { |
||||||
|
_cleanup_(mnt_free_tablep) struct libmnt_table *t = NULL; |
||||||
|
_cleanup_(mnt_free_iterp) struct libmnt_iter *i = NULL; |
||||||
|
- int r = 0; |
||||||
|
+ int r; |
||||||
|
|
||||||
|
assert(m); |
||||||
|
|
||||||
|
@@ -1587,7 +1587,6 @@ static int mount_load_proc_self_mountinfo(Manager *m, bool set_flags) { |
||||||
|
if (r < 0) |
||||||
|
return log_error_errno(r, "Failed to parse /proc/self/mountinfo: %m"); |
||||||
|
|
||||||
|
- r = 0; |
||||||
|
for (;;) { |
||||||
|
const char *device, *path, *options, *fstype; |
||||||
|
_cleanup_free_ const char *d = NULL, *p = NULL; |
||||||
|
@@ -1615,12 +1614,10 @@ static int mount_load_proc_self_mountinfo(Manager *m, bool set_flags) { |
||||||
|
|
||||||
|
(void) device_found_node(m, d, true, DEVICE_FOUND_MOUNT, set_flags); |
||||||
|
|
||||||
|
- k = mount_setup_unit(m, d, p, options, fstype, set_flags); |
||||||
|
- if (r == 0 && k < 0) |
||||||
|
- r = k; |
||||||
|
+ (void) mount_setup_unit(m, d, p, options, fstype, set_flags); |
||||||
|
} |
||||||
|
|
||||||
|
- return r; |
||||||
|
+ return 0; |
||||||
|
} |
||||||
|
|
||||||
|
static void mount_shutdown(Manager *m) { |
@ -0,0 +1,35 @@ |
|||||||
|
From 58407f55ccfc83eef2bd14e672d13213ef93069d Mon Sep 17 00:00:00 2001 |
||||||
|
From: Lennart Poettering <lennart@poettering.net> |
||||||
|
Date: Wed, 28 Nov 2018 14:51:04 +0100 |
||||||
|
Subject: [PATCH] mount: when allocating a Mount object based on |
||||||
|
/proc/self/mountinfo mark it so |
||||||
|
|
||||||
|
Let's set 'from_proc_self_mountinfo' right away, since we know its from |
||||||
|
there. This is important so that when the load queue is dispatched (and |
||||||
|
thus mount_load() called) this |
||||||
|
fact is already known. |
||||||
|
|
||||||
|
(cherry picked from commit 6d7e89b07065b8c49af47aaf1ccc336d017fc3a2) |
||||||
|
Related: #1809159 |
||||||
|
--- |
||||||
|
src/core/mount.c | 7 +++++++ |
||||||
|
1 file changed, 7 insertions(+) |
||||||
|
|
||||||
|
diff --git a/src/core/mount.c b/src/core/mount.c |
||||||
|
index 126038c27f..34c4b548ad 100644 |
||||||
|
--- a/src/core/mount.c |
||||||
|
+++ b/src/core/mount.c |
||||||
|
@@ -1480,6 +1480,13 @@ static int mount_setup_unit( |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
+ /* This unit was generated because /proc/self/mountinfo reported it. Remember this, so that by the time we load |
||||||
|
+ * the unit file for it (and thus add in extra deps right after) we know what source to attributes the deps |
||||||
|
+ * to.*/ |
||||||
|
+ MOUNT(u)->from_proc_self_mountinfo = true; |
||||||
|
+ |
||||||
|
+ /* We have only allocated the stub now, let's enqueue this unit for loading now, so that everything else is |
||||||
|
+ * loaded in now. */ |
||||||
|
unit_add_to_load_queue(u); |
||||||
|
changed = true; |
||||||
|
} else { |
@ -0,0 +1,60 @@ |
|||||||
|
From f57ee0c7862260f3c7054b224f360cdef5140685 Mon Sep 17 00:00:00 2001 |
||||||
|
From: Lennart Poettering <lennart@poettering.net> |
||||||
|
Date: Tue, 19 May 2015 16:00:24 +0200 |
||||||
|
Subject: [PATCH] core: enforce a ratelimiter when stopping units due to |
||||||
|
StopWhenUnneeded=1 |
||||||
|
|
||||||
|
Otherwise we might end up in an endless stop loop. |
||||||
|
|
||||||
|
http://lists.freedesktop.org/archives/systemd-devel/2015-April/030224.html |
||||||
|
(cherry picked from commit bea355dac94e82697aa98e25d80ee4248263bf92) |
||||||
|
(cherry picked from commit 6c72a575c7c61e17c8e96b23042f7b4a5ac39339) |
||||||
|
|
||||||
|
Related: #1810576 |
||||||
|
--- |
||||||
|
src/core/unit.c | 10 ++++++++++ |
||||||
|
src/core/unit.h | 3 +++ |
||||||
|
2 files changed, 13 insertions(+) |
||||||
|
|
||||||
|
diff --git a/src/core/unit.c b/src/core/unit.c |
||||||
|
index eff9fdbe70..583b9fae28 100644 |
||||||
|
--- a/src/core/unit.c |
||||||
|
+++ b/src/core/unit.c |
||||||
|
@@ -97,6 +97,8 @@ Unit *unit_new(Manager *m, size_t size) { |
||||||
|
u->on_failure_job_mode = JOB_REPLACE; |
||||||
|
u->sigchldgen = 0; |
||||||
|
|
||||||
|
+ RATELIMIT_INIT(u->check_unneeded_ratelimit, 10 * USEC_PER_SEC, 16); |
||||||
|
+ |
||||||
|
return u; |
||||||
|
} |
||||||
|
|
||||||
|
@@ -1594,6 +1596,14 @@ static void unit_check_unneeded(Unit *u) { |
||||||
|
if (unit_active_or_pending(other)) |
||||||
|
return; |
||||||
|
|
||||||
|
+ /* If stopping a unit fails continously we might enter a stop |
||||||
|
+ * loop here, hence stop acting on the service being |
||||||
|
+ * unnecessary after a while. */ |
||||||
|
+ if (!ratelimit_test(&u->check_unneeded_ratelimit)) { |
||||||
|
+ log_unit_warning(u->id, "Unit not needed anymore, but not stopping since we tried this too often recently."); |
||||||
|
+ return; |
||||||
|
+ } |
||||||
|
+ |
||||||
|
log_unit_info(u->id, "Unit %s is not needed anymore. Stopping.", u->id); |
||||||
|
|
||||||
|
/* Ok, nobody needs us anymore. Sniff. Then let's commit suicide */ |
||||||
|
diff --git a/src/core/unit.h b/src/core/unit.h |
||||||
|
index 3b0fd8d9df..29353ea81c 100644 |
||||||
|
--- a/src/core/unit.h |
||||||
|
+++ b/src/core/unit.h |
||||||
|
@@ -185,6 +185,9 @@ struct Unit { |
||||||
|
/* Error code when we didn't manage to load the unit (negative) */ |
||||||
|
int load_error; |
||||||
|
|
||||||
|
+ /* Make sure we never enter endless loops with the check unneeded logic */ |
||||||
|
+ RateLimit check_unneeded_ratelimit; |
||||||
|
+ |
||||||
|
/* Cached unit file state and preset */ |
||||||
|
UnitFileState unit_file_state; |
||||||
|
int unit_file_preset; |
@ -0,0 +1,343 @@ |
|||||||
|
From c7c8a7648623a25c00dc585bd42b9037a20396c8 Mon Sep 17 00:00:00 2001 |
||||||
|
From: Lennart Poettering <lennart@poettering.net> |
||||||
|
Date: Thu, 9 Aug 2018 16:26:27 +0200 |
||||||
|
Subject: [PATCH] core: rework StopWhenUnneeded= logic |
||||||
|
|
||||||
|
Previously, we'd act immediately on StopWhenUnneeded= when a unit state |
||||||
|
changes. With this rework we'll maintain a queue instead: whenever |
||||||
|
there's the chance that StopWhenUneeded= might have an effect we enqueue |
||||||
|
the unit, and process it later when we have nothing better to do. |
||||||
|
|
||||||
|
This should make the implementation a bit more reliable, as the unit notify event |
||||||
|
cannot immediately enqueue tons of side-effect jobs that might |
||||||
|
contradict each other, but we do so only in a strictly ordered fashion, |
||||||
|
from the main event loop. |
||||||
|
|
||||||
|
This slightly changes the check when to consider a unit "unneeded". |
||||||
|
Previously, we'd assume that a unit in "deactivating" state could also |
||||||
|
be cleaned up. With this new logic we'll only consider units unneeded |
||||||
|
that are fully up and have no job queued. This means that whenever |
||||||
|
there's something pending for a unit we won't clean it up. |
||||||
|
|
||||||
|
(cherry picked from commit a3c1168ac293f16d9343d248795bb4c246aaff4a) |
||||||
|
(cherry picked from commit 65ebf5e453846e29ab5894670a83b5d8b942c858) |
||||||
|
|
||||||
|
Resolves: #1810576 |
||||||
|
--- |
||||||
|
src/core/manager.c | 43 +++++++++++++++ |
||||||
|
src/core/manager.h | 3 ++ |
||||||
|
src/core/unit.c | 132 ++++++++++++++++++++++++--------------------- |
||||||
|
src/core/unit.h | 7 +++ |
||||||
|
4 files changed, 124 insertions(+), 61 deletions(-) |
||||||
|
|
||||||
|
diff --git a/src/core/manager.c b/src/core/manager.c |
||||||
|
index 4c87ad8a2f..f0553b4df9 100644 |
||||||
|
--- a/src/core/manager.c |
||||||
|
+++ b/src/core/manager.c |
||||||
|
@@ -961,6 +961,45 @@ static unsigned manager_dispatch_gc_queue(Manager *m) { |
||||||
|
return n; |
||||||
|
} |
||||||
|
|
||||||
|
+static unsigned manager_dispatch_stop_when_unneeded_queue(Manager *m) { |
||||||
|
+ unsigned n = 0; |
||||||
|
+ Unit *u; |
||||||
|
+ int r; |
||||||
|
+ |
||||||
|
+ assert(m); |
||||||
|
+ |
||||||
|
+ while ((u = m->stop_when_unneeded_queue)) { |
||||||
|
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; |
||||||
|
+ assert(m->stop_when_unneeded_queue); |
||||||
|
+ |
||||||
|
+ assert(u->in_stop_when_unneeded_queue); |
||||||
|
+ LIST_REMOVE(stop_when_unneeded_queue, m->stop_when_unneeded_queue, u); |
||||||
|
+ u->in_stop_when_unneeded_queue = false; |
||||||
|
+ |
||||||
|
+ n++; |
||||||
|
+ |
||||||
|
+ if (!unit_is_unneeded(u)) |
||||||
|
+ continue; |
||||||
|
+ |
||||||
|
+ log_unit_debug(u->id, "Unit is not needed anymore."); |
||||||
|
+ |
||||||
|
+ /* If stopping a unit fails continuously we might enter a stop loop here, hence stop acting on the |
||||||
|
+ * service being unnecessary after a while. */ |
||||||
|
+ |
||||||
|
+ if (!ratelimit_test(&u->check_unneeded_ratelimit)) { |
||||||
|
+ log_unit_warning(u->id, "Unit not needed anymore, but not stopping since we tried this too often recently."); |
||||||
|
+ continue; |
||||||
|
+ } |
||||||
|
+ |
||||||
|
+ /* Ok, nobody needs us anymore. Sniff. Then let's commit suicide */ |
||||||
|
+ r = manager_add_job(u->manager, JOB_STOP, u, JOB_FAIL, true, &error, NULL); |
||||||
|
+ if (r < 0) |
||||||
|
+ log_unit_warning_errno(u->id, r, "Failed to enqueue stop job, ignoring: %s", bus_error_message(&error, r)); |
||||||
|
+ } |
||||||
|
+ |
||||||
|
+ return n; |
||||||
|
+} |
||||||
|
+ |
||||||
|
static void manager_clear_jobs_and_units(Manager *m) { |
||||||
|
Unit *u; |
||||||
|
|
||||||
|
@@ -977,6 +1016,7 @@ static void manager_clear_jobs_and_units(Manager *m) { |
||||||
|
assert(!m->dbus_job_queue); |
||||||
|
assert(!m->cleanup_queue); |
||||||
|
assert(!m->gc_queue); |
||||||
|
+ assert(!m->stop_when_unneeded_queue); |
||||||
|
|
||||||
|
assert(hashmap_isempty(m->jobs)); |
||||||
|
assert(hashmap_isempty(m->units)); |
||||||
|
@@ -2259,6 +2299,9 @@ int manager_loop(Manager *m) { |
||||||
|
if (manager_dispatch_cgroup_queue(m) > 0) |
||||||
|
continue; |
||||||
|
|
||||||
|
+ if (manager_dispatch_stop_when_unneeded_queue(m) > 0) |
||||||
|
+ continue; |
||||||
|
+ |
||||||
|
if (manager_dispatch_dbus_queue(m) > 0) |
||||||
|
continue; |
||||||
|
|
||||||
|
diff --git a/src/core/manager.h b/src/core/manager.h |
||||||
|
index cfc564dfb6..f9280956e9 100644 |
||||||
|
--- a/src/core/manager.h |
||||||
|
+++ b/src/core/manager.h |
||||||
|
@@ -117,6 +117,9 @@ struct Manager { |
||||||
|
/* Target units whose default target dependencies haven't been set yet */ |
||||||
|
LIST_HEAD(Unit, target_deps_queue); |
||||||
|
|
||||||
|
+ /* Units that might be subject to StopWhenUnneeded= clean-up */ |
||||||
|
+ LIST_HEAD(Unit, stop_when_unneeded_queue); |
||||||
|
+ |
||||||
|
sd_event *event; |
||||||
|
|
||||||
|
/* We use two hash tables here, since the same PID might be |
||||||
|
diff --git a/src/core/unit.c b/src/core/unit.c |
||||||
|
index 583b9fae28..dc2df4c89c 100644 |
||||||
|
--- a/src/core/unit.c |
||||||
|
+++ b/src/core/unit.c |
||||||
|
@@ -380,6 +380,22 @@ void unit_add_to_dbus_queue(Unit *u) { |
||||||
|
u->in_dbus_queue = true; |
||||||
|
} |
||||||
|
|
||||||
|
+void unit_add_to_stop_when_unneeded_queue(Unit *u) { |
||||||
|
+ assert(u); |
||||||
|
+ |
||||||
|
+ if (u->in_stop_when_unneeded_queue) |
||||||
|
+ return; |
||||||
|
+ |
||||||
|
+ if (!u->stop_when_unneeded) |
||||||
|
+ return; |
||||||
|
+ |
||||||
|
+ if (!UNIT_IS_ACTIVE_OR_RELOADING(unit_active_state(u))) |
||||||
|
+ return; |
||||||
|
+ |
||||||
|
+ LIST_PREPEND(stop_when_unneeded_queue, u->manager->stop_when_unneeded_queue, u); |
||||||
|
+ u->in_stop_when_unneeded_queue = true; |
||||||
|
+} |
||||||
|
+ |
||||||
|
static void bidi_set_free(Unit *u, Set *s) { |
||||||
|
Iterator i; |
||||||
|
Unit *other; |
||||||
|
@@ -544,6 +560,9 @@ void unit_free(Unit *u) { |
||||||
|
u->manager->n_in_gc_queue--; |
||||||
|
} |
||||||
|
|
||||||
|
+ if (u->in_stop_when_unneeded_queue) |
||||||
|
+ LIST_REMOVE(stop_when_unneeded_queue, u->manager->stop_when_unneeded_queue, u); |
||||||
|
+ |
||||||
|
if (u->on_console) |
||||||
|
manager_unref_console(u->manager); |
||||||
|
|
||||||
|
@@ -1565,49 +1584,68 @@ bool unit_can_reload(Unit *u) { |
||||||
|
return UNIT_VTABLE(u)->can_reload(u); |
||||||
|
} |
||||||
|
|
||||||
|
-static void unit_check_unneeded(Unit *u) { |
||||||
|
- Iterator i; |
||||||
|
- Unit *other; |
||||||
|
+bool unit_is_unneeded(Unit *u) { |
||||||
|
+ static const UnitDependency deps[] = { |
||||||
|
+ UNIT_REQUIRED_BY, |
||||||
|
+ UNIT_REQUIRED_BY_OVERRIDABLE, |
||||||
|
+ UNIT_WANTED_BY, |
||||||
|
+ UNIT_BOUND_BY, |
||||||
|
+ }; |
||||||
|
+ size_t j; |
||||||
|
|
||||||
|
assert(u); |
||||||
|
|
||||||
|
- /* If this service shall be shut down when unneeded then do |
||||||
|
- * so. */ |
||||||
|
- |
||||||
|
if (!u->stop_when_unneeded) |
||||||
|
- return; |
||||||
|
+ return false; |
||||||
|
|
||||||
|
- if (!UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(u))) |
||||||
|
- return; |
||||||
|
+ /* Don't clean up while the unit is transitioning or is even inactive. */ |
||||||
|
+ if (!UNIT_IS_ACTIVE_OR_RELOADING(unit_active_state(u))) |
||||||
|
+ return false; |
||||||
|
+ if (u->job) |
||||||
|
+ return false; |
||||||
|
|
||||||
|
- SET_FOREACH(other, u->dependencies[UNIT_REQUIRED_BY], i) |
||||||
|
- if (unit_active_or_pending(other)) |
||||||
|
- return; |
||||||
|
+ for (j = 0; j < ELEMENTSOF(deps); j++) { |
||||||
|
+ Unit *other; |
||||||
|
+ Iterator i; |
||||||
|
|
||||||
|
- SET_FOREACH(other, u->dependencies[UNIT_REQUIRED_BY_OVERRIDABLE], i) |
||||||
|
- if (unit_active_or_pending(other)) |
||||||
|
- return; |
||||||
|
+ /* If a dependending unit has a job queued, or is active (or in transitioning), or is marked for |
||||||
|
+ * restart, then don't clean this one up. */ |
||||||
|
|
||||||
|
- SET_FOREACH(other, u->dependencies[UNIT_WANTED_BY], i) |
||||||
|
- if (unit_active_or_pending(other)) |
||||||
|
- return; |
||||||
|
+ SET_FOREACH(other, u->dependencies[deps[j]], i) { |
||||||
|
+ if (u->job) |
||||||
|
+ return false; |
||||||
|
|
||||||
|
- SET_FOREACH(other, u->dependencies[UNIT_BOUND_BY], i) |
||||||
|
- if (unit_active_or_pending(other)) |
||||||
|
- return; |
||||||
|
- |
||||||
|
- /* If stopping a unit fails continously we might enter a stop |
||||||
|
- * loop here, hence stop acting on the service being |
||||||
|
- * unnecessary after a while. */ |
||||||
|
- if (!ratelimit_test(&u->check_unneeded_ratelimit)) { |
||||||
|
- log_unit_warning(u->id, "Unit not needed anymore, but not stopping since we tried this too often recently."); |
||||||
|
- return; |
||||||
|
+ if (!UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(other))) |
||||||
|
+ return false; |
||||||
|
+ } |
||||||
|
} |
||||||
|
|
||||||
|
- log_unit_info(u->id, "Unit %s is not needed anymore. Stopping.", u->id); |
||||||
|
+ return true; |
||||||
|
+} |
||||||
|
|
||||||
|
- /* Ok, nobody needs us anymore. Sniff. Then let's commit suicide */ |
||||||
|
- manager_add_job(u->manager, JOB_STOP, u, JOB_FAIL, true, NULL, NULL); |
||||||
|
+static void check_unneeded_dependencies(Unit *u) { |
||||||
|
+ |
||||||
|
+ static const UnitDependency deps[] = { |
||||||
|
+ UNIT_REQUIRES, |
||||||
|
+ UNIT_REQUIRES_OVERRIDABLE, |
||||||
|
+ UNIT_REQUISITE, |
||||||
|
+ UNIT_REQUISITE_OVERRIDABLE, |
||||||
|
+ UNIT_WANTS, |
||||||
|
+ UNIT_BINDS_TO, |
||||||
|
+ }; |
||||||
|
+ size_t j; |
||||||
|
+ |
||||||
|
+ assert(u); |
||||||
|
+ |
||||||
|
+ /* Add all units this unit depends on to the queue that processes StopWhenUnneeded= behaviour. */ |
||||||
|
+ |
||||||
|
+ for (j = 0; j < ELEMENTSOF(deps); j++) { |
||||||
|
+ Unit *other; |
||||||
|
+ Iterator i; |
||||||
|
+ |
||||||
|
+ SET_FOREACH(other, u->dependencies[deps[j]], i) |
||||||
|
+ unit_add_to_stop_when_unneeded_queue(other); |
||||||
|
+ } |
||||||
|
} |
||||||
|
|
||||||
|
static void unit_check_binds_to(Unit *u) { |
||||||
|
@@ -1693,34 +1731,6 @@ static void retroactively_stop_dependencies(Unit *u) { |
||||||
|
manager_add_job(u->manager, JOB_STOP, other, JOB_REPLACE, true, NULL, NULL); |
||||||
|
} |
||||||
|
|
||||||
|
-static void check_unneeded_dependencies(Unit *u) { |
||||||
|
- Iterator i; |
||||||
|
- Unit *other; |
||||||
|
- |
||||||
|
- assert(u); |
||||||
|
- assert(UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(u))); |
||||||
|
- |
||||||
|
- /* Garbage collect services that might not be needed anymore, if enabled */ |
||||||
|
- SET_FOREACH(other, u->dependencies[UNIT_REQUIRES], i) |
||||||
|
- if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other))) |
||||||
|
- unit_check_unneeded(other); |
||||||
|
- SET_FOREACH(other, u->dependencies[UNIT_REQUIRES_OVERRIDABLE], i) |
||||||
|
- if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other))) |
||||||
|
- unit_check_unneeded(other); |
||||||
|
- SET_FOREACH(other, u->dependencies[UNIT_WANTS], i) |
||||||
|
- if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other))) |
||||||
|
- unit_check_unneeded(other); |
||||||
|
- SET_FOREACH(other, u->dependencies[UNIT_REQUISITE], i) |
||||||
|
- if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other))) |
||||||
|
- unit_check_unneeded(other); |
||||||
|
- SET_FOREACH(other, u->dependencies[UNIT_REQUISITE_OVERRIDABLE], i) |
||||||
|
- if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other))) |
||||||
|
- unit_check_unneeded(other); |
||||||
|
- SET_FOREACH(other, u->dependencies[UNIT_BINDS_TO], i) |
||||||
|
- if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other))) |
||||||
|
- unit_check_unneeded(other); |
||||||
|
-} |
||||||
|
- |
||||||
|
void unit_start_on_failure(Unit *u) { |
||||||
|
Unit *other; |
||||||
|
Iterator i; |
||||||
|
@@ -1898,7 +1908,7 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, bool reload_su |
||||||
|
} |
||||||
|
|
||||||
|
/* stop unneeded units regardless if going down was expected or not */ |
||||||
|
- if (UNIT_IS_INACTIVE_OR_DEACTIVATING(ns)) |
||||||
|
+ if (UNIT_IS_INACTIVE_OR_FAILED(ns)) |
||||||
|
check_unneeded_dependencies(u); |
||||||
|
|
||||||
|
if (ns != os && ns == UNIT_FAILED) { |
||||||
|
@@ -1959,7 +1969,7 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, bool reload_su |
||||||
|
if (u->manager->n_reloading <= 0) { |
||||||
|
/* Maybe we finished startup and are now ready for |
||||||
|
* being stopped because unneeded? */ |
||||||
|
- unit_check_unneeded(u); |
||||||
|
+ unit_add_to_stop_when_unneeded_queue(u); |
||||||
|
|
||||||
|
/* Maybe we finished startup, but something we needed |
||||||
|
* has vanished? Let's die then. (This happens when |
||||||
|
diff --git a/src/core/unit.h b/src/core/unit.h |
||||||
|
index 29353ea81c..38c97397ee 100644 |
||||||
|
--- a/src/core/unit.h |
||||||
|
+++ b/src/core/unit.h |
||||||
|
@@ -165,6 +165,9 @@ struct Unit { |
||||||
|
/* Target dependencies queue */ |
||||||
|
LIST_FIELDS(Unit, target_deps_queue); |
||||||
|
|
||||||
|
+ /* Queue of units with StopWhenUnneeded set that shell be checked for clean-up. */ |
||||||
|
+ LIST_FIELDS(Unit, stop_when_unneeded_queue); |
||||||
|
+ |
||||||
|
/* PIDs we keep an eye on. Note that a unit might have many |
||||||
|
* more, but these are the ones we care enough about to |
||||||
|
* process SIGCHLD for */ |
||||||
|
@@ -235,6 +238,7 @@ struct Unit { |
||||||
|
bool in_gc_queue:1; |
||||||
|
bool in_cgroup_queue:1; |
||||||
|
bool in_target_deps_queue:1; |
||||||
|
+ bool in_stop_when_unneeded_queue:1; |
||||||
|
|
||||||
|
bool sent_dbus_new_signal:1; |
||||||
|
|
||||||
|
@@ -508,6 +512,7 @@ void unit_add_to_dbus_queue(Unit *u); |
||||||
|
void unit_add_to_cleanup_queue(Unit *u); |
||||||
|
void unit_add_to_gc_queue(Unit *u); |
||||||
|
void unit_add_to_target_deps_queue(Unit *u); |
||||||
|
+void unit_add_to_stop_when_unneeded_queue(Unit *u); |
||||||
|
|
||||||
|
int unit_merge(Unit *u, Unit *other); |
||||||
|
int unit_merge_by_name(Unit *u, const char *other); |
||||||
|
@@ -627,6 +632,8 @@ int unit_make_transient(Unit *u); |
||||||
|
|
||||||
|
int unit_require_mounts_for(Unit *u, const char *path); |
||||||
|
|
||||||
|
+bool unit_is_unneeded(Unit *u); |
||||||
|
+ |
||||||
|
pid_t unit_control_pid(Unit *u); |
||||||
|
pid_t unit_main_pid(Unit *u); |
||||||
|
|
@ -0,0 +1,53 @@ |
|||||||
|
From 659b97b93d93ad05732831f6f097cf6f2a9c6410 Mon Sep 17 00:00:00 2001 |
||||||
|
From: David Tardon <dtardon@redhat.com> |
||||||
|
Date: Mon, 16 Mar 2020 09:37:22 +0100 |
||||||
|
Subject: [PATCH] fix the fix for #1691511 |
||||||
|
|
||||||
|
The fix for #1691511 should have been used only for existing mounts |
||||||
|
(mount_setup_existing_unit() in current master). |
||||||
|
|
||||||
|
(cherry picked from commit 4584818bea998d257a166c238b829025b6138e55) |
||||||
|
|
||||||
|
Related: #1809159 |
||||||
|
--- |
||||||
|
src/core/mount.c | 6 +++++- |
||||||
|
1 file changed, 5 insertions(+), 1 deletion(-) |
||||||
|
|
||||||
|
diff --git a/src/core/mount.c b/src/core/mount.c |
||||||
|
index 34c4b548ad..56fda1b73f 100644 |
||||||
|
--- a/src/core/mount.c |
||||||
|
+++ b/src/core/mount.c |
||||||
|
@@ -1416,6 +1416,7 @@ static int mount_setup_unit( |
||||||
|
bool load_extras = false; |
||||||
|
MountParameters *p; |
||||||
|
bool delete, changed = false; |
||||||
|
+ bool just_mounted; |
||||||
|
Unit *u; |
||||||
|
int r; |
||||||
|
|
||||||
|
@@ -1489,6 +1490,7 @@ static int mount_setup_unit( |
||||||
|
* loaded in now. */ |
||||||
|
unit_add_to_load_queue(u); |
||||||
|
changed = true; |
||||||
|
+ just_mounted = true; |
||||||
|
} else { |
||||||
|
delete = false; |
||||||
|
|
||||||
|
@@ -1518,6 +1520,8 @@ static int mount_setup_unit( |
||||||
|
load_extras = true; |
||||||
|
changed = true; |
||||||
|
} |
||||||
|
+ |
||||||
|
+ just_mounted = !MOUNT(u)->from_proc_self_mountinfo || MOUNT(u)->just_mounted; |
||||||
|
} |
||||||
|
|
||||||
|
w = strdup(what); |
||||||
|
@@ -1537,7 +1541,7 @@ static int mount_setup_unit( |
||||||
|
|
||||||
|
if (set_flags) { |
||||||
|
MOUNT(u)->is_mounted = true; |
||||||
|
- MOUNT(u)->just_mounted = !MOUNT(u)->from_proc_self_mountinfo || MOUNT(u)->just_mounted; |
||||||
|
+ MOUNT(u)->just_mounted = just_mounted; |
||||||
|
MOUNT(u)->just_changed = changed; |
||||||
|
} |
||||||
|
|
@ -0,0 +1,106 @@ |
|||||||
|
From e525ce5713f8263258c2cdf687adc67108425f6a Mon Sep 17 00:00:00 2001 |
||||||
|
From: Lennart Poettering <lennart@poettering.net> |
||||||
|
Date: Fri, 15 Dec 2017 22:24:16 +0100 |
||||||
|
Subject: [PATCH] sd-bus: when attached to an sd-event loop, disconnect on |
||||||
|
processing errors |
||||||
|
|
||||||
|
If we can't process the bus for some reason we shouldn't just disable |
||||||
|
the event source, but log something and give up on the connection. Hence |
||||||
|
do that, and disconnect. |
||||||
|
|
||||||
|
(cherry-picked from commit 5ae37ad833583e6c1c7765767b7f8360afca3b07) |
||||||
|
|
||||||
|
Resolves: #1817504 |
||||||
|
--- |
||||||
|
src/libsystemd/sd-bus/sd-bus.c | 45 +++++++++++++++++++++------------- |
||||||
|
1 file changed, 28 insertions(+), 17 deletions(-) |
||||||
|
|
||||||
|
diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c |
||||||
|
index 44ed2c7497..2c8cc66367 100644 |
||||||
|
--- a/src/libsystemd/sd-bus/sd-bus.c |
||||||
|
+++ b/src/libsystemd/sd-bus/sd-bus.c |
||||||
|
@@ -3037,8 +3037,10 @@ static int io_callback(sd_event_source *s, int fd, uint32_t revents, void *userd |
||||||
|
assert(bus); |
||||||
|
|
||||||
|
r = sd_bus_process(bus, NULL); |
||||||
|
- if (r < 0) |
||||||
|
- return r; |
||||||
|
+ if (r < 0) { |
||||||
|
+ log_debug_errno(r, "Processing of bus failed, closing down: %m"); |
||||||
|
+ bus_enter_closing(bus); |
||||||
|
+ } |
||||||
|
|
||||||
|
return 1; |
||||||
|
} |
||||||
|
@@ -3050,8 +3052,10 @@ static int time_callback(sd_event_source *s, uint64_t usec, void *userdata) { |
||||||
|
assert(bus); |
||||||
|
|
||||||
|
r = sd_bus_process(bus, NULL); |
||||||
|
- if (r < 0) |
||||||
|
- return r; |
||||||
|
+ if (r < 0) { |
||||||
|
+ log_debug_errno(r, "Processing of bus failed, closing down: %m"); |
||||||
|
+ bus_enter_closing(bus); |
||||||
|
+ } |
||||||
|
|
||||||
|
return 1; |
||||||
|
} |
||||||
|
@@ -3065,38 +3069,45 @@ static int prepare_callback(sd_event_source *s, void *userdata) { |
||||||
|
assert(bus); |
||||||
|
|
||||||
|
e = sd_bus_get_events(bus); |
||||||
|
- if (e < 0) |
||||||
|
- return e; |
||||||
|
+ if (e < 0) { |
||||||
|
+ r = e; |
||||||
|
+ goto fail; |
||||||
|
+ } |
||||||
|
|
||||||
|
if (bus->output_fd != bus->input_fd) { |
||||||
|
|
||||||
|
r = sd_event_source_set_io_events(bus->input_io_event_source, e & POLLIN); |
||||||
|
if (r < 0) |
||||||
|
- return r; |
||||||
|
+ goto fail; |
||||||
|
|
||||||
|
r = sd_event_source_set_io_events(bus->output_io_event_source, e & POLLOUT); |
||||||
|
- if (r < 0) |
||||||
|
- return r; |
||||||
|
- } else { |
||||||
|
+ } else |
||||||
|
r = sd_event_source_set_io_events(bus->input_io_event_source, e); |
||||||
|
- if (r < 0) |
||||||
|
- return r; |
||||||
|
- } |
||||||
|
+ if (r < 0) |
||||||
|
+ goto fail; |
||||||
|
|
||||||
|
r = sd_bus_get_timeout(bus, &until); |
||||||
|
if (r < 0) |
||||||
|
- return r; |
||||||
|
+ goto fail; |
||||||
|
if (r > 0) { |
||||||
|
int j; |
||||||
|
|
||||||
|
j = sd_event_source_set_time(bus->time_event_source, until); |
||||||
|
- if (j < 0) |
||||||
|
- return j; |
||||||
|
+ if (j < 0) { |
||||||
|
+ r = j; |
||||||
|
+ goto fail; |
||||||
|
+ } |
||||||
|
} |
||||||
|
|
||||||
|
r = sd_event_source_set_enabled(bus->time_event_source, r > 0); |
||||||
|
if (r < 0) |
||||||
|
- return r; |
||||||
|
+ goto fail; |
||||||
|
+ |
||||||
|
+ return 1; |
||||||
|
+ |
||||||
|
+fail: |
||||||
|
+ log_debug_errno(r, "Preparing of bus events failed, closing down: %m"); |
||||||
|
+ bus_enter_closing(bus); |
||||||
|
|
||||||
|
return 1; |
||||||
|
} |
@ -0,0 +1,75 @@ |
|||||||
|
From f813fe0bebb2dddf0fe961527c6e840b88d49dc3 Mon Sep 17 00:00:00 2001 |
||||||
|
From: =?UTF-8?q?Michal=20Sekleta=CC=81r?= <msekleta@redhat.com> |
||||||
|
Date: Tue, 4 Feb 2020 14:23:14 +0100 |
||||||
|
Subject: [PATCH] sd-journal: close journal files that were deleted by journald |
||||||
|
before we've setup inotify watch |
||||||
|
|
||||||
|
(cherry-picked from commit 28ca867abdb20d0e4ac1901e2ed669cdb41ea3f6) |
||||||
|
|
||||||
|
Fixes #14695 |
||||||
|
|
||||||
|
Related: #1820073 |
||||||
|
--- |
||||||
|
src/journal/journal-file.c | 2 +- |
||||||
|
src/journal/journal-file.h | 1 + |
||||||
|
src/journal/sd-journal.c | 15 +++++++++++++++ |
||||||
|
3 files changed, 17 insertions(+), 1 deletion(-) |
||||||
|
|
||||||
|
diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c |
||||||
|
index cf8dad3fcd..86a7e2642a 100644 |
||||||
|
--- a/src/journal/journal-file.c |
||||||
|
+++ b/src/journal/journal-file.c |
||||||
|
@@ -337,7 +337,7 @@ static int journal_file_verify_header(JournalFile *f) { |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
-static int journal_file_fstat(JournalFile *f) { |
||||||
|
+int journal_file_fstat(JournalFile *f) { |
||||||
|
assert(f); |
||||||
|
assert(f->fd >= 0); |
||||||
|
|
||||||
|
diff --git a/src/journal/journal-file.h b/src/journal/journal-file.h |
||||||
|
index 37749c4459..ee9772b9bb 100644 |
||||||
|
--- a/src/journal/journal-file.h |
||||||
|
+++ b/src/journal/journal-file.h |
||||||
|
@@ -139,6 +139,7 @@ int journal_file_open( |
||||||
|
|
||||||
|
int journal_file_set_offline(JournalFile *f); |
||||||
|
void journal_file_close(JournalFile *j); |
||||||
|
+int journal_file_fstat(JournalFile *j); |
||||||
|
|
||||||
|
int journal_file_open_reliably( |
||||||
|
const char *fname, |
||||||
|
diff --git a/src/journal/sd-journal.c b/src/journal/sd-journal.c |
||||||
|
index 004fe646d4..09466df810 100644 |
||||||
|
--- a/src/journal/sd-journal.c |
||||||
|
+++ b/src/journal/sd-journal.c |
||||||
|
@@ -2386,6 +2386,8 @@ _public_ int sd_journal_wait(sd_journal *j, uint64_t timeout_usec) { |
||||||
|
assert_return(!journal_pid_changed(j), -ECHILD); |
||||||
|
|
||||||
|
if (j->inotify_fd < 0) { |
||||||
|
+ Iterator i; |
||||||
|
+ JournalFile *f; |
||||||
|
|
||||||
|
/* This is the first invocation, hence create the |
||||||
|
* inotify watch */ |
||||||
|
@@ -2393,6 +2395,19 @@ _public_ int sd_journal_wait(sd_journal *j, uint64_t timeout_usec) { |
||||||
|
if (r < 0) |
||||||
|
return r; |
||||||
|
|
||||||
|
+ /* Server might have done some vacuuming while we weren't watching. |
||||||
|
+ Get rid of the deleted files now so they don't stay around indefinitely. */ |
||||||
|
+ ORDERED_HASHMAP_FOREACH(f, j->files, i) { |
||||||
|
+ r = journal_file_fstat(f); |
||||||
|
+ if (r < 0) { |
||||||
|
+ log_error("Failed to fstat() journal file '%s' : %m", f->path); |
||||||
|
+ continue; |
||||||
|
+ } |
||||||
|
+ |
||||||
|
+ if (f->last_stat.st_nlink <= 0) |
||||||
|
+ remove_file_real(j, f); |
||||||
|
+ } |
||||||
|
+ |
||||||
|
/* The journal might have changed since the context |
||||||
|
* object was created and we weren't watching before, |
||||||
|
* hence don't wait for anything, and return |
@ -0,0 +1,42 @@ |
|||||||
|
From fadf2a316458ac262f3d5f690bd481fac2d4e566 Mon Sep 17 00:00:00 2001 |
||||||
|
From: =?UTF-8?q?Michal=20Sekleta=CC=81r?= <msekleta@redhat.com> |
||||||
|
Date: Fri, 27 Mar 2020 17:01:59 +0100 |
||||||
|
Subject: [PATCH] sd-journal: remove the dead code and actually fix #14695 |
||||||
|
|
||||||
|
journal_file_fstat() returns an error if we call it on already unlinked |
||||||
|
journal file and hence we never reach remove_file_real() which is the |
||||||
|
entire point. |
||||||
|
|
||||||
|
I must have made some mistake while testing the fix that got me thinking |
||||||
|
the issue is gone while opposite was true. |
||||||
|
|
||||||
|
Fixes #14695 |
||||||
|
|
||||||
|
(cherry-picked from commit 8581b9f9732d4c158bb5f773230a65ce77f2c292) |
||||||
|
|
||||||
|
Resolves: #1820073 |
||||||
|
--- |
||||||
|
src/journal/sd-journal.c | 7 +++---- |
||||||
|
1 file changed, 3 insertions(+), 4 deletions(-) |
||||||
|
|
||||||
|
diff --git a/src/journal/sd-journal.c b/src/journal/sd-journal.c |
||||||
|
index 09466df810..1f03c8e8ba 100644 |
||||||
|
--- a/src/journal/sd-journal.c |
||||||
|
+++ b/src/journal/sd-journal.c |
||||||
|
@@ -2399,13 +2399,12 @@ _public_ int sd_journal_wait(sd_journal *j, uint64_t timeout_usec) { |
||||||
|
Get rid of the deleted files now so they don't stay around indefinitely. */ |
||||||
|
ORDERED_HASHMAP_FOREACH(f, j->files, i) { |
||||||
|
r = journal_file_fstat(f); |
||||||
|
- if (r < 0) { |
||||||
|
+ if (r == -EIDRM) |
||||||
|
+ remove_file_real(j, f); |
||||||
|
+ else if (r < 0) { |
||||||
|
log_error("Failed to fstat() journal file '%s' : %m", f->path); |
||||||
|
continue; |
||||||
|
} |
||||||
|
- |
||||||
|
- if (f->last_stat.st_nlink <= 0) |
||||||
|
- remove_file_real(j, f); |
||||||
|
} |
||||||
|
|
||||||
|
/* The journal might have changed since the context |
@ -0,0 +1,260 @@ |
|||||||
|
From 6181124fac6fbfd83e12fbe5f0068da826ab5772 Mon Sep 17 00:00:00 2001 |
||||||
|
From: Lennart Poettering <lennart@poettering.net> |
||||||
|
Date: Mon, 25 Sep 2017 19:53:19 +0200 |
||||||
|
Subject: [PATCH] swap: adjust swap.c in a similar way to what we just did to |
||||||
|
mount.c |
||||||
|
|
||||||
|
Also drop the redundant states and make all similar changes too. |
||||||
|
Thankfully the swap.c state engine is much simpler than mount.c's, hence |
||||||
|
this should be easier to digest. |
||||||
|
|
||||||
|
(cherry picked from commit 50864457e1bc5f7a4ab2fd02e1565bc5d135d2f3) |
||||||
|
(cherry picked from commit 714dbded2ac725e1e2e6b61a289c118dae555dee) |
||||||
|
|
||||||
|
Related: #1821261 |
||||||
|
--- |
||||||
|
src/core/swap.c | 96 +++++++++++++++++++++++-------------------------- |
||||||
|
src/core/swap.h | 2 -- |
||||||
|
2 files changed, 44 insertions(+), 54 deletions(-) |
||||||
|
|
||||||
|
diff --git a/src/core/swap.c b/src/core/swap.c |
||||||
|
index 4a5e882332..c9cce3d945 100644 |
||||||
|
--- a/src/core/swap.c |
||||||
|
+++ b/src/core/swap.c |
||||||
|
@@ -49,8 +49,6 @@ static const UnitActiveState state_translation_table[_SWAP_STATE_MAX] = { |
||||||
|
[SWAP_ACTIVATING_DONE] = UNIT_ACTIVE, |
||||||
|
[SWAP_ACTIVE] = UNIT_ACTIVE, |
||||||
|
[SWAP_DEACTIVATING] = UNIT_DEACTIVATING, |
||||||
|
- [SWAP_ACTIVATING_SIGTERM] = UNIT_DEACTIVATING, |
||||||
|
- [SWAP_ACTIVATING_SIGKILL] = UNIT_DEACTIVATING, |
||||||
|
[SWAP_DEACTIVATING_SIGTERM] = UNIT_DEACTIVATING, |
||||||
|
[SWAP_DEACTIVATING_SIGKILL] = UNIT_DEACTIVATING, |
||||||
|
[SWAP_FAILED] = UNIT_FAILED |
||||||
|
@@ -490,8 +488,6 @@ static void swap_set_state(Swap *s, SwapState state) { |
||||||
|
s->state = state; |
||||||
|
|
||||||
|
if (state != SWAP_ACTIVATING && |
||||||
|
- state != SWAP_ACTIVATING_SIGTERM && |
||||||
|
- state != SWAP_ACTIVATING_SIGKILL && |
||||||
|
state != SWAP_ACTIVATING_DONE && |
||||||
|
state != SWAP_DEACTIVATING && |
||||||
|
state != SWAP_DEACTIVATING_SIGTERM && |
||||||
|
@@ -538,8 +534,6 @@ static int swap_coldplug(Unit *u, Hashmap *deferred_work) { |
||||||
|
return 0; |
||||||
|
|
||||||
|
if (new_state == SWAP_ACTIVATING || |
||||||
|
- new_state == SWAP_ACTIVATING_SIGTERM || |
||||||
|
- new_state == SWAP_ACTIVATING_SIGKILL || |
||||||
|
new_state == SWAP_ACTIVATING_DONE || |
||||||
|
new_state == SWAP_DEACTIVATING || |
||||||
|
new_state == SWAP_DEACTIVATING_SIGTERM || |
||||||
|
@@ -682,6 +676,15 @@ static void swap_enter_active(Swap *s, SwapResult f) { |
||||||
|
swap_set_state(s, SWAP_ACTIVE); |
||||||
|
} |
||||||
|
|
||||||
|
+static void swap_enter_dead_or_active(Swap *s, SwapResult f) { |
||||||
|
+ assert(s); |
||||||
|
+ |
||||||
|
+ if (s->from_proc_swaps) |
||||||
|
+ swap_enter_active(s, f); |
||||||
|
+ else |
||||||
|
+ swap_enter_dead(s, f); |
||||||
|
+} |
||||||
|
+ |
||||||
|
static void swap_enter_signal(Swap *s, SwapState state, SwapResult f) { |
||||||
|
int r; |
||||||
|
|
||||||
|
@@ -693,8 +696,7 @@ static void swap_enter_signal(Swap *s, SwapState state, SwapResult f) { |
||||||
|
r = unit_kill_context( |
||||||
|
UNIT(s), |
||||||
|
&s->kill_context, |
||||||
|
- (state != SWAP_ACTIVATING_SIGTERM && state != SWAP_DEACTIVATING_SIGTERM) ? |
||||||
|
- KILL_KILL : KILL_TERMINATE, |
||||||
|
+ state != SWAP_DEACTIVATING_SIGTERM ? KILL_KILL : KILL_TERMINATE, |
||||||
|
-1, |
||||||
|
s->control_pid, |
||||||
|
false); |
||||||
|
@@ -707,18 +709,16 @@ static void swap_enter_signal(Swap *s, SwapState state, SwapResult f) { |
||||||
|
goto fail; |
||||||
|
|
||||||
|
swap_set_state(s, state); |
||||||
|
- } else if (state == SWAP_ACTIVATING_SIGTERM) |
||||||
|
- swap_enter_signal(s, SWAP_ACTIVATING_SIGKILL, SWAP_SUCCESS); |
||||||
|
- else if (state == SWAP_DEACTIVATING_SIGTERM) |
||||||
|
+ } else if (state == SWAP_DEACTIVATING_SIGTERM && s->kill_context.send_sigkill) |
||||||
|
swap_enter_signal(s, SWAP_DEACTIVATING_SIGKILL, SWAP_SUCCESS); |
||||||
|
else |
||||||
|
- swap_enter_dead(s, SWAP_SUCCESS); |
||||||
|
+ swap_enter_dead_or_active(s, SWAP_SUCCESS); |
||||||
|
|
||||||
|
return; |
||||||
|
|
||||||
|
fail: |
||||||
|
log_unit_warning_errno(UNIT(s)->id, r, "%s failed to kill processes: %m", UNIT(s)->id); |
||||||
|
- swap_enter_dead(s, SWAP_FAILURE_RESOURCES); |
||||||
|
+ swap_enter_dead_or_active(s, SWAP_FAILURE_RESOURCES); |
||||||
|
} |
||||||
|
|
||||||
|
static void swap_enter_activating(Swap *s) { |
||||||
|
@@ -781,7 +781,7 @@ static void swap_enter_activating(Swap *s) { |
||||||
|
|
||||||
|
fail: |
||||||
|
log_unit_warning_errno(UNIT(s)->id, r, "%s failed to run 'swapon' task: %m", UNIT(s)->id); |
||||||
|
- swap_enter_dead(s, SWAP_FAILURE_RESOURCES); |
||||||
|
+ swap_enter_dead_or_active(s, SWAP_FAILURE_RESOURCES); |
||||||
|
} |
||||||
|
|
||||||
|
static void swap_enter_deactivating(Swap *s) { |
||||||
|
@@ -811,7 +811,7 @@ static void swap_enter_deactivating(Swap *s) { |
||||||
|
|
||||||
|
fail: |
||||||
|
log_unit_warning_errno(UNIT(s)->id, r, "%s failed to run 'swapoff' task: %m", UNIT(s)->id); |
||||||
|
- swap_enter_active(s, SWAP_FAILURE_RESOURCES); |
||||||
|
+ swap_enter_dead_or_active(s, SWAP_FAILURE_RESOURCES); |
||||||
|
} |
||||||
|
|
||||||
|
static int swap_start(Unit *u) { |
||||||
|
@@ -824,11 +824,10 @@ static int swap_start(Unit *u) { |
||||||
|
|
||||||
|
if (s->state == SWAP_DEACTIVATING || |
||||||
|
s->state == SWAP_DEACTIVATING_SIGTERM || |
||||||
|
- s->state == SWAP_DEACTIVATING_SIGKILL || |
||||||
|
- s->state == SWAP_ACTIVATING_SIGTERM || |
||||||
|
- s->state == SWAP_ACTIVATING_SIGKILL) |
||||||
|
+ s->state == SWAP_DEACTIVATING_SIGKILL) |
||||||
|
return -EAGAIN; |
||||||
|
|
||||||
|
+ /* Already on it! */ |
||||||
|
if (s->state == SWAP_ACTIVATING) |
||||||
|
return 0; |
||||||
|
|
||||||
|
@@ -854,22 +853,30 @@ static int swap_stop(Unit *u) { |
||||||
|
|
||||||
|
assert(s); |
||||||
|
|
||||||
|
- if (s->state == SWAP_DEACTIVATING || |
||||||
|
- s->state == SWAP_DEACTIVATING_SIGTERM || |
||||||
|
- s->state == SWAP_DEACTIVATING_SIGKILL || |
||||||
|
- s->state == SWAP_ACTIVATING_SIGTERM || |
||||||
|
- s->state == SWAP_ACTIVATING_SIGKILL) |
||||||
|
+ switch (s->state) { |
||||||
|
+ |
||||||
|
+ case SWAP_DEACTIVATING: |
||||||
|
+ case SWAP_DEACTIVATING_SIGTERM: |
||||||
|
+ case SWAP_DEACTIVATING_SIGKILL: |
||||||
|
+ /* Already on it */ |
||||||
|
+ return 0; |
||||||
|
+ |
||||||
|
+ case SWAP_ACTIVATING: |
||||||
|
+ case SWAP_ACTIVATING_DONE: |
||||||
|
+ /* There's a control process pending, directly enter kill mode */ |
||||||
|
+ swap_enter_signal(s, SWAP_DEACTIVATING_SIGTERM, SWAP_SUCCESS); |
||||||
|
return 0; |
||||||
|
|
||||||
|
- assert(s->state == SWAP_ACTIVATING || |
||||||
|
- s->state == SWAP_ACTIVATING_DONE || |
||||||
|
- s->state == SWAP_ACTIVE); |
||||||
|
+ case SWAP_ACTIVE: |
||||||
|
+ if (detect_container(NULL) > 0) |
||||||
|
+ return -EPERM; |
||||||
|
|
||||||
|
- if (detect_container(NULL) > 0) |
||||||
|
- return -EPERM; |
||||||
|
+ swap_enter_deactivating(s); |
||||||
|
+ return 1; |
||||||
|
|
||||||
|
- swap_enter_deactivating(s); |
||||||
|
- return 1; |
||||||
|
+ default: |
||||||
|
+ assert_not_reached("Unexpected state."); |
||||||
|
+ } |
||||||
|
} |
||||||
|
|
||||||
|
static int swap_serialize(Unit *u, FILE *f, FDSet *fds) { |
||||||
|
@@ -1002,10 +1009,8 @@ static void swap_sigchld_event(Unit *u, pid_t pid, int code, int status) { |
||||||
|
|
||||||
|
case SWAP_ACTIVATING: |
||||||
|
case SWAP_ACTIVATING_DONE: |
||||||
|
- case SWAP_ACTIVATING_SIGTERM: |
||||||
|
- case SWAP_ACTIVATING_SIGKILL: |
||||||
|
|
||||||
|
- if (f == SWAP_SUCCESS) |
||||||
|
+ if (f == SWAP_SUCCESS || s->from_proc_swaps) |
||||||
|
swap_enter_active(s, f); |
||||||
|
else |
||||||
|
swap_enter_dead(s, f); |
||||||
|
@@ -1015,7 +1020,7 @@ static void swap_sigchld_event(Unit *u, pid_t pid, int code, int status) { |
||||||
|
case SWAP_DEACTIVATING_SIGKILL: |
||||||
|
case SWAP_DEACTIVATING_SIGTERM: |
||||||
|
|
||||||
|
- swap_enter_dead(s, f); |
||||||
|
+ swap_enter_dead_or_active(s, f); |
||||||
|
break; |
||||||
|
|
||||||
|
default: |
||||||
|
@@ -1037,7 +1042,7 @@ static int swap_dispatch_timer(sd_event_source *source, usec_t usec, void *userd |
||||||
|
case SWAP_ACTIVATING: |
||||||
|
case SWAP_ACTIVATING_DONE: |
||||||
|
log_unit_warning(UNIT(s)->id, "%s activation timed out. Stopping.", UNIT(s)->id); |
||||||
|
- swap_enter_signal(s, SWAP_ACTIVATING_SIGTERM, SWAP_FAILURE_TIMEOUT); |
||||||
|
+ swap_enter_signal(s, SWAP_DEACTIVATING_SIGTERM, SWAP_FAILURE_TIMEOUT); |
||||||
|
break; |
||||||
|
|
||||||
|
case SWAP_DEACTIVATING: |
||||||
|
@@ -1045,30 +1050,19 @@ static int swap_dispatch_timer(sd_event_source *source, usec_t usec, void *userd |
||||||
|
swap_enter_signal(s, SWAP_DEACTIVATING_SIGTERM, SWAP_FAILURE_TIMEOUT); |
||||||
|
break; |
||||||
|
|
||||||
|
- case SWAP_ACTIVATING_SIGTERM: |
||||||
|
- if (s->kill_context.send_sigkill) { |
||||||
|
- log_unit_warning(UNIT(s)->id, "%s activation timed out. Killing.", UNIT(s)->id); |
||||||
|
- swap_enter_signal(s, SWAP_ACTIVATING_SIGKILL, SWAP_FAILURE_TIMEOUT); |
||||||
|
- } else { |
||||||
|
- log_unit_warning(UNIT(s)->id, "%s activation timed out. Skipping SIGKILL. Ignoring.", UNIT(s)->id); |
||||||
|
- swap_enter_dead(s, SWAP_FAILURE_TIMEOUT); |
||||||
|
- } |
||||||
|
- break; |
||||||
|
- |
||||||
|
case SWAP_DEACTIVATING_SIGTERM: |
||||||
|
if (s->kill_context.send_sigkill) { |
||||||
|
- log_unit_warning(UNIT(s)->id, "%s deactivation timed out. Killing.", UNIT(s)->id); |
||||||
|
+ log_unit_warning(UNIT(s)->id, "Swap process timed out. Killing."); |
||||||
|
swap_enter_signal(s, SWAP_DEACTIVATING_SIGKILL, SWAP_FAILURE_TIMEOUT); |
||||||
|
} else { |
||||||
|
- log_unit_warning(UNIT(s)->id, "%s deactivation timed out. Skipping SIGKILL. Ignoring.", UNIT(s)->id); |
||||||
|
- swap_enter_dead(s, SWAP_FAILURE_TIMEOUT); |
||||||
|
+ log_unit_warning(UNIT(s)->id, "Swap process timed out. Skipping SIGKILL. Ignoring."); |
||||||
|
+ swap_enter_dead_or_active(s, SWAP_FAILURE_TIMEOUT); |
||||||
|
} |
||||||
|
break; |
||||||
|
|
||||||
|
- case SWAP_ACTIVATING_SIGKILL: |
||||||
|
case SWAP_DEACTIVATING_SIGKILL: |
||||||
|
log_unit_warning(UNIT(s)->id, "%s swap process still around after SIGKILL. Ignoring.", UNIT(s)->id); |
||||||
|
- swap_enter_dead(s, SWAP_FAILURE_TIMEOUT); |
||||||
|
+ swap_enter_dead_or_active(s, SWAP_FAILURE_TIMEOUT); |
||||||
|
break; |
||||||
|
|
||||||
|
default: |
||||||
|
@@ -1428,8 +1422,6 @@ static const char* const swap_state_table[_SWAP_STATE_MAX] = { |
||||||
|
[SWAP_ACTIVATING_DONE] = "activating-done", |
||||||
|
[SWAP_ACTIVE] = "active", |
||||||
|
[SWAP_DEACTIVATING] = "deactivating", |
||||||
|
- [SWAP_ACTIVATING_SIGTERM] = "activating-sigterm", |
||||||
|
- [SWAP_ACTIVATING_SIGKILL] = "activating-sigkill", |
||||||
|
[SWAP_DEACTIVATING_SIGTERM] = "deactivating-sigterm", |
||||||
|
[SWAP_DEACTIVATING_SIGKILL] = "deactivating-sigkill", |
||||||
|
[SWAP_FAILED] = "failed" |
||||||
|
diff --git a/src/core/swap.h b/src/core/swap.h |
||||||
|
index 914a2dbccd..f46873b5e1 100644 |
||||||
|
--- a/src/core/swap.h |
||||||
|
+++ b/src/core/swap.h |
||||||
|
@@ -34,8 +34,6 @@ typedef enum SwapState { |
||||||
|
SWAP_ACTIVATING_DONE, /* /sbin/swapon is running, and the swap is done. */ |
||||||
|
SWAP_ACTIVE, |
||||||
|
SWAP_DEACTIVATING, |
||||||
|
- SWAP_ACTIVATING_SIGTERM, |
||||||
|
- SWAP_ACTIVATING_SIGKILL, |
||||||
|
SWAP_DEACTIVATING_SIGTERM, |
||||||
|
SWAP_DEACTIVATING_SIGKILL, |
||||||
|
SWAP_FAILED, |
@ -0,0 +1,80 @@ |
|||||||
|
From 8877bffec31185b58ffa867d59ae0da213fae080 Mon Sep 17 00:00:00 2001 |
||||||
|
From: HATAYAMA Daisuke <d.hatayama@fujitsu.com> |
||||||
|
Date: Wed, 24 Jul 2019 23:54:48 -0400 |
||||||
|
Subject: [PATCH] swap: finish the secondary swap units' jobs if deactivation |
||||||
|
of the primary swap unit fails |
||||||
|
|
||||||
|
Currently, if deactivation of the primary swap unit fails: |
||||||
|
|
||||||
|
# LANG=C systemctl --no-pager stop dev-mapper-fedora\\x2dswap.swap |
||||||
|
Job for dev-mapper-fedora\x2dswap.swap failed. |
||||||
|
See "systemctl status "dev-mapper-fedora\\x2dswap.swap"" and "journalctl -xe" for details. |
||||||
|
|
||||||
|
then there are still the running stop jobs for all the secondary swap units |
||||||
|
that follow the primary one: |
||||||
|
|
||||||
|
# systemctl list-jobs |
||||||
|
JOB UNIT TYPE STATE |
||||||
|
3233 dev-disk-by\x2duuid-2dc8b9b1\x2da0a5\x2d44d8\x2d89c4\x2d6cdd26cd5ce0.swap stop running |
||||||
|
3232 dev-dm\x2d1.swap stop running |
||||||
|
3231 dev-disk-by\x2did-dm\x2duuid\x2dLVM\x2dyuXWpCCIurGzz2nkGCVnUFSi7GH6E3ZcQjkKLnF0Fil0RJmhoLN8fcOnDybWCMTj.swap stop running |
||||||
|
3230 dev-disk-by\x2did-dm\x2dname\x2dfedora\x2dswap.swap stop running |
||||||
|
3234 dev-fedora-swap.swap stop running |
||||||
|
|
||||||
|
5 jobs listed. |
||||||
|
|
||||||
|
This remains endlessly because their JobTimeoutUSec is infinity: |
||||||
|
|
||||||
|
# LANG=C systemctl show -p JobTimeoutUSec dev-fedora-swap.swap |
||||||
|
JobTimeoutUSec=infinity |
||||||
|
|
||||||
|
If this issue happens during system shutdown, the system shutdown appears to |
||||||
|
get hang and the system will be forcibly shutdown or rebooted 30 minutes later |
||||||
|
by the following configuration: |
||||||
|
|
||||||
|
# grep -E "^JobTimeout" /usr/lib/systemd/system/reboot.target |
||||||
|
JobTimeoutSec=30min |
||||||
|
JobTimeoutAction=reboot-force |
||||||
|
|
||||||
|
The scenario in the real world seems that there is some service unit with |
||||||
|
KillMode=none, processes whose memory is being swapped out are not killed |
||||||
|
during stop operation in the service unit and then swapoff command fails. |
||||||
|
|
||||||
|
On the other hand, it works well in successful case of swapoff command because |
||||||
|
the secondary jobs monitor /proc/swaps file and can detect deletion of the |
||||||
|
corresponding swap file. |
||||||
|
|
||||||
|
This commit fixes the issue by finishing the secondary swap units' jobs if |
||||||
|
deactivation of the primary swap unit fails. |
||||||
|
|
||||||
|
Fixes: #11577 |
||||||
|
(cherry picked from commit 9c1f969d40f84d5cc98d810bab8b24148b2d8928) |
||||||
|
(cherry picked from commit 1e5b6b9930db88c3a5fb464bad13853885ea82f1) |
||||||
|
|
||||||
|
Resolves: #1821261 |
||||||
|
--- |
||||||
|
src/core/swap.c | 10 ++++++++-- |
||||||
|
1 file changed, 8 insertions(+), 2 deletions(-) |
||||||
|
|
||||||
|
diff --git a/src/core/swap.c b/src/core/swap.c |
||||||
|
index c9cce3d945..ff27936142 100644 |
||||||
|
--- a/src/core/swap.c |
||||||
|
+++ b/src/core/swap.c |
||||||
|
@@ -679,9 +679,15 @@ static void swap_enter_active(Swap *s, SwapResult f) { |
||||||
|
static void swap_enter_dead_or_active(Swap *s, SwapResult f) { |
||||||
|
assert(s); |
||||||
|
|
||||||
|
- if (s->from_proc_swaps) |
||||||
|
+ if (s->from_proc_swaps) { |
||||||
|
+ Swap *other; |
||||||
|
+ |
||||||
|
swap_enter_active(s, f); |
||||||
|
- else |
||||||
|
+ |
||||||
|
+ LIST_FOREACH_OTHERS(same_devnode, other, s) |
||||||
|
+ if (UNIT(other)->job) |
||||||
|
+ swap_enter_dead_or_active(other, f); |
||||||
|
+ } else |
||||||
|
swap_enter_dead(s, f); |
||||||
|
} |
||||||
|
|
@ -0,0 +1,57 @@ |
|||||||
|
From 13f9e172d4a3576efa1ddacaca26286266866d2d Mon Sep 17 00:00:00 2001 |
||||||
|
From: Joerg Steffens <joerg.steffens@bareos.com> |
||||||
|
Date: Tue, 21 Nov 2017 12:21:49 +0100 |
||||||
|
Subject: [PATCH] udev-rules: make tape-changers also apprear in |
||||||
|
/dev/tape/by-path/ |
||||||
|
|
||||||
|
It is important to be able to access tape changer ("Medium Changers") by |
||||||
|
persistant name. |
||||||
|
While tape devices can be accessed via /dev/tape/by-id/ and |
||||||
|
/dev/tape/by-path/, tape-changers could only be accessed by |
||||||
|
/dev/tape/by-id/. |
||||||
|
However, in some cases, especially when accessing Amazon Webservice |
||||||
|
Storage Gateway VTLs (or accessing iSCSI VTLs in general?) this does not |
||||||
|
work, as all tape devices and the tape changer have the same ENV{ID_SERIAL}. |
||||||
|
The results is, that only the last device is available in |
||||||
|
/dev/tape/by-id/, as the former devices have been overwritten. |
||||||
|
|
||||||
|
As this behavior is hard to change without breaking consistentcy, |
||||||
|
this additional device in /dev/tape/by-path/ can be used to access the medium changes. |
||||||
|
The tape devices can also be accessed by this path. |
||||||
|
|
||||||
|
The content of the directory will now look like: |
||||||
|
|
||||||
|
# SCSI tape device, rewind (unchanged) |
||||||
|
/dev/tape/by-path/$env{ID_PATH} -> ../../st* |
||||||
|
|
||||||
|
# SCSI tape device, no-rewind (unchanged) |
||||||
|
/dev/tape/by-path/$env{ID_PATH}-nst -> ../../nst* |
||||||
|
|
||||||
|
# SCSI tape changer device (newly added) |
||||||
|
/dev/tape/by-path/$env{ID_PATH}-changer -> ../../sg* |
||||||
|
|
||||||
|
Tape devices and tape changer have different ID_PATHs. |
||||||
|
SCSI tape changer get the suffix "-changer" |
||||||
|
to make them better distinguishable from tape devices. |
||||||
|
|
||||||
|
(cherry-picked from commit 7f8ddf96a25162f06bd94a684cf700c128d18142) |
||||||
|
(cherry picked from commit 1b723aea42e29becd0be2fdef990401803dbfba6) |
||||||
|
Resolves: #1814028 |
||||||
|
--- |
||||||
|
rules/60-persistent-storage-tape.rules | 3 +++ |
||||||
|
1 file changed, 3 insertions(+) |
||||||
|
|
||||||
|
diff --git a/rules/60-persistent-storage-tape.rules b/rules/60-persistent-storage-tape.rules |
||||||
|
index f2eabd92a8..99898c147b 100644 |
||||||
|
--- a/rules/60-persistent-storage-tape.rules |
||||||
|
+++ b/rules/60-persistent-storage-tape.rules |
||||||
|
@@ -8,6 +8,9 @@ ACTION=="remove", GOTO="persistent_storage_tape_end" |
||||||
|
SUBSYSTEM=="scsi_generic", SUBSYSTEMS=="scsi", ATTRS{type}=="8", IMPORT{program}="scsi_id --sg-version=3 --export --whitelisted -d $devnode", \ |
||||||
|
SYMLINK+="tape/by-id/scsi-$env{ID_SERIAL}" |
||||||
|
|
||||||
|
+SUBSYSTEM=="scsi_generic", SUBSYSTEMS=="scsi", ATTRS{type}=="8", IMPORT{builtin}="path_id", \ |
||||||
|
+ SYMLINK+="tape/by-path/$env{ID_PATH}-changer" |
||||||
|
+ |
||||||
|
SUBSYSTEM!="scsi_tape", GOTO="persistent_storage_tape_end" |
||||||
|
|
||||||
|
KERNEL=="st*[0-9]|nst*[0-9]", ATTRS{ieee1394_id}=="?*", ENV{ID_SERIAL}="$attr{ieee1394_id}", ENV{ID_BUS}="ieee1394" |
@ -0,0 +1,30 @@ |
|||||||
|
From 714d1c41100be669bd106df9a0efa76e49182e69 Mon Sep 17 00:00:00 2001 |
||||||
|
From: Lennart Poettering <lennart@poettering.net> |
||||||
|
Date: Wed, 22 Apr 2020 20:34:02 +0200 |
||||||
|
Subject: [PATCH] core: make sure to restore the control command id, too |
||||||
|
|
||||||
|
Fixes: #15356 |
||||||
|
(cherry picked from commit e9da62b18af647bfa73807e1c7fc3bfa4bb4b2ac) |
||||||
|
|
||||||
|
Resolves: #1837973 |
||||||
|
--- |
||||||
|
src/core/service.c | 5 +++-- |
||||||
|
1 file changed, 3 insertions(+), 2 deletions(-) |
||||||
|
|
||||||
|
diff --git a/src/core/service.c b/src/core/service.c |
||||||
|
index e32cdf4594..df64fbaf60 100644 |
||||||
|
--- a/src/core/service.c |
||||||
|
+++ b/src/core/service.c |
||||||
|
@@ -2263,9 +2263,10 @@ static int service_deserialize_exec_command(Unit *u, const char *key, const char |
||||||
|
break; |
||||||
|
} |
||||||
|
|
||||||
|
- if (command && control) |
||||||
|
+ if (command && control) { |
||||||
|
s->control_command = command; |
||||||
|
- else if (command) |
||||||
|
+ s->control_command_id = id; |
||||||
|
+ } else if (command) |
||||||
|
s->main_command = command; |
||||||
|
else |
||||||
|
log_unit_warning(u->id, "Current command vanished from the unit file, execution of the command list won't be resumed."); |
Loading…
Reference in new issue