Browse Source

systemd version update

Signed-off-by: basebuilder_pel7x64builder0 <basebuilder@powerel.org>
master
basebuilder_pel7x64builder0 4 years ago
parent
commit
3d3e0a4de0
  1. 28
      SOURCES/0801-sd-bus-bump-message-queue-size-again.patch
  2. 39
      SOURCES/0802-unit-fix-potential-use-of-cgroup_path-after-free-whe.patch
  3. 261
      SOURCES/0803-add-test-for-ExecStopPost.patch
  4. 112
      SOURCES/0804-core-when-restarting-services-don-t-close-fds.patch
  5. 170
      SOURCES/0805-unit-rework-a-bit-how-we-keep-the-service-fdstore-fr.patch
  6. 145
      SOURCES/0806-tests-add-basic-journal-test.patch
  7. 54
      SOURCES/0807-tests-add-regression-test-for-systemctl-restart-syst.patch
  8. 33
      SOURCES/0808-tests-add-test-that-journald-keeps-fds-over-terminat.patch
  9. 51
      SOURCES/0809-nss-util-silence-warning-about-deprecated-RES_USE_IN.patch
  10. 49
      SOURCES/0810-journal-do-not-trigger-assertion-when-journal_file_c.patch
  11. 53
      SOURCES/0811-mount-don-t-propagate-errors-from-mount_setup_unit-f.patch
  12. 35
      SOURCES/0812-mount-when-allocating-a-Mount-object-based-on-proc-s.patch
  13. 51
      SOURCES/0813-fix-the-fix-for-1691511.patch
  14. 68
      SOURCES/0814-v3-Properly-parsing-SCSI-Hyperv-devices-8509.patch
  15. 29
      SOURCES/0815-Consider-smb3-as-remote-filesystem.patch
  16. 26
      SOURCES/0816-mount-don-t-add-Requires-for-tmp.mount.patch
  17. 106
      SOURCES/0817-sd-bus-when-attached-to-an-sd-event-loop-disconnect-.patch
  18. 75
      SOURCES/0818-sd-journal-close-journal-files-that-were-deleted-by-.patch
  19. 42
      SOURCES/0819-sd-journal-remove-the-dead-code-and-actually-fix-146.patch
  20. 259
      SOURCES/0820-swap-adjust-swap.c-in-a-similar-way-to-what-we-just-.patch
  21. 79
      SOURCES/0821-swap-finish-the-secondary-swap-units-jobs-if-deactiv.patch
  22. 317
      SOURCES/0822-core-add-a-new-unit-file-setting-CollectMode-for-twe.patch
  23. 108
      SOURCES/0823-run-add-G-as-shortcut-for-property-CollectMode-inact.patch
  24. 27
      SOURCES/0824-core-clarify-that-the-CollectMode-bus-property-is-co.patch
  25. 57
      SOURCES/0825-udev-rules-make-tape-changers-also-apprear-in-dev-ta.patch
  26. 209
      SOURCES/0826-logind-check-PolicyKit-before-allowing-VT-switch.patch
  27. 50
      SOURCES/0827-timer-don-t-use-persietent-file-timestamps-from-the-.patch
  28. 193
      SOURCES/0828-core-transition-to-FINAL_SIGTERM-state-after-ExecSto.patch
  29. 30
      SOURCES/0829-bus_open-leak-sd_event_source-when-udevadm-trigger.patch
  30. 117
      SOURCES/0830-journal-remote-split-mode-host-remove-port-from-jour.patch
  31. 45
      SOURCES/0831-core-downgrade-log-message-about-inability-to-propag.patch
  32. 48
      SOURCES/0832-units-move-Before-deps-for-quota-services-to-remote-.patch
  33. 24
      SOURCES/0833-set-kptr_restrict-1.patch
  34. 82
      SOURCES/0834-journal-break-recursion.patch
  35. 59
      SOURCES/0835-core-enforce-a-ratelimiter-when-stopping-units-due-t.patch
  36. 342
      SOURCES/0836-core-rework-StopWhenUnneeded-logic.patch
  37. 52
      SOURCES/0837-core-coldplug-possible-nop_job.patch
  38. 30
      SOURCES/0838-core-make-sure-to-restore-the-control-command-id-too.patch
  39. 26
      SOURCES/0839-avoid-double-free.patch
  40. 12
      SOURCES/org.freedesktop.login1.policy
  41. 100
      SPECS/systemd.spec

28
SOURCES/0801-sd-bus-bump-message-queue-size-again.patch

@ -0,0 +1,28 @@ @@ -0,0 +1,28 @@
From 4ebd0ef2af8b302bafa76383a5c182a5a749654a Mon Sep 17 00:00:00 2001
From: Jan Synacek <jsynacek@redhat.com>
Date: Fri, 8 Nov 2019 12:46:23 +0100
Subject: [PATCH] sd-bus: bump message queue size again

Simliarly to issue #4068, the current limit turns out to be too small for a
big storage setup that uses many small disks. Let's bump it further.

Resolves: #1770158
---
src/libsystemd/sd-bus/bus-internal.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/libsystemd/sd-bus/bus-internal.h b/src/libsystemd/sd-bus/bus-internal.h
index 33a5569146..87c6d8cb76 100644
--- a/src/libsystemd/sd-bus/bus-internal.h
+++ b/src/libsystemd/sd-bus/bus-internal.h
@@ -326,8 +326,8 @@ struct sd_bus {
#define BUS_DEFAULT_TIMEOUT ((usec_t) (25 * USEC_PER_SEC))
-#define BUS_WQUEUE_MAX (192*1024)
-#define BUS_RQUEUE_MAX (192*1024)
+#define BUS_WQUEUE_MAX (384*1024)
+#define BUS_RQUEUE_MAX (384*1024)
#define BUS_MESSAGE_SIZE_MAX (128*1024*1024)
#define BUS_AUTH_SIZE_MAX (64*1024)

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

@ -0,0 +1,39 @@ @@ -0,0 +1,39 @@
From 8a2dc9e983d6fb67955ae68da0a4af4248ecaf2d 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);

261
SOURCES/0803-add-test-for-ExecStopPost.patch

@ -0,0 +1,261 @@ @@ -0,0 +1,261 @@
From 94da4f86eab658c14feac290663634ca29348a60 Mon Sep 17 00:00:00 2001
From: David Tardon <dtardon@redhat.com>
Date: Thu, 3 Oct 2019 19:05:06 +0200
Subject: [PATCH] add test for ExecStopPost

This is a follow-up to #4843.

(cherry picked from commit 02baf239d87295362740d961765091b778795573)

Related: #1733998
---
test/TEST-42-EXECSTOPPOST/Makefile | 10 +++
test/TEST-42-EXECSTOPPOST/test.sh | 95 ++++++++++++++++++++
test/TEST-42-EXECSTOPPOST/testsuite.sh | 119 +++++++++++++++++++++++++
3 files changed, 224 insertions(+)
create mode 100644 test/TEST-42-EXECSTOPPOST/Makefile
create mode 100755 test/TEST-42-EXECSTOPPOST/test.sh
create mode 100755 test/TEST-42-EXECSTOPPOST/testsuite.sh

diff --git a/test/TEST-42-EXECSTOPPOST/Makefile b/test/TEST-42-EXECSTOPPOST/Makefile
new file mode 100644
index 0000000000..5e89a29eff
--- /dev/null
+++ b/test/TEST-42-EXECSTOPPOST/Makefile
@@ -0,0 +1,10 @@
+all:
+ @make -s --no-print-directory -C ../.. all
+ @basedir=../.. TEST_BASE_DIR=../ ./test.sh --all
+setup:
+ @make --no-print-directory -C ../.. all
+ @basedir=../.. TEST_BASE_DIR=../ ./test.sh --setup
+clean:
+ @basedir=../.. TEST_BASE_DIR=../ ./test.sh --clean
+run:
+ @basedir=../.. TEST_BASE_DIR=../ ./test.sh --run
diff --git a/test/TEST-42-EXECSTOPPOST/test.sh b/test/TEST-42-EXECSTOPPOST/test.sh
new file mode 100755
index 0000000000..0958e01d68
--- /dev/null
+++ b/test/TEST-42-EXECSTOPPOST/test.sh
@@ -0,0 +1,95 @@
+#!/bin/bash
+TEST_DESCRIPTION="test that ExecStopPost= is always run"
+
+. $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
+ [[ -f $TESTDIR/root/var/log/journal ]] && 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
+
+ (
+ LOG_LEVEL=5
+ eval $(udevadm info --export --query=env --name=${LOOPDEV}p2)
+
+ setup_basic_environment
+ dracut_install false true env touch
+
+ # mask some services that we do not want to run in these tests
+ ln -s /dev/null $initdir/etc/systemd/system/systemd-hwdb-update.service
+ ln -s /dev/null $initdir/etc/systemd/system/systemd-journal-catalog-update.service
+ ln -s /dev/null $initdir/etc/systemd/system/systemd-networkd.service
+ ln -s /dev/null $initdir/etc/systemd/system/systemd-networkd.socket
+ ln -s /dev/null $initdir/etc/systemd/system/systemd-resolved.service
+
+ # setup policy for Type=dbus test
+ mkdir -p $initdir/etc/dbus-1/system.d
+ cat > $initdir/etc/dbus-1/system.d/systemd.test.ExecStopPost.conf <<EOF
+<?xml version="1.0"?>
+<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+<busconfig>
+ <policy user="root">
+ <allow own="systemd.test.ExecStopPost"/>
+ </policy>
+</busconfig>
+EOF
+
+ # setup the testsuite service
+ cat >$initdir/etc/systemd/system/testsuite.service <<EOF
+[Unit]
+Description=Testsuite service
+
+[Service]
+ExecStart=/bin/bash -x /testsuite.sh
+Type=oneshot
+StandardOutput=tty
+StandardError=tty
+NotifyAccess=all
+EOF
+ cp testsuite.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-42-EXECSTOPPOST/testsuite.sh b/test/TEST-42-EXECSTOPPOST/testsuite.sh
new file mode 100755
index 0000000000..a7e663adb3
--- /dev/null
+++ b/test/TEST-42-EXECSTOPPOST/testsuite.sh
@@ -0,0 +1,119 @@
+#!/bin/bash
+set -ex
+
+systemd-analyze set-log-level debug
+
+# Emulates systemd-run to overcome its limitations on RHEL-7, like nonexistent
+# support for --wait and only a handful of supported properties.
+systemd-run-wait() {
+ local unit="$1"
+ local unitfile=/etc/systemd/system/$unit
+
+ shift
+
+ cat > $unitfile <<EOF
+[Service]
+StandardOutput=tty
+StandardError=tty
+EOF
+
+ # The $OPTIND variable used by geopts is NOT reset on function exit in the
+ # same shell session, so let's do it manually to always get relevant results
+ OPTIND=1
+
+ while getopts p: opt ; do
+ case $opt in
+ p) echo "$OPTARG" >> $unitfile ;;
+ esac
+ done
+ shift $((OPTIND - 1))
+ echo "ExecStart=/usr/bin/env $@" >> $unitfile
+ systemctl daemon-reload
+
+ systemctl start $unit
+ while systemctl is-active -q $unit ; do
+ sleep 1
+ done
+ ! systemctl is-failed -q $unit
+}
+
+systemd-run-wait simple1.service -p Type=simple -p ExecStopPost='/bin/touch /run/simple1' true
+test -f /run/simple1
+
+! systemd-run-wait simple2.service -p Type=simple -p ExecStopPost='/bin/touch /run/simple2' false
+test -f /run/simple2
+
+cat > /tmp/forking1.sh <<EOF
+#!/bin/bash
+
+set -eux
+
+sleep 4 &
+MAINPID=\$!
+disown
+
+systemd-notify MAINPID=\$MAINPID
+EOF
+chmod +x /tmp/forking1.sh
+
+# RHEL 7 doesn't support NotifyAccess=exec
+systemd-run-wait forking1.service -p Type=forking -p NotifyAccess=main -p ExecStopPost='/bin/touch /run/forking1' /tmp/forking1.sh
+test -f /run/forking1
+
+cat > /tmp/forking2.sh <<EOF
+#!/bin/bash
+
+set -eux
+
+( sleep 4; exit 1 ) &
+MAINPID=\$!
+disown
+
+systemd-notify MAINPID=\$MAINPID
+EOF
+chmod +x /tmp/forking2.sh
+
+# RHEL 7 doesn't support NotifyAccess=exec
+! systemd-run-wait forking2.service -p Type=forking -p NotifyAccess=main -p ExecStopPost='/bin/touch /run/forking2' /tmp/forking2.sh
+test -f /run/forking2
+
+systemd-run-wait oneshot1.service -p Type=oneshot -p ExecStopPost='/bin/touch /run/oneshot1' true
+test -f /run/oneshot1
+
+! systemd-run-wait oneshot2.service -p Type=oneshot -p ExecStopPost='/bin/touch /run/oneshot2' false
+test -f /run/oneshot2
+
+systemd-run-wait dbus1.service -p Type=dbus -p BusName=systemd.test.ExecStopPost -p ExecStopPost='/bin/touch /run/dbus1' \
+ busctl call org.freedesktop.DBus /org/freedesktop/DBus org.freedesktop.DBus RequestName su systemd.test.ExecStopPost 4 \
+ || :
+test -f /run/dbus1
+
+! systemd-run-wait dbus2.service -p Type=dbus -p BusName=systemd.test.ExecStopPost -p ExecStopPost='/bin/touch /run/dbus2' true
+test -f /run/dbus2
+
+cat > /tmp/notify1.sh <<EOF
+#!/bin/bash
+
+set -eux
+
+systemd-notify --ready
+EOF
+chmod +x /tmp/notify1.sh
+
+systemd-run-wait notify1.service -p Type=notify -p ExecStopPost='/bin/touch /run/notify1' /tmp/notify1.sh
+test -f /run/notify1
+
+! systemd-run-wait notify2.service -p Type=notify -p ExecStopPost='/bin/touch /run/notify2' true
+test -f /run/notify2
+
+systemd-run-wait idle1.service -p Type=idle -p ExecStopPost='/bin/touch /run/idle1' true
+test -f /run/idle1
+
+! systemd-run-wait idle2.service -p Type=idle -p ExecStopPost='/bin/touch /run/idle2' false
+test -f /run/idle2
+
+systemd-analyze log-level info
+
+echo OK > /testok
+
+exit 0

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

