Browse Source

systemd add another set of missing patches

Signed-off-by: basebuilder_pel7x64builder0 <basebuilder@powerel.org>
master
basebuilder_pel7x64builder0 4 years ago
parent
commit
f4321154eb
  1. 35
      SOURCES/0800-path-stop-watching-path-specs-once-we-triggered-the-.patch
  2. 39
      SOURCES/0801-unit-fix-potential-use-of-cgroup_path-after-free-whe.patch
  3. 112
      SOURCES/0802-core-when-restarting-services-don-t-close-fds.patch
  4. 170
      SOURCES/0803-unit-rework-a-bit-how-we-keep-the-service-fdstore-fr.patch
  5. 145
      SOURCES/0804-tests-add-basic-journal-test.patch
  6. 54
      SOURCES/0805-tests-add-regression-test-for-systemctl-restart-syst.patch
  7. 33
      SOURCES/0806-tests-add-test-that-journald-keeps-fds-over-terminat.patch
  8. 50
      SOURCES/0807-journal-do-not-trigger-assertion-when-journal_file_c.patch
  9. 53
      SOURCES/0808-mount-don-t-propagate-errors-from-mount_setup_unit-f.patch
  10. 35
      SOURCES/0809-mount-when-allocating-a-Mount-object-based-on-proc-s.patch
  11. 60
      SOURCES/0810-core-enforce-a-ratelimiter-when-stopping-units-due-t.patch
  12. 343
      SOURCES/0811-core-rework-StopWhenUnneeded-logic.patch
  13. 53
      SOURCES/0812-fix-the-fix-for-1691511.patch
  14. 106
      SOURCES/0813-sd-bus-when-attached-to-an-sd-event-loop-disconnect-.patch
  15. 75
      SOURCES/0814-sd-journal-close-journal-files-that-were-deleted-by-.patch
  16. 42
      SOURCES/0815-sd-journal-remove-the-dead-code-and-actually-fix-146.patch
  17. 260
      SOURCES/0816-swap-adjust-swap.c-in-a-similar-way-to-what-we-just-.patch
  18. 80
      SOURCES/0817-swap-finish-the-secondary-swap-units-jobs-if-deactiv.patch
  19. 57
      SOURCES/0818-udev-rules-make-tape-changers-also-apprear-in-dev-ta.patch
  20. 30
      SOURCES/0819-core-make-sure-to-restore-the-control-command-id-too.patch

35
SOURCES/0800-path-stop-watching-path-specs-once-we-triggered-the-.patch

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

39
SOURCES/0801-unit-fix-potential-use-of-cgroup_path-after-free-whe.patch

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

112
SOURCES/0802-core-when-restarting-services-don-t-close-fds.patch

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

170
SOURCES/0803-unit-rework-a-bit-how-we-keep-the-service-fdstore-fr.patch

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

145
SOURCES/0804-tests-add-basic-journal-test.patch

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

54
SOURCES/0805-tests-add-regression-test-for-systemctl-restart-syst.patch

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

33
SOURCES/0806-tests-add-test-that-journald-keeps-fds-over-terminat.patch

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

50
SOURCES/0807-journal-do-not-trigger-assertion-when-journal_file_c.patch

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

53
SOURCES/0808-mount-don-t-propagate-errors-from-mount_setup_unit-f.patch

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

35
SOURCES/0809-mount-when-allocating-a-Mount-object-based-on-proc-s.patch

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

60
SOURCES/0810-core-enforce-a-ratelimiter-when-stopping-units-due-t.patch

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

343
SOURCES/0811-core-rework-StopWhenUnneeded-logic.patch

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

53
SOURCES/0812-fix-the-fix-for-1691511.patch

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

106
SOURCES/0813-sd-bus-when-attached-to-an-sd-event-loop-disconnect-.patch

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

75
SOURCES/0814-sd-journal-close-journal-files-that-were-deleted-by-.patch

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

42
SOURCES/0815-sd-journal-remove-the-dead-code-and-actually-fix-146.patch

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

260
SOURCES/0816-swap-adjust-swap.c-in-a-similar-way-to-what-we-just-.patch

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

80
SOURCES/0817-swap-finish-the-secondary-swap-units-jobs-if-deactiv.patch

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

57
SOURCES/0818-udev-rules-make-tape-changers-also-apprear-in-dev-ta.patch

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

30
SOURCES/0819-core-make-sure-to-restore-the-control-command-id-too.patch

@ -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…
Cancel
Save