basebuilder_pel7x64builder0
4 years ago
20 changed files with 1832 additions and 0 deletions
@ -0,0 +1,35 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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