@ -0,0 +1,112 @@ @@ -0,0 +1,112 @@
From 70215e23a5c77445ed1b62186c069a173c632618 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: #1757704
---
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/0805-unit-rework-a-bit-how-we-keep-the-service-fdstore-fr.patch

@ -0,0 +1,170 @@ @@ -0,0 +1,170 @@
From 29254c6a73ede5af4df1c364c958a978f5a7af8a 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: #1757704
---
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/0806-tests-add-basic-journal-test.patch

@ -0,0 +1,145 @@ @@ -0,0 +1,145 @@
From 5042511b6d12e30fc66e5a404153aac6c63af7d9 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: #1757704
---
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/0807-tests-add-regression-test-for-systemctl-restart-syst.patch

@ -0,0 +1,54 @@ @@ -0,0 +1,54 @@
From ae68ff48fffe8df34c2065ad221b7d2377523edc 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: #1757704
---
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/0808-tests-add-test-that-journald-keeps-fds-over-terminat.patch

@ -0,0 +1,33 @@ @@ -0,0 +1,33 @@
From 65fb1fbdcf80b77378bfea8962611eeb8220cb28 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: #1757704
---
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

51
SOURCES/0809-nss-util-silence-warning-about-deprecated-RES_USE_IN.patch

@ -0,0 +1,51 @@ @@ -0,0 +1,51 @@
From 351e67e1a7259ac31ec3a7c2d5e850e60f622a5a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
Date: Tue, 31 Jan 2017 19:55:33 -0500
Subject: [PATCH] nss-util: silence warning about deprecated RES_USE_INET6
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

src/nss-resolve/nss-resolve.c: In function ‘_nss_resolve_gethostbyname_r’:
src/nss-resolve/nss-resolve.c:680:13: warning: RES_USE_INET6 is deprecated
NSS_GETHOSTBYNAME_FALLBACKS(resolve);
^~~~~~~~~~~~~~~~~~~~~~~~~

In glibc bz #19582, RES_USE_INET6 was deprecated. This might make sense for
clients, but they didn't take into account nss module implementations which
*must* continue to support the option. glibc internally defines
DEPRECATED_RES_USE_INET6 which can be used without emitting a warning, but
it's not exported publicly. Let's do the same, and just copy the definition
to our header.

(cherry picked from commit 6154d33de3f15bbd5d5df718103af9c37ba0a768)

Resolves: #1799002
---
src/shared/nss-util.h | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/src/shared/nss-util.h b/src/shared/nss-util.h
index 230a986040..01524289c5 100644
--- a/src/shared/nss-util.h
+++ b/src/shared/nss-util.h
@@ -25,6 +25,10 @@
#include <netdb.h>
#include <resolv.h>
+#ifndef DEPRECATED_RES_USE_INET6
+# define DEPRECATED_RES_USE_INET6 0x00002000
+#endif
+
#define NSS_GETHOSTBYNAME_PROTOTYPES(module) \
enum nss_status _nss_##module##_gethostbyname4_r( \
const char *name, \
@@ -90,7 +94,7 @@ enum nss_status _nss_##module##_gethostbyname_r( \
int *errnop, int *h_errnop) { \
enum nss_status ret = NSS_STATUS_NOTFOUND; \
\
- if (_res.options & RES_USE_INET6) \
+ if (_res.options & DEPRECATED_RES_USE_INET6) \
ret = _nss_##module##_gethostbyname3_r( \
name, \
AF_INET6, \

49
SOURCES/0810-journal-do-not-trigger-assertion-when-journal_file_c.patch

@ -0,0 +1,49 @@ @@ -0,0 +1,49 @@
From 248925c68092bab7ce0231449176db153f55d818 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)
Resolves: #1786046
---
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/0811-mount-don-t-propagate-errors-from-mount_setup_unit-f.patch

@ -0,0 +1,53 @@ @@ -0,0 +1,53 @@
From f5e4e0c8139bc0fe001846fabe83c3220fe4bea7 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: #1804757
---
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/0812-mount-when-allocating-a-Mount-object-based-on-proc-s.patch

@ -0,0 +1,35 @@ @@ -0,0 +1,35 @@
From 774f040ecc62e9c559269bb13afb1c4d04e1b6ab 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: #1804757
---
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 {

51
SOURCES/0813-fix-the-fix-for-1691511.patch

@ -0,0 +1,51 @@ @@ -0,0 +1,51 @@
From 591bcfa98983c97df4dbb9d15bc272c3fc093863 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).

Related: #1804757
---
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;
}

68
SOURCES/0814-v3-Properly-parsing-SCSI-Hyperv-devices-8509.patch

@ -0,0 +1,68 @@ @@ -0,0 +1,68 @@
From f99cc28e392874b317b4ff2054bbd6970f71ecdd Mon Sep 17 00:00:00 2001
From: Long Li <longli@microsoft.com>
Date: Wed, 21 Mar 2018 03:51:28 -0700
Subject: [PATCH] v3: Properly parsing SCSI Hyperv devices (#8509)

Since 2016, Hyperv devices moved to using standard way to expose UUID to sysfs. Fix the parsing function to work with the newer format.

Change log:
v2: changed code to work with both old and new path format
v3: changed guid_str_len type to size_t, fixed length in char guid[] in handle_scsi_hyperv()

(cherry picked from commit cf3fabacaa141a1224a2ad239806a1fa28b51687)

Resolves: #1809053
---
src/udev/udev-builtin-path_id.c | 18 ++++++++++++------
1 file changed, 12 insertions(+), 6 deletions(-)

diff --git a/src/udev/udev-builtin-path_id.c b/src/udev/udev-builtin-path_id.c
index d113ff21b0..b0bcd80571 100644
--- a/src/udev/udev-builtin-path_id.c
+++ b/src/udev/udev-builtin-path_id.c
@@ -424,14 +424,16 @@ out:
return hostdev;
}
-static struct udev_device *handle_scsi_hyperv(struct udev_device *parent, char **path) {
+static struct udev_device *handle_scsi_hyperv(struct udev_device *parent, char **path, size_t guid_str_len) {
struct udev_device *hostdev;
struct udev_device *vmbusdev;
const char *guid_str;
- char *lun = NULL;
- char guid[38];
+ _cleanup_free_ char *lun = NULL;
+ char guid[39];
size_t i, k;
+ assert(guid_str_len < sizeof(guid));
+
hostdev = udev_device_get_parent_with_subsystem_devtype(parent, "scsi", "scsi_host");
if (!hostdev)
return NULL;
@@ -444,10 +446,10 @@ static struct udev_device *handle_scsi_hyperv(struct udev_device *parent, char *
if (!guid_str)
return NULL;
- if (strlen(guid_str) < 37 || guid_str[0] != '{' || guid_str[36] != '}')
+ if (strlen(guid_str) < guid_str_len || guid_str[0] != '{' || guid_str[guid_str_len-1] != '}')
return NULL;
- for (i = 1, k = 0; i < 36; i++) {
+ for (i = 1, k = 0; i < guid_str_len-1; i++) {
if (guid_str[i] == '-')
continue;
guid[k++] = guid_str[i];
@@ -545,7 +547,11 @@ static struct udev_device *handle_scsi(struct udev_device *parent, bool enable_n
}
if (strstr(name, "/vmbus_") != NULL) {
- parent = handle_scsi_hyperv(parent, path);
+ parent = handle_scsi_hyperv(parent, path, 37);
+ goto out;
+ }
+ else if (strstr(name, "/VMBUS")) {
+ parent = handle_scsi_hyperv(parent, path, 38);
goto out;
}

29
SOURCES/0815-Consider-smb3-as-remote-filesystem.patch

@ -0,0 +1,29 @@ @@ -0,0 +1,29 @@
From a1e395b76292480649c1d94893af93c1262b2f5f Mon Sep 17 00:00:00 2001
From: Kenneth D'souza <kdsouza@redhat.com>
Date: Mon, 30 Sep 2019 16:01:21 +0530
Subject: [PATCH] Consider smb3 as remote filesystem

Currently systemd will treat smb3 as local filesystem and cause
can't boot failures. Add smb3 to the list of remote filesystems
to fix this issue.

Signed-off-by: Kenneth D'souza <kdsouza@redhat.com>
(cherry picked from commit ff7d6a740b0c6fa3be63d3908a0858730a0837c5)

Resolves: #1811700
---
src/shared/util.c | 1 +
1 file changed, 1 insertion(+)

diff --git a/src/shared/util.c b/src/shared/util.c
index ce6678eb38..3fb4492a81 100644
--- a/src/shared/util.c
+++ b/src/shared/util.c
@@ -1937,6 +1937,7 @@ bool fstype_is_network(const char *fstype) {
static const char table[] =
"afs\0"
"cifs\0"
+ "smb3\0"
"smbfs\0"
"sshfs\0"
"ncpfs\0"

26
SOURCES/0816-mount-don-t-add-Requires-for-tmp.mount.patch

@ -0,0 +1,26 @@ @@ -0,0 +1,26 @@
From 070dfe9be5cf873e2a815232900da9651dfe4544 Mon Sep 17 00:00:00 2001
From: David Tardon <dtardon@redhat.com>
Date: Tue, 17 Mar 2020 10:49:44 +0100
Subject: [PATCH] mount: don't add Requires for tmp.mount

This is a follow-up to #1372249.

rhel-only
Resolves: #1813270
---
src/core/mount.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/core/mount.c b/src/core/mount.c
index 56fda1b73f..72e981676d 100644
--- a/src/core/mount.c
+++ b/src/core/mount.c
@@ -300,7 +300,7 @@ static int mount_add_mount_links(Mount *m) {
if (r < 0)
return r;
- if (UNIT(m)->fragment_path) {
+ if (UNIT(m)->fragment_path && !streq(UNIT(m)->id, "tmp.mount")) {
/* If we have fragment configuration, then make this dependency required */
r = unit_add_dependency(other, UNIT_REQUIRES, UNIT(m), true);
if (r < 0)

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

@ -0,0 +1,106 @@ @@ -0,0 +1,106 @@
From 24622692a67b59e943afc1d309da696e48bf6a54 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: #1769928
---
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/0818-sd-journal-close-journal-files-that-were-deleted-by-.patch

@ -0,0 +1,75 @@ @@ -0,0 +1,75 @@
From 8a98e68dc1fdf10881fffc40604dfd28a49fdc27 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: #1812889
---
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/0819-sd-journal-remove-the-dead-code-and-actually-fix-146.patch

@ -0,0 +1,42 @@ @@ -0,0 +1,42 @@
From 7fe6194a2a7872532f121e6159d4fa60d1c85c50 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: #1812889
---
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

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

@ -0,0 +1,259 @@ @@ -0,0 +1,259 @@
From b77d7c2a22c679cb9445f34c59462804051bd12f 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)

Related: #1749621
---
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,

79
SOURCES/0821-swap-finish-the-secondary-swap-units-jobs-if-deactiv.patch

@ -0,0 +1,79 @@ @@ -0,0 +1,79 @@
From e2cf8d5fcec71c1c4ca7223c51552847eb2a456e 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)

Resolves: #1749621
---
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);
}

317
SOURCES/0822-core-add-a-new-unit-file-setting-CollectMode-for-twe.patch

@ -0,0 +1,317 @@ @@ -0,0 +1,317 @@
From 909d27fffffb28f4da7752be25e5c47990eba641 Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Mon, 13 Nov 2017 17:14:07 +0100
Subject: [PATCH] core: add a new unit file setting CollectMode= for tweaking
the GC logic

Right now, the option only takes one of two possible values "inactive"
or "inactive-or-failed", the former being the default, and exposing same
behaviour as the status quo ante. If set to "inactive-or-failed" units
may be collected by the GC logic when in the "failed" state too.

This logic should be a nicer alternative to using the "-" modifier for
ExecStart= and friends, as the exit data is collected and logged about
and only removed when the GC comes along. This should be useful in
particular for per-connection socket-activated services, as well as
"systemd-run" command lines that shall leave no artifacts in the
system.

I was thinking about whether to expose this as a boolean, but opted for
an enum instead, as I have the suspicion other tweaks like this might be
a added later on, in which case we extend this setting instead of having
to add yet another one.

Also, let's add some documentation for the GC logic.

(cherry-picked from commit 5afe510c89f26b0e721b276a0e78af914b47f0b0)

Resolves: #1817576
---
man/systemd.unit.xml | 56 +++++++++++++++++++++++++++
src/core/dbus-unit.c | 20 ++++++++++
src/core/load-fragment-gperf.gperf.m4 | 1 +
src/core/load-fragment.c | 2 +
src/core/load-fragment.h | 1 +
src/core/unit.c | 36 ++++++++++++++---
src/core/unit.h | 13 +++++++
7 files changed, 124 insertions(+), 5 deletions(-)

diff --git a/man/systemd.unit.xml b/man/systemd.unit.xml
index 414749bae9..0c06add166 100644
--- a/man/systemd.unit.xml
+++ b/man/systemd.unit.xml
@@ -303,6 +303,45 @@
</para>
</refsect1>
+ <refsect1>
+ <title>Unit Garbage Collection</title>
+
+ <para>The system and service manager loads a unit's configuration automatically when a unit is referenced for the
+ first time. It will automatically unload the unit configuration and state again when the unit is not needed anymore
+ ("garbage collection"). A unit may be referenced through a number of different mechanisms:</para>
+
+ <orderedlist>
+ <listitem><para>Another loaded unit references it with a dependency such as <varname>After=</varname>,
+ <varname>Wants=</varname>, …</para></listitem>
+
+ <listitem><para>The unit is currently starting, running, reloading or stopping.</para></listitem>
+
+ <listitem><para>The unit is currently in the <constant>failed</constant> state. (But see below.)</para></listitem>
+
+ <listitem><para>A job for the unit is pending.</para></listitem>
+
+ <listitem><para>The unit is pinned by an active IPC client program.</para></listitem>
+
+ <listitem><para>The unit is a special "perpetual" unit that is always active and loaded. Examples for perpetual
+ units are the root mount unit <filename>-.mount</filename> or the scope unit <filename>init.scope</filename> that
+ the service manager itself lives in.</para></listitem>
+
+ <listitem><para>The unit has running processes associated with it.</para></listitem>
+ </orderedlist>
+
+ <para>The garbage collection logic may be altered with the <varname>CollectMode=</varname> option, which allows
+ configuration whether automatic unloading of units that are in <constant>failed</constant> state is permissible,
+ see below.</para>
+
+ <para>Note that when a unit's configuration and state is unloaded, all execution results, such as exit codes, exit
+ signals, resource consumption and other statistics are lost, except for what is stored in the log subsystem.</para>
+
+ <para>Use <command>systemctl daemon-reload</command> or an equivalent command to reload unit configuration while
+ the unit is already loaded. In this case all configuration settings are flushed out and replaced with the new
+ configuration (which however might not be in effect immediately), however all runtime state is
+ saved/restored.</para>
+ </refsect1>
+
<refsect1>
<title>[Unit] Section Options</title>
@@ -666,6 +705,23 @@
ones.</para></listitem>
</varlistentry>
+ <varlistentry>
+ <term><varname>CollectMode=</varname></term>
+
+ <listitem><para>Tweaks the "garbage collection" algorithm for this unit. Takes one of <option>inactive</option>
+ or <option>inactive-or-failed</option>. If set to <option>inactive</option> the unit will be unloaded if it is
+ in the <constant>inactive</constant> state and is not referenced by clients, jobs or other units — however it
+ is not unloaded if it is in the <constant>failed</constant> state. In <option>failed</option> mode, failed
+ units are not unloaded until the user invoked <command>systemctl reset-failed</command> on them to reset the
+ <constant>failed</constant> state, or an equivalent command. This behaviour is altered if this option is set to
+ <option>inactive-or-failed</option>: in this case the unit is unloaded even if the unit is in a
+ <constant>failed</constant> state, and thus an explicitly resetting of the <constant>failed</constant> state is
+ not necessary. Note that if this mode is used unit results (such as exit codes, exit signals, consumed
+ resources, …) are flushed out immediately after the unit completed, except for what is stored in the logging
+ subsystem. Defaults to <option>inactive</option>.</para>
+ </listitem>
+ </varlistentry>
+
<varlistentry>
<term><varname>JobTimeoutSec=</varname></term>
<term><varname>JobTimeoutAction=</varname></term>
diff --git a/src/core/dbus-unit.c b/src/core/dbus-unit.c
index 77073308c8..ea6ac6767f 100644
--- a/src/core/dbus-unit.c
+++ b/src/core/dbus-unit.c
@@ -34,6 +34,7 @@
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_load_state, unit_load_state, UnitLoadState);
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_job_mode, job_mode, JobMode);
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_emergency_action, emergency_action, EmergencyAction);
+static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_collect_mode, collect_mode, CollectMode);
static int property_get_names(
sd_bus *bus,
@@ -605,6 +606,7 @@ const sd_bus_vtable bus_unit_vtable[] = {
SD_BUS_PROPERTY("Asserts", "a(sbbsi)", property_get_conditions, offsetof(Unit, asserts), 0),
SD_BUS_PROPERTY("LoadError", "(ss)", property_get_load_error, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("Transient", "b", bus_property_get_bool, offsetof(Unit, transient), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("CollectMode", "s", property_get_collect_mode, offsetof(Unit, collect_mode), 0),
SD_BUS_METHOD("Start", "s", "o", method_start, 0),
SD_BUS_METHOD("Stop", "s", "o", method_stop, 0),
@@ -937,6 +939,24 @@ static int bus_unit_set_transient_property(
return 1;
+ } else if (streq(name, "CollectMode")) {
+ const char *s;
+ CollectMode m;
+
+ r = sd_bus_message_read(message, "s", &s);
+ if (r < 0)
+ return r;
+
+ m = collect_mode_from_string(s);
+ if (m < 0)
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown garbage collection mode: %s", s);
+
+ if (mode != UNIT_CHECK) {
+ u->collect_mode = m;
+ unit_write_drop_in_format(u, mode, name, "[Unit]\nCollectMode=%s", collect_mode_to_string(m));
+ }
+
+ return 1;
} else if (streq(name, "Slice") && unit_get_cgroup_context(u)) {
const char *s;
diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4
index 664bba0ef6..3a8ee96fa3 100644
--- a/src/core/load-fragment-gperf.gperf.m4
+++ b/src/core/load-fragment-gperf.gperf.m4
@@ -200,6 +200,7 @@ Unit.AssertCapability, config_parse_unit_condition_string, CONDITION_C
Unit.AssertHost, config_parse_unit_condition_string, CONDITION_HOST, offsetof(Unit, asserts)
Unit.AssertACPower, config_parse_unit_condition_string, CONDITION_AC_POWER, offsetof(Unit, asserts)
Unit.AssertNull, config_parse_unit_condition_null, 0, offsetof(Unit, asserts)
+Unit.CollectMode, config_parse_collect_mode, 0, offsetof(Unit, collect_mode)
m4_dnl
Service.PIDFile, config_parse_unit_path_printf, 0, offsetof(Service, pid_file)
Service.ExecStartPre, config_parse_exec, SERVICE_EXEC_START_PRE, offsetof(Service, exec_command)
diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c
index 1721fea8f3..8d73d5df41 100644
--- a/src/core/load-fragment.c
+++ b/src/core/load-fragment.c
@@ -98,6 +98,8 @@ int config_parse_warn_compat(
return 0;
}
+DEFINE_CONFIG_PARSE_ENUM(config_parse_collect_mode, collect_mode, CollectMode, "Failed to parse garbage collection mode");
+
int config_parse_unit_deps(const char *unit,
const char *filename,
unsigned line,
diff --git a/src/core/load-fragment.h b/src/core/load-fragment.h
index 4bd286c11b..7b1193ddb2 100644
--- a/src/core/load-fragment.h
+++ b/src/core/load-fragment.h
@@ -110,6 +110,7 @@ int config_parse_cpu_quota(const char *unit, const char *filename, unsigned line
int config_parse_protect_home(const char* unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_protect_system(const char* unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_bus_name(const char* unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+int config_parse_collect_mode(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
/* gperf prototypes */
const struct ConfigPerfItem* load_fragment_gperf_lookup(const char *key, GPERF_LEN_TYPE length);
diff --git a/src/core/unit.c b/src/core/unit.c
index eff9fdbe70..502830d2cb 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -67,7 +67,7 @@ const UnitVTable * const unit_vtable[_UNIT_TYPE_MAX] = {
[UNIT_TIMER] = &timer_vtable,
[UNIT_PATH] = &path_vtable,
[UNIT_SLICE] = &slice_vtable,
- [UNIT_SCOPE] = &scope_vtable
+ [UNIT_SCOPE] = &scope_vtable,
};
static int maybe_warn_about_dependency(const char *id, const char *other, UnitDependency dependency);
@@ -285,6 +285,7 @@ int unit_set_description(Unit *u, const char *description) {
bool unit_may_gc(Unit *u) {
UnitActiveState state;
+
assert(u);
/* Checks whether the unit is ready to be unloaded for garbage collection.
@@ -308,16 +309,31 @@ bool unit_may_gc(Unit *u) {
UNIT_VTABLE(u)->release_resources)
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 (state != UNIT_INACTIVE)
- return false;
-
if (UNIT_VTABLE(u)->no_gc)
return false;
if (u->no_gc)
return false;
+ /* But we keep the unit object around for longer when it is referenced or configured to not be gc'ed */
+ switch (u->collect_mode) {
+
+ case COLLECT_INACTIVE:
+ if (state != UNIT_INACTIVE)
+ return false;
+
+ break;
+
+ case COLLECT_INACTIVE_OR_FAILED:
+ if (!IN_SET(state, UNIT_INACTIVE, UNIT_FAILED))
+ return false;
+
+ break;
+
+ default:
+ assert_not_reached("Unknown garbage collection mode");
+ }
+
if (UNIT_VTABLE(u)->may_gc && !UNIT_VTABLE(u)->may_gc(u))
return false;
@@ -896,6 +912,7 @@ void unit_dump(Unit *u, FILE *f, const char *prefix) {
"%s\tMay GC: %s\n"
"%s\tNeed Daemon Reload: %s\n"
"%s\tTransient: %s\n"
+ "%s\tGarbage Collection Mode: %s\n"
"%s\tSlice: %s\n"
"%s\tCGroup: %s\n"
"%s\tCGroup realized: %s\n"
@@ -913,6 +930,7 @@ void unit_dump(Unit *u, FILE *f, const char *prefix) {
prefix, yes_no(unit_may_gc(u)),
prefix, yes_no(unit_need_daemon_reload(u)),
prefix, yes_no(u->transient),
+ prefix, collect_mode_to_string(u->collect_mode),
prefix, strna(unit_slice_name(u)),
prefix, strna(u->cgroup_path),
prefix, yes_no(u->cgroup_realized),
@@ -3732,3 +3750,11 @@ static const char* const unit_active_state_table[_UNIT_ACTIVE_STATE_MAX] = {
};
DEFINE_STRING_TABLE_LOOKUP(unit_active_state, UnitActiveState);
+
+static const char* const collect_mode_table[_COLLECT_MODE_MAX] = {
+ [COLLECT_INACTIVE] = "inactive",
+ [COLLECT_INACTIVE_OR_FAILED] = "inactive-or-failed",
+};
+
+DEFINE_STRING_TABLE_LOOKUP(collect_mode, CollectMode);
+
diff --git a/src/core/unit.h b/src/core/unit.h
index 3b0fd8d9df..8cc7a9e0b2 100644
--- a/src/core/unit.h
+++ b/src/core/unit.h
@@ -60,6 +60,13 @@ typedef enum KillOperation {
KILL_ABORT,
} KillOperation;
+typedef enum CollectMode {
+ COLLECT_INACTIVE,
+ COLLECT_INACTIVE_OR_FAILED,
+ _COLLECT_MODE_MAX,
+ _COLLECT_MODE_INVALID = -1,
+} CollectMode;
+
static inline bool UNIT_IS_ACTIVE_OR_RELOADING(UnitActiveState t) {
return t == UNIT_ACTIVE || t == UNIT_RELOADING;
}
@@ -198,6 +205,9 @@ struct Unit {
/* How to start OnFailure units */
JobMode on_failure_job_mode;
+ /* Tweaking the GC logic */
+ CollectMode collect_mode;
+
/* Garbage collect us we nobody wants or requires us anymore */
bool stop_when_unneeded;
@@ -630,6 +640,9 @@ pid_t unit_main_pid(Unit *u);
const char *unit_active_state_to_string(UnitActiveState i) _const_;
UnitActiveState unit_active_state_from_string(const char *s) _pure_;
+const char* collect_mode_to_string(CollectMode m) _const_;
+CollectMode collect_mode_from_string(const char *s) _pure_;
+
bool unit_needs_console(Unit *u);
/* Macros which append UNIT= or USER_UNIT= to the message */

108
SOURCES/0823-run-add-G-as-shortcut-for-property-CollectMode-inact.patch

@ -0,0 +1,108 @@ @@ -0,0 +1,108 @@
From c2975479c63cafea5a5f0254f4525136244f3301 Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Mon, 13 Nov 2017 17:17:53 +0100
Subject: [PATCH] run: add "-G" as shortcut for
"--property=CollectMode=inactive-or-failed"

This option is likely to be very useful for systemd-run invocations,
hence let's add a shortcut for it.

With this new concepts it's now very easy to put together systemd-run
invocations that leave zero artifacts in the system, including when they
fail.

(cherry-picked from commit fe9d0be90ba142bf06d43a831d8be53283415caa)

Related: #1817576
---
man/systemd-run.xml | 15 +++++++++++++++
src/run/run.c | 15 ++++++++++++++-
2 files changed, 29 insertions(+), 1 deletion(-)

diff --git a/man/systemd-run.xml b/man/systemd-run.xml
index f46fc3abf4..97cf2879eb 100644
--- a/man/systemd-run.xml
+++ b/man/systemd-run.xml
@@ -294,6 +294,21 @@
<command>set-property</command> command.</para> </listitem>
</varlistentry>
+ <varlistentry>
+ <term><option>-G</option></term>
+ <term><option>--collect</option></term>
+
+ <listitem><para>Unload the transient unit after it completed, even if it failed. Normally, without this option,
+ all units that ran and failed are kept in memory until the user explicitly resets their failure state with
+ <command>systemctl reset-failed</command> or an equivalent command. On the other hand, units that ran
+ successfully are unloaded immediately. If this option is turned on the "garbage collection" of units is more
+ aggressive, and unloads units regardless if they exited successfully or failed. This option is a shortcut for
+ <command>--property=CollectMode=inactive-or-failed</command>, see the explanation for
+ <varname>CollectMode=</varname> in
+ <citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry> for further
+ information.</para></listitem>
+ </varlistentry>
+
<xi:include href="user-system-options.xml" xpointer="system" />
<xi:include href="user-system-options.xml" xpointer="host" />
<xi:include href="user-system-options.xml" xpointer="machine" />
diff --git a/src/run/run.c b/src/run/run.c
index bbb542b65b..df97641f87 100644
--- a/src/run/run.c
+++ b/src/run/run.c
@@ -60,6 +60,7 @@ static usec_t arg_on_unit_inactive = 0;
static char *arg_on_calendar = NULL;
static char **arg_timer_property = NULL;
static bool arg_quiet = false;
+static bool arg_aggressive_gc = false;
static void help(void) {
printf("%s [OPTIONS...] {COMMAND} [ARGS...]\n\n"
@@ -84,6 +85,7 @@ static void help(void) {
" --setenv=NAME=VALUE Set environment\n"
" -t --pty Run service on pseudo tty\n"
" -q --quiet Suppress information messages during runtime\n\n"
+ " -G --collect Unload unit after it ran, even when failed\n\n"
"Timer options:\n\n"
" --on-active=SECONDS Run after SECONDS delay\n"
" --on-boot=SECONDS Run SECONDS after machine was booted up\n"
@@ -153,6 +155,7 @@ static int parse_argv(int argc, char *argv[]) {
{ "on-unit-inactive", required_argument, NULL, ARG_ON_UNIT_INACTIVE },
{ "on-calendar", required_argument, NULL, ARG_ON_CALENDAR },
{ "timer-property", required_argument, NULL, ARG_TIMER_PROPERTY },
+ { "collect", no_argument, NULL, 'G' },
{},
};
@@ -162,7 +165,7 @@ static int parse_argv(int argc, char *argv[]) {
assert(argc >= 0);
assert(argv);
- while ((c = getopt_long(argc, argv, "+hrH:M:p:tq", options, NULL)) >= 0)
+ while ((c = getopt_long(argc, argv, "+hrH:M:p:tqG", options, NULL)) >= 0)
switch (c) {
@@ -329,6 +332,10 @@ static int parse_argv(int argc, char *argv[]) {
break;
+ case 'G':
+ arg_aggressive_gc = true;
+ break;
+
case '?':
return -EINVAL;
@@ -382,6 +389,12 @@ static int transient_unit_set_properties(sd_bus_message *m, char **properties) {
if (r < 0)
return r;
+ if (arg_aggressive_gc) {
+ r = sd_bus_message_append(m, "(sv)", "CollectMode", "s", "inactive-or-failed");
+ if (r < 0)
+ return r;
+ }
+
STRV_FOREACH(i, properties) {
r = sd_bus_message_open_container(m, 'r', "sv");
if (r < 0)

27
SOURCES/0824-core-clarify-that-the-CollectMode-bus-property-is-co.patch

@ -0,0 +1,27 @@ @@ -0,0 +1,27 @@
From b12e40d3e16b998542faef3fe916d5605b3fe0cb Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Thu, 29 Nov 2018 16:40:13 +0100
Subject: [PATCH] core: clarify that the CollectMode bus property is constant

it's configured from unit files only, and hence is constant.

(cherry-picked from commit 641e0d7a1bf4e24f5bf5f99a2d74a97635335c8e)

Related: #1817576
---
src/core/dbus-unit.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/core/dbus-unit.c b/src/core/dbus-unit.c
index ea6ac6767f..8febdfd021 100644
--- a/src/core/dbus-unit.c
+++ b/src/core/dbus-unit.c
@@ -606,7 +606,7 @@ const sd_bus_vtable bus_unit_vtable[] = {
SD_BUS_PROPERTY("Asserts", "a(sbbsi)", property_get_conditions, offsetof(Unit, asserts), 0),
SD_BUS_PROPERTY("LoadError", "(ss)", property_get_load_error, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("Transient", "b", bus_property_get_bool, offsetof(Unit, transient), SD_BUS_VTABLE_PROPERTY_CONST),
- SD_BUS_PROPERTY("CollectMode", "s", property_get_collect_mode, offsetof(Unit, collect_mode), 0),
+ SD_BUS_PROPERTY("CollectMode", "s", property_get_collect_mode, offsetof(Unit, collect_mode), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_METHOD("Start", "s", "o", method_start, 0),
SD_BUS_METHOD("Stop", "s", "o", method_stop, 0),

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

@ -0,0 +1,57 @@ @@ -0,0 +1,57 @@
From 1b723aea42e29becd0be2fdef990401803dbfba6 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 commmit 7f8ddf96a25162f06bd94a684cf700c128d18142)

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"

209
SOURCES/0826-logind-check-PolicyKit-before-allowing-VT-switch.patch

@ -0,0 +1,209 @@ @@ -0,0 +1,209 @@
From fb419649754767124f30dba36f8fdbd114b0e9d7 Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Wed, 22 Jan 2020 12:04:38 +0100
Subject: [PATCH] logind: check PolicyKit before allowing VT switch

Let's lock this down a bit. Effectively nothing much changes, since the
default PK policy will allow users on the VT to change VT. Only users
with no local VT session won't be able to switch VTs.

(cherry picked from commit 4acf0cfd2f92edb94ad48d04f1ce6c9ab4e19d55)

Resolves: #1797672
---
src/login/logind-dbus.c | 18 ++++++--
src/login/logind-seat-dbus.c | 50 +++++++++++++++++++++-
src/login/logind-session-dbus.c | 16 ++++++-
src/login/logind-session.h | 2 +
src/login/org.freedesktop.login1.policy.in | 10 +++++
5 files changed, 89 insertions(+), 7 deletions(-)

diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c
index 63b9a0df36..019aa193f5 100644
--- a/src/login/logind-dbus.c
+++ b/src/login/logind-dbus.c
@@ -854,11 +854,9 @@ static int method_activate_session(sd_bus *bus, sd_bus_message *message, void *u
if (r < 0)
return r;
- r = session_activate(session);
- if (r < 0)
- return r;
+ /* PolicyKit is done by bus_session_method_activate() */
- return sd_bus_reply_method_return(message, NULL);
+ return bus_session_method_activate(bus, message, session, error);
}
static int method_activate_session_on_seat(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
@@ -890,6 +888,18 @@ static int method_activate_session_on_seat(sd_bus *bus, sd_bus_message *message,
if (session->seat != seat)
return sd_bus_error_setf(error, BUS_ERROR_SESSION_NOT_ON_SEAT, "Session %s not on seat %s", session_name, seat_name);
+ r = bus_verify_polkit_async(
+ message,
+ CAP_SYS_ADMIN,
+ "org.freedesktop.login1.chvt",
+ false,
+ &m->polkit_registry,
+ error);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ return 1; /* Will call us back */
+
r = session_activate(session);
if (r < 0)
return r;
diff --git a/src/login/logind-seat-dbus.c b/src/login/logind-seat-dbus.c
index 50b0b8842f..f49e416fce 100644
--- a/src/login/logind-seat-dbus.c
+++ b/src/login/logind-seat-dbus.c
@@ -229,6 +229,18 @@ static int method_activate_session(sd_bus *bus, sd_bus_message *message, void *u
if (session->seat != s)
return sd_bus_error_setf(error, BUS_ERROR_SESSION_NOT_ON_SEAT, "Session %s not on seat %s", name, s->id);
+ r = bus_verify_polkit_async(
+ message,
+ CAP_SYS_ADMIN,
+ "org.freedesktop.login1.chvt",
+ false,
+ &s->manager->polkit_registry,
+ error);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ return 1; /* Will call us back */
+
r = session_activate(session);
if (r < 0)
return r;
@@ -250,7 +262,19 @@ static int method_switch_to(sd_bus *bus, sd_bus_message *message, void *userdata
return r;
if (to <= 0)
- return -EINVAL;
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid virtual terminal");
+
+ r = bus_verify_polkit_async(
+ message,
+ CAP_SYS_ADMIN,
+ "org.freedesktop.login1.chvt",
+ false,
+ &s->manager->polkit_registry,
+ error);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ return 1; /* Will call us back */
r = seat_switch_to(s, to);
if (r < 0)
@@ -267,6 +291,18 @@ static int method_switch_to_next(sd_bus *bus, sd_bus_message *message, void *use
assert(message);
assert(s);
+ r = bus_verify_polkit_async(
+ message,
+ CAP_SYS_ADMIN,
+ "org.freedesktop.login1.chvt",
+ false,
+ &s->manager->polkit_registry,
+ error);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ return 1; /* Will call us back */
+
r = seat_switch_to_next(s);
if (r < 0)
return r;
@@ -282,6 +318,18 @@ static int method_switch_to_previous(sd_bus *bus, sd_bus_message *message, void
assert(message);
assert(s);
+ r = bus_verify_polkit_async(
+ message,
+ CAP_SYS_ADMIN,
+ "org.freedesktop.login1.chvt",
+ false,
+ &s->manager->polkit_registry,
+ error);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ return 1; /* Will call us back */
+
r = seat_switch_to_previous(s);
if (r < 0)
return r;
diff --git a/src/login/logind-session-dbus.c b/src/login/logind-session-dbus.c
index 75b7186e8f..0ec4196257 100644
--- a/src/login/logind-session-dbus.c
+++ b/src/login/logind-session-dbus.c
@@ -213,7 +213,7 @@ static int method_terminate(sd_bus *bus, sd_bus_message *message, void *userdata
return sd_bus_reply_method_return(message, NULL);
}
-static int method_activate(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+int bus_session_method_activate(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
Session *s = userdata;
int r;
@@ -221,6 +221,18 @@ static int method_activate(sd_bus *bus, sd_bus_message *message, void *userdata,
assert(message);
assert(s);
+ r = bus_verify_polkit_async(
+ message,
+ CAP_SYS_ADMIN,
+ "org.freedesktop.login1.chvt",
+ false,
+ &s->manager->polkit_registry,
+ error);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ return 1; /* Will call us back */
+
r = session_activate(s);
if (r < 0)
return r;
@@ -506,7 +518,7 @@ const sd_bus_vtable session_vtable[] = {
SD_BUS_PROPERTY("LockedHint", "b", property_get_locked_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_METHOD("Terminate", NULL, NULL, method_terminate, SD_BUS_VTABLE_CAPABILITY(CAP_KILL)),
- SD_BUS_METHOD("Activate", NULL, NULL, method_activate, SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD("Activate", NULL, NULL, bus_session_method_activate, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("Lock", NULL, NULL, method_lock, 0),
SD_BUS_METHOD("Unlock", NULL, NULL, method_lock, 0),
SD_BUS_METHOD("SetIdleHint", "b", NULL, method_set_idle_hint, SD_BUS_VTABLE_UNPRIVILEGED),
diff --git a/src/login/logind-session.h b/src/login/logind-session.h
index d662082d85..b498f49592 100644
--- a/src/login/logind-session.h
+++ b/src/login/logind-session.h
@@ -184,3 +184,5 @@ void session_leave_vt(Session *s);
bool session_is_controller(Session *s, const char *sender);
int session_set_controller(Session *s, const char *sender, bool force);
void session_drop_controller(Session *s);
+
+int bus_session_method_activate(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error);
diff --git a/src/login/org.freedesktop.login1.policy.in b/src/login/org.freedesktop.login1.policy.in
index 49094eeddb..fa51ed8d74 100644
--- a/src/login/org.freedesktop.login1.policy.in
+++ b/src/login/org.freedesktop.login1.policy.in
@@ -270,4 +270,14 @@
<annotate key="org.freedesktop.policykit.imply">org.freedesktop.login1.hibernate</annotate>
</action>
+ <action id="org.freedesktop.login1.chvt">
+ <description gettext-domain="systemd">Change Session</description>
+ <message gettext-domain="systemd">Authentication is required for changing the virtual terminal.</message>
+ <defaults>
+ <allow_any>auth_admin_keep</allow_any>
+ <allow_inactive>auth_admin_keep</allow_inactive>
+ <allow_active>yes</allow_active>
+ </defaults>
+ </action>
+
</policyconfig>

50
SOURCES/0827-timer-don-t-use-persietent-file-timestamps-from-the-.patch

@ -0,0 +1,50 @@ @@ -0,0 +1,50 @@
From 016f8f9305a5584d718579f90ee537398dfed33b Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Thu, 14 Sep 2017 18:26:10 +0200
Subject: [PATCH] timer: don't use persietent file timestamps from the future
(#6823)

Also, use the mtime rather than the atime of the timestamp file. While
the atime is not completely wrong, the mtime appears more appropriate
as that's what we actually explicitly change, and is not effected by
mere reading.

Fixes: #6821
(cherry picked from commit 77542a7905520f1d637912bf47bddb4855506e41)

Resolves: #1769923
---
src/core/timer.c | 20 +++++++++++++++++---
1 file changed, 17 insertions(+), 3 deletions(-)

diff --git a/src/core/timer.c b/src/core/timer.c
index 1d4868643a..fb192d558a 100644
--- a/src/core/timer.c
+++ b/src/core/timer.c
@@ -595,9 +595,23 @@ static int timer_start(Unit *u) {
if (t->stamp_path) {
struct stat st;
- if (stat(t->stamp_path, &st) >= 0)
- t->last_trigger.realtime = timespec_load(&st.st_atim);
- else if (errno == ENOENT)
+ if (stat(t->stamp_path, &st) >= 0) {
+ usec_t ft;
+
+ /* Load the file timestamp, but only if it is actually in the past. If it is in the future,
+ * something is wrong with the system clock. */
+
+ ft = timespec_load(&st.st_mtim);
+ if (ft < now(CLOCK_REALTIME))
+ t->last_trigger.realtime = ft;
+ else {
+ char z[FORMAT_TIMESTAMP_MAX];
+
+ log_unit_warning(u->id, "%s not using persistent file timestamp %s as it is in the future.",
+ u->id, format_timestamp(z, sizeof(z), ft));
+ }
+
+ } else if (errno == ENOENT)
/* The timer has never run before,
* make sure a stamp file exists.
*/

193
SOURCES/0828-core-transition-to-FINAL_SIGTERM-state-after-ExecSto.patch

@ -0,0 +1,193 @@ @@ -0,0 +1,193 @@
From b1135a4f292a4bc193bcef768898d06f8b732215 Mon Sep 17 00:00:00 2001
From: Anita Zhang <the.anitazha@gmail.com>
Date: Sat, 25 Jan 2020 16:46:16 +0100
Subject: [PATCH] core: transition to FINAL_SIGTERM state after ExecStopPost=

Fixes #14566

(cherry picked from commit c1566ef0d22ed786b9ecf4c476e53b8a91e67578)

Resolves: #1766477
---
src/core/service.c | 10 +++
test/TEST-47-ISSUE-14566/Makefile | 1 +
test/TEST-47-ISSUE-14566/repro.sh | 5 ++
test/TEST-47-ISSUE-14566/test.sh | 91 +++++++++++++++++++++++++++
test/TEST-47-ISSUE-14566/testsuite.sh | 21 +++++++
5 files changed, 128 insertions(+)
create mode 120000 test/TEST-47-ISSUE-14566/Makefile
create mode 100755 test/TEST-47-ISSUE-14566/repro.sh
create mode 100755 test/TEST-47-ISSUE-14566/test.sh
create mode 100755 test/TEST-47-ISSUE-14566/testsuite.sh

diff --git a/src/core/service.c b/src/core/service.c
index e32cdf4594..7f0e6df412 100644
--- a/src/core/service.c
+++ b/src/core/service.c
@@ -2751,6 +2751,12 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
break;
case SERVICE_STOP_POST:
+
+ if (control_pid_good(s) <= 0)
+ service_enter_signal(s, SERVICE_FINAL_SIGTERM, f);
+
+ break;
+
case SERVICE_FINAL_SIGTERM:
case SERVICE_FINAL_SIGKILL:
@@ -2894,6 +2900,10 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
break;
case SERVICE_STOP_POST:
+ if (main_pid_good(s) <= 0)
+ service_enter_signal(s, SERVICE_FINAL_SIGTERM, f);
+ break;
+
case SERVICE_FINAL_SIGTERM:
case SERVICE_FINAL_SIGKILL:
if (main_pid_good(s) <= 0)
diff --git a/test/TEST-47-ISSUE-14566/Makefile b/test/TEST-47-ISSUE-14566/Makefile
new file mode 120000
index 0000000000..e9f93b1104
--- /dev/null
+++ b/test/TEST-47-ISSUE-14566/Makefile
@@ -0,0 +1 @@
+../TEST-01-BASIC/Makefile
\ No newline at end of file
diff --git a/test/TEST-47-ISSUE-14566/repro.sh b/test/TEST-47-ISSUE-14566/repro.sh
new file mode 100755
index 0000000000..5217602257
--- /dev/null
+++ b/test/TEST-47-ISSUE-14566/repro.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+
+sleep infinity &
+echo $! > /leakedtestpid
+wait $!
diff --git a/test/TEST-47-ISSUE-14566/test.sh b/test/TEST-47-ISSUE-14566/test.sh
new file mode 100755
index 0000000000..35d72d17ee
--- /dev/null
+++ b/test/TEST-47-ISSUE-14566/test.sh
@@ -0,0 +1,91 @@
+#!/bin/bash
+TEST_DESCRIPTION="Test that KillMode=mixed does not leave left over proccesses with ExecStopPost="
+. $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
+ [[ -f $TESTDIR/root/var/log/journal ]] && 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
+
+ (
+ LOG_LEVEL=5
+ eval $(udevadm info --export --query=env --name=${LOOPDEV}p2)
+
+ setup_basic_environment
+
+ # mask some services that we do not want to run in these tests
+ ln -s /dev/null $initdir/etc/systemd/system/systemd-hwdb-update.service
+ ln -s /dev/null $initdir/etc/systemd/system/systemd-journal-catalog-update.service
+ ln -s /dev/null $initdir/etc/systemd/system/systemd-networkd.service
+ ln -s /dev/null $initdir/etc/systemd/system/systemd-networkd.socket
+ ln -s /dev/null $initdir/etc/systemd/system/systemd-resolved.service
+
+ # setup the testsuite service
+ cat >$initdir/etc/systemd/system/testsuite.service <<EOF
+[Unit]
+Description=Testsuite service
+
+[Service]
+ExecStart=/testsuite.sh
+Type=oneshot
+StandardOutput=tty
+StandardError=tty
+NotifyAccess=all
+EOF
+ cat > $initdir/etc/systemd/system/issue_14566_test.service << EOF
+[Unit]
+Description=Issue 14566 Repro
+
+[Service]
+ExecStart=/repro.sh
+ExecStopPost=/bin/true
+KillMode=mixed
+EOF
+
+ cp testsuite.sh $initdir/
+ cp repro.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-47-ISSUE-14566/testsuite.sh b/test/TEST-47-ISSUE-14566/testsuite.sh
new file mode 100755
index 0000000000..6363266713
--- /dev/null
+++ b/test/TEST-47-ISSUE-14566/testsuite.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+set -ex
+
+systemd-analyze set-log-level debug
+
+systemctl start issue_14566_test
+systemctl status issue_14566_test
+
+leaked_pid=$(cat /leakedtestpid)
+
+systemctl stop issue_14566_test
+
+# Leaked PID will still be around if we're buggy.
+# I personally prefer to see 42.
+ps -p "$leaked_pid" && exit 42
+
+systemd-analyze log-level info
+
+echo OK > /testok
+
+exit 0

30
SOURCES/0829-bus_open-leak-sd_event_source-when-udevadm-trigger.patch

@ -0,0 +1,30 @@ @@ -0,0 +1,30 @@
From b88483b804e92a59800e8785c87d17a7213aafc4 Mon Sep 17 00:00:00 2001
From: ven <2988994+hexiaowen@users.noreply.github.com>
Date: Wed, 22 May 2019 14:24:28 +0800
Subject: [PATCH] =?UTF-8?q?bus=5Fopen=20leak=20sd=5Fevent=5Fsource=20when?=
=?UTF-8?q?=20udevadm=20trigger=E3=80=82?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

On my host, when executing the udevadm trigger, I only receive the change event, which causes memleak

(cherry picked from commit b2774a3ae692113e1f47a336a6c09bac9cfb49ad)

Resolves: #1798503
---
src/login/logind-button.c | 1 +
1 file changed, 1 insertion(+)

diff --git a/src/login/logind-button.c b/src/login/logind-button.c
index d7211e66ce..9145176e58 100644
--- a/src/login/logind-button.c
+++ b/src/login/logind-button.c
@@ -259,6 +259,7 @@ int button_open(Button *b) {
goto fail;
}
+ b->io_event_source = sd_event_source_unref(b->io_event_source);
r = sd_event_add_io(b->manager->event, &b->io_event_source, b->fd, EPOLLIN, button_dispatch, b);
if (r < 0) {
log_error_errno(r, "Failed to add button event: %m");

117
SOURCES/0830-journal-remote-split-mode-host-remove-port-from-jour.patch

@ -0,0 +1,117 @@ @@ -0,0 +1,117 @@
From 21b3ef4130291a1e3c184bb47c80cb962b32b782 Mon Sep 17 00:00:00 2001
From: Klearchos Chaloulos <klearchos.chaloulos@nokia.com>
Date: Tue, 1 Dec 2015 19:29:59 +0200
Subject: [PATCH] journal-remote: split-mode=host, remove port from journal
filename

When constructing the journal filename to store logs from a remote host, remove the port of the tcp connection, as the port will change with every reboot/connection loss between sender/reveiver machines. Having the port in the filename will cause a new journal file to be created for every reboot or connection loss.
For the implementation, a new argument "bool include_port" is added to the getpeername_pretty() function. This is passed to the sockaddr_pretty() function. The value of the include_port argument is set to true in all calls of getpeername_pretty(), except for 2 calls in journal-remote.c, where it is set to false.

(cherry picked from commit 366b7db4b65b994cd33cf4fd3c1be429be561307)

Resolves: #1244691
---
src/activate/activate.c | 2 +-
src/core/service.c | 2 +-
src/journal-remote/journal-remote.c | 4 ++--
src/shared/socket-util.c | 4 ++--
src/shared/socket-util.h | 2 +-
src/socket-proxy/socket-proxyd.c | 2 +-
6 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/src/activate/activate.c b/src/activate/activate.c
index 2689934c40..a456af1573 100644
--- a/src/activate/activate.c
+++ b/src/activate/activate.c
@@ -241,7 +241,7 @@ static int do_accept(const char* name, char **argv, char **envp, int fd) {
}
getsockname_pretty(fd2, &local);
- getpeername_pretty(fd2, &peer);
+ getpeername_pretty(fd2, true, &peer);
log_info("Connection from %s to %s", strna(peer), strna(local));
return launch1(name, argv, envp, fd2);
diff --git a/src/core/service.c b/src/core/service.c
index 7f0e6df412..dd0ae7cb88 100644
--- a/src/core/service.c
+++ b/src/core/service.c
@@ -3309,7 +3309,7 @@ int service_set_socket_fd(Service *s, int fd, Socket *sock, bool selinux_context
if (s->state != SERVICE_DEAD)
return -EAGAIN;
- if (getpeername_pretty(fd, &peer) >= 0) {
+ if (getpeername_pretty(fd, true, &peer) >= 0) {
if (UNIT(s)->description) {
_cleanup_free_ char *a;
diff --git a/src/journal-remote/journal-remote.c b/src/journal-remote/journal-remote.c
index 431e28329b..166bdad541 100644
--- a/src/journal-remote/journal-remote.c
+++ b/src/journal-remote/journal-remote.c
@@ -620,7 +620,7 @@ static int request_handler(
if (r < 0)
return code;
} else {
- r = getnameinfo_pretty(fd, &hostname);
+ r = getpeername_pretty(fd, false, &hostname);
if (r < 0) {
return mhd_respond(connection, MHD_HTTP_INTERNAL_SERVER_ERROR,
"Cannot check remote hostname");
@@ -880,7 +880,7 @@ static int remoteserver_init(RemoteServer *s,
} else if (sd_is_socket(fd, AF_UNSPEC, 0, false)) {
char *hostname;
- r = getnameinfo_pretty(fd, &hostname);
+ r = getpeername_pretty(fd, false, &hostname);
if (r < 0)
return log_error_errno(r, "Failed to retrieve remote name: %m");
diff --git a/src/shared/socket-util.c b/src/shared/socket-util.c
index b14e368176..d492ae4222 100644
--- a/src/shared/socket-util.c
+++ b/src/shared/socket-util.c
@@ -612,7 +612,7 @@ int sockaddr_pretty(const struct sockaddr *_sa, socklen_t salen, bool translate_
return 0;
}
-int getpeername_pretty(int fd, char **ret) {
+int getpeername_pretty(int fd, bool include_port, char **ret) {
union sockaddr_union sa;
socklen_t salen = sizeof(sa);
int r;
@@ -642,7 +642,7 @@ int getpeername_pretty(int fd, char **ret) {
/* For remote sockets we translate IPv6 addresses back to IPv4
* if applicable, since that's nicer. */
- return sockaddr_pretty(&sa.sa, salen, true, true, ret);
+ return sockaddr_pretty(&sa.sa, salen, true, include_port, ret);
}
int getsockname_pretty(int fd, char **ret) {
diff --git a/src/shared/socket-util.h b/src/shared/socket-util.h
index 9200ce8822..403c9bc098 100644
--- a/src/shared/socket-util.h
+++ b/src/shared/socket-util.h
@@ -102,7 +102,7 @@ bool socket_ipv6_is_supported(void);
int sockaddr_port(const struct sockaddr *_sa) _pure_;
int sockaddr_pretty(const struct sockaddr *_sa, socklen_t salen, bool translate_ipv6, bool include_port, char **ret);
-int getpeername_pretty(int fd, char **ret);
+int getpeername_pretty(int fd, bool include_port, char **ret);
int getsockname_pretty(int fd, char **ret);
int socknameinfo_pretty(union sockaddr_union *sa, socklen_t salen, char **_ret);
diff --git a/src/socket-proxy/socket-proxyd.c b/src/socket-proxy/socket-proxyd.c
index a3c3c87f11..b0a062b716 100644
--- a/src/socket-proxy/socket-proxyd.c
+++ b/src/socket-proxy/socket-proxyd.c
@@ -504,7 +504,7 @@ static int accept_cb(sd_event_source *s, int fd, uint32_t revents, void *userdat
if (errno != -EAGAIN)
log_warning_errno(errno, "Failed to accept() socket: %m");
} else {
- getpeername_pretty(nfd, &peer);
+ getpeername_pretty(nfd, true, &peer);
log_debug("New connection from %s", strna(peer));
r = add_connection_socket(context, nfd);

45
SOURCES/0831-core-downgrade-log-message-about-inability-to-propag.patch

@ -0,0 +1,45 @@ @@ -0,0 +1,45 @@
From d081baa951ee0d1c918170c7c666208fe04944e2 Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Fri, 8 Sep 2017 17:24:57 +0200
Subject: [PATCH] core: downgrade log message about inability to propagate
cgroup release message

If dbus is already down during shutdown, we can't propagate the cgroup
release message anymore, but that's expected and nothing to warn about.
Hence let's downgrade the message from LOG_WARN to LOG_DEBUG.

Fixes: #6777
(cherry picked from commit d5f1532657da107f1c8be8a97c15d964cd96665c)

Resolves: #1679934
---
src/core/dbus.c | 2 +-
src/core/manager.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/core/dbus.c b/src/core/dbus.c
index d551eab016..9d19138ab3 100644
--- a/src/core/dbus.c
+++ b/src/core/dbus.c
@@ -93,7 +93,7 @@ int bus_forward_agent_released(Manager *m, const char *path) {
"Released",
"s", path);
if (r < 0)
- return log_warning_errno(r, "Failed to propagate agent release message: %m");
+ return log_debug_errno(r, "Failed to propagate agent release message: %m");
return 1;
}
diff --git a/src/core/manager.c b/src/core/manager.c
index 4c87ad8a2f..7bbe912dc9 100644
--- a/src/core/manager.c
+++ b/src/core/manager.c
@@ -1666,7 +1666,7 @@ static int manager_dispatch_cgroups_agent_fd(sd_event_source *source, int fd, ui
buf[n] = 0;
manager_notify_cgroup_empty(m, buf);
- bus_forward_agent_released(m, buf);
+ (void) bus_forward_agent_released(m, buf);
return 0;
}

48
SOURCES/0832-units-move-Before-deps-for-quota-services-to-remote-.patch

@ -0,0 +1,48 @@ @@ -0,0 +1,48 @@
From 0693f51f979f260426cddc1f270e28e3cb2b46fa Mon Sep 17 00:00:00 2001
From: tblume <Thomas.Blume@suse.com>
Date: Thu, 30 Mar 2017 11:21:18 +0200
Subject: [PATCH] units: move Before deps for quota services to
remote-fs.target (#5627)

Creating quota on an iscsi device is causing dependency loops at next reboot.
Reason is that systemd-quotacheck and quotaon.service are ordered before
local-fs.target and quota enabled mounts have a before dependency to them.
This cannot work for _netdev mounts, because network activation is ordered
after local-fs.target.
Moving the Before dependency for systemd-quotacheck and quotaon.service
to remote-fs.target fixes this.

(cherry picked from commit 4e6f13af93a551933a75331b1f67123b3d09f6ef)

Resolves: #1693374
---
units/quotaon.service.in | 2 +-
units/systemd-quotacheck.service.in | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/units/quotaon.service.in b/units/quotaon.service.in
index 49a50a7feb..57667e110d 100644
--- a/units/quotaon.service.in
+++ b/units/quotaon.service.in
@@ -10,7 +10,7 @@ Description=Enable File System Quotas
Documentation=man:quotaon(8)
DefaultDependencies=no
After=systemd-readahead-collect.service systemd-readahead-replay.service systemd-quotacheck.service
-Before=local-fs.target shutdown.target
+Before=remote-fs.target shutdown.target
ConditionPathExists=@QUOTAON@
[Service]
diff --git a/units/systemd-quotacheck.service.in b/units/systemd-quotacheck.service.in
index f726ea1bcd..41c9bea6d2 100644
--- a/units/systemd-quotacheck.service.in
+++ b/units/systemd-quotacheck.service.in
@@ -10,7 +10,7 @@ Description=File System Quota Check
Documentation=man:systemd-quotacheck.service(8)
DefaultDependencies=no
After=systemd-readahead-collect.service systemd-readahead-replay.service systemd-remount-fs.service
-Before=local-fs.target shutdown.target
+Before=remote-fs.target shutdown.target
ConditionPathExists=@QUOTACHECK@
[Service]

24
SOURCES/0833-set-kptr_restrict-1.patch

@ -0,0 +1,24 @@ @@ -0,0 +1,24 @@
From 7e8934693393c45ba76155088b01ad1ace9daeac Mon Sep 17 00:00:00 2001
From: David Tardon <dtardon@redhat.com>
Date: Tue, 3 Dec 2019 13:57:38 +0100
Subject: [PATCH] set kptr_restrict=1

Resolves: #1689344
---
sysctl.d/50-default.conf | 3 +++
1 file changed, 3 insertions(+)

diff --git a/sysctl.d/50-default.conf b/sysctl.d/50-default.conf
index 44c48236cc..b1806502e8 100644
--- a/sysctl.d/50-default.conf
+++ b/sysctl.d/50-default.conf
@@ -20,6 +20,9 @@ kernel.sysrq = 16
# Append the PID to the core filename
kernel.core_uses_pid = 1
+# https://bugzilla.redhat.com/show_bug.cgi?id=1689344
+kernel.kptr_restrict = 1
+
# Source route verification
net.ipv4.conf.default.rp_filter = 1
net.ipv4.conf.all.rp_filter = 1

82
SOURCES/0834-journal-break-recursion.patch

@ -0,0 +1,82 @@ @@ -0,0 +1,82 @@
From 19bb218559b8dca65bbb68ad7a4ff0bc9cbfe8fb Mon Sep 17 00:00:00 2001
From: Stepan Broz <sbroz@redhat.com>
Date: Wed, 11 Mar 2020 14:45:26 +0100
Subject: [PATCH] journal: break recursion

available_space(s, true) tries to log the current status, which does, in
turn, lead to another call to available_space(s, true) and so on and so
on... The call sequence is:

available_space()
server_driver_message()
dispatch_message_real()
write_to_journal()
find_journal()
system_journal_open()
available_space()

RHEL-only

Resolves: #1778744
---
src/journal/journald-server.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c
index ffe2daa7be..11348af490 100644
--- a/src/journal/journald-server.c
+++ b/src/journal/journald-server.c
@@ -311,7 +311,7 @@ static bool flushed_flag_is_set(void) {
return access("/run/systemd/journal/flushed", F_OK) >= 0;
}
-static int system_journal_open(Server *s, bool flush_requested) {
+static int system_journal_open(Server *s, bool flush_requested, bool verbose) {
int r;
char *fn;
sd_id128_t machine;
@@ -344,7 +344,7 @@ static int system_journal_open(Server *s, bool flush_requested) {
if (r >= 0) {
server_fix_perms(s, s->system_journal, 0);
- available_space(s, true);
+ available_space(s, verbose);
} else {
if (r != -ENOENT && r != -EROFS)
log_warning_errno(r, "Failed to open system journal: %m");
@@ -406,7 +406,7 @@ static int system_journal_open(Server *s, bool flush_requested) {
if (s->runtime_journal) {
server_fix_perms(s, s->runtime_journal, 0);
- available_space(s, true);
+ available_space(s, verbose);
}
}
@@ -430,7 +430,7 @@ static JournalFile* find_journal(Server *s, uid_t uid) {
* else that's left the journals as NULL).
*
* Fixes https://github.com/systemd/systemd/issues/3968 */
- (void) system_journal_open(s, false);
+ (void) system_journal_open(s, false, false);
/* We split up user logs only on /var, not on /run. If the
* runtime file is open, we write to it exclusively, in order
@@ -1132,7 +1132,7 @@ int server_flush_to_var(Server *s, bool require_flag_file) {
if (require_flag_file && !flushed_flag_is_set())
return 0;
- system_journal_open(s, true);
+ system_journal_open(s, true, true);
if (!s->system_journal)
return 0;
@@ -1903,7 +1903,7 @@ int server_init(Server *s) {
(void) server_connect_notify(s);
- r = system_journal_open(s, false);
+ r = system_journal_open(s, false, true);
if (r < 0)
return r;

59
SOURCES/0835-core-enforce-a-ratelimiter-when-stopping-units-due-t.patch

@ -0,0 +1,59 @@ @@ -0,0 +1,59 @@
From d27610cfef24a985116ed88f29a462f627745b19 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)

Related: #1775291
---
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 502830d2cb..750b8b9a5c 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;
}
@@ -1612,6 +1614,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 8cc7a9e0b2..e930d8ba5f 100644
--- a/src/core/unit.h
+++ b/src/core/unit.h
@@ -192,6 +192,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;

342
SOURCES/0836-core-rework-StopWhenUnneeded-logic.patch

@ -0,0 +1,342 @@ @@ -0,0 +1,342 @@
From ba36c6a8c8d134aa7196750af4a6651d5810f6d3 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)

Resolves: #1775291
---
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 7bbe912dc9..db562b18a5 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 750b8b9a5c..2b058dd3e8 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -396,6 +396,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;
@@ -560,6 +576,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);
@@ -1583,49 +1602,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) {
@@ -1711,34 +1749,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;
@@ -1916,7 +1926,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) {
@@ -1977,7 +1987,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 e930d8ba5f..f426f3df21 100644
--- a/src/core/unit.h
+++ b/src/core/unit.h
@@ -172,6 +172,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 */
@@ -245,6 +248,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;
@@ -518,6 +522,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);
@@ -637,6 +642,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);

52
SOURCES/0837-core-coldplug-possible-nop_job.patch

@ -0,0 +1,52 @@ @@ -0,0 +1,52 @@
From 8ee652948b0255005e4c9d278ac06b30711d9dbd Mon Sep 17 00:00:00 2001
From: chenglin130 <cheng.lin130@zte.com.cn>
Date: Sat, 9 Nov 2019 23:04:04 +0800
Subject: [PATCH] core: coldplug possible nop_job

When a unit in a state INACTIVE or DEACTIVATING, JobType JOB_TRY_RESTART or
JOB_TRY_RELOAD will be collapsed to JOB_NOP. And use u->nop_job instead
of u->job.

If a JOB_NOP job is going on with a waiting state, a parallel daemon-reload
just install it during deserialization. Without a coldplug, the job will
not be in m->run_queue, which results in a hung try-restart or
try-reload process.

Reproduce:
1. run systemctl try-restart test.servcie (inactive) repeatly in a terminal.
2. run systemctl daemon-reload repeatly in other terminals.

After successful reproduce, systemctl list-jobs will list the hang job.

Upsteam:
https://github.com/systemd/systemd/pull/13124

Resolves: #1829754
---
src/core/unit.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/src/core/unit.c b/src/core/unit.c
index 2b058dd3e8..d953780a52 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -2918,6 +2918,7 @@ static int unit_add_deserialized_job_coldplug(Unit *u) {
int unit_coldplug(Unit *u, Hashmap *deferred_work) {
int r;
+ Job *uj;
assert(u);
@@ -2925,8 +2926,9 @@ int unit_coldplug(Unit *u, Hashmap *deferred_work) {
if ((r = UNIT_VTABLE(u)->coldplug(u, deferred_work)) < 0)
return r;
- if (u->job) {
- r = job_coldplug(u->job);
+ uj = u->job ?: u->nop_job;
+ if (uj) {
+ r = job_coldplug(uj);
if (r < 0)
return r;
} else if (u->deserialized_job >= 0)

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

@ -0,0 +1,30 @@ @@ -0,0 +1,30 @@
From df8adf9c8a8258ae041db28f4bf411da6156170a 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: #1828953
---
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 dd0ae7cb88..4c73b6ef96 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.");

26
SOURCES/0839-avoid-double-free.patch

@ -0,0 +1,26 @@ @@ -0,0 +1,26 @@
From 20fb5227cd981c5eb188a6ad738672486e40a50e Mon Sep 17 00:00:00 2001
From: David Tardon <dtardon@redhat.com>
Date: Mon, 11 May 2020 13:34:24 +0200
Subject: [PATCH] avoid double free

This was a mis-merge in the fix for #1809053 (commit
f99cc28e392874b317b4ff2054bbd6970f71ecdd).

Resolves: #1832816
---
src/udev/udev-builtin-path_id.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/udev/udev-builtin-path_id.c b/src/udev/udev-builtin-path_id.c
index b0bcd80571..1db403b39c 100644
--- a/src/udev/udev-builtin-path_id.c
+++ b/src/udev/udev-builtin-path_id.c
@@ -428,7 +428,7 @@ static struct udev_device *handle_scsi_hyperv(struct udev_device *parent, char *
struct udev_device *hostdev;
struct udev_device *vmbusdev;
const char *guid_str;
- _cleanup_free_ char *lun = NULL;
+ char *lun = NULL;
char guid[39];
size_t i, k;

12
SOURCES/org.freedesktop.login1.policy

@ -740,4 +740,14 @@ @@ -740,4 +740,14 @@
<annotate key="org.freedesktop.policykit.imply">org.freedesktop.login1.hibernate</annotate>
</action>

</policyconfig>
<action id="org.freedesktop.login1.chvt">
<description>Change Session</description>
<message>Authentication is required for changing the virtual terminal.</message>
<defaults>
<allow_any>auth_admin_keep</allow_any>
<allow_inactive>auth_admin_keep</allow_inactive>
<allow_active>yes</allow_active>
</defaults>
</action>

</policyconfig>

100
SPECS/systemd.spec

@ -840,25 +840,45 @@ Patch0797: 0797-service-go-through-stop_post-on-failure-4770.patch @@ -840,25 +840,45 @@ Patch0797: 0797-service-go-through-stop_post-on-failure-4770.patch
Patch0798: 0798-Call-getgroups-to-know-size-of-supplementary-groups-.patch
Patch0799: 0799-udev-introduce-CONST-key-name.patch
Patch0800: 0800-path-stop-watching-path-specs-once-we-triggered-the-.patch
Patch0801: 0801-unit-fix-potential-use-of-cgroup_path-after-free-whe.patch
Patch0802: 0802-core-when-restarting-services-don-t-close-fds.patch
Patch0803: 0803-unit-rework-a-bit-how-we-keep-the-service-fdstore-fr.patch
Patch0804: 0804-tests-add-basic-journal-test.patch
Patch0805: 0805-tests-add-regression-test-for-systemctl-restart-syst.patch
Patch0806: 0806-tests-add-test-that-journald-keeps-fds-over-terminat.patch
Patch0807: 0807-journal-do-not-trigger-assertion-when-journal_file_c.patch
Patch0808: 0808-mount-don-t-propagate-errors-from-mount_setup_unit-f.patch
Patch0809: 0809-mount-when-allocating-a-Mount-object-based-on-proc-s.patch
Patch0810: 0810-core-enforce-a-ratelimiter-when-stopping-units-due-t.patch
Patch0811: 0811-core-rework-StopWhenUnneeded-logic.patch
Patch0812: 0812-fix-the-fix-for-1691511.patch
Patch0813: 0813-sd-bus-when-attached-to-an-sd-event-loop-disconnect-.patch
Patch0814: 0814-sd-journal-close-journal-files-that-were-deleted-by-.patch
Patch0815: 0815-sd-journal-remove-the-dead-code-and-actually-fix-146.patch
Patch0816: 0816-swap-adjust-swap.c-in-a-similar-way-to-what-we-just-.patch
Patch0817: 0817-swap-finish-the-secondary-swap-units-jobs-if-deactiv.patch
Patch0818: 0818-udev-rules-make-tape-changers-also-apprear-in-dev-ta.patch
Patch0819: 0819-core-make-sure-to-restore-the-control-command-id-too.patch
Patch0801: 0801-sd-bus-bump-message-queue-size-again.patch
Patch0802: 0802-unit-fix-potential-use-of-cgroup_path-after-free-whe.patch
Patch0803: 0803-add-test-for-ExecStopPost.patch
Patch0804: 0804-core-when-restarting-services-don-t-close-fds.patch
Patch0805: 0805-unit-rework-a-bit-how-we-keep-the-service-fdstore-fr.patch
Patch0806: 0806-tests-add-basic-journal-test.patch
Patch0807: 0807-tests-add-regression-test-for-systemctl-restart-syst.patch
Patch0808: 0808-tests-add-test-that-journald-keeps-fds-over-terminat.patch
Patch0809: 0809-nss-util-silence-warning-about-deprecated-RES_USE_IN.patch
Patch0810: 0810-journal-do-not-trigger-assertion-when-journal_file_c.patch
Patch0811: 0811-mount-don-t-propagate-errors-from-mount_setup_unit-f.patch
Patch0812: 0812-mount-when-allocating-a-Mount-object-based-on-proc-s.patch
Patch0813: 0813-fix-the-fix-for-1691511.patch
Patch0814: 0814-v3-Properly-parsing-SCSI-Hyperv-devices-8509.patch
Patch0815: 0815-Consider-smb3-as-remote-filesystem.patch
Patch0816: 0816-mount-don-t-add-Requires-for-tmp.mount.patch
Patch0817: 0817-sd-bus-when-attached-to-an-sd-event-loop-disconnect-.patch
Patch0818: 0818-sd-journal-close-journal-files-that-were-deleted-by-.patch
Patch0819: 0819-sd-journal-remove-the-dead-code-and-actually-fix-146.patch
Patch0820: 0820-swap-adjust-swap.c-in-a-similar-way-to-what-we-just-.patch
Patch0821: 0821-swap-finish-the-secondary-swap-units-jobs-if-deactiv.patch
Patch0822: 0822-core-add-a-new-unit-file-setting-CollectMode-for-twe.patch
Patch0823: 0823-run-add-G-as-shortcut-for-property-CollectMode-inact.patch
Patch0824: 0824-core-clarify-that-the-CollectMode-bus-property-is-co.patch
Patch0825: 0825-udev-rules-make-tape-changers-also-apprear-in-dev-ta.patch
Patch0826: 0826-logind-check-PolicyKit-before-allowing-VT-switch.patch
Patch0827: 0827-timer-don-t-use-persietent-file-timestamps-from-the-.patch
Patch0828: 0828-core-transition-to-FINAL_SIGTERM-state-after-ExecSto.patch
Patch0829: 0829-bus_open-leak-sd_event_source-when-udevadm-trigger.patch
Patch0830: 0830-journal-remote-split-mode-host-remove-port-from-jour.patch
Patch0831: 0831-core-downgrade-log-message-about-inability-to-propag.patch
Patch0832: 0832-units-move-Before-deps-for-quota-services-to-remote-.patch
Patch0833: 0833-set-kptr_restrict-1.patch
Patch0834: 0834-journal-break-recursion.patch
Patch0835: 0835-core-enforce-a-ratelimiter-when-stopping-units-due-t.patch
Patch0836: 0836-core-rework-StopWhenUnneeded-logic.patch
Patch0837: 0837-core-coldplug-possible-nop_job.patch
Patch0838: 0838-core-make-sure-to-restore-the-control-command-id-too.patch
Patch0839: 0839-avoid-double-free.patch
Patch9999: 9999-Update-kernel-install-script-by-backporting-fedora-p.patch

%global num_patches %{lua: c=0; for i,p in ipairs(patches) do c=c+1; end; print(c);}
@ -1837,10 +1857,46 @@ fi @@ -1837,10 +1857,46 @@ fi
%{_mandir}/man8/systemd-resolved.*

%changelog
* Mon May 25 2020 systemd maintenance team <systemd-maint@redhat.com> - 219-73.8
- core: make sure to restore the control command id, too (#1837973)
* Tue May 12 2020 systemd maintenance team <systemd-maint@redhat.com> - 219-78
- avoid double free (#1832816)

* Thu Apr 30 2020 systemd maintenance team <systemd-maint@redhat.com> - 219-77
- core: coldplug possible nop_job (#1829754)
- core: make sure to restore the control command id, too (#1828953)

* Wed Apr 29 2020 systemd maintenance team <systemd-maint@redhat.com> - 219-76
- core: enforce a ratelimiter when stopping units due to StopWhenUnneeded=1 (#1775291)
- core: rework StopWhenUnneeded= logic (#1775291)

* Mon May 18 2020 systemd maintenance team <systemd-maint@redhat.com> - 219-73.7
* Wed Apr 29 2020 systemd maintenance team <systemd-maint@redhat.com> - 219-75
- journal: break recursion (#1778744)

* Tue Apr 28 2020 systemd maintenance team <systemd-maint@redhat.com> - 219-74
- sd-bus: bump message queue size again (#1770158)
- unit: fix potential use of cgroup_path after free() when freeing unit (#1760149)
- add test for ExecStopPost (#1733998)
- core: when restarting services, don't close fds (#1757704)
- unit: rework a bit how we keep the service fdstore from being destroyed during service restart (#1757704)
- tests: add basic journal test (#1757704)
- tests: add regression test for `systemctl restart systemd-journald` (#1757704)
- tests: add test that journald keeps fds over termination by signal (#1757704)
- nss-util: silence warning about deprecated RES_USE_INET6 (#1799002)
- journal: do not trigger assertion when journal_file_close() get NULL (#1786046)
- mount: don't propagate errors from mount_setup_unit() further up (#1804757)
- mount: when allocating a Mount object based on /proc/self/mountinfo mark it so (#1804757)
- fix the fix for #1691511 (#1804757)
- v3: Properly parsing SCSI Hyperv devices (#8509) (#1809053)
- Consider smb3 as remote filesystem (#1811700)
- mount: don't add Requires for tmp.mount (#1813270)
- sd-bus: when attached to an sd-event loop, disconnect on processing errors (#1769928)
- sd-journal: close journal files that were deleted by journald before we've setup inotify watch (#1812889)
- sd-journal: remove the dead code and actually fix #14695 (#1812889)
- swap: adjust swap.c in a similar way to what we just did to mount.c (#1749621)
- swap: finish the secondary swap units' jobs if deactivation of the primary swap unit fails (#1749621)
- core: add a new unit file setting CollectMode= for tweaking the GC logic (#1817576)
- run: add "-G" as shortcut for "--property=CollectMode=inactive-or-failed" (#1817576)
- core: clarify that the CollectMode bus property is constant (#1817576)
- core: make sure to restore the control command id, too (#1837973)
- udev-rules: make tape-changers also apprear in /dev/tape/by-path/ (#1814028)

* Mon Apr 06 2020 systemd maintenance team <systemd-maint@redhat.com> - 219-73.6

Loading…
Cancel
Save