import systemd-252-18.el9

i9c changed/i9c/systemd-252-18.el9
MSVSphere Packaging Team 1 year ago
parent c1e3f99157
commit fb370302cb

@ -1,4 +1,4 @@
From 9603354ef8d1e0456718703920e41e6fadad95a8 Mon Sep 17 00:00:00 2001
From 97e7419df4912abc62ca379afbb6721b008fbf87 Mon Sep 17 00:00:00 2001
From: Mark Laws <mdl@60hz.org>
Date: Mon, 14 Nov 2022 21:48:09 +0900
Subject: [PATCH] systemd: Support OOMPolicy in scope units
@ -7,7 +7,7 @@ Closes #25376.
(cherry picked from commit 5fa098357e0ea9f05b00ed5b04a36ef9f64037db)
Resolves: #2175619
Resolves: #2176918
---
man/org.freedesktop.systemd1.xml | 6 ++++++
src/core/dbus-scope.c | 6 ++++++

@ -1,4 +1,4 @@
From df85e937594d551c91a1efd5ba73d56399304f19 Mon Sep 17 00:00:00 2001
From 60f4b73b48b7e9d3f734ecdf63fa5ba9ab3c2338 Mon Sep 17 00:00:00 2001
From: Mark Laws <mdl@60hz.org>
Date: Thu, 24 Nov 2022 14:56:29 +0900
Subject: [PATCH] systemd: Default to OOMPolicy=continue for login session
@ -9,7 +9,7 @@ kill the user's other processes for no good reason.
(cherry picked from commit 98b6c94b577205d31b019286c2a84cc9af244ea0)
Resolves: #2175619
Resolves: #2176918
---
src/login/logind-dbus.c | 6 ++++++
1 file changed, 6 insertions(+)

@ -1,4 +1,4 @@
From b2d0c171a9ef84fb8ab8d8a428a8f51db37f58ea Mon Sep 17 00:00:00 2001
From 1e066581a0bdfe5848dfc701e84e5d7d431699f5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
Date: Tue, 13 Dec 2022 15:25:55 +0100
Subject: [PATCH] man: rework description of OOMPolicy= a bit
@ -9,7 +9,7 @@ right at the beginning.
(cherry picked from commit 100d37d4f3111a97f51e37b51eea9243cb037b61)
Resolves: #2175619
Resolves: #2176918
---
man/systemd.service.xml | 19 ++++++++++---------
1 file changed, 10 insertions(+), 9 deletions(-)

@ -1,4 +1,4 @@
From 6013f45b86f39a502d9e92b96adee402a32de062 Mon Sep 17 00:00:00 2001
From 53464ce69ec5202b9abfb35ddbd58c61e2e0ba18 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
Date: Tue, 13 Dec 2022 15:26:58 +0100
Subject: [PATCH] core,man: add missing integration of OOMPolicy= in scopes
@ -7,7 +7,7 @@ Fixup for 5fa098357e0ea9f05b00ed5b04a36ef9f64037db.
(cherry picked from commit d5a1657d5a78e9a101fa91e60921bed54ec162b8)
Resolves: #2175619
Resolves: #2176918
---
man/systemd.scope.xml | 2 ++
man/systemd.service.xml | 22 ++++++++++------------

@ -1,4 +1,4 @@
From c37de74b2eeefcbcd3f6d7f218e33cda3c3b5397 Mon Sep 17 00:00:00 2001
From d2bab1cb6c0d7242dbaca55d507f886f7ec0fa6c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michal=20Koutn=C3=BD?= <mkoutny@suse.com>
Date: Thu, 6 Oct 2022 19:06:08 +0200
Subject: [PATCH] meson: Store fuzz tests in structured way
@ -9,7 +9,7 @@ This is just refactoring with no intentional .
(cherry picked from commit 7db5761ddaa53eba197b5abc485e3290f47c661f)
Related: #2175619
Related: #2176918
---
meson.build | 69 ++++++++++++++++++-------------------------
test/fuzz/meson.build | 22 ++++++++++----

@ -1,4 +1,4 @@
From d8468261b4f42c4252db283a9fcb2aef5abc39fd Mon Sep 17 00:00:00 2001
From fd7d93a34d8ef8a194544dba9763e8d58a805641 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michal=20Koutn=C3=BD?= <mkoutny@suse.com>
Date: Thu, 6 Oct 2022 16:48:01 +0200
Subject: [PATCH] meson: Generate fuzzer inputs with directives
@ -19,7 +19,7 @@ script neither).
(cherry picked from commit 7e343b530e68c55f868a4a8261824ca543319a52)
Related: #2175619
Related: #2176918
---
meson.build | 31 +-
test/fuzz/fuzz-link-parser/directives.link | 97 ---

@ -1,4 +1,4 @@
From 3892f0c14a5cb99399d54d9b6fde9c0a09fd1b89 Mon Sep 17 00:00:00 2001
From a810aef1f95727ec3e044441bf02e0261b2e09ec Mon Sep 17 00:00:00 2001
From: Frantisek Sumsal <frantisek@sumsal.cz>
Date: Sat, 7 Jan 2023 10:27:05 +0100
Subject: [PATCH] oss-fuzz: include generated corpora in the final zip file
@ -12,7 +12,7 @@ Fixes: #25859
(cherry picked from commit bef8d18b3f9776fdb28fc9a4820f9ce9418422f9)
Related: #2175619
Related: #2176918
---
tools/oss-fuzz.sh | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)

@ -1,4 +1,4 @@
From 6b22e9c84c00989ea58b1d9df75f2c20eaa2c274 Mon Sep 17 00:00:00 2001
From 25223b64f043d9b78d1f70ee7e4a2a3b7a579a84 Mon Sep 17 00:00:00 2001
From: Jan Macku <jamacku@redhat.com>
Date: Fri, 17 Mar 2023 14:00:15 +0100
Subject: [PATCH] unit: In cgroupv1, gracefully terminate delegated scopes
@ -12,7 +12,7 @@ Co-authored-by: Colin Walters <walters@verbum.org>
rhel-only
Resolves: #2179165
Resolves: #2180120
---
src/core/unit.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)

@ -0,0 +1,47 @@
From e92d004898cb36db27a2ceba6647793ff9617561 Mon Sep 17 00:00:00 2001
From: Jan Macku <jamacku@redhat.com>
Date: Thu, 30 Mar 2023 17:07:51 +0200
Subject: [PATCH] ci: trigger `differential-shellcheck` workflow on push
Fixes: redhat-plumbers-in-action/differential-shellcheck#215
rhel-only
Related: #2100440
---
.github/workflows/differential-shellcheck.yml | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/.github/workflows/differential-shellcheck.yml b/.github/workflows/differential-shellcheck.yml
index 105f92d1c9..3662126304 100644
--- a/.github/workflows/differential-shellcheck.yml
+++ b/.github/workflows/differential-shellcheck.yml
@@ -3,6 +3,10 @@
name: Differential ShellCheck
on:
+ push:
+ branches:
+ - main
+ - rhel-9.*.0
pull_request:
branches:
- main
@@ -18,15 +22,14 @@ jobs:
permissions:
security-events: write
- pull-requests: write
steps:
- name: Repository checkout
- uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b
+ uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Differential ShellCheck
- uses: redhat-plumbers-in-action/differential-shellcheck@1b1b75e42f0694c1012228513b21617a748c866e
+ uses: redhat-plumbers-in-action/differential-shellcheck@v4
with:
token: ${{ secrets.GITHUB_TOKEN }}

@ -1,4 +1,4 @@
From 15d494b7ee019ab3e3a2a8e61c73ea8693ddb8ba Mon Sep 17 00:00:00 2001
From 44f29dde7b88fbaed0972b155a6c7c4751f74839 Mon Sep 17 00:00:00 2001
From: Jan Macku <jamacku@redhat.com>
Date: Mon, 17 Apr 2023 14:51:19 +0200
Subject: [PATCH] ci: workflow for gathering metadata for source-git automation
@ -9,7 +9,7 @@ This workflow also triggers for rest of the source-git automation workflows.
rhel-only
Related: #2184929
Related: #2100440
---
.github/workflows/gather-metadata.yml | 28 +++++++++++++++++++++++++++
1 file changed, 28 insertions(+)

@ -1,4 +1,4 @@
From 47c1a02ba0e669484e93dd78dd475592ecaa4cbd Mon Sep 17 00:00:00 2001
From 6a84f210a9a4dd4fde22ea5d60dff46cad36597f Mon Sep 17 00:00:00 2001
From: Jan Macku <jamacku@redhat.com>
Date: Mon, 17 Apr 2023 14:59:55 +0200
Subject: [PATCH] ci: first part of the source-git automation - commit linter
@ -13,7 +13,7 @@ is configured via the `advanced-commit-linter.yml` file.
rhel-only
Related: #2184929
Related: #2100440
---
.github/advanced-commit-linter.yml | 23 +++++++++++
.github/workflows/source-git-automation.yml | 45 +++++++++++++++++++++

@ -0,0 +1,107 @@
From 049f899364c844326d00ee81b0a4f022315a8206 Mon Sep 17 00:00:00 2001
From: Jan Macku <jamacku@redhat.com>
Date: Tue, 25 Apr 2023 15:18:39 +0200
Subject: [PATCH] ci(Mergify): check CodeQL and build workflows based on
changed files
CodeQL and build workflow aren't run for all PRs. They are only run when specific files are changed.
from the CodeQL workflow:
```yml
paths:
- '**/meson.build'
- '.github/**/codeql*'
- 'src/**'
- 'test/**'
- 'tools/**'
```
This results in Mergify incorrectly labeling PRs with `needs-ci` label.
Let's update the Mergify config to check for the changed files as well.
rhel-only
Related: #2100440
---
.mergify.yml | 40 +++++++++++++++++++++++++++-------------
1 file changed, 27 insertions(+), 13 deletions(-)
diff --git a/.mergify.yml b/.mergify.yml
index bc1743e8ea..e862808ca7 100644
--- a/.mergify.yml
+++ b/.mergify.yml
@@ -9,11 +9,15 @@ pull_request_rules:
- label!=ci-waived
- or:
# Build test
- - -check-success=build (gcc, 11, bfd, gcrypt)
- - -check-success=build (gcc, 12, gold, openssl)
- - -check-success=build (clang, 13, mold, gcrypt)
- - -check-success=build (clang, 14, lld, openssl)
- - -check-success=build (clang, 15, bfd, auto)
+ # test build check only when the tests have been run ...
+ - and:
+ - files~=^(\S+\/meson\.build|\.github\/workflows\/\S+|meson_options\.txt|src\/\S+|test\/fuzz\/\S+)
+ - or:
+ - -check-success=build (gcc, 11, bfd, gcrypt)
+ - -check-success=build (gcc, 12, gold, openssl)
+ - -check-success=build (clang, 13, mold, gcrypt)
+ - -check-success=build (clang, 14, lld, openssl)
+ - -check-success=build (clang, 15, bfd, auto)
# Unit tests
- -check-success=build (GCC, auto)
- -check-success=build (GCC_ASAN_UBSAN, auto)
@@ -30,14 +34,17 @@ pull_request_rules:
# CentOS CI
- -check-success=CentOS CI (CentOS Stream 9)
- -check-success=CentOS CI (CentOS Stream 9 + sanitizers)
- # CodeQL
- - -check-success=CodeQL
# Packit
- -check-success=rpm-build:centos-stream-9-aarch64
- -check-success=rpm-build:centos-stream-9-x86_64
# Other
- -check-success=Lint Code Base
- -check-success=Differential ShellCheck
+ # CodeQL
+ # test CodeQL check only when the CodeQL have been run ...
+ - and:
+ - files~=^(\S+\/meson\.build|\.github\/\S+\/codeql|src\/\S+|test\/\S+|tools\/\S+)
+ - -check-success=CodeQL
actions:
label:
add:
@@ -81,11 +88,15 @@ pull_request_rules:
- label=ci-waived
- and:
# Build test
- - check-success=build (gcc, 11, bfd, gcrypt)
- - check-success=build (gcc, 12, gold, openssl)
- - check-success=build (clang, 13, mold, gcrypt)
- - check-success=build (clang, 14, lld, openssl)
- - check-success=build (clang, 15, bfd, auto)
+ # test build check only when specific files are changed ...
+ - or:
+ - -files~=^(\S+\/meson\.build|\.github\/workflows\/\S+|meson_options\.txt|src\/\S+|test\/fuzz\/\S+)
+ - and:
+ - check-success=build (gcc, 11, bfd, gcrypt)
+ - check-success=build (gcc, 12, gold, openssl)
+ - check-success=build (clang, 13, mold, gcrypt)
+ - check-success=build (clang, 14, lld, openssl)
+ - check-success=build (clang, 15, bfd, auto)
# Unit tests
- check-success=build (GCC, auto)
- check-success=build (GCC_ASAN_UBSAN, auto)
@@ -103,7 +114,10 @@ pull_request_rules:
- check-success=CentOS CI (CentOS Stream 9)
- check-success=CentOS CI (CentOS Stream 9 + sanitizers)
# CodeQL
- - check-success=CodeQL
+ # test CodeQL check only when specific files are changed ...
+ - or:
+ - -files~=^(\S+\/meson\.build|\.github\/\S+\/codeql|src\/\S+|test\/\S+|tools\/\S+)
+ - check-success=CodeQL
# Packit
- check-success=rpm-build:centos-stream-9-aarch64
- check-success=rpm-build:centos-stream-9-x86_64

@ -0,0 +1,38 @@
From e6c01cbcf4cd9b7a3d4ed93e5c6693d83b735c0e Mon Sep 17 00:00:00 2001
From: Jan Macku <jamacku@redhat.com>
Date: Thu, 27 Apr 2023 18:29:26 +0200
Subject: [PATCH] ci: add NOTICE to also update regexp in `.mergify.yml` when
updating `paths` property
rhel-only
Related: #2100440
---
.github/workflows/build_test.yml | 1 +
.github/workflows/codeql.yml | 1 +
2 files changed, 2 insertions(+)
diff --git a/.github/workflows/build_test.yml b/.github/workflows/build_test.yml
index cd6937e390..fdd5a462b6 100644
--- a/.github/workflows/build_test.yml
+++ b/.github/workflows/build_test.yml
@@ -6,6 +6,7 @@ name: Build test
on:
pull_request:
paths:
+ # If changed, also change regexp in `.mergify.yml`
- '**/meson.build'
- '.github/workflows/**'
- 'meson_options.txt'
diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml
index e8236b1857..3ee772b370 100644
--- a/.github/workflows/codeql.yml
+++ b/.github/workflows/codeql.yml
@@ -10,6 +10,7 @@ on:
- main
- rhel-9.*.0
paths:
+ # If changed, also change regexp in `.mergify.yml`
- '**/meson.build'
- '.github/**/codeql*'
- 'src/**'

@ -0,0 +1,205 @@
From a986415fec990de0ed0c8919d64b1eb6b78c485a Mon Sep 17 00:00:00 2001
From: Eric Curtin <ecurtin@redhat.com>
Date: Mon, 17 Apr 2023 22:09:24 +0100
Subject: [PATCH] Support /etc/system-update for OSTree systems
(cherry picked from commit b9dac418372401742609bd600f05267ae3a724de)
Resolves: #2203133
---
man/systemd-system-update-generator.xml | 2 +-
man/systemd.offline-updates.xml | 46 +++++++++++--------
man/systemd.special.xml | 9 ++--
.../system-update-generator.c | 25 ++++++----
units/system-update-cleanup.service | 4 +-
5 files changed, 51 insertions(+), 35 deletions(-)
diff --git a/man/systemd-system-update-generator.xml b/man/systemd-system-update-generator.xml
index 8711be26e3..1611a71550 100644
--- a/man/systemd-system-update-generator.xml
+++ b/man/systemd-system-update-generator.xml
@@ -30,7 +30,7 @@
<para><filename>systemd-system-update-generator</filename> is a
generator that automatically redirects the boot process to
<filename>system-update.target</filename>, if
- <filename>/system-update</filename> exists. This is required to
+ <filename>/system-update</filename> or <filename>/etc/system-update</filename> exists. This is required to
implement the logic explained in the
<citerefentry><refentrytitle>systemd.offline-updates</refentrytitle><manvolnum>7</manvolnum></citerefentry>.
</para>
diff --git a/man/systemd.offline-updates.xml b/man/systemd.offline-updates.xml
index 6706451766..7285f9e263 100644
--- a/man/systemd.offline-updates.xml
+++ b/man/systemd.offline-updates.xml
@@ -40,18 +40,20 @@
</listitem>
<listitem>
- <para>When the user OK'ed the update, the symlink <filename>/system-update</filename> is
- created that points to <filename index="false">/var/lib/system-update</filename> (or
- wherever the directory with the upgrade files is located) and the system is rebooted. This
- symlink is in the root directory, since we need to check for it very early at boot, at a
- time where <filename>/var/</filename> is not available yet.</para>
+ <para>When the user OK'ed the update, the symlink <filename>/system-update</filename> or
+ <filename>/etc/system-update</filename> is created that points to
+ <filename index="false">/var/lib/system-update</filename> (or wherever the directory with
+ the upgrade files is located) and the system is rebooted. This symlink is in the root
+ directory, since we need to check for it very early at boot, at a time where
+ <filename>/var/</filename> is not available yet.</para>
</listitem>
<listitem>
<para>Very early in the new boot
<citerefentry><refentrytitle>systemd-system-update-generator</refentrytitle><manvolnum>8</manvolnum></citerefentry>
- checks whether <filename>/system-update</filename> exists. If so, it (temporarily and for
- this boot only) redirects (i.e. symlinks) <filename>default.target</filename> to
+ checks whether <filename>/system-update</filename> or
+ <filename>/etc/system-update</filename> exists. If so, it (temporarily and for this boot
+ only) redirects (i.e. symlinks) <filename>default.target</filename> to
<filename>system-update.target</filename>, a special target that pulls in the base system
(i.e. <filename>sysinit.target</filename>, so that all file systems are mounted but little
else) and the system update units.</para>
@@ -68,12 +70,13 @@
<listitem>
<para>As the first step, an update service should check if the
- <filename>/system-update</filename> symlink points to the location used by that update
- service. In case it does not exist or points to a different location, the service must exit
- without error. It is possible for multiple update services to be installed, and for multiple
- update services to be launched in parallel, and only the one that corresponds to the tool
- that <emphasis>created</emphasis> the symlink before reboot should perform any actions. It
- is unsafe to run multiple updates in parallel.</para>
+ <filename>/system-update</filename> or <filename>/etc/system-update</filename> symlink
+ points to the location used by that update service. In case it does not exist or points to a
+ different location, the service must exit without error. It is possible for multiple update
+ services to be installed, and for multiple update services to be launched in parallel, and
+ only the one that corresponds to the tool that <emphasis>created</emphasis> the symlink
+ before reboot should perform any actions. It is unsafe to run multiple updates in
+ parallel.</para>
</listitem>
<listitem>
@@ -88,14 +91,16 @@
<para>The update scripts should exit only after the update is finished. It is expected
that the service which performs the update will cause the machine to reboot after it
is done. If the <filename>system-update.target</filename> is successfully reached, i.e.
- all update services have run, and the <filename>/system-update</filename> symlink still
- exists, it will be removed and the machine rebooted as a safety measure.</para>
+ all update services have run, and the <filename>/system-update</filename> or
+ <filename>/etc/system-update</filename> symlink still exists, it will be removed and
+ the machine rebooted as a safety measure.</para>
</listitem>
<listitem>
- <para>After a reboot, now that the <filename>/system-update</filename> symlink is gone,
- the generator won't redirect <filename>default.target</filename> anymore and the system
- now boots into the default target again.</para>
+ <para>After a reboot, now that the <filename>/system-update</filename> and
+ <filename>/etc/system-update</filename> symlink is gone, the generator won't redirect
+ <filename>default.target</filename> anymore and the system now boots into the default
+ target again.</para>
</listitem>
</orderedlist>
</refsect1>
@@ -115,8 +120,9 @@
</listitem>
<listitem>
- <para>Make sure to remove the <filename>/system-update</filename> symlink as early as
- possible in the update script to avoid reboot loops in case the update fails.</para>
+ <para>Make sure to remove the <filename>/system-update</filename> and
+ <filename>/etc/system-update</filename> symlinks as early as possible in the update
+ script to avoid reboot loops in case the update fails.</para>
</listitem>
<listitem>
diff --git a/man/systemd.special.xml b/man/systemd.special.xml
index 85eb8ad076..1620895511 100644
--- a/man/systemd.special.xml
+++ b/man/systemd.special.xml
@@ -753,8 +753,8 @@
<listitem>
<para>A special target unit that is used for offline system updates.
<citerefentry><refentrytitle>systemd-system-update-generator</refentrytitle><manvolnum>8</manvolnum></citerefentry>
- will redirect the boot process to this target if <filename>/system-update</filename>
- exists. For more information see
+ will redirect the boot process to this target if <filename>/system-update</filename> or
+ <filename>/etc/system-update</filename> exists. For more information see
<citerefentry><refentrytitle>systemd.offline-updates</refentrytitle><manvolnum>7</manvolnum></citerefentry>.
</para>
@@ -764,9 +764,10 @@
<filename>system-update-pre.target</filename> but not pull it in. Services which want to
run during system updates only, but before the actual system update is executed should
order themselves before this unit and pull it in. As a safety measure, if this does not
- happen, and <filename>/system-update</filename> still exists after
+ happen, and <filename>/system-update</filename> or
+ <filename>/etc/system-update</filename> still exists after
<filename>system-update.target</filename> is reached,
- <filename>system-update-cleanup.service</filename> will remove this symlink and reboot
+ <filename>system-update-cleanup.service</filename> will remove the symlinks and reboot
the machine.</para>
</listitem>
</varlistentry>
diff --git a/src/system-update-generator/system-update-generator.c b/src/system-update-generator/system-update-generator.c
index fc5aaa9bac..08b357f356 100644
--- a/src/system-update-generator/system-update-generator.c
+++ b/src/system-update-generator/system-update-generator.c
@@ -6,6 +6,7 @@
#include "fs-util.h"
#include "generator.h"
#include "log.h"
+#include "path-util.h"
#include "proc-cmdline.h"
#include "special.h"
#include "string-util.h"
@@ -19,19 +20,25 @@
static const char *arg_dest = NULL;
static int generate_symlink(void) {
- const char *p = NULL;
+ _cleanup_free_ char *j = NULL;
- if (laccess("/system-update", F_OK) < 0) {
- if (errno == ENOENT)
- return 0;
+ FOREACH_STRING(p, "/system-update", "/etc/system-update") {
+ if (laccess(p, F_OK) >= 0)
+ goto link_found;
- log_error_errno(errno, "Failed to check for system update: %m");
- return -EINVAL;
+ if (errno != ENOENT)
+ log_warning_errno(errno, "Failed to check if %s symlink exists, ignoring: %m", p);
}
- p = strjoina(arg_dest, "/" SPECIAL_DEFAULT_TARGET);
- if (symlink(SYSTEM_DATA_UNIT_DIR "/system-update.target", p) < 0)
- return log_error_errno(errno, "Failed to create symlink %s: %m", p);
+ return 0;
+
+link_found:
+ j = path_join(arg_dest, SPECIAL_DEFAULT_TARGET);
+ if (!j)
+ return log_oom();
+
+ if (symlink(SYSTEM_DATA_UNIT_DIR "/system-update.target", j) < 0)
+ return log_error_errno(errno, "Failed to create symlink %s: %m", j);
return 1;
}
diff --git a/units/system-update-cleanup.service b/units/system-update-cleanup.service
index 5a5dd725a1..a54e74567e 100644
--- a/units/system-update-cleanup.service
+++ b/units/system-update-cleanup.service
@@ -29,7 +29,9 @@ SuccessAction=reboot
# reboot or some other action on its own.
ConditionPathExists=|/system-update
ConditionPathIsSymbolicLink=|/system-update
+ConditionPathExists=|/etc/system-update
+ConditionPathIsSymbolicLink=|/etc/system-update
[Service]
Type=oneshot
-ExecStart=rm -fv /system-update
+ExecStart=rm -fv /system-update /etc/system-update

@ -1,4 +1,4 @@
From 6b6f61668c539329bc95fb7f3c3b644b793dfb52 Mon Sep 17 00:00:00 2001
From 05b7dfdcc4893fac9adcbf80bcc3f6a8f8f520c1 Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Wed, 25 Jan 2023 18:47:05 +0100
Subject: [PATCH] journal-def: fix type of signature to match the actual field
@ -6,7 +6,7 @@ Subject: [PATCH] journal-def: fix type of signature to match the actual field
(cherry picked from commit 6fe167d0a77f72086b457125fad6931ca02a4baf)
Related: #2184929
Related: #2183546
---
src/libsystemd/sd-journal/journal-def.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

@ -1,4 +1,4 @@
From de2a4abb178021ab6700f0bc4038daf88f92cb03 Mon Sep 17 00:00:00 2001
From b418b2d17e258f10211b529f9beb8b090283307f Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Wed, 25 Jan 2023 18:48:31 +0100
Subject: [PATCH] journal: use compound initialization for journal file Header
@ -6,7 +6,7 @@ Subject: [PATCH] journal: use compound initialization for journal file Header
(cherry picked from commit c3dd0dcb888fd8da7ce4e5299caf45e90ddcd41b)
Related: #2184929
Related: #2183546
---
src/libsystemd/sd-journal/journal-file.c | 23 +++++++++++------------
1 file changed, 11 insertions(+), 12 deletions(-)

@ -1,11 +1,11 @@
From de88fa23f060ab5f554f4c0d41b0f93430f1db8a Mon Sep 17 00:00:00 2001
From 27c91e79d3cbb79efa9efdd10a7ed5a06c80cba6 Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Tue, 4 Apr 2023 17:11:28 +0900
Subject: [PATCH] journald: fix log message
(cherry picked from commit 01aa59979bc61125f599a5b8a6c911fff5daaee7)
Resolves: #2184929
Resolves: #2183546
---
src/journal/journald-server.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

@ -1,11 +1,11 @@
From c7919b02b504e2c0ccacf02c6f21f65c3f18ea4c Mon Sep 17 00:00:00 2001
From 509b535eaad77038984604eac486b0bb76accc6d Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Tue, 4 Apr 2023 16:43:44 +0900
Subject: [PATCH] sd-journal: cache results of parsing environment variables
(cherry picked from commit 9dfbae203e3afa500163bc46e0070c4cb2180aac)
Resolves: #2184929
Resolves: #2183546
---
src/libsystemd/sd-journal/journal-file.c | 34 +++++++++++++++---------
1 file changed, 22 insertions(+), 12 deletions(-)

@ -1,11 +1,11 @@
From c926e4ff48022a71665e7e7833fd59a1bf2ad5fb Mon Sep 17 00:00:00 2001
From 2c755739d84e409a6331902f5c15943a192a40f4 Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Tue, 4 Apr 2023 14:34:32 +0900
Subject: [PATCH] compress: introduce compression_supported() helper function
(cherry picked from commit 83f3d73da8d132773dd91aae0fa7babb74920774)
Resolves: #2184929
Resolves: #2183546
---
src/basic/compress.c | 10 ++++++++++
src/basic/compress.h | 3 +++

@ -1,4 +1,4 @@
From 3baac68b2bcad46062b12aa11e15adf8e6d80a40 Mon Sep 17 00:00:00 2001
From 0eb906f1a10a8667ead6f1dc5c308f07c9c2b691 Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Tue, 4 Apr 2023 18:22:50 +0900
Subject: [PATCH] sd-journal: always use the compression algorithm specified in
@ -9,7 +9,7 @@ mentioned in the header.
(cherry picked from commit 2360352ef02548723ac0c8eaf5ff6905eb9eeca5)
Resolves: #2184929
Resolves: #2183546
---
src/libsystemd/sd-journal/journal-file.c | 40 ++++++++++++++----------
src/libsystemd/sd-journal/journal-file.h | 12 +++++--

@ -1,4 +1,4 @@
From 6d0fb28f2d7b64146361673be99bc2586e3763ce Mon Sep 17 00:00:00 2001
From 7816037425c80202ed375cff0cc6249c2bc91e2c Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Tue, 4 Apr 2023 14:19:51 +0900
Subject: [PATCH] sd-journal: allow to specify compression algorithm through
@ -14,7 +14,7 @@ algorithm.
Co-authored-by: Colin Walters <walters@verbum.org>
(cherry picked from commit 1f06ea747b5939a1083c436dd7dae97b37bedee7)
Resolves: #2184929
Resolves: #2183546
---
docs/ENVIRONMENT.md | 8 +++++
src/libsystemd/sd-journal/journal-file.c | 44 +++++++++++++++++++++++-

@ -1,4 +1,4 @@
From 7c20d0bfec62de66e81f6b6e1c7ce9f3a3b3d5cf Mon Sep 17 00:00:00 2001
From 1ed71d6c6613509cc851a3099de8dc6a4d181f56 Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Tue, 4 Apr 2023 15:03:35 +0900
Subject: [PATCH] test: add test case that journal file is created with the
@ -6,7 +6,7 @@ Subject: [PATCH] test: add test case that journal file is created with the
(cherry picked from commit d23a1c52a93206b0dbabcb4336752ccb796c11c3)
Resolves: #2184929
Resolves: #2183546
---
test/units/testsuite-04.sh | 32 ++++++++++++++++++++++++++++++++
1 file changed, 32 insertions(+)

@ -0,0 +1,31 @@
From 94c7e260b499cd9e5ad8d99d95b9413df2d50cc6 Mon Sep 17 00:00:00 2001
From: Michal Sekletar <msekleta@redhat.com>
Date: Thu, 30 Mar 2023 14:56:16 +0200
Subject: [PATCH] rules: do not online CPU automatically on IBM platforms
RHEL-only
Resolves: #2143107
---
rules.d/40-redhat.rules | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/rules.d/40-redhat.rules b/rules.d/40-redhat.rules
index 3c95cd2df0..efb866966e 100644
--- a/rules.d/40-redhat.rules
+++ b/rules.d/40-redhat.rules
@@ -1,7 +1,13 @@
# do not edit this file, it will be overwritten on update
# CPU hotadd request
-SUBSYSTEM=="cpu", ACTION=="add", TEST=="online", ATTR{online}=="0", ATTR{online}="1"
+SUBSYSTEM!="cpu", GOTO="cpu_online_end"
+ACTION!="add", GOTO="cpu_online_end"
+CONST{arch}=="s390*|ppc64*", GOTO="cpu_online_end"
+
+TEST=="online", ATTR{online}=="0", ATTR{online}="1"
+
+LABEL="cpu_online_end"
# Memory hotadd request
SUBSYSTEM!="memory", GOTO="memory_hotplug_end"

@ -0,0 +1,30 @@
From d5de6c135caa4cb5871ccfa7d739e0ab46bf02e5 Mon Sep 17 00:00:00 2001
From: Jan Macku <jamacku@redhat.com>
Date: Fri, 19 May 2023 16:37:37 +0200
Subject: [PATCH] ci: update permissions for source-git automation workflows
new version of `redhat-plumbers-in-action/advanced-commit-linter` requires new permission:
`checks: write`.
https://github.com/redhat-plumbers-in-action/advanced-commit-linter/commit/f1bb35fcdeff83d40eb67b5e7c58baad6be689b2
rhel-only
Related: #2170883
---
.github/workflows/source-git-automation.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/source-git-automation.yml b/.github/workflows/source-git-automation.yml
index 140f21b116..e653e28a7f 100644
--- a/.github/workflows/source-git-automation.yml
+++ b/.github/workflows/source-git-automation.yml
@@ -33,7 +33,7 @@ jobs:
validated-pr-metadata: ${{ steps.commit-linter.outputs.validated-pr-metadata }}
permissions:
- statuses: write
+ checks: write
pull-requests: write
steps:

@ -0,0 +1,492 @@
From a6d9977a0cafaaf1dcf5c7658d958aea8e5284f0 Mon Sep 17 00:00:00 2001
From: Eric DeVolder <eric.devolder@oracle.com>
Date: Mon, 21 Nov 2022 11:27:27 -0500
Subject: [PATCH] pstore: fixes for dmesg.txt reconstruction
This patch fixes problems with the re-assembly of the dmesg
from the records stored in pstore.
The current code simply ignores the last 6 characters of the
file name to form a base record id, which then groups any
pstore files with this base id into the reconstructed dmesg.txt.
This approach fails when the following oops generated the
following in pstore:
-rw-------. 1 root root 1808 Oct 27 22:07 dmesg-efi-166692286101001
-rw-------. 1 root root 1341 Oct 27 22:07 dmesg-efi-166692286101002
-rw-------. 1 root root 1812 Oct 27 22:07 dmesg-efi-166692286102001
-rw-------. 1 root root 1820 Oct 27 22:07 dmesg-efi-166692286102002
-rw-------. 1 root root 1807 Oct 27 22:07 dmesg-efi-166692286103001
-rw-------. 1 root root 1791 Oct 27 22:07 dmesg-efi-166692286103002
-rw-------. 1 root root 1773 Oct 27 22:07 dmesg-efi-166692286104001
-rw-------. 1 root root 1801 Oct 27 22:07 dmesg-efi-166692286104002
-rw-------. 1 root root 1821 Oct 27 22:07 dmesg-efi-166692286105001
-rw-------. 1 root root 1809 Oct 27 22:07 dmesg-efi-166692286105002
-rw-------. 1 root root 1804 Oct 27 22:07 dmesg-efi-166692286106001
-rw-------. 1 root root 1817 Oct 27 22:07 dmesg-efi-166692286106002
-rw-------. 1 root root 1792 Oct 27 22:07 dmesg-efi-166692286107001
-rw-------. 1 root root 1810 Oct 27 22:07 dmesg-efi-166692286107002
-rw-------. 1 root root 1717 Oct 27 22:07 dmesg-efi-166692286108001
-rw-------. 1 root root 1808 Oct 27 22:07 dmesg-efi-166692286108002
-rw-------. 1 root root 1764 Oct 27 22:07 dmesg-efi-166692286109001
-rw-------. 1 root root 1765 Oct 27 22:07 dmesg-efi-166692286109002
-rw-------. 1 root root 1796 Oct 27 22:07 dmesg-efi-166692286110001
-rw-------. 1 root root 1816 Oct 27 22:07 dmesg-efi-166692286110002
-rw-------. 1 root root 1793 Oct 27 22:07 dmesg-efi-166692286111001
-rw-------. 1 root root 1751 Oct 27 22:07 dmesg-efi-166692286111002
-rw-------. 1 root root 1813 Oct 27 22:07 dmesg-efi-166692286112001
-rw-------. 1 root root 1786 Oct 27 22:07 dmesg-efi-166692286112002
-rw-------. 1 root root 1754 Oct 27 22:07 dmesg-efi-166692286113001
-rw-------. 1 root root 1752 Oct 27 22:07 dmesg-efi-166692286113002
-rw-------. 1 root root 1803 Oct 27 22:07 dmesg-efi-166692286114001
-rw-------. 1 root root 1759 Oct 27 22:07 dmesg-efi-166692286114002
-rw-------. 1 root root 1805 Oct 27 22:07 dmesg-efi-166692286115001
-rw-------. 1 root root 1787 Oct 27 22:07 dmesg-efi-166692286115002
-rw-------. 1 root root 1815 Oct 27 22:07 dmesg-efi-166692286116001
-rw-------. 1 root root 1771 Oct 27 22:07 dmesg-efi-166692286116002
-rw-------. 1 root root 1816 Oct 27 22:07 dmesg-efi-166692286117002
-rw-------. 1 root root 1388 Oct 27 22:07 dmesg-efi-166692286701003
-rw-------. 1 root root 1824 Oct 27 22:07 dmesg-efi-166692286702003
-rw-------. 1 root root 1795 Oct 27 22:07 dmesg-efi-166692286703003
-rw-------. 1 root root 1805 Oct 27 22:07 dmesg-efi-166692286704003
-rw-------. 1 root root 1813 Oct 27 22:07 dmesg-efi-166692286705003
-rw-------. 1 root root 1821 Oct 27 22:07 dmesg-efi-166692286706003
-rw-------. 1 root root 1814 Oct 27 22:07 dmesg-efi-166692286707003
-rw-------. 1 root root 1812 Oct 27 22:07 dmesg-efi-166692286708003
-rw-------. 1 root root 1769 Oct 27 22:07 dmesg-efi-166692286709003
-rw-------. 1 root root 1820 Oct 27 22:07 dmesg-efi-166692286710003
-rw-------. 1 root root 1755 Oct 27 22:07 dmesg-efi-166692286711003
-rw-------. 1 root root 1790 Oct 27 22:07 dmesg-efi-166692286712003
-rw-------. 1 root root 1756 Oct 27 22:07 dmesg-efi-166692286713003
-rw-------. 1 root root 1763 Oct 27 22:07 dmesg-efi-166692286714003
-rw-------. 1 root root 1791 Oct 27 22:07 dmesg-efi-166692286715003
-rw-------. 1 root root 1775 Oct 27 22:07 dmesg-efi-166692286716003
-rw-------. 1 root root 1820 Oct 27 22:07 dmesg-efi-166692286717003
The "reconstructed" dmesg.txt that resulted from the above contained
the following (ignoring actual contents, just providing the Part info):
Emergency#3 Part17
Emergency#3 Part16
Emergency#3 Part15
Emergency#3 Part14
Emergency#3 Part13
Emergency#3 Part12
Emergency#3 Part11
Emergency#3 Part10
Emergency#3 Part9
Emergency#3 Part8
Emergency#3 Part7
Emergency#3 Part6
Emergency#3 Part5
Emergency#3 Part4
Emergency#3 Part3
Emergency#3 Part2
Emergency#3 Part1
Panic#2 Part17
Panic#2 Part16
Oops#1 Part16
Panic#2 Part15
Oops#1 Part15
Panic#2 Part14
Oops#1 Part14
Panic#2 Part13
Oops#1 Part13
Panic#2 Part12
Oops#1 Part12
Panic#2 Part11
Oops#1 Part11
Panic#2 Part10
Oops#1 Part10
Panic#2 Part9
Oops#1 Part9
Panic#2 Part8
Oops#1 Part8
Panic#2 Part7
Oops#1 Part7
Panic#2 Part6
Oops#1 Part6
Panic#2 Part5
Oops#1 Part5
Panic#2 Part4
Oops#1 Part4
Panic#2 Part3
Oops#1 Part3
Panic#2 Part2
Oops#1 Part2
Panic#2 Part1
Oops#1 Part1
The above is a interleaved mess of three dmesg dumps.
This patch fixes the above problems, and simplifies the dmesg
reconstruction process. The code now distinguishes between
records on EFI vs ERST, which have differently formatted
record identifiers. Using knowledge of the format of the
record ids allows vastly improved reconstruction process.
With this change in place, the above pstore records now
result in the following:
# ls -alR /var/lib/systemd/pstore
1666922861:
total 8
drwxr-xr-x. 4 root root 28 Nov 18 14:58 .
drwxr-xr-x. 7 root root 144 Nov 18 14:58 ..
drwxr-xr-x. 2 root root 4096 Nov 18 14:58 001
drwxr-xr-x. 2 root root 4096 Nov 18 14:58 002
1666922861/001:
total 100
drwxr-xr-x. 2 root root 4096 Nov 18 14:58 .
drwxr-xr-x. 4 root root 28 Nov 18 14:58 ..
-rw-------. 1 root root 1808 Oct 27 22:07 dmesg-efi-166692286101001
-rw-------. 1 root root 1812 Oct 27 22:07 dmesg-efi-166692286102001
-rw-------. 1 root root 1807 Oct 27 22:07 dmesg-efi-166692286103001
-rw-------. 1 root root 1773 Oct 27 22:07 dmesg-efi-166692286104001
-rw-------. 1 root root 1821 Oct 27 22:07 dmesg-efi-166692286105001
-rw-------. 1 root root 1804 Oct 27 22:07 dmesg-efi-166692286106001
-rw-------. 1 root root 1792 Oct 27 22:07 dmesg-efi-166692286107001
-rw-------. 1 root root 1717 Oct 27 22:07 dmesg-efi-166692286108001
-rw-------. 1 root root 1764 Oct 27 22:07 dmesg-efi-166692286109001
-rw-------. 1 root root 1796 Oct 27 22:07 dmesg-efi-166692286110001
-rw-------. 1 root root 1793 Oct 27 22:07 dmesg-efi-166692286111001
-rw-------. 1 root root 1813 Oct 27 22:07 dmesg-efi-166692286112001
-rw-------. 1 root root 1754 Oct 27 22:07 dmesg-efi-166692286113001
-rw-------. 1 root root 1803 Oct 27 22:07 dmesg-efi-166692286114001
-rw-------. 1 root root 1805 Oct 27 22:07 dmesg-efi-166692286115001
-rw-------. 1 root root 1815 Oct 27 22:07 dmesg-efi-166692286116001
-rw-r-----. 1 root root 28677 Nov 18 14:58 dmesg.txt
1666922861/002:
total 104
drwxr-xr-x. 2 root root 4096 Nov 18 14:58 .
drwxr-xr-x. 4 root root 28 Nov 18 14:58 ..
-rw-------. 1 root root 1341 Oct 27 22:07 dmesg-efi-166692286101002
-rw-------. 1 root root 1820 Oct 27 22:07 dmesg-efi-166692286102002
-rw-------. 1 root root 1791 Oct 27 22:07 dmesg-efi-166692286103002
-rw-------. 1 root root 1801 Oct 27 22:07 dmesg-efi-166692286104002
-rw-------. 1 root root 1809 Oct 27 22:07 dmesg-efi-166692286105002
-rw-------. 1 root root 1817 Oct 27 22:07 dmesg-efi-166692286106002
-rw-------. 1 root root 1810 Oct 27 22:07 dmesg-efi-166692286107002
-rw-------. 1 root root 1808 Oct 27 22:07 dmesg-efi-166692286108002
-rw-------. 1 root root 1765 Oct 27 22:07 dmesg-efi-166692286109002
-rw-------. 1 root root 1816 Oct 27 22:07 dmesg-efi-166692286110002
-rw-------. 1 root root 1751 Oct 27 22:07 dmesg-efi-166692286111002
-rw-------. 1 root root 1786 Oct 27 22:07 dmesg-efi-166692286112002
-rw-------. 1 root root 1752 Oct 27 22:07 dmesg-efi-166692286113002
-rw-------. 1 root root 1759 Oct 27 22:07 dmesg-efi-166692286114002
-rw-------. 1 root root 1787 Oct 27 22:07 dmesg-efi-166692286115002
-rw-------. 1 root root 1771 Oct 27 22:07 dmesg-efi-166692286116002
-rw-------. 1 root root 1816 Oct 27 22:07 dmesg-efi-166692286117002
-rw-r-----. 1 root root 30000 Nov 18 14:58 dmesg.txt
1666922867:
total 4
drwxr-xr-x. 3 root root 17 Nov 18 14:58 .
drwxr-xr-x. 7 root root 144 Nov 18 14:58 ..
drwxr-xr-x. 2 root root 4096 Nov 18 14:58 003
1666922867/003:
total 104
drwxr-xr-x. 2 root root 4096 Nov 18 14:58 .
drwxr-xr-x. 3 root root 17 Nov 18 14:58 ..
-rw-------. 1 root root 1388 Oct 27 22:07 dmesg-efi-166692286701003
-rw-------. 1 root root 1824 Oct 27 22:07 dmesg-efi-166692286702003
-rw-------. 1 root root 1795 Oct 27 22:07 dmesg-efi-166692286703003
-rw-------. 1 root root 1805 Oct 27 22:07 dmesg-efi-166692286704003
-rw-------. 1 root root 1813 Oct 27 22:07 dmesg-efi-166692286705003
-rw-------. 1 root root 1821 Oct 27 22:07 dmesg-efi-166692286706003
-rw-------. 1 root root 1814 Oct 27 22:07 dmesg-efi-166692286707003
-rw-------. 1 root root 1812 Oct 27 22:07 dmesg-efi-166692286708003
-rw-------. 1 root root 1769 Oct 27 22:07 dmesg-efi-166692286709003
-rw-------. 1 root root 1820 Oct 27 22:07 dmesg-efi-166692286710003
-rw-------. 1 root root 1755 Oct 27 22:07 dmesg-efi-166692286711003
-rw-------. 1 root root 1790 Oct 27 22:07 dmesg-efi-166692286712003
-rw-------. 1 root root 1756 Oct 27 22:07 dmesg-efi-166692286713003
-rw-------. 1 root root 1763 Oct 27 22:07 dmesg-efi-166692286714003
-rw-------. 1 root root 1791 Oct 27 22:07 dmesg-efi-166692286715003
-rw-------. 1 root root 1775 Oct 27 22:07 dmesg-efi-166692286716003
-rw-------. 1 root root 1820 Oct 27 22:07 dmesg-efi-166692286717003
-rw-r-----. 1 root root 30111 Nov 18 14:58 dmesg.txt
Furthemore, pstore records on ERST are now able to accurately
identify the change in timestamp sequence in order to start a
new dmesg.txt, as needed.
(cherry picked from commit 5fbaa757077bde2db8d33b1c358518c41b990339)
Related: #2170883
---
src/pstore/pstore.c | 204 ++++++++++++++++++--------------------------
1 file changed, 83 insertions(+), 121 deletions(-)
diff --git a/src/pstore/pstore.c b/src/pstore/pstore.c
index d820ceb9f6..cfce994bec 100644
--- a/src/pstore/pstore.c
+++ b/src/pstore/pstore.c
@@ -115,7 +115,7 @@ static int compare_pstore_entries(const PStoreEntry *a, const PStoreEntry *b) {
return strcmp(a->dirent.d_name, b->dirent.d_name);
}
-static int move_file(PStoreEntry *pe, const char *subdir) {
+static int move_file(PStoreEntry *pe, const char *subdir1, const char *subdir2) {
_cleanup_free_ char *ifd_path = NULL, *ofd_path = NULL;
_cleanup_free_ void *field = NULL;
const char *suffix, *message;
@@ -129,7 +129,7 @@ static int move_file(PStoreEntry *pe, const char *subdir) {
if (!ifd_path)
return log_oom();
- ofd_path = path_join(arg_archivedir, subdir, pe->dirent.d_name);
+ ofd_path = path_join(arg_archivedir, subdir1, subdir2, pe->dirent.d_name);
if (!ofd_path)
return log_oom();
@@ -172,153 +172,115 @@ static int move_file(PStoreEntry *pe, const char *subdir) {
return 0;
}
-static int write_dmesg(const char *dmesg, size_t size, const char *id) {
- _cleanup_(unlink_and_freep) char *tmp_path = NULL;
+static int append_dmesg(PStoreEntry *pe, const char *subdir1, const char *subdir2) {
+ /* Append dmesg chunk to end, create if needed */
_cleanup_free_ char *ofd_path = NULL;
_cleanup_close_ int ofd = -1;
ssize_t wr;
- int r;
- if (size == 0)
- return 0;
+ assert(pe);
- assert(dmesg);
+ if (pe->content_size == 0)
+ return 0;
- ofd_path = path_join(arg_archivedir, id, "dmesg.txt");
+ ofd_path = path_join(arg_archivedir, subdir1, subdir2, "dmesg.txt");
if (!ofd_path)
return log_oom();
- ofd = open_tmpfile_linkable(ofd_path, O_CLOEXEC|O_CREAT|O_TRUNC|O_WRONLY, &tmp_path);
+ ofd = open(ofd_path, O_CREAT|O_NOFOLLOW|O_NOCTTY|O_CLOEXEC|O_APPEND|O_WRONLY, 0640);
if (ofd < 0)
- return log_error_errno(ofd, "Failed to open temporary file %s: %m", ofd_path);
- wr = write(ofd, dmesg, size);
+ return log_error_errno(ofd, "Failed to open file %s: %m", ofd_path);
+ wr = write(ofd, pe->content, pe->content_size);
if (wr < 0)
return log_error_errno(errno, "Failed to store dmesg to %s: %m", ofd_path);
- if (wr != (ssize_t)size)
- return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to store dmesg to %s. %zu bytes are lost.", ofd_path, size - wr);
- r = link_tmpfile(ofd, tmp_path, ofd_path);
- if (r < 0)
- return log_error_errno(r, "Failed to write temporary file %s: %m", ofd_path);
- tmp_path = mfree(tmp_path);
+ if ((size_t)wr != pe->content_size)
+ return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to store dmesg to %s. %zu bytes are lost.", ofd_path, pe->content_size - wr);
return 0;
}
-static void process_dmesg_files(PStoreList *list) {
+static int process_dmesg_files(PStoreList *list) {
/* Move files, reconstruct dmesg.txt */
- _cleanup_free_ char *dmesg = NULL, *dmesg_id = NULL;
- size_t dmesg_size = 0;
- bool dmesg_bad = false;
- PStoreEntry *pe;
+ _cleanup_free_ char *erst_subdir = NULL;
+ uint64_t last_record_id = 0;
+
+ /* When dmesg is written into pstore, it is done so in small chunks, whatever the exchange buffer
+ * size is with the underlying pstore backend (ie. EFI may be ~2KiB), which means an example
+ * pstore with approximately 64KB of storage may have up to roughly 32 dmesg files, some likely
+ * related.
+ *
+ * Here we look at the dmesg filename and try to discern if files are part of a related group,
+ * meaning the same original dmesg.
+ *
+ * The dmesg- filename contains the backend-type and the Common Platform Error Record, CPER,
+ * record id, a 64-bit number.
+ *
+ * Files are processed in reverse lexigraphical order so as to properly reconstruct original dmesg.*/
- /* Handle each dmesg file: files processed in reverse
- * order so as to properly reconstruct original dmesg */
for (size_t n = list->n_entries; n > 0; n--) {
- bool move_file_and_continue = false;
- _cleanup_free_ char *pe_id = NULL;
+ PStoreEntry *pe;
char *p;
- size_t plen;
pe = &list->entries[n-1];
if (pe->handled)
continue;
- if (!startswith(pe->dirent.d_name, "dmesg-"))
- continue;
-
if (endswith(pe->dirent.d_name, ".enc.z")) /* indicates a problem */
- move_file_and_continue = true;
- p = strrchr(pe->dirent.d_name, '-');
- if (!p)
- move_file_and_continue = true;
-
- if (move_file_and_continue) {
- /* A dmesg file on which we do NO additional processing */
- (void) move_file(pe, NULL);
- continue;
- }
-
- /* See if this file is one of a related group of files
- * in order to reconstruct dmesg */
-
- /* When dmesg is written into pstore, it is done so in
- * small chunks, whatever the exchange buffer size is
- * with the underlying pstore backend (ie. EFI may be
- * ~2KiB), which means an example pstore with approximately
- * 64KB of storage may have up to roughly 32 dmesg files
- * that could be related, depending upon the size of the
- * original dmesg.
- *
- * Here we look at the dmesg filename and try to discern
- * if files are part of a related group, meaning the same
- * original dmesg.
- *
- * The two known pstore backends are EFI and ERST. These
- * backends store data in the Common Platform Error
- * Record, CPER, format. The dmesg- filename contains the
- * CPER record id, a 64bit number (in decimal notation).
- * In Linux, the record id is encoded with two digits for
- * the dmesg part (chunk) number and 3 digits for the
- * count number. So allowing an additional digit to
- * compensate for advancing time, this code ignores the
- * last six digits of the filename in determining the
- * record id.
- *
- * For the EFI backend, the record id encodes an id in the
- * upper 32 bits, and a timestamp in the lower 32-bits.
- * So ignoring the least significant 6 digits has proven
- * to generally identify related dmesg entries. */
-#define PSTORE_FILENAME_IGNORE 6
-
- /* determine common portion of record id */
- ++p; /* move beyond dmesg- */
- plen = strlen(p);
- if (plen > PSTORE_FILENAME_IGNORE) {
- pe_id = memdup_suffix0(p, plen - PSTORE_FILENAME_IGNORE);
- if (!pe_id) {
- log_oom();
- return;
- }
- } else
- pe_id = mfree(pe_id);
-
- /* Now move file from pstore to archive storage */
- move_file(pe, pe_id);
-
- if (dmesg_bad)
continue;
-
- /* If the current record id is NOT the same as the
- * previous record id, then start a new dmesg.txt file */
- if (!streq_ptr(pe_id, dmesg_id)) {
- /* Encountered a new dmesg group, close out old one, open new one */
- (void) write_dmesg(dmesg, dmesg_size, dmesg_id);
- dmesg_size = 0;
-
- /* now point dmesg_id to storage of pe_id */
- free_and_replace(dmesg_id, pe_id);
- }
-
- /* Reconstruction of dmesg is done as a useful courtesy: do not fail, but don't write garbled
- * output either. */
- size_t needed = strlen(pe->dirent.d_name) + strlen(":\n") + pe->content_size + 1;
- if (!GREEDY_REALLOC(dmesg, dmesg_size + needed)) {
- log_oom();
- dmesg_bad = true;
+ if (!startswith(pe->dirent.d_name, "dmesg-"))
continue;
- }
-
- dmesg_size += sprintf(dmesg + dmesg_size, "%s:\n", pe->dirent.d_name);
- if (pe->content) {
- memcpy(dmesg + dmesg_size, pe->content, pe->content_size);
- dmesg_size += pe->content_size;
- }
- pe_id = mfree(pe_id);
+ if ((p = startswith(pe->dirent.d_name, "dmesg-efi-"))) {
+ /* For the EFI backend, the 3 least significant digits of record id encodes a
+ * "count" number, the next 2 least significant digits for the dmesg part
+ * (chunk) number, and the remaining digits as the timestamp. See
+ * linux/drivers/firmware/efi/efi-pstore.c in efi_pstore_write(). */
+ _cleanup_free_ char *subdir1 = NULL, *subdir2 = NULL;
+ size_t plen = strlen(p);
+
+ if (plen < 6)
+ continue;
+
+ /* Extract base record id */
+ subdir1 = strndup(p, plen - 5);
+ if (!subdir1)
+ return log_oom();
+ /* Extract "count" field */
+ subdir2 = strndup(p + plen - 3, 3);
+ if (!subdir2)
+ return log_oom();
+
+ /* Now move file from pstore to archive storage */
+ (void) move_file(pe, subdir1, subdir2);
+
+ /* Append to the dmesg */
+ (void) append_dmesg(pe, subdir1, subdir2);
+ } else if ((p = startswith(pe->dirent.d_name, "dmesg-erst-"))) {
+ /* For the ERST backend, the record is a monotonically increasing number, seeded as
+ * a timestamp. See linux/drivers/acpi/apei/erst.c in erst_writer(). */
+ uint64_t record_id;
+
+ if (safe_atou64(p, &record_id) < 0)
+ continue;
+ if (last_record_id - 1 != record_id)
+ /* A discontinuity in the number has been detected, this current record id
+ * will become the directory name for all pieces of the dmesg in this
+ * series. */
+ if (free_and_strdup(&erst_subdir, p) < 0)
+ return log_oom();
+
+ /* Now move file from pstore to archive storage */
+ (void) move_file(pe, erst_subdir, NULL);
+
+ /* Append to the dmesg */
+ (void) append_dmesg(pe, erst_subdir, NULL);
+
+ /* Update, but keep erst_subdir for next file */
+ last_record_id = record_id;
+ } else
+ log_debug("Unknown backend, ignoring \"%s\".", pe->dirent.d_name);
}
-
- if (!dmesg_bad)
- (void) write_dmesg(dmesg, dmesg_size, dmesg_id);
+ return 0;
}
static int list_files(PStoreList *list, const char *sourcepath) {
@@ -394,11 +356,11 @@ static int run(int argc, char *argv[]) {
typesafe_qsort(list.entries, list.n_entries, compare_pstore_entries);
/* Process known file types */
- process_dmesg_files(&list);
+ (void) process_dmesg_files(&list);
/* Move left over files out of pstore */
for (size_t n = 0; n < list.n_entries; n++)
- move_file(&list.entries[n], NULL);
+ (void) move_file(&list.entries[n], NULL, NULL);
return 0;
}

@ -0,0 +1,37 @@
From f781f42f512b77b4283f0b96cc87907306075b52 Mon Sep 17 00:00:00 2001
From: Frantisek Sumsal <frantisek@sumsal.cz>
Date: Fri, 28 Apr 2023 11:09:22 +0200
Subject: [PATCH] pstore: explicitly set the base when converting record ID
(cherry picked from commit a95d96a2430db171b40fc2e50589807236f8f746)
Related: #2170883
---
src/pstore/pstore.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/pstore/pstore.c b/src/pstore/pstore.c
index cfce994bec..066d8ebb81 100644
--- a/src/pstore/pstore.c
+++ b/src/pstore/pstore.c
@@ -202,7 +202,7 @@ static int append_dmesg(PStoreEntry *pe, const char *subdir1, const char *subdir
static int process_dmesg_files(PStoreList *list) {
/* Move files, reconstruct dmesg.txt */
_cleanup_free_ char *erst_subdir = NULL;
- uint64_t last_record_id = 0;
+ unsigned long long last_record_id = 0;
/* When dmesg is written into pstore, it is done so in small chunks, whatever the exchange buffer
* size is with the underlying pstore backend (ie. EFI may be ~2KiB), which means an example
@@ -258,9 +258,9 @@ static int process_dmesg_files(PStoreList *list) {
} else if ((p = startswith(pe->dirent.d_name, "dmesg-erst-"))) {
/* For the ERST backend, the record is a monotonically increasing number, seeded as
* a timestamp. See linux/drivers/acpi/apei/erst.c in erst_writer(). */
- uint64_t record_id;
+ unsigned long long record_id;
- if (safe_atou64(p, &record_id) < 0)
+ if (safe_atollu_full(p, 10, &record_id) < 0)
continue;
if (last_record_id - 1 != record_id)
/* A discontinuity in the number has been detected, this current record id

@ -0,0 +1,68 @@
From 4c6c7127a96f086b919b4c082b9da6b29f791bb8 Mon Sep 17 00:00:00 2001
From: Frantisek Sumsal <frantisek@sumsal.cz>
Date: Fri, 28 Apr 2023 11:50:33 +0200
Subject: [PATCH] pstore: avoid opening the dmesg.txt file if not requested
Even with Storage=journal we would still attempt to open the final
dmesg.txt file which causes a lot of noise in the journal:
```
[ 5.764111] H testsuite-82.sh[658]: + systemctl start systemd-pstore
[ 5.806385] H systemd[1]: Starting modprobe@efi_pstore.service...
[ 5.808656] H systemd[1]: modprobe@efi_pstore.service: Deactivated successfully.
[ 5.808971] H systemd[1]: Finished modprobe@efi_pstore.service.
[ 5.818845] H kernel: audit: type=1130 audit(1682630623.637:114): pid=1 uid=0 auid=4294967295 ses=4294967295 subj=kernel msg='unit=modprobe@efi_pstore comm="systemd" exe="/usr/lib/systemd/systemd" hostname=? addr=? termin>
[ 5.818865] H kernel: audit: type=1131 audit(1682630623.637:115): pid=1 uid=0 auid=4294967295 ses=4294967295 subj=kernel msg='unit=modprobe@efi_pstore comm="systemd" exe="/usr/lib/systemd/systemd" hostname=? addr=? termin>
[ 5.816052] H systemd[1]: Starting systemd-pstore.service...
[ 5.840703] H systemd-pstore[806]: PStore dmesg-efi-168263062313014.
[ 5.841239] H systemd-pstore[806]: Failed to open file /var/lib/systemd/pstore/1682630623/014/dmesg.txt: Operation not permitted
[ 5.841428] H systemd-pstore[806]: PStore dmesg-efi-168263062312014.
[ 5.841575] H systemd-pstore[806]: Failed to open file /var/lib/systemd/pstore/1682630623/014/dmesg.txt: Operation not permitted
[ 5.841712] H systemd-pstore[806]: PStore dmesg-efi-168263062311014.
[ 5.841839] H systemd-pstore[806]: Failed to open file /var/lib/systemd/pstore/1682630623/014/dmesg.txt: Operation not permitted
[ 5.841989] H systemd-pstore[806]: PStore dmesg-efi-168263062310014.
[ 5.842141] H systemd-pstore[806]: Failed to open file /var/lib/systemd/pstore/1682630623/014/dmesg.txt: Operation not permitted
[ 5.842274] H systemd-pstore[806]: PStore dmesg-efi-168263062309014.
[ 5.842423] H systemd-pstore[806]: Failed to open file /var/lib/systemd/pstore/1682630623/014/dmesg.txt: Operation not permitted
[ 5.842589] H systemd-pstore[806]: PStore dmesg-efi-168263062308014.
[ 5.842722] H systemd-pstore[806]: Failed to open file /var/lib/systemd/pstore/1682630623/014/dmesg.txt: Operation not permitted
[ 5.842865] H systemd-pstore[806]: PStore dmesg-efi-168263062307014.
[ 5.843003] H systemd-pstore[806]: Failed to open file /var/lib/systemd/pstore/1682630623/014/dmesg.txt: Operation not permitted
[ 5.843153] H systemd-pstore[806]: PStore dmesg-efi-168263062306014.
[ 5.843280] H systemd-pstore[806]: Failed to open file /var/lib/systemd/pstore/1682630623/014/dmesg.txt: Operation not permitted
[ 5.843434] H systemd-pstore[806]: PStore dmesg-efi-168263062305014.
[ 5.843570] H systemd-pstore[806]: Failed to open file /var/lib/systemd/pstore/1682630623/014/dmesg.txt: Operation not permitted
[ 5.843702] H systemd-pstore[806]: PStore dmesg-efi-168263062304014.
[ 5.843831] H systemd-pstore[806]: Failed to open file /var/lib/systemd/pstore/1682630623/014/dmesg.txt: Operation not permitted
[ 5.843958] H systemd-pstore[806]: PStore dmesg-efi-168263062303014.
[ 5.844093] H systemd-pstore[806]: Failed to open file /var/lib/systemd/pstore/1682630623/014/dmesg.txt: Operation not permitted
[ 5.844250] H systemd-pstore[806]: PStore dmesg-efi-168263062302014.
[ 5.844412] H systemd-pstore[806]: Failed to open file /var/lib/systemd/pstore/1682630623/014/dmesg.txt: Operation not permitted
[ 5.844619] H systemd-pstore[806]: PStore dmesg-efi-168263062301014.
[ 5.844781] H systemd-pstore[806]: Failed to open file /var/lib/systemd/pstore/1682630623/014/dmesg.txt: Operation not permitted
[ 5.844956] H systemd-pstore[806]: PStore dmesg-efi-168263062300014.
[ 5.845168] H systemd-pstore[806]: Failed to open file /var/lib/systemd/pstore/1682630623/014/dmesg.txt: Operation not permitted
[ 5.851101] H systemd[1]: Finished systemd-pstore.service.
```
(cherry picked from commit ad5980803adac8dc1cf980447a07cb18962c238b)
Related: #2170883
---
src/pstore/pstore.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/src/pstore/pstore.c b/src/pstore/pstore.c
index 066d8ebb81..7fff6cee62 100644
--- a/src/pstore/pstore.c
+++ b/src/pstore/pstore.c
@@ -180,6 +180,9 @@ static int append_dmesg(PStoreEntry *pe, const char *subdir1, const char *subdir
assert(pe);
+ if (arg_storage != PSTORE_STORAGE_EXTERNAL)
+ return 0;
+
if (pe->content_size == 0)
return 0;

@ -0,0 +1,240 @@
From 356247b0fb704e62bf378a7940a8190677358daa Mon Sep 17 00:00:00 2001
From: Frantisek Sumsal <frantisek@sumsal.cz>
Date: Thu, 27 Apr 2023 23:17:52 +0200
Subject: [PATCH] test: add a couple of tests for systemd-pstore
(cherry picked from commit 6858e32d730fd5574eaa3d7fbf4cb12aacaea336)
Related: #2170883
---
test/units/testsuite-74.pstore.sh | 221 ++++++++++++++++++++++++++++++
1 file changed, 221 insertions(+)
create mode 100755 test/units/testsuite-74.pstore.sh
diff --git a/test/units/testsuite-74.pstore.sh b/test/units/testsuite-74.pstore.sh
new file mode 100755
index 0000000000..b4e442c1be
--- /dev/null
+++ b/test/units/testsuite-74.pstore.sh
@@ -0,0 +1,221 @@
+#!/usr/bin/env bash
+# SPDX-License-Identifier: LGPL-2.1-or-later
+set -eux
+set -o pipefail
+
+systemctl log-level info
+
+if systemd-detect-virt -cq; then
+ echo "Running in a container, skipping the systemd-pstore test..."
+ exit 0
+fi
+
+DUMMY_DMESG_1="$(mktemp)"
+cat >"$DUMMY_DMESG_1" <<\EOF
+6,17159,5340096332127,-;usb 1-4: USB disconnect, device number 124
+6,17160,5340109662397,-;input: WH-1000XM3 (AVRCP) as /devices/virtual/input/input293
+6,17161,5343126458360,-;loop0: detected capacity change from 0 to 3145728
+6,17162,5343126766065,-; loop0: p1 p2
+6,17163,5343126815038,-;EXT4-fs (loop0p1): mounted filesystem with ordered data mode. Quota mode: none.
+6,17164,5343158037334,-;EXT4-fs (loop0p1): unmounting filesystem.
+6,17165,5343158072598,-;loop0: detected capacity change from 0 to 3145728
+6,17166,5343158073563,-; loop0: p1 p2
+6,17167,5343158074325,-; loop0: p1 p2
+6,17168,5343158140859,-;EXT4-fs (loop0p1): mounted filesystem with ordered data mode. Quota mode: none.
+6,17169,5343158182977,-;EXT4-fs (loop0p1): unmounting filesystem.
+6,17170,5343158700241,-;loop0: detected capacity change from 0 to 3145728
+6,17171,5343158700439,-; loop0: p1 p2
+6,17172,5343158701120,-; loop0: p1 p2
+EOF
+
+DUMMY_DMESG_2="$(mktemp)"
+cat >"$DUMMY_DMESG_2" <<\EOF
+Nechť již hříšné saxofony ďáblů rozezvučí síň úděsnými tóny waltzu, tanga a quickstepu.
+Příliš žluťoučký kůň úpěl ďábelské ódy.
+Zvlášť zákeřný učeň s ďolíčky běží podél zóny úlů.
+Vyciď křišťálový nůž, ó učiň úděsné líbivým!
+Loď čeří kýlem tůň obzvlášť v Grónské úžině
+Ó, náhlý déšť již zvířil prach a čilá laň teď běží s houfcem gazel k úkrytům.
+Vypätá dcéra grófa Maxwella s IQ nižším ako kôň núti čeľaď hrýzť hŕbu jabĺk.
+Kŕdeľ šťastných ďatľov učí pri ústí Váhu mĺkveho koňa obhrýzať kôru a žrať čerstvé mäso.
+Stróż pchnął kość w quiz gędźb vel fax myjń.
+Portez ce vieux whisky au juge blond qui fume!
+EOF
+
+file_count() { find "${1:?}" -type f | wc -l; }
+file_size() { wc -l <"${1:?}"; }
+random_efi_timestamp() { printf "%0.10d" "$((1000000000 + RANDOM))"; }
+
+# The dmesg- filename contains the backend-type and the Common Platform Error Record, CPER,
+# record id, a 64-bit number.
+#
+# Files are processed in reverse lexigraphical order so as to properly reconstruct original dmesg.
+
+prepare_efi_logs() {
+ local file="${1:?}"
+ local timestamp="${2:?}"
+ local chunk count filename
+
+ # For the EFI backend, the 3 least significant digits of record id encodes a
+ # "count" number, the next 2 least significant digits for the dmesg part
+ # (chunk) number, and the remaining digits as the timestamp. See
+ # linux/drivers/firmware/efi/efi-pstore.c in efi_pstore_write().
+ count="$(file_size "$file")"
+ chunk=0
+ # The sed in the process substitution below just reverses the file
+ while read -r line; do
+ filename="$(printf "dmesg-efi-%0.10d%0.2d%0.3d" "$timestamp" "$chunk" "$count")"
+ echo "$line" >"/sys/fs/pstore/$filename"
+ chunk=$((chunk + 1))
+ done < <(sed '1!G;h;$!d' "$file")
+
+ if [[ "$chunk" -eq 0 ]]; then
+ echo >&2 "No dmesg-efi files were created"
+ exit 1
+ fi
+}
+
+prepare_erst_logs() {
+ local file="${1:?}"
+ local start_id="${2:?}"
+ local id filename
+
+ # For the ERST backend, the record is a monotonically increasing number, seeded as
+ # a timestamp. See linux/drivers/acpi/apei/erst.c in erst_writer().
+ id="$start_id"
+ # The sed in the process substitution below just reverses the file
+ while read -r line; do
+ filename="$(printf "dmesg-erst-%0.16d" "$id")"
+ echo "$line" >"/sys/fs/pstore/$filename"
+ id=$((id + 1))
+ done < <(sed '1!G;h;$!d' "$file")
+
+ if [[ "$id" -eq "$start_id" ]]; then
+ echo >&2 "No dmesg-erst files were created"
+ exit 1
+ fi
+
+ # ID of the last dmesg file will be the ID of the erst subfolder
+ echo "$((id - 1))"
+}
+
+prepare_pstore_config() {
+ local storage="${1:?}"
+ local unlink="${2:?}"
+
+ systemctl stop systemd-pstore
+
+ rm -fr /sys/fs/pstore/* /var/lib/systemd/pstore/*
+
+ mkdir -p /run/systemd/pstore.conf.d
+ cat >"/run/systemd/pstore.conf.d/99-test.conf" <<EOF
+[PStore]
+Storage=$storage
+Unlink=$unlink
+EOF
+
+ systemd-analyze cat-config systemd/pstore.conf | grep "$storage"
+ systemd-analyze cat-config systemd/pstore.conf | grep "$unlink"
+}
+
+start_pstore() {
+ rm -f /tmp/journal.cursor
+ journalctl -q -n 0 --cursor-file=/tmp/journal.cursor
+ systemctl start systemd-pstore
+ journalctl --sync
+}
+
+# To avoid having to depend on the VM providing the pstore, let's simulate
+# it using a simple bind mount
+PSTORE_DIR="$(mktemp -d)"
+mount --bind "${PSTORE_DIR:?}" "/sys/fs/pstore"
+
+# systemd-pstore is a no-op with Storage=none
+for unlink in yes no; do
+ : "Backend: N/A; Storage: none; Unlink: $unlink"
+ timestamp="$(random_efi_timestamp)"
+ prepare_pstore_config "none" "$unlink"
+ prepare_efi_logs "$DUMMY_DMESG_1" "$timestamp"
+ old_count="$(file_count /sys/fs/pstore/)"
+ start_pstore
+ [[ "$(file_count /sys/fs/pstore)" -ge "$old_count" ]]
+ [[ "$(file_count /var/lib/systemd/pstore/)" -eq 0 ]]
+
+ : "Backend: EFI; Storage: external; Unlink: $unlink"
+ timestamp="$(random_efi_timestamp)"
+ prepare_pstore_config "external" "$unlink"
+ prepare_efi_logs "$DUMMY_DMESG_1" "$timestamp"
+ [[ "$unlink" == yes ]] && exp_count=0 || exp_count="$(file_count /sys/fs/pstore/)"
+ start_pstore
+ [[ "$(file_count /sys/fs/pstore)" -ge "$exp_count" ]]
+ [[ "$(file_count /var/lib/systemd/pstore/)" -ne 0 ]]
+ # We always log to journal
+ diff "$DUMMY_DMESG_1" <(journalctl -o cat -u systemd-pstore --output-fields=FILE --cursor-file=/tmp/journal.cursor | sed "/^$/d")
+ filename="$(printf "/var/lib/systemd/pstore/%s/%0.3d/dmesg.txt" "$timestamp" "$(file_size "$DUMMY_DMESG_1")")"
+ diff "$DUMMY_DMESG_1" "$filename"
+
+ : "Backend: EFI; Storage: external; Unlink: $unlink; multiple dmesg files"
+ timestamp_1="$(random_efi_timestamp)"
+ timestamp_2="$((timestamp_1 + 1))"
+ prepare_pstore_config "external" "$unlink"
+ prepare_efi_logs "$DUMMY_DMESG_1" "$timestamp_1"
+ prepare_efi_logs "$DUMMY_DMESG_2" "$timestamp_2"
+ # Add one "random" (non-dmesg) file as well
+ echo "hello world" >/sys/fs/pstore/foo.bar
+ [[ "$unlink" == yes ]] && exp_count=0 || exp_count="$(file_count /sys/fs/pstore/)"
+ start_pstore
+ [[ "$(file_count /sys/fs/pstore)" -ge "$exp_count" ]]
+ [[ "$(file_count /var/lib/systemd/pstore/)" -ne 0 ]]
+ filename_1="$(printf "/var/lib/systemd/pstore/%s/%0.3d/dmesg.txt" "$timestamp_1" "$(file_size "$DUMMY_DMESG_1")")"
+ diff "$DUMMY_DMESG_1" "$filename_1"
+ filename_2="$(printf "/var/lib/systemd/pstore/%s/%0.3d/dmesg.txt" "$timestamp_2" "$(file_size "$DUMMY_DMESG_2")")"
+ diff "$DUMMY_DMESG_2" "$filename_2"
+ grep "hello world" "/var/lib/systemd/pstore/foo.bar"
+
+ : "Backend: EFI; Storage: journal; Unlink: $unlink"
+ timestamp="$(random_efi_timestamp)"
+ prepare_pstore_config "journal" "$unlink"
+ prepare_efi_logs "$DUMMY_DMESG_1" "$timestamp"
+ [[ "$unlink" == yes ]] && exp_count=0 || exp_count="$(file_count /sys/fs/pstore/)"
+ start_pstore
+ [[ "$(file_count /sys/fs/pstore)" -ge "$exp_count" ]]
+ [[ "$(file_count /var/lib/systemd/pstore/)" -eq 0 ]]
+ diff "$DUMMY_DMESG_1" <(journalctl -o cat -u systemd-pstore --output-fields=FILE --cursor-file=/tmp/journal.cursor | sed "/^$/d")
+
+ : "Backend: ERST; Storage: external; Unlink: $unlink"
+ prepare_pstore_config "external" "$unlink"
+ last_id="$(prepare_erst_logs "$DUMMY_DMESG_1" 0)"
+ [[ "$unlink" == yes ]] && exp_count=0 || exp_count="$(file_count /sys/fs/pstore/)"
+ start_pstore
+ [[ "$(file_count /sys/fs/pstore)" -ge "$exp_count" ]]
+ [[ "$(file_count /var/lib/systemd/pstore/)" -ne 0 ]]
+ # We always log to journal
+ diff "$DUMMY_DMESG_1" <(journalctl -o cat -u systemd-pstore --output-fields=FILE --cursor-file=/tmp/journal.cursor | sed "/^$/d")
+ filename="$(printf "/var/lib/systemd/pstore/%0.16d/dmesg.txt" "$last_id")"
+ diff "$DUMMY_DMESG_1" "$filename"
+
+ : "Backend: ERST; Storage: external; Unlink: $unlink; multiple dmesg files"
+ prepare_pstore_config "external" "$unlink"
+ last_id_1="$(prepare_erst_logs "$DUMMY_DMESG_1" 0)"
+ last_id_2="$(prepare_erst_logs "$DUMMY_DMESG_2" "$((last_id_1 + 10))")"
+ # Add one "random" (non-dmesg) file as well
+ echo "hello world" >/sys/fs/pstore/foo.bar
+ [[ "$unlink" == yes ]] && exp_count=0 || exp_count="$(file_count /sys/fs/pstore/)"
+ start_pstore
+ [[ "$(file_count /sys/fs/pstore)" -ge "$exp_count" ]]
+ [[ "$(file_count /var/lib/systemd/pstore/)" -ne 0 ]]
+ filename_1="$(printf "/var/lib/systemd/pstore/%0.16d/dmesg.txt" "$last_id_1")"
+ diff "$DUMMY_DMESG_1" "$filename_1"
+ filename_2="$(printf "/var/lib/systemd/pstore/%0.16d/dmesg.txt" "$last_id_2")"
+ diff "$DUMMY_DMESG_2" "$filename_2"
+ grep "hello world" "/var/lib/systemd/pstore/foo.bar"
+
+ : "Backend: ERST; Storage: journal; Unlink: $unlink"
+ prepare_pstore_config "journal" "$unlink"
+ last_id="$(prepare_erst_logs "$DUMMY_DMESG_1" 0)"
+ [[ "$unlink" == yes ]] && exp_count=0 || exp_count="$(file_count /sys/fs/pstore/)"
+ start_pstore
+ [[ "$(file_count /sys/fs/pstore)" -ge "$exp_count" ]]
+ [[ "$(file_count /var/lib/systemd/pstore/)" -eq 0 ]]
+ diff "$DUMMY_DMESG_1" <(journalctl -o cat -u systemd-pstore --output-fields=FILE --cursor-file=/tmp/journal.cursor | sed "/^$/d")
+done

@ -0,0 +1,57 @@
From ea861dba363ac970a838a183c71e333f9f201f02 Mon Sep 17 00:00:00 2001
From: Frantisek Sumsal <frantisek@sumsal.cz>
Date: Sat, 29 Apr 2023 09:33:18 +0200
Subject: [PATCH] test: match all messages with the FILE field
As the systemd-pstore process is quite short lived, it might sometimes
lack the necessary metadata to make matching against a unit or a syslog
tag work. Since we already use a cursor file to make the matching window
small as possible, let's just drop the unit match completely and hope
for the best.
Resolves: #27453
(cherry picked from commit edea0d6ac57610b7af603b833b19a846327e3638)
Related: #2170883
---
test/units/testsuite-74.pstore.sh | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/test/units/testsuite-74.pstore.sh b/test/units/testsuite-74.pstore.sh
index b4e442c1be..b8bf5534a1 100755
--- a/test/units/testsuite-74.pstore.sh
+++ b/test/units/testsuite-74.pstore.sh
@@ -150,7 +150,7 @@ for unlink in yes no; do
[[ "$(file_count /sys/fs/pstore)" -ge "$exp_count" ]]
[[ "$(file_count /var/lib/systemd/pstore/)" -ne 0 ]]
# We always log to journal
- diff "$DUMMY_DMESG_1" <(journalctl -o cat -u systemd-pstore --output-fields=FILE --cursor-file=/tmp/journal.cursor | sed "/^$/d")
+ diff "$DUMMY_DMESG_1" <(journalctl -o cat --output-fields=FILE --cursor-file=/tmp/journal.cursor | sed "/^$/d")
filename="$(printf "/var/lib/systemd/pstore/%s/%0.3d/dmesg.txt" "$timestamp" "$(file_size "$DUMMY_DMESG_1")")"
diff "$DUMMY_DMESG_1" "$filename"
@@ -180,7 +180,7 @@ for unlink in yes no; do
start_pstore
[[ "$(file_count /sys/fs/pstore)" -ge "$exp_count" ]]
[[ "$(file_count /var/lib/systemd/pstore/)" -eq 0 ]]
- diff "$DUMMY_DMESG_1" <(journalctl -o cat -u systemd-pstore --output-fields=FILE --cursor-file=/tmp/journal.cursor | sed "/^$/d")
+ diff "$DUMMY_DMESG_1" <(journalctl -o cat --output-fields=FILE --cursor-file=/tmp/journal.cursor | sed "/^$/d")
: "Backend: ERST; Storage: external; Unlink: $unlink"
prepare_pstore_config "external" "$unlink"
@@ -190,7 +190,7 @@ for unlink in yes no; do
[[ "$(file_count /sys/fs/pstore)" -ge "$exp_count" ]]
[[ "$(file_count /var/lib/systemd/pstore/)" -ne 0 ]]
# We always log to journal
- diff "$DUMMY_DMESG_1" <(journalctl -o cat -u systemd-pstore --output-fields=FILE --cursor-file=/tmp/journal.cursor | sed "/^$/d")
+ diff "$DUMMY_DMESG_1" <(journalctl -o cat --output-fields=FILE --cursor-file=/tmp/journal.cursor | sed "/^$/d")
filename="$(printf "/var/lib/systemd/pstore/%0.16d/dmesg.txt" "$last_id")"
diff "$DUMMY_DMESG_1" "$filename"
@@ -217,5 +217,5 @@ for unlink in yes no; do
start_pstore
[[ "$(file_count /sys/fs/pstore)" -ge "$exp_count" ]]
[[ "$(file_count /var/lib/systemd/pstore/)" -eq 0 ]]
- diff "$DUMMY_DMESG_1" <(journalctl -o cat -u systemd-pstore --output-fields=FILE --cursor-file=/tmp/journal.cursor | sed "/^$/d")
+ diff "$DUMMY_DMESG_1" <(journalctl -o cat --output-fields=FILE --cursor-file=/tmp/journal.cursor | sed "/^$/d")
done

@ -0,0 +1,116 @@
From 0baa19a28f07328fa4357efc97a522bc0e29f74e Mon Sep 17 00:00:00 2001
From: Frantisek Sumsal <frantisek@sumsal.cz>
Date: Fri, 19 May 2023 11:45:11 +0200
Subject: [PATCH] test: build the SELinux test module on the host
Let's save some time and build the SELinux test module on the host
instead of a possibly unaccelerated VM. This brings the runtime of
TEST-06-SELINUX from ~12 minutes down to a ~1 minute.
(cherry picked from commit 038efe6df154b04a4c2a1d9da7263e5f49d2a1b0)
Related: #2170883
---
test/TEST-06-SELINUX/test.sh | 68 ++++++++++---------
.../load-systemd-test-module.service | 2 +-
2 files changed, 36 insertions(+), 34 deletions(-)
diff --git a/test/TEST-06-SELINUX/test.sh b/test/TEST-06-SELINUX/test.sh
index a867dea4b7..5d72638ec6 100755
--- a/test/TEST-06-SELINUX/test.sh
+++ b/test/TEST-06-SELINUX/test.sh
@@ -7,7 +7,6 @@ IMAGE_NAME="selinux"
TEST_NO_NSPAWN=1
# Requirements:
-# Fedora 23
# selinux-policy-targeted
# selinux-policy-devel
@@ -21,38 +20,41 @@ SETUP_SELINUX=yes
KERNEL_APPEND="${KERNEL_APPEND:=} selinux=1 security=selinux"
test_append_files() {
- (
- local workspace="${1:?}"
- local policy_headers_dir=/usr/share/selinux/devel
- local modules_dir=/var/lib/selinux
-
- setup_selinux
- # Make sure we never expand this to "/..."
- rm -rf "${workspace:?}/$modules_dir"
-
- if ! cp -ar "$modules_dir" "$workspace/$modules_dir"; then
- dfatal "Failed to copy $modules_dir"
- exit 1
- fi
-
- rm -rf "${workspace:?}/$policy_headers_dir"
- inst_dir /usr/share/selinux
-
- if ! cp -ar "$policy_headers_dir" "$workspace/$policy_headers_dir"; then
- dfatal "Failed to copy $policy_headers_dir"
- exit 1
- fi
-
- mkdir "$workspace/systemd-test-module"
- cp systemd_test.te "$workspace/systemd-test-module"
- cp systemd_test.if "$workspace/systemd-test-module"
- cp systemd_test.fc "$workspace/systemd-test-module"
- image_install -o sesearch
- image_install runcon
- image_install checkmodule semodule semodule_package m4 make load_policy sefcontext_compile
- image_install -o /usr/libexec/selinux/hll/pp # Fedora/RHEL/...
- image_install -o /usr/lib/selinux/hll/pp # Debian/Ubuntu/...
- )
+ local workspace="${1:?}"
+ local policy_headers_dir=/usr/share/selinux/devel
+ local modules_dir=/var/lib/selinux
+
+ setup_selinux
+ # Make sure we never expand this to "/..."
+ rm -rf "${workspace:?}/$modules_dir"
+
+ if ! cp -ar "$modules_dir" "$workspace/$modules_dir"; then
+ dfatal "Failed to copy $modules_dir"
+ exit 1
+ fi
+
+ rm -rf "${workspace:?}/$policy_headers_dir"
+ inst_dir /usr/share/selinux
+
+ if ! cp -ar "$policy_headers_dir" "$workspace/$policy_headers_dir"; then
+ dfatal "Failed to copy $policy_headers_dir"
+ exit 1
+ fi
+
+ mkdir "$workspace/systemd-test-module"
+ cp systemd_test.te "$workspace/systemd-test-module"
+ cp systemd_test.if "$workspace/systemd-test-module"
+ cp systemd_test.fc "$workspace/systemd-test-module"
+ image_install -o sesearch
+ image_install runcon
+ image_install checkmodule semodule semodule_package m4 make load_policy sefcontext_compile
+ image_install -o /usr/libexec/selinux/hll/pp # Fedora/RHEL/...
+ image_install -o /usr/lib/selinux/hll/pp # Debian/Ubuntu/...
+
+ if ! chroot "$workspace" make -C /systemd-test-module -f /usr/share/selinux/devel/Makefile clean systemd_test.pp; then
+ dfatal "Failed to build the systemd test module"
+ exit 1
+ fi
}
do_test "$@"
diff --git a/test/testsuite-06.units/load-systemd-test-module.service b/test/testsuite-06.units/load-systemd-test-module.service
index 3a22c15b25..2d15a62715 100644
--- a/test/testsuite-06.units/load-systemd-test-module.service
+++ b/test/testsuite-06.units/load-systemd-test-module.service
@@ -9,7 +9,7 @@ Before=sysinit.target shutdown.target autorelabel.service
ConditionSecurity=selinux
[Service]
-ExecStart=sh -x -c 'echo 0 >/sys/fs/selinux/enforce && cd /systemd-test-module && make -f /usr/share/selinux/devel/Makefile clean load'
+ExecStart=sh -x -c 'echo 0 >/sys/fs/selinux/enforce && make -C /systemd-test-module -f /usr/share/selinux/devel/Makefile load'
Type=oneshot
TimeoutSec=0
RemainAfterExit=yes

@ -0,0 +1,32 @@
From 36426e030fc9f2afc5926b2c484b9943f9970529 Mon Sep 17 00:00:00 2001
From: Frantisek Sumsal <frantisek@sumsal.cz>
Date: Fri, 19 May 2023 10:48:15 +0200
Subject: [PATCH] test: make the stress test slightly less stressful on slower
machines
Without acceleration this part of the test takes over 10 minutes (!),
which feels quite unnecessary. Let's cut down the number of stuff we
dump to the journal in such case, but keep the original value if we run
with acceleration (since in that case it takes less than 10 seconds).
(cherry picked from commit ff40235b9bd2a944131c36b1c7ccfd88f49a194e)
Related: #2170883
---
test/units/testsuite-04.sh | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/test/units/testsuite-04.sh b/test/units/testsuite-04.sh
index bb41045809..b5ff2ff704 100755
--- a/test/units/testsuite-04.sh
+++ b/test/units/testsuite-04.sh
@@ -8,7 +8,8 @@ trap "journalctl --rotate --vacuum-size=16M" EXIT
# Rotation/flush test, see https://github.com/systemd/systemd/issues/19895
journalctl --relinquish-var
-for _ in {0..50}; do
+[[ "$(systemd-detect-virt -v)" == "qemu" ]] && ITERATIONS=10 || ITERATIONS=50
+for ((i = 0; i < ITERATIONS; i++)); do
dd if=/dev/urandom bs=1M count=1 | base64 | systemd-cat
done
journalctl --rotate

@ -0,0 +1,202 @@
From 58aba81d1e530d53e462ec4ae542570cd537264a Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Wed, 22 Mar 2023 08:49:49 +0900
Subject: [PATCH] coredump: use unaligned_read_ne{32,64}() to parse auxv
Fixes a bug introduced by 3e4d0f6cf99f8677edd6a237382a65bfe758de03.
The auxv metadata is unaligned, as the length of the prefix
"COREDUMP_PROC_AUXV=" is 19. Hence, parse_auxv{32,64}() may triger
an undefined behavior (or at least cause slow down), which can be
detected when running on an undefined behavior sanitizer.
This also introduces a macro to define `parse_auxv{32,64}()`.
Fixes #26912.
(cherry picked from commit 9b032f932c4172fac379234d9d42cf2b266ccaea)
Related: #2170883
---
src/coredump/coredump.c | 149 ++++++++++++++++------------------------
1 file changed, 60 insertions(+), 89 deletions(-)
diff --git a/src/coredump/coredump.c b/src/coredump/coredump.c
index ea3d8c415a..b9c5f3ad04 100644
--- a/src/coredump/coredump.c
+++ b/src/coredump/coredump.c
@@ -48,6 +48,7 @@
#include "sync-util.h"
#include "tmpfile-util.h"
#include "uid-alloc-range.h"
+#include "unaligned.h"
#include "user-util.h"
/* The maximum size up to which we process coredumps. We use 1G on 32bit systems, and 32G on 64bit systems */
@@ -339,95 +340,65 @@ static int make_filename(const Context *context, char **ret) {
return 0;
}
-static int parse_auxv64(
- const uint64_t *auxv,
- size_t size_bytes,
- int *at_secure,
- uid_t *uid,
- uid_t *euid,
- gid_t *gid,
- gid_t *egid) {
-
- assert(auxv || size_bytes == 0);
-
- if (size_bytes % (2 * sizeof(uint64_t)) != 0)
- return log_warning_errno(SYNTHETIC_ERRNO(EIO), "Incomplete auxv structure (%zu bytes).", size_bytes);
-
- size_t words = size_bytes / sizeof(uint64_t);
-
- /* Note that we set output variables even on error. */
-
- for (size_t i = 0; i + 1 < words; i += 2)
- switch (auxv[i]) {
- case AT_SECURE:
- *at_secure = auxv[i + 1] != 0;
- break;
- case AT_UID:
- *uid = auxv[i + 1];
- break;
- case AT_EUID:
- *euid = auxv[i + 1];
- break;
- case AT_GID:
- *gid = auxv[i + 1];
- break;
- case AT_EGID:
- *egid = auxv[i + 1];
- break;
- case AT_NULL:
- if (auxv[i + 1] != 0)
- goto error;
- return 0;
- }
- error:
- return log_warning_errno(SYNTHETIC_ERRNO(ENODATA),
- "AT_NULL terminator not found, cannot parse auxv structure.");
-}
-
-static int parse_auxv32(
- const uint32_t *auxv,
- size_t size_bytes,
- int *at_secure,
- uid_t *uid,
- uid_t *euid,
- gid_t *gid,
- gid_t *egid) {
-
- assert(auxv || size_bytes == 0);
-
- size_t words = size_bytes / sizeof(uint32_t);
-
- if (size_bytes % (2 * sizeof(uint32_t)) != 0)
- return log_warning_errno(SYNTHETIC_ERRNO(EIO), "Incomplete auxv structure (%zu bytes).", size_bytes);
+#define _DEFINE_PARSE_AUXV(size, type, unaligned_read) \
+ static int parse_auxv##size( \
+ const void *auxv, \
+ size_t size_bytes, \
+ int *at_secure, \
+ uid_t *uid, \
+ uid_t *euid, \
+ gid_t *gid, \
+ gid_t *egid) { \
+ \
+ assert(auxv || size_bytes == 0); \
+ \
+ if (size_bytes % (2 * sizeof(type)) != 0) \
+ return log_warning_errno(SYNTHETIC_ERRNO(EIO), \
+ "Incomplete auxv structure (%zu bytes).", \
+ size_bytes); \
+ \
+ size_t words = size_bytes / sizeof(type); \
+ \
+ /* Note that we set output variables even on error. */ \
+ \
+ for (size_t i = 0; i + 1 < words; i += 2) { \
+ type key, val; \
+ \
+ key = unaligned_read((uint8_t*) auxv + i * sizeof(type)); \
+ val = unaligned_read((uint8_t*) auxv + (i + 1) * sizeof(type)); \
+ \
+ switch (key) { \
+ case AT_SECURE: \
+ *at_secure = val != 0; \
+ break; \
+ case AT_UID: \
+ *uid = val; \
+ break; \
+ case AT_EUID: \
+ *euid = val; \
+ break; \
+ case AT_GID: \
+ *gid = val; \
+ break; \
+ case AT_EGID: \
+ *egid = val; \
+ break; \
+ case AT_NULL: \
+ if (val != 0) \
+ goto error; \
+ return 0; \
+ } \
+ } \
+ error: \
+ return log_warning_errno(SYNTHETIC_ERRNO(ENODATA), \
+ "AT_NULL terminator not found, cannot parse auxv structure."); \
+ }
- /* Note that we set output variables even on error. */
+#define DEFINE_PARSE_AUXV(size)\
+ _DEFINE_PARSE_AUXV(size, uint##size##_t, unaligned_read_ne##size)
- for (size_t i = 0; i + 1 < words; i += 2)
- switch (auxv[i]) {
- case AT_SECURE:
- *at_secure = auxv[i + 1] != 0;
- break;
- case AT_UID:
- *uid = auxv[i + 1];
- break;
- case AT_EUID:
- *euid = auxv[i + 1];
- break;
- case AT_GID:
- *gid = auxv[i + 1];
- break;
- case AT_EGID:
- *egid = auxv[i + 1];
- break;
- case AT_NULL:
- if (auxv[i + 1] != 0)
- goto error;
- return 0;
- }
- error:
- return log_warning_errno(SYNTHETIC_ERRNO(ENODATA),
- "AT_NULL terminator not found, cannot parse auxv structure.");
-}
+DEFINE_PARSE_AUXV(32);
+DEFINE_PARSE_AUXV(64);
static int grant_user_access(int core_fd, const Context *context) {
int at_secure = -1;
@@ -464,11 +435,11 @@ static int grant_user_access(int core_fd, const Context *context) {
"Core file has non-native endianness, not adjusting permissions.");
if (elf[EI_CLASS] == ELFCLASS64)
- r = parse_auxv64((const uint64_t*) context->meta[META_PROC_AUXV],
+ r = parse_auxv64(context->meta[META_PROC_AUXV],
context->meta_size[META_PROC_AUXV],
&at_secure, &uid, &euid, &gid, &egid);
else
- r = parse_auxv32((const uint32_t*) context->meta[META_PROC_AUXV],
+ r = parse_auxv32(context->meta[META_PROC_AUXV],
context->meta_size[META_PROC_AUXV],
&at_secure, &uid, &euid, &gid, &egid);
if (r < 0)

@ -0,0 +1,57 @@
From 1c7d14785d8975df5f6400d22fa5eae4693f7288 Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Sat, 18 Mar 2023 12:12:01 +0900
Subject: [PATCH] core/transaction: make merge_unit_ids() always return
NUL-terminated string
Follow-up for 924775e8ce49817f96df19c2b06356c12ecfc754.
The loop run with `STRV_FOREACH_PAIR()`, hence `if (*(unit_id+1))` is
not a good way to detect if there exist a next entry.
Fixes #26872.
(cherry picked from commit 366eced4c81a15a25b9225347fa203aa67798b02)
Related: #2170883
---
src/core/transaction.c | 17 ++++++++++-------
1 file changed, 10 insertions(+), 7 deletions(-)
diff --git a/src/core/transaction.c b/src/core/transaction.c
index 8ec853d58d..043998078c 100644
--- a/src/core/transaction.c
+++ b/src/core/transaction.c
@@ -323,22 +323,25 @@ _pure_ static bool unit_matters_to_anchor(Unit *u, Job *job) {
return false;
}
-static char* merge_unit_ids(const char* unit_log_field, char **pairs) {
- char *ans = NULL;
- size_t size = 0, next;
+static char* merge_unit_ids(const char* unit_log_field, char * const* pairs) {
+ _cleanup_free_ char *ans = NULL;
+ size_t size = 0;
STRV_FOREACH_PAIR(unit_id, job_type, pairs) {
+ size_t next;
+
+ if (size > 0)
+ ans[size - 1] = '\n';
+
next = strlen(unit_log_field) + strlen(*unit_id);
if (!GREEDY_REALLOC(ans, size + next + 1))
- return mfree(ans);
+ return NULL;
sprintf(ans + size, "%s%s", unit_log_field, *unit_id);
- if (*(unit_id+1))
- ans[size + next] = '\n';
size += next + 1;
}
- return ans;
+ return TAKE_PTR(ans);
}
static int transaction_verify_order_one(Transaction *tr, Job *j, Job *from, unsigned generation, sd_bus_error *e) {

@ -0,0 +1,27 @@
From dbdeb09d8893a680c8241b4af3fd096c7aabe03f Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Sat, 18 Mar 2023 12:17:54 +0900
Subject: [PATCH] core/transaction: make merge_unit_ids() return non-NULL on
success
(cherry picked from commit 999f16514367224cbc50cb3ccc1e4392e43f6811)
Related: #2170883
---
src/core/transaction.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/src/core/transaction.c b/src/core/transaction.c
index 043998078c..7c862f35be 100644
--- a/src/core/transaction.c
+++ b/src/core/transaction.c
@@ -341,6 +341,9 @@ static char* merge_unit_ids(const char* unit_log_field, char * const* pairs) {
size += next + 1;
}
+ if (!ans)
+ return strdup("");
+
return TAKE_PTR(ans);
}

@ -0,0 +1,45 @@
From 8e0b41ea9bf9afedcda713934f424b17195f9add Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Sat, 18 Mar 2023 12:15:10 +0900
Subject: [PATCH] core/transaction: do not log "(null)"
As we ignores the failure in merge_unit_ids(), so unit_ids may be NULL.
(cherry picked from commit 5803c24da5cf543a55c4fce9009a9c5f2b18519a)
Related: #2170883
---
src/core/transaction.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/core/transaction.c b/src/core/transaction.c
index 7c862f35be..bb51f51318 100644
--- a/src/core/transaction.c
+++ b/src/core/transaction.c
@@ -400,7 +400,7 @@ static int transaction_verify_order_one(Transaction *tr, Job *j, Job *from, unsi
"Found %s on %s/%s",
unit_id == array ? "ordering cycle" : "dependency",
*unit_id, *job_type),
- "%s", unit_ids);
+ "%s", strna(unit_ids));
if (delete) {
const char *status;
@@ -410,7 +410,7 @@ static int transaction_verify_order_one(Transaction *tr, Job *j, Job *from, unsi
"Job %s/%s deleted to break ordering cycle starting with %s/%s",
delete->unit->id, job_type_to_string(delete->type),
j->unit->id, job_type_to_string(j->type)),
- "%s", unit_ids);
+ "%s", strna(unit_ids));
if (log_get_show_color())
status = ANSI_HIGHLIGHT_RED " SKIP " ANSI_NORMAL;
@@ -429,7 +429,7 @@ static int transaction_verify_order_one(Transaction *tr, Job *j, Job *from, unsi
log_struct(LOG_ERR,
LOG_UNIT_MESSAGE(j->unit, "Unable to break cycle starting with %s/%s",
j->unit->id, job_type_to_string(j->type)),
- "%s", unit_ids);
+ "%s", strna(unit_ids));
return sd_bus_error_setf(e, BUS_ERROR_TRANSACTION_ORDER_IS_CYCLIC,
"Transaction order is cyclic. See system logs for details.");

@ -0,0 +1,24 @@
From ea5817de22075c8770775e8ee113a90417517fee Mon Sep 17 00:00:00 2001
From: Jan Macku <jamacku@redhat.com>
Date: Mon, 10 Jul 2023 12:31:05 +0200
Subject: [PATCH] ci: allow `RHEL-only` labels to mark downstream-only commits
RHEL-only
Related: #2170883
---
.github/advanced-commit-linter.yml | 1 +
1 file changed, 1 insertion(+)
diff --git a/.github/advanced-commit-linter.yml b/.github/advanced-commit-linter.yml
index 491836abbb..327af0467a 100644
--- a/.github/advanced-commit-linter.yml
+++ b/.github/advanced-commit-linter.yml
@@ -6,6 +6,7 @@ policy:
exception:
note:
- rhel-only
+ - RHEL-only
tracker:
- keyword:
- 'Resolves: #?'

@ -1,4 +1,4 @@
From ea011ddb65272c74d6378deae3f3a3365aadd77d Mon Sep 17 00:00:00 2001
From 7924438d595c7c77ead2e9ed475212fab7792fe4 Mon Sep 17 00:00:00 2001
From: Romain Geissler <romain.geissler@amadeus.com>
Date: Tue, 20 Jun 2023 16:06:31 +0000
Subject: [PATCH] elf-util: discard PT_LOAD segment early based on the start
@ -47,7 +47,7 @@ https://sourceware.org/pipermail/elfutils-devel/2023q2/006225.html.
(cherry picked from commit 21a2c735e2bfdc3bfdc42f894d6e3d00f4a38dcd)
Resolves: #2222259
Resolves: #2215412
---
src/shared/elf-util.c | 4 ++++
1 file changed, 4 insertions(+)

@ -1,4 +1,4 @@
From 2fcb340ec5faf51a8d9b0cb2ddd8386b4db6a33d Mon Sep 17 00:00:00 2001
From 57d92dd0f1fd55f2bb2ff7f4228ca01b29dbd054 Mon Sep 17 00:00:00 2001
From: Romain Geissler <romain.geissler@amadeus.com>
Date: Thu, 22 Jun 2023 16:05:18 +0000
Subject: [PATCH] elf-util: check for overflow when computing end of core's
@ -6,7 +6,7 @@ Subject: [PATCH] elf-util: check for overflow when computing end of core's
(cherry picked from commit 3965f173eae4701a014113cfaf4a28a6bb63bed7)
Resolves: #2222259
Related: #2215412
---
src/shared/elf-util.c | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)

@ -0,0 +1,46 @@
From b3053fa0f83a55bb9fb8148eab51089171da21cb Mon Sep 17 00:00:00 2001
From: HATAYAMA Daisuke <d.hatayama@fujitsu.com>
Date: Tue, 14 Feb 2023 22:10:13 -0500
Subject: [PATCH] sulogin: use DEFINE_MAIN_FUNCTION()
Let's use DEFINE_MAIN_FUNCTION() as the other commands for consistency.
This commit should be no functional change.
(cherry picked from commit 2ffbf44344983d64949e032e74edb19c48b16cc0)
Related: #2169959
---
src/sulogin-shell/sulogin-shell.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/src/sulogin-shell/sulogin-shell.c b/src/sulogin-shell/sulogin-shell.c
index 5648dfd83b..e3601de8d4 100644
--- a/src/sulogin-shell/sulogin-shell.c
+++ b/src/sulogin-shell/sulogin-shell.c
@@ -14,6 +14,7 @@
#include "def.h"
#include "env-util.h"
#include "log.h"
+#include "main-func.h"
#include "process-util.h"
#include "signal-util.h"
#include "special.h"
@@ -86,7 +87,7 @@ static void print_mode(const char* mode) {
fflush(stdout);
}
-int main(int argc, char *argv[]) {
+static int run(int argc, char *argv[]) {
const char* sulogin_cmdline[] = {
SULOGIN,
NULL, /* --force */
@@ -115,5 +116,7 @@ int main(int argc, char *argv[]) {
r = start_default_target(bus);
}
- return r >= 0 ? EXIT_SUCCESS : EXIT_FAILURE;
+ return r;
}
+
+DEFINE_MAIN_FUNCTION(run);

@ -0,0 +1,131 @@
From 348854f8023fa6233ce7549b32eb8319b91c24e6 Mon Sep 17 00:00:00 2001
From: HATAYAMA Daisuke <d.hatayama@fujitsu.com>
Date: Sun, 12 Feb 2023 12:15:08 +0000
Subject: [PATCH] sulogin: fix control lost of the current terminal when
default.target is rescue.target
When default.target is rescue.target, exiting from the single-user shell
results in lost of the control of the current terminal. This is because the
operation performed to continue to boot is systemctl default but default.target
is now rescue.target and it is already active. Hence, no new process that
controls the current terminal is created. Users need to make hardware reset to
recover the situation.
This sounds like a bit corner case issue and some might feel configuring
default.target as rescue.target is odd because there are several other ways to
transition to rescue.mode without configuring default.target to rescue.target
such as systemctl rescue or systemd.unit=rescue.target something like
that. However, users unfamiliar with systemd operations tend to come up with
systemctl set-default rescue.target.
To fix this issue, let's transition to default.target only when default.target
is inactive. Otherwise, invoke the single-user shell again to keep control of
the current terminal for users.
This new logic depends on whether D-Bus working well. Exiting without any check
of result of systemctl default could lead to again the control lost of the
current terminal. Hence, add checking results of each D-Bus operations
including systemctl default and invoke the single-user shell if they fail.
(cherry picked from commit 937ca8330d11e406b8ef343bead6f4f6244e39c7)
Resolves: #2169959
---
src/sulogin-shell/sulogin-shell.c | 59 +++++++++++++++++++++++++------
1 file changed, 49 insertions(+), 10 deletions(-)
diff --git a/src/sulogin-shell/sulogin-shell.c b/src/sulogin-shell/sulogin-shell.c
index e3601de8d4..f1660c69e0 100644
--- a/src/sulogin-shell/sulogin-shell.c
+++ b/src/sulogin-shell/sulogin-shell.c
@@ -18,6 +18,7 @@
#include "process-util.h"
#include "signal-util.h"
#include "special.h"
+#include "unit-def.h"
static int reload_manager(sd_bus *bus) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
@@ -42,6 +43,28 @@ static int reload_manager(sd_bus *bus) {
return 0;
}
+static int default_target_is_inactive(sd_bus *bus) {
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_free_ char *path = NULL, *state = NULL;
+ int r;
+
+ path = unit_dbus_path_from_name(SPECIAL_DEFAULT_TARGET);
+ if (!path)
+ return log_oom();
+
+ r = sd_bus_get_property_string(bus,
+ "org.freedesktop.systemd1",
+ path,
+ "org.freedesktop.systemd1.Unit",
+ "ActiveState",
+ &error,
+ &state);
+ if (r < 0)
+ return log_error_errno(r, "Failed to retrieve unit state: %s", bus_error_message(&error, r));
+
+ return streq_ptr(state, "inactive");
+}
+
static int start_default_target(sd_bus *bus) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
int r;
@@ -93,7 +116,6 @@ static int run(int argc, char *argv[]) {
NULL, /* --force */
NULL
};
- _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
int r;
log_setup();
@@ -104,19 +126,36 @@ static int run(int argc, char *argv[]) {
/* allows passwordless logins if root account is locked. */
sulogin_cmdline[1] = "--force";
- (void) fork_wait(sulogin_cmdline);
+ for (;;) {
+ _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
+
+ (void) fork_wait(sulogin_cmdline);
+
+ r = bus_connect_system_systemd(&bus);
+ if (r < 0) {
+ log_warning_errno(r, "Failed to get D-Bus connection: %m");
+ goto fallback;
+ }
- r = bus_connect_system_systemd(&bus);
- if (r < 0) {
- log_warning_errno(r, "Failed to get D-Bus connection: %m");
- r = 0;
- } else {
- (void) reload_manager(bus);
+ if (reload_manager(bus) < 0)
+ goto fallback;
- r = start_default_target(bus);
+ r = default_target_is_inactive(bus);
+ if (r < 0)
+ goto fallback;
+ if (!r) {
+ log_warning(SPECIAL_DEFAULT_TARGET" is not inactive. Please review the "SPECIAL_DEFAULT_TARGET" setting.\n");
+ goto fallback;
+ }
+
+ if (start_default_target(bus) >= 0)
+ break;
+
+ fallback:
+ log_warning("Fallback to the single-user shell.\n");
}
- return r;
+ return 0;
}
DEFINE_MAIN_FUNCTION(run);

@ -0,0 +1,90 @@
From 407e6bbb46a67200ea27a04c10c931dba9727cdd Mon Sep 17 00:00:00 2001
From: David Tardon <dtardon@redhat.com>
Date: Wed, 22 Mar 2023 12:36:54 +0100
Subject: [PATCH] journal-vacuum: count size of all journal files
Currently, active journal files are excluded, which means that vacuuming
may not remove anything even if *MaxUse= has been exceeded.
(cherry picked from commit 9ea46af4f2368b41d57705bac09774778126507f)
Resolves: #2182632
---
src/libsystemd/sd-journal/journal-vacuum.c | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/src/libsystemd/sd-journal/journal-vacuum.c b/src/libsystemd/sd-journal/journal-vacuum.c
index eac3500202..23497af28e 100644
--- a/src/libsystemd/sd-journal/journal-vacuum.c
+++ b/src/libsystemd/sd-journal/journal-vacuum.c
@@ -158,6 +158,8 @@ int journal_directory_vacuum(
if (!S_ISREG(st.st_mode))
continue;
+ size = 512UL * (uint64_t) st.st_blocks;
+
q = strlen(de->d_name);
if (endswith(de->d_name, ".journal")) {
@@ -167,6 +169,7 @@ int journal_directory_vacuum(
if (q < 1 + 32 + 1 + 16 + 1 + 16 + 8) {
n_active_files++;
+ sum += size;
continue;
}
@@ -174,6 +177,7 @@ int journal_directory_vacuum(
de->d_name[q-8-16-1-16-1] != '-' ||
de->d_name[q-8-16-1-16-1-32-1] != '@') {
n_active_files++;
+ sum += size;
continue;
}
@@ -186,11 +190,13 @@ int journal_directory_vacuum(
de->d_name[q-8-16-1-16-1] = 0;
if (sd_id128_from_string(de->d_name + q-8-16-1-16-1-32, &seqnum_id) < 0) {
n_active_files++;
+ sum += size;
continue;
}
if (sscanf(de->d_name + q-8-16-1-16, "%16llx-%16llx.journal", &seqnum, &realtime) != 2) {
n_active_files++;
+ sum += size;
continue;
}
@@ -206,12 +212,14 @@ int journal_directory_vacuum(
if (q < 1 + 16 + 1 + 16 + 8 + 1) {
n_active_files++;
+ sum += size;
continue;
}
if (de->d_name[q-1-8-16-1] != '-' ||
de->d_name[q-1-8-16-1-16-1] != '@') {
n_active_files++;
+ sum += size;
continue;
}
@@ -223,6 +231,7 @@ int journal_directory_vacuum(
if (sscanf(de->d_name + q-1-8-16-1-16, "%16llx-%16llx.journal~", &realtime, &tmp) != 2) {
n_active_files++;
+ sum += size;
continue;
}
@@ -233,8 +242,6 @@ int journal_directory_vacuum(
continue;
}
- size = 512UL * (uint64_t) st.st_blocks;
-
r = journal_file_empty(dirfd(d), p);
if (r < 0) {
log_debug_errno(r, "Failed check if %s is empty, ignoring: %m", p);

@ -0,0 +1,133 @@
From f49fbc3ebbb026f87b974c11c40808cc777bd277 Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Wed, 22 Feb 2023 23:10:25 +0100
Subject: [PATCH] memory-util: add a concept for gcc cleanup attribute based
array destruction
(cherry picked from commit ff3f1464ec2dd40c9d8eb92e1474cb4d1c8c676b)
Related: #2182632
---
src/basic/alloc-util.h | 1 +
src/basic/memory-util.h | 34 +++++++++++++++++++++++++++++
src/test/meson.build | 2 ++
src/test/test-memory-util.c | 43 +++++++++++++++++++++++++++++++++++++
4 files changed, 80 insertions(+)
create mode 100644 src/test/test-memory-util.c
diff --git a/src/basic/alloc-util.h b/src/basic/alloc-util.h
index b38db7d473..e4c8b71a2b 100644
--- a/src/basic/alloc-util.h
+++ b/src/basic/alloc-util.h
@@ -14,6 +14,7 @@
typedef void (*free_func_t)(void *p);
typedef void* (*mfree_func_t)(void *p);
+typedef void (*free_array_func_t)(void *p, size_t n);
/* If for some reason more than 4M are allocated on the stack, let's abort immediately. It's better than
* proceeding and smashing the stack limits. Note that by default RLIMIT_STACK is 8M on Linux. */
diff --git a/src/basic/memory-util.h b/src/basic/memory-util.h
index 6e3280b9df..8d75befed5 100644
--- a/src/basic/memory-util.h
+++ b/src/basic/memory-util.h
@@ -121,3 +121,37 @@ static inline void erase_and_freep(void *p) {
static inline void erase_char(char *p) {
explicit_bzero_safe(p, sizeof(char));
}
+
+/* An automatic _cleanup_-like logic for destroy arrays (i.e. pointers + size) when leaving scope */
+struct ArrayCleanup {
+ void **parray;
+ size_t *pn;
+ free_array_func_t pfunc;
+};
+
+static inline void array_cleanup(struct ArrayCleanup *c) {
+ assert(c);
+
+ assert(!c->parray == !c->pn);
+
+ if (!c->parray)
+ return;
+
+ if (*c->parray) {
+ assert(c->pfunc);
+ c->pfunc(*c->parray, *c->pn);
+ *c->parray = NULL;
+ }
+
+ *c->pn = 0;
+}
+
+#define CLEANUP_ARRAY(array, n, func) \
+ _cleanup_(array_cleanup) _unused_ struct ArrayCleanup CONCATENATE(_cleanup_array_, UNIQ) = { \
+ .parray = (void**) &(array), \
+ .pn = &(n), \
+ .pfunc = (free_array_func_t) ({ \
+ void (*_f)(typeof(array[0]) *a, size_t b) = func; \
+ _f; \
+ }), \
+ }
diff --git a/src/test/meson.build b/src/test/meson.build
index 2a4dfe26db..536ab08652 100644
--- a/src/test/meson.build
+++ b/src/test/meson.build
@@ -213,6 +213,8 @@ tests += [
[],
[libm]],
+ [files('test-memory-util.c')],
+
[files('test-mkdir.c')],
[files('test-json.c'),
diff --git a/src/test/test-memory-util.c b/src/test/test-memory-util.c
new file mode 100644
index 0000000000..a81b0e0120
--- /dev/null
+++ b/src/test/test-memory-util.c
@@ -0,0 +1,43 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include "memory-util.h"
+#include "tests.h"
+
+static void my_destructor(struct iovec *iov, size_t n) {
+ /* not really a destructor, just something we can use to check if the destruction worked */
+ memset(iov, 'y', sizeof(struct iovec) * n);
+}
+
+TEST(cleanup_array) {
+ struct iovec *iov, *saved_iov;
+ size_t n, saved_n;
+
+ n = 7;
+ iov = new(struct iovec, n);
+ assert_se(iov);
+
+ memset(iov, 'x', sizeof(struct iovec) * n);
+
+ saved_iov = iov;
+ saved_n = n;
+
+ {
+ assert_se(memeqbyte('x', saved_iov, sizeof(struct iovec) * saved_n));
+ assert_se(iov);
+ assert_se(n > 0);
+
+ CLEANUP_ARRAY(iov, n, my_destructor);
+
+ assert_se(memeqbyte('x', saved_iov, sizeof(struct iovec) * saved_n));
+ assert_se(iov);
+ assert_se(n > 0);
+ }
+
+ assert_se(memeqbyte('y', saved_iov, sizeof(struct iovec) * saved_n));
+ assert_se(!iov);
+ assert_se(n == 0);
+
+ free(saved_iov);
+}
+
+DEFINE_TEST_MAIN(LOG_INFO);

@ -0,0 +1,94 @@
From b9f50b820804113811bcf291f586793de434fcdc Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Sun, 5 Mar 2023 14:56:15 +0900
Subject: [PATCH] macro: introduce FOREACH_ARRAY() macro
The pattern that runs all array element is quite common.
But, sometimes, the number of element may be in a signed integer, or the
array may be NULL.
(cherry picked from commit 5716c27e1f52d2aba9dd02916c01d6271d9d0b16)
Related: #2182632
---
src/basic/macro.h | 7 ++++++
src/test/test-macro.c | 50 +++++++++++++++++++++++++++++++++++++++++++
2 files changed, 57 insertions(+)
diff --git a/src/basic/macro.h b/src/basic/macro.h
index 237117db12..b977730e54 100644
--- a/src/basic/macro.h
+++ b/src/basic/macro.h
@@ -329,6 +329,13 @@ static inline int __coverity_check_and_return__(int condition) {
#endif
#endif
+#define _FOREACH_ARRAY(i, array, num, m, s) \
+ for (typeof(num) m = (num); m > 0; m = 0) \
+ for (typeof(array[0]) *s = (array), *i = s; s && i < s + m; i++)
+
+#define FOREACH_ARRAY(i, array, num) \
+ _FOREACH_ARRAY(i, array, num, UNIQ_T(m, UNIQ), UNIQ_T(s, UNIQ))
+
#define DEFINE_TRIVIAL_DESTRUCTOR(name, type, func) \
static inline void name(type *p) { \
func(p); \
diff --git a/src/test/test-macro.c b/src/test/test-macro.c
index 049ea2c14e..6a5f4bbeb7 100644
--- a/src/test/test-macro.c
+++ b/src/test/test-macro.c
@@ -521,4 +521,54 @@ TEST(ISPOWEROF2) {
assert_se(!ISPOWEROF2(u));
}
+TEST(FOREACH_ARRAY) {
+ int a[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+ int b[10] = { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };
+ int x, n;
+
+ x = n = 0;
+ FOREACH_ARRAY(i, a, 10) {
+ x += *i;
+ n++;
+ }
+ assert_se(x == 45);
+ assert_se(n == 10);
+
+ x = n = 0;
+ FOREACH_ARRAY(i, a, 10)
+ FOREACH_ARRAY(j, b, 10) {
+ x += (*i) * (*j);
+ n++;
+ }
+ assert_se(x == 45 * 45);
+ assert_se(n == 10 * 10);
+
+ x = n = 0;
+ FOREACH_ARRAY(i, a, 5)
+ FOREACH_ARRAY(j, b, 5) {
+ x += (*i) * (*j);
+ n++;
+ }
+ assert_se(x == 10 * 35);
+ assert_se(n == 5 * 5);
+
+ x = n = 0;
+ FOREACH_ARRAY(i, a, 0)
+ FOREACH_ARRAY(j, b, 0) {
+ x += (*i) * (*j);
+ n++;
+ }
+ assert_se(x == 0);
+ assert_se(n == 0);
+
+ x = n = 0;
+ FOREACH_ARRAY(i, a, -1)
+ FOREACH_ARRAY(j, b, -1) {
+ x += (*i) * (*j);
+ n++;
+ }
+ assert_se(x == 0);
+ assert_se(n == 0);
+}
+
DEFINE_TEST_MAIN(LOG_INFO);

@ -0,0 +1,64 @@
From 2f59a7790dc32bd9ba9e76331dbef6c80d07b705 Mon Sep 17 00:00:00 2001
From: David Tardon <dtardon@redhat.com>
Date: Wed, 22 Mar 2023 12:43:25 +0100
Subject: [PATCH] journal-vacuum: rename function to match struct name
(cherry picked from commit 646d5df49e1806b8c6322854ddb21903d906f471)
Related: #2182632
---
src/libsystemd/sd-journal/journal-vacuum.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/src/libsystemd/sd-journal/journal-vacuum.c b/src/libsystemd/sd-journal/journal-vacuum.c
index 23497af28e..e3d691a1e9 100644
--- a/src/libsystemd/sd-journal/journal-vacuum.c
+++ b/src/libsystemd/sd-journal/journal-vacuum.c
@@ -19,7 +19,7 @@
#include "time-util.h"
#include "xattr-util.h"
-struct vacuum_info {
+typedef struct vacuum_info {
uint64_t usage;
char *filename;
@@ -28,9 +28,9 @@ struct vacuum_info {
sd_id128_t seqnum_id;
uint64_t seqnum;
bool have_seqnum;
-};
+} vacuum_info;
-static int vacuum_compare(const struct vacuum_info *a, const struct vacuum_info *b) {
+static int vacuum_info_compare(const vacuum_info *a, const vacuum_info *b) {
int r;
if (a->have_seqnum && b->have_seqnum &&
@@ -125,7 +125,7 @@ int journal_directory_vacuum(
uint64_t sum = 0, freed = 0, n_active_files = 0;
size_t n_list = 0, i;
_cleanup_closedir_ DIR *d = NULL;
- struct vacuum_info *list = NULL;
+ vacuum_info *list = NULL;
usec_t retention_limit = 0;
int r;
@@ -270,7 +270,7 @@ int journal_directory_vacuum(
goto finish;
}
- list[n_list++] = (struct vacuum_info) {
+ list[n_list++] = (vacuum_info) {
.filename = TAKE_PTR(p),
.usage = size,
.seqnum = seqnum,
@@ -282,7 +282,7 @@ int journal_directory_vacuum(
sum += size;
}
- typesafe_qsort(list, n_list, vacuum_compare);
+ typesafe_qsort(list, n_list, vacuum_info_compare);
for (i = 0; i < n_list; i++) {
uint64_t left;

@ -0,0 +1,107 @@
From e548d975a79204ab88ab6638aa5b24c173402723 Mon Sep 17 00:00:00 2001
From: David Tardon <dtardon@redhat.com>
Date: Wed, 22 Mar 2023 12:53:20 +0100
Subject: [PATCH] journal-vacuum: use CLEANUP_ARRAY
(cherry picked from commit 567cb18cc9185900ac6f701f0783a7d378e213cf)
Related: #2182632
---
src/libsystemd/sd-journal/journal-vacuum.c | 41 +++++++++++-----------
1 file changed, 20 insertions(+), 21 deletions(-)
diff --git a/src/libsystemd/sd-journal/journal-vacuum.c b/src/libsystemd/sd-journal/journal-vacuum.c
index e3d691a1e9..6f8aaaee4c 100644
--- a/src/libsystemd/sd-journal/journal-vacuum.c
+++ b/src/libsystemd/sd-journal/journal-vacuum.c
@@ -47,6 +47,16 @@ static int vacuum_info_compare(const vacuum_info *a, const vacuum_info *b) {
return strcmp(a->filename, b->filename);
}
+static void vacuum_info_array_free(vacuum_info *list, size_t n) {
+ if (!list)
+ return;
+
+ FOREACH_ARRAY(i, list, n)
+ free(i->filename);
+
+ free(list);
+}
+
static void patch_realtime(
int fd,
const char *fn,
@@ -129,6 +139,8 @@ int journal_directory_vacuum(
usec_t retention_limit = 0;
int r;
+ CLEANUP_ARRAY(list, n_list, vacuum_info_array_free);
+
assert(directory);
if (max_use <= 0 && max_retention_usec <= 0 && n_max_files <= 0)
@@ -141,7 +153,7 @@ int journal_directory_vacuum(
if (!d)
return -errno;
- FOREACH_DIRENT_ALL(de, d, r = -errno; goto finish) {
+ FOREACH_DIRENT_ALL(de, d, return -errno) {
unsigned long long seqnum = 0, realtime;
_cleanup_free_ char *p = NULL;
sd_id128_t seqnum_id;
@@ -182,10 +194,8 @@ int journal_directory_vacuum(
}
p = strdup(de->d_name);
- if (!p) {
- r = -ENOMEM;
- goto finish;
- }
+ if (!p)
+ return -ENOMEM;
de->d_name[q-8-16-1-16-1] = 0;
if (sd_id128_from_string(de->d_name + q-8-16-1-16-1-32, &seqnum_id) < 0) {
@@ -224,10 +234,8 @@ int journal_directory_vacuum(
}
p = strdup(de->d_name);
- if (!p) {
- r = -ENOMEM;
- goto finish;
- }
+ if (!p)
+ return -ENOMEM;
if (sscanf(de->d_name + q-1-8-16-1-16, "%16llx-%16llx.journal~", &realtime, &tmp) != 2) {
n_active_files++;
@@ -265,10 +273,8 @@ int journal_directory_vacuum(
patch_realtime(dirfd(d), p, &st, &realtime);
- if (!GREEDY_REALLOC(list, n_list + 1)) {
- r = -ENOMEM;
- goto finish;
- }
+ if (!GREEDY_REALLOC(list, n_list + 1))
+ return -ENOMEM;
list[n_list++] = (vacuum_info) {
.filename = TAKE_PTR(p),
@@ -312,15 +318,8 @@ int journal_directory_vacuum(
if (oldest_usec && i < n_list && (*oldest_usec == 0 || list[i].realtime < *oldest_usec))
*oldest_usec = list[i].realtime;
- r = 0;
-
-finish:
- for (i = 0; i < n_list; i++)
- free(list[i].filename);
- free(list);
-
log_full(verbose ? LOG_INFO : LOG_DEBUG, "Vacuuming done, freed %s of archived journals from %s.",
FORMAT_BYTES(freed), directory);
- return r;
+ return 0;
}

@ -0,0 +1,28 @@
From 12894fae724cee1e5b94e6b36708e0b6752c9cec Mon Sep 17 00:00:00 2001
From: Michal Sekletar <msekleta@redhat.com>
Date: Wed, 31 May 2023 18:50:12 +0200
Subject: [PATCH] pam: add call to pam_umask
Setting umask for user sessions via UMASK setting in /etc/login.defs is
a well-known feature. Let's make sure that user manager also runs with
this umask value.
Follow-up for 5e37d1930b41b24c077ce37c6db0e36c745106c7.
(cherry picked from commit 159f1b78576ce91c3932f4867f07361a530875d3)
Resolves: #2210145
---
src/login/systemd-user.in | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/login/systemd-user.in b/src/login/systemd-user.in
index 39bcbd71fe..5906a7481b 100644
--- a/src/login/systemd-user.in
+++ b/src/login/systemd-user.in
@@ -18,4 +18,5 @@ session optional pam_keyinit.so force revoke
{% if ENABLE_HOMED %}
-session optional pam_systemd_home.so
{% endif %}
+session optional pam_umask.so silent
session optional pam_systemd.so

@ -0,0 +1,196 @@
From ac7fc3fd00a6f468b14ba05b80d7e2d41b46d485 Mon Sep 17 00:00:00 2001
From: Ivan Vecera <ivecera@redhat.com>
Date: Thu, 22 Jun 2023 10:06:27 +0200
Subject: [PATCH] udev-builtin-net_id: align VF representor names with VF names
Certain cards support to set their eswitch to switchdev mode. In this
mode for each created VF there is also created so called VF representor.
This representor is helper network interface used for configuration of
mentioned eswitch and belongs to an appropriate PF.
VF representors are identified by the specific value of phys_port_name
attribute and the value has format "pfMvfN" where M is PF function
number and N is VF number inside this PF.
As the VF representor interfaces belong to PF PCI device the naming
scheme used for them is the same like for other PCI devices. In this
case name of PF interface is used and phys_port_name suffix is appended.
E.g.
PF=enp65s0f0np0 # phys_port_name for PF interface is 'p0'
VF=enp65s0f0np0v0 # v0 is appended for VF0 in case of NAMING_SR_IOV_V
REP=enp65s0f0np0pf0vf0 # phys_port_name for VF0 representor is 'pf0vf0'
First as the phys_port_name for representors is long (6+ chars) then the
generated name does not fit into IFNAMSIZ so this name is used only as
alternate interface name and for the primary one is used generic one
like eth<N>. Second 'f0' and 'pf0' in REP name is redundant.
This patch fixes this issue by introducing another naming scheme for VF
representors and appending 'rN' suffix to PF interface name for them.
N is VF number so the name used for representor interface is similar to
VF interface and differs only by the suffix.
For the example above we get:
PF=enp65s0f0np0
VF=enp65s0f0np0v0
REP=enp65s0f0np0r0
This eases for userspace to determine which representor interface
represents particular VF.
Signed-off-by: Ivan Vecera <ivecera@redhat.com>
(cherry picked from commit 88d2bda8120dcc375a90e28b64de06b9646ab3b6)
Resolves: #2218886
---
man/systemd.net-naming-scheme.xml | 22 ++++++++++++++++++++++
src/shared/netif-naming-scheme.h | 2 ++
src/udev/udev-builtin-net_id.c | 25 ++++++++++++++++++++-----
3 files changed, 44 insertions(+), 5 deletions(-)
diff --git a/man/systemd.net-naming-scheme.xml b/man/systemd.net-naming-scheme.xml
index 0886369c9b..ade4e27e31 100644
--- a/man/systemd.net-naming-scheme.xml
+++ b/man/systemd.net-naming-scheme.xml
@@ -158,6 +158,7 @@
<term><varname>ID_NET_NAME_SLOT=<replaceable>prefix</replaceable>[<constant>P</constant><replaceable>domain</replaceable>]<constant>s</constant><replaceable>slot</replaceable>[<constant>f</constant><replaceable>function</replaceable>][<constant>n</constant><replaceable>port_name</replaceable>|<constant>d</constant><replaceable>dev_port</replaceable>]<constant>b</constant><replaceable>number</replaceable></varname></term>
<term><varname>ID_NET_NAME_SLOT=<replaceable>prefix</replaceable>[<constant>P</constant><replaceable>domain</replaceable>]<constant>s</constant><replaceable>slot</replaceable>[<constant>f</constant><replaceable>function</replaceable>][<constant>n</constant><replaceable>port_name</replaceable>|<constant>d</constant><replaceable>dev_port</replaceable>]<constant>u</constant><replaceable>port</replaceable>…[<constant>c</constant><replaceable>config</replaceable>][<constant>i</constant><replaceable>interface</replaceable>]</varname></term>
<term><varname>ID_NET_NAME_SLOT=<replaceable>prefix</replaceable>[<constant>P</constant><replaceable>domain</replaceable>]<constant>s</constant><replaceable>slot</replaceable>[<constant>f</constant><replaceable>function</replaceable>][<constant>n</constant><replaceable>port_name</replaceable>|<constant>d</constant><replaceable>dev_port</replaceable>]<constant>v</constant><replaceable>slot</replaceable></varname></term>
+ <term><varname>ID_NET_NAME_SLOT=<replaceable>prefix</replaceable>[<constant>P</constant><replaceable>domain</replaceable>]<constant>s</constant><replaceable>slot</replaceable>[<constant>f</constant><replaceable>function</replaceable>][<constant>n</constant><replaceable>port_name</replaceable>|<constant>d</constant><replaceable>dev_port</replaceable>]<constant>r</constant><replaceable>slot</replaceable></varname></term>
<listitem><para>This property describes the slot position. Different schemes are used depending on
the bus type, as described in the table below. In case of USB, BCMA, and SR-VIO devices, the full
@@ -205,6 +206,11 @@
<entry>… <constant>v</constant><replaceable>slot</replaceable></entry>
<entry>SR-VIO slot number</entry>
</row>
+
+ <row>
+ <entry>… <constant>r</constant><replaceable>slot</replaceable></entry>
+ <entry>SR-IOV slot number</entry>
+ </row>
</tbody>
</tgroup>
</table>
@@ -225,6 +231,11 @@
<constant>v</constant> and the virtual device number, with any leading zeros removed. The bus
number is ignored.</para>
+ <para>SR-IOV virtual device representors are named based on the name of the physical device
+ interface, with a suffix of <constant>r</constant> and the number of the virtual device that
+ is linked to the particular representor, with any leading zeros removed. The physical port
+ name and the bus number are ignored.</para>
+
<para>In some configurations a parent PCI bridge of a given network controller may be associated
with a slot. In such case we don't generate this device property to avoid possible naming conflicts.</para>
</listitem>
@@ -472,6 +483,17 @@
<listitem><para>Same as naming scheme <constant>rhel-9.0</constant>.</para></listitem>
</varlistentry>
+ <varlistentry>
+ <term><constant>rhel-9.3</constant></term>
+
+ <listitem><para>Naming was changed for SR-IOV virtual device representors.</para>
+
+ <para>The <literal>r<replaceable>slot</replaceable></literal> suffix was added to differentiate SR-IOV
+ virtual device representors attached to a single physical device interface.
+ </para>
+ </listitem>
+ </varlistentry>
+
</variablelist>
<para>Note that <constant>latest</constant> may be used to denote the latest scheme known (to this
diff --git a/src/shared/netif-naming-scheme.h b/src/shared/netif-naming-scheme.h
index 3e35c5e2fa..fb3c8eb9b3 100644
--- a/src/shared/netif-naming-scheme.h
+++ b/src/shared/netif-naming-scheme.h
@@ -38,6 +38,7 @@ typedef enum NamingSchemeFlags {
NAMING_XEN_VIF = 1 << 13, /* Generate names for Xen netfront devices */
NAMING_BRIDGE_MULTIFUNCTION_SLOT = 1 << 14, /* Use PCI hotplug slot information associated with bridge, but only if PCI device is multifunction */
NAMING_DEVICETREE_ALIASES = 1 << 15, /* Generate names from devicetree aliases */
+ NAMING_SR_IOV_R = 1 << 17, /* Use "r" suffix for SR-IOV VF representors */
/* And now the masks that combine the features above */
NAMING_V238 = 0,
@@ -54,6 +55,7 @@ typedef enum NamingSchemeFlags {
NAMING_RHEL_9_0 = NAMING_V250 | NAMING_BRIDGE_MULTIFUNCTION_SLOT,
NAMING_RHEL_9_1 = NAMING_RHEL_9_0,
NAMING_RHEL_9_2 = NAMING_RHEL_9_0,
+ NAMING_RHEL_9_3 = NAMING_RHEL_9_0 | NAMING_SR_IOV_R,
EXTRA_NET_NAMING_SCHEMES
diff --git a/src/udev/udev-builtin-net_id.c b/src/udev/udev-builtin-net_id.c
index d4e9dcb60d..c57568f8cb 100644
--- a/src/udev/udev-builtin-net_id.c
+++ b/src/udev/udev-builtin-net_id.c
@@ -80,6 +80,7 @@ typedef struct LinkInfo {
int ifindex;
int iflink;
int iftype;
+ int vf_representor_id;
const char *devtype;
const char *phys_port_name;
struct hw_addr_data hw_addr;
@@ -208,7 +209,10 @@ static int dev_pci_onboard(sd_device *dev, const LinkInfo *info, NetNames *names
s = names->pci_onboard;
l = sizeof(names->pci_onboard);
l = strpcpyf(&s, l, "o%lu", idx);
- if (!isempty(info->phys_port_name))
+ if (naming_scheme_has(NAMING_SR_IOV_R) && info->vf_representor_id >= 0)
+ /* For VF representor append 'r<VF_NUM>' and not phys_port_name */
+ l = strpcpyf(&s, l, "r%d", info->vf_representor_id);
+ else if (!isempty(info->phys_port_name))
/* kernel provided front panel port name for multiple port PCI device */
l = strpcpyf(&s, l, "n%s", info->phys_port_name);
else if (dev_port > 0)
@@ -391,7 +395,10 @@ static int dev_pci_slot(sd_device *dev, const LinkInfo *info, NetNames *names) {
l = strpcpyf(&s, l, "p%us%u", bus, slot);
if (func > 0 || is_pci_multifunction(names->pcidev) > 0)
l = strpcpyf(&s, l, "f%u", func);
- if (!isempty(info->phys_port_name))
+ if (naming_scheme_has(NAMING_SR_IOV_R) && info->vf_representor_id >= 0)
+ /* For VF representor append 'r<VF_NUM>' and not phys_port_name */
+ l = strpcpyf(&s, l, "r%d", info->vf_representor_id);
+ else if (!isempty(info->phys_port_name))
/* kernel provided front panel port name for multi-port PCI device */
l = strpcpyf(&s, l, "n%s", info->phys_port_name);
else if (dev_port > 0)
@@ -485,7 +492,10 @@ static int dev_pci_slot(sd_device *dev, const LinkInfo *info, NetNames *names) {
l = strpcpyf(&s, l, "s%"PRIu32, hotplug_slot);
if (func > 0 || is_pci_multifunction(names->pcidev) > 0)
l = strpcpyf(&s, l, "f%u", func);
- if (!isempty(info->phys_port_name))
+ if (naming_scheme_has(NAMING_SR_IOV_R) && info->vf_representor_id >= 0)
+ /* For VF representor append 'r<VF_NUM>' and not phys_port_name */
+ l = strpcpyf(&s, l, "r%d", info->vf_representor_id);
+ else if (!isempty(info->phys_port_name))
l = strpcpyf(&s, l, "n%s", info->phys_port_name);
else if (dev_port > 0)
l = strpcpyf(&s, l, "d%lu", dev_port);
@@ -1082,7 +1092,10 @@ static int get_link_info(sd_device *dev, LinkInfo *info) {
if (r < 0 && r != -ENOENT)
return r;
- (void) sd_device_get_sysattr_value(dev, "phys_port_name", &info->phys_port_name);
+ r = sd_device_get_sysattr_value(dev, "phys_port_name", &info->phys_port_name);
+ if (r >= 0)
+ /* Check if phys_port_name indicates virtual device representor */
+ (void) sscanf(info->phys_port_name, "pf%*uvf%d", &info->vf_representor_id);
r = sd_device_get_sysattr_value(dev, "address", &s);
if (r < 0 && r != -ENOENT)
@@ -1099,7 +1112,9 @@ static int get_link_info(sd_device *dev, LinkInfo *info) {
static int builtin_net_id(sd_device *dev, sd_netlink **rtnl, int argc, char *argv[], bool test) {
const char *prefix;
NetNames names = {};
- LinkInfo info = {};
+ LinkInfo info = {
+ .vf_representor_id = -1,
+ };
int r;
r = get_link_info(dev, &info);

@ -0,0 +1,42 @@
From 7c717362136027e8efa82edba061158f4bb1fd07 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
Date: Wed, 23 Nov 2022 16:09:56 +0100
Subject: [PATCH] pam: add a call to pam_namespace
A call to pam_namespace is required so that children of user@.service end up in
a namespace as expected. pam_namespace gets called as part of the stack that
creates a session (login, sshd, gdm, etc.) and those processes end up in a
namespace, but it also needs to be called from our stack which is parallel and
descends from pid1 itself.
The call to pam_namespace is similar to the call to pam_keyinit that was added
in ab79099d1684457d040ee7c28b2012e8c1ea9a4f. The pam stack for user@.service
creates a new session which is disconnected from the parent environment. Both
calls are not suitable for inclusion in the shared part of the stack (e.g.
@system-auth on Fedora/RHEL systems), because for example su/sudo/runuser
should not include them.
Fixes #17043 (Allow to execute user service into dedicated namespace
if pam_namespace enabled)
Related to https://bugzilla.redhat.com/show_bug.cgi?id=1861836
(Polyinstantiation is ignored/bypassed in GNOME sessions)
(cherry picked from commit 0ef48896d9f23b9fd547a532a4e6e6b8f8b12901)
Resolves: #2218184
---
src/login/systemd-user.in | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/login/systemd-user.in b/src/login/systemd-user.in
index 5906a7481b..8805306908 100644
--- a/src/login/systemd-user.in
+++ b/src/login/systemd-user.in
@@ -15,6 +15,7 @@ session required pam_selinux.so nottys open
{% endif %}
session required pam_loginuid.so
session optional pam_keyinit.so force revoke
+session required pam_namespace.so
{% if ENABLE_HOMED %}
-session optional pam_systemd_home.so
{% endif %}

@ -0,0 +1,39 @@
From 65d993c2efe52d683396dc3181cc79f29698bf39 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= <clg@redhat.com>
Date: Wed, 21 Jun 2023 17:10:46 +0200
Subject: [PATCH] rules: online CPU automatically on IBM s390x platforms when
configured
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
RHEL-only
Fix CPU hotplug regression on s390x introduced by commit 94c7e260b499 ("rules:
do not online CPU automatically on IBM platforms"). After discussion with IBM,
CPUs should be auto-enabled when in the configured state after a hotplug.
However, if the CPU is deconfigured, it should not.
This is because on zVM and KVM hotplugged CPUs are configured and on LPAR/DPM
they are deconfigured.
Resolves: #2212612
Signed-off-by: Cédric Le Goater <clg@redhat.com>
---
rules.d/40-redhat.rules | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/rules.d/40-redhat.rules b/rules.d/40-redhat.rules
index efb866966e..00c02a59bd 100644
--- a/rules.d/40-redhat.rules
+++ b/rules.d/40-redhat.rules
@@ -3,7 +3,8 @@
# CPU hotadd request
SUBSYSTEM!="cpu", GOTO="cpu_online_end"
ACTION!="add", GOTO="cpu_online_end"
-CONST{arch}=="s390*|ppc64*", GOTO="cpu_online_end"
+CONST{arch}=="ppc64*", GOTO="cpu_online_end"
+CONST{arch}=="s390*", ATTR{configure}=="0", GOTO="cpu_online_end"
TEST=="online", ATTR{online}=="0", ATTR{online}="1"

@ -0,0 +1,106 @@
From fcdec60764cd1d6f2d859558303390fffcec3633 Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Thu, 11 May 2023 19:21:57 +0900
Subject: [PATCH] core/mount: escape invalid UTF8 char in dbus reply
When What= or Options= may contain invalid UTF8 chars.
Replaces aaf7b0e41105d7b7cf30912cdac32820f011a219 (#27541).
(cherry picked from commit 4804da58536ab7ad46178a03f4d2da49fd8e4ba2)
Resolves: #2208240
---
src/core/dbus-mount.c | 67 +++++++++++++++++++++++++++++++++++--------
1 file changed, 55 insertions(+), 12 deletions(-)
diff --git a/src/core/dbus-mount.c b/src/core/dbus-mount.c
index 73702b1a16..55ad4f2c98 100644
--- a/src/core/dbus-mount.c
+++ b/src/core/dbus-mount.c
@@ -9,21 +9,66 @@
#include "mount.h"
#include "string-util.h"
#include "unit.h"
+#include "utf8.h"
+
+static int property_get_what(
+ sd_bus *bus,
+ const char *path,
+ const char *interface,
+ const char *property,
+ sd_bus_message *reply,
+ void *userdata,
+ sd_bus_error *error) {
+
+ _cleanup_free_ char *escaped = NULL;
+ Mount *m = ASSERT_PTR(userdata);
+ const char *s = NULL;
+
+ assert(bus);
+ assert(reply);
-static const char *mount_get_what(const Mount *m) {
if (m->from_proc_self_mountinfo && m->parameters_proc_self_mountinfo.what)
- return m->parameters_proc_self_mountinfo.what;
- if (m->from_fragment && m->parameters_fragment.what)
- return m->parameters_fragment.what;
- return NULL;
+ s = m->parameters_proc_self_mountinfo.what;
+ else if (m->from_fragment && m->parameters_fragment.what)
+ s = m->parameters_fragment.what;
+
+ if (s) {
+ escaped = utf8_escape_invalid(s);
+ if (!escaped)
+ return -ENOMEM;
+ }
+
+ return sd_bus_message_append_basic(reply, 's', escaped);
}
-static const char *mount_get_options(const Mount *m) {
+static int property_get_options(
+ sd_bus *bus,
+ const char *path,
+ const char *interface,
+ const char *property,
+ sd_bus_message *reply,
+ void *userdata,
+ sd_bus_error *error) {
+
+ _cleanup_free_ char *escaped = NULL;
+ Mount *m = ASSERT_PTR(userdata);
+ const char *s = NULL;
+
+ assert(bus);
+ assert(reply);
+
if (m->from_proc_self_mountinfo && m->parameters_proc_self_mountinfo.options)
- return m->parameters_proc_self_mountinfo.options;
- if (m->from_fragment && m->parameters_fragment.options)
- return m->parameters_fragment.options;
- return NULL;
+ s = m->parameters_proc_self_mountinfo.options;
+ else if (m->from_fragment && m->parameters_fragment.options)
+ s = m->parameters_fragment.options;
+
+ if (s) {
+ escaped = utf8_escape_invalid(s);
+ if (!escaped)
+ return -ENOMEM;
+ }
+
+ return sd_bus_message_append_basic(reply, 's', escaped);
}
static const char *mount_get_fstype(const Mount *m) {
@@ -34,8 +79,6 @@ static const char *mount_get_fstype(const Mount *m) {
return NULL;
}
-static BUS_DEFINE_PROPERTY_GET(property_get_what, "s", Mount, mount_get_what);
-static BUS_DEFINE_PROPERTY_GET(property_get_options, "s", Mount, mount_get_options);
static BUS_DEFINE_PROPERTY_GET(property_get_type, "s", Mount, mount_get_fstype);
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result, mount_result, MountResult);

@ -1,4 +1,4 @@
From a540b3e604d921200ee35f859770c9fbed6b669a Mon Sep 17 00:00:00 2001
From 1d38915c7ac741cd1772521b3921b4e1655af9f8 Mon Sep 17 00:00:00 2001
From: Michal Sekletar <msekleta@redhat.com>
Date: Fri, 3 Mar 2023 10:58:37 +0100
Subject: [PATCH] Revert "user: delegate cpu controller, assign weights to user
@ -6,7 +6,7 @@ Subject: [PATCH] Revert "user: delegate cpu controller, assign weights to user
This reverts commit b8df7f8629cb310beac982a4779b27eabe5362c6.
Resolves: #2173996
Resolves: #2176899
---
TODO | 2 --
units/user/app.slice | 3 ---

@ -0,0 +1,61 @@
From b4bf6261b5025dabf92997bf124f57e2e314935e Mon Sep 17 00:00:00 2001
From: Thomas Blume <Thomas.Blume@suse.com>
Date: Thu, 2 Mar 2023 12:06:13 +0100
Subject: [PATCH] udev-rules: fix nvme symlink creation on namespace changes
The nvme by-id symlink changes to the latest namespace when a new namespace gets
added, for example by connecting multiple NVMe/TCP host controllers via nvme
connect-all.
That is incorrect for persistent device links.
The persistent symbolic device link should continue to point to the same NVMe
namespace throughout the lifetime of the current boot.
Therefore the namespace id needs to be added to the link name.
(cherry picked from commit c5ba7a2a4dd19a2d31b8a9d52d3c4bdde78387f0)
Resolves: #2172509
---
rules.d/60-persistent-storage.rules | 8 ++++++++
test/units/testsuite-64.sh | 2 ++
2 files changed, 10 insertions(+)
diff --git a/rules.d/60-persistent-storage.rules b/rules.d/60-persistent-storage.rules
index 18588e4c45..d6612daf7d 100644
--- a/rules.d/60-persistent-storage.rules
+++ b/rules.d/60-persistent-storage.rules
@@ -37,14 +37,22 @@ KERNEL=="nvme*[0-9]n*[0-9]", ENV{DEVTYPE}=="disk", ATTRS{serial}=="?*", ENV{ID_S
KERNEL=="nvme*[0-9]n*[0-9]", ENV{DEVTYPE}=="disk", ATTRS{wwid}=="?*", ENV{ID_WWN}="$attr{wwid}"
KERNEL=="nvme*[0-9]n*[0-9]", ENV{DEVTYPE}=="disk", ATTRS{model}=="?*", ENV{ID_MODEL}="$attr{model}"
KERNEL=="nvme*[0-9]n*[0-9]", ENV{DEVTYPE}=="disk", ATTRS{firmware_rev}=="?*", ENV{ID_REVISION}="$attr{firmware_rev}"
+KERNEL=="nvme*[0-9]n*[0-9]", ENV{DEVTYPE}=="disk", ATTRS{nsid}=="?*", ENV{ID_NSID}="$attr{nsid}"
+# obsolete symlink that might get overridden on adding a new nvme controller, kept for backward compatibility
KERNEL=="nvme*[0-9]n*[0-9]", ENV{DEVTYPE}=="disk", ENV{ID_MODEL}=="?*", ENV{ID_SERIAL_SHORT}=="?*", \
OPTIONS="string_escape=replace", ENV{ID_SERIAL}="$env{ID_MODEL}_$env{ID_SERIAL_SHORT}", SYMLINK+="disk/by-id/nvme-$env{ID_SERIAL}"
+KERNEL=="nvme*[0-9]n*[0-9]", ENV{DEVTYPE}=="disk", ENV{ID_MODEL}=="?*", ENV{ID_SERIAL_SHORT}=="?*", ENV{ID_NSID}=="?*",\
+ OPTIONS="string_escape=replace", ENV{ID_SERIAL}="$env{ID_MODEL}_$env{ID_SERIAL_SHORT}_$env{ID_NSID}", SYMLINK+="disk/by-id/nvme-$env{ID_SERIAL}"
KERNEL=="nvme*[0-9]n*[0-9]p*[0-9]", ENV{DEVTYPE}=="partition", ATTRS{serial}=="?*", ENV{ID_SERIAL_SHORT}="$attr{serial}"
KERNEL=="nvme*[0-9]n*[0-9]p*[0-9]", ENV{DEVTYPE}=="partition", ATTRS{model}=="?*", ENV{ID_MODEL}="$attr{model}"
KERNEL=="nvme*[0-9]n*[0-9]p*[0-9]", ENV{DEVTYPE}=="partition", ATTRS{firmware_rev}=="?*", ENV{ID_REVISION}="$attr{firmware_rev}"
+KERNEL=="nvme*[0-9]n*[0-9]p*[0-9]", ENV{DEVTYPE}=="partition", ATTRS{nsid}=="?*", ENV{ID_NSID}="$attr{nsid}"
+# obsolete symlink that might get overridden on adding a new nvme controller, kept for backward compatibility
KERNEL=="nvme*[0-9]n*[0-9]p*[0-9]", ENV{DEVTYPE}=="partition", ENV{ID_MODEL}=="?*", ENV{ID_SERIAL_SHORT}=="?*", \
OPTIONS="string_escape=replace", ENV{ID_SERIAL}="$env{ID_MODEL}_$env{ID_SERIAL_SHORT}", SYMLINK+="disk/by-id/nvme-$env{ID_SERIAL}-part%n"
+KERNEL=="nvme*[0-9]n*[0-9]p*[0-9]", ENV{DEVTYPE}=="partition", ENV{ID_MODEL}=="?*", ENV{ID_SERIAL_SHORT}=="?*", ENV{ID_NSID}=="?*",\
+ OPTIONS="string_escape=replace", ENV{ID_SERIAL}="$env{ID_MODEL}_$env{ID_SERIAL_SHORT}_$env{ID_NSID}", SYMLINK+="disk/by-id/nvme-$env{ID_SERIAL}-part%n"
# virtio-blk
KERNEL=="vd*[!0-9]", ATTRS{serial}=="?*", ENV{ID_SERIAL}="$attr{serial}", SYMLINK+="disk/by-id/virtio-$env{ID_SERIAL}"
diff --git a/test/units/testsuite-64.sh b/test/units/testsuite-64.sh
index 201a673d06..f7298ed0d6 100755
--- a/test/units/testsuite-64.sh
+++ b/test/units/testsuite-64.sh
@@ -182,6 +182,8 @@ testcase_nvme_subsystem() {
local expected_symlinks=(
# Controller(s)
/dev/disk/by-id/nvme-QEMU_NVMe_Ctrl_deadbeef
+ /dev/disk/by-id/nvme-QEMU_NVMe_Ctrl_deadbeef_16
+ /dev/disk/by-id/nvme-QEMU_NVMe_Ctrl_deadbeef_17
# Shared namespaces
/dev/disk/by-path/pci-*-nvme-16
/dev/disk/by-path/pci-*-nvme-17

@ -0,0 +1,35 @@
From b3a19cc848f1f7046fb19c6a27b56fa3bf341728 Mon Sep 17 00:00:00 2001
From: "Dmitry V. Levin" <ldv@strace.io>
Date: Sat, 25 Mar 2023 08:00:00 +0000
Subject: [PATCH] rules: add whitespace after comma before the line
continuation
(cherry picked from commit 519044f565cf32f4ebd0ecca5eb162555aa006b2)
Related: #2172509
---
rules.d/60-persistent-storage.rules | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/rules.d/60-persistent-storage.rules b/rules.d/60-persistent-storage.rules
index d6612daf7d..f5178ed6bd 100644
--- a/rules.d/60-persistent-storage.rules
+++ b/rules.d/60-persistent-storage.rules
@@ -41,7 +41,7 @@ KERNEL=="nvme*[0-9]n*[0-9]", ENV{DEVTYPE}=="disk", ATTRS{nsid}=="?*", ENV{ID_NSI
# obsolete symlink that might get overridden on adding a new nvme controller, kept for backward compatibility
KERNEL=="nvme*[0-9]n*[0-9]", ENV{DEVTYPE}=="disk", ENV{ID_MODEL}=="?*", ENV{ID_SERIAL_SHORT}=="?*", \
OPTIONS="string_escape=replace", ENV{ID_SERIAL}="$env{ID_MODEL}_$env{ID_SERIAL_SHORT}", SYMLINK+="disk/by-id/nvme-$env{ID_SERIAL}"
-KERNEL=="nvme*[0-9]n*[0-9]", ENV{DEVTYPE}=="disk", ENV{ID_MODEL}=="?*", ENV{ID_SERIAL_SHORT}=="?*", ENV{ID_NSID}=="?*",\
+KERNEL=="nvme*[0-9]n*[0-9]", ENV{DEVTYPE}=="disk", ENV{ID_MODEL}=="?*", ENV{ID_SERIAL_SHORT}=="?*", ENV{ID_NSID}=="?*", \
OPTIONS="string_escape=replace", ENV{ID_SERIAL}="$env{ID_MODEL}_$env{ID_SERIAL_SHORT}_$env{ID_NSID}", SYMLINK+="disk/by-id/nvme-$env{ID_SERIAL}"
KERNEL=="nvme*[0-9]n*[0-9]p*[0-9]", ENV{DEVTYPE}=="partition", ATTRS{serial}=="?*", ENV{ID_SERIAL_SHORT}="$attr{serial}"
@@ -51,7 +51,7 @@ KERNEL=="nvme*[0-9]n*[0-9]p*[0-9]", ENV{DEVTYPE}=="partition", ATTRS{nsid}=="?*"
# obsolete symlink that might get overridden on adding a new nvme controller, kept for backward compatibility
KERNEL=="nvme*[0-9]n*[0-9]p*[0-9]", ENV{DEVTYPE}=="partition", ENV{ID_MODEL}=="?*", ENV{ID_SERIAL_SHORT}=="?*", \
OPTIONS="string_escape=replace", ENV{ID_SERIAL}="$env{ID_MODEL}_$env{ID_SERIAL_SHORT}", SYMLINK+="disk/by-id/nvme-$env{ID_SERIAL}-part%n"
-KERNEL=="nvme*[0-9]n*[0-9]p*[0-9]", ENV{DEVTYPE}=="partition", ENV{ID_MODEL}=="?*", ENV{ID_SERIAL_SHORT}=="?*", ENV{ID_NSID}=="?*",\
+KERNEL=="nvme*[0-9]n*[0-9]p*[0-9]", ENV{DEVTYPE}=="partition", ENV{ID_MODEL}=="?*", ENV{ID_SERIAL_SHORT}=="?*", ENV{ID_NSID}=="?*", \
OPTIONS="string_escape=replace", ENV{ID_SERIAL}="$env{ID_MODEL}_$env{ID_SERIAL_SHORT}_$env{ID_NSID}", SYMLINK+="disk/by-id/nvme-$env{ID_SERIAL}-part%n"
# virtio-blk

@ -0,0 +1,61 @@
From b4c71f09f1933324593aef453f70e986d0175b70 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
Date: Thu, 6 Apr 2023 12:28:14 +0200
Subject: [PATCH] udev: restore compat symlink for nvme devices
In 5118e8e71dda211d20e34ec8d3012186ba27d3d3, the rules were changed to add
OPTIONS="string_escape=replace" to creation of
ENV{ID_SERIAL}="$env{ID_MODEL}_$env{ID_SERIAL_SHORT}", so that "/" would be
escaped. But this also changes how the symlink looks for devices that do not
have "/". This adds back the old symlink for compat, except when a slash
is present.
In the meantime, we changed the symlink format to include ${ND_NSID}. Since
the symlink with unescaped characters are older than that, for compat we
only need to cover the older type. (Symlinks without escaping and with ${ND_NSID}
were never created.) This makes it slightly easier on users: the non-deprecated
symlinks are with "_${ND_NSID}", so they are easier to distinguish.
Fixes #27155.
Mostly untested :( I only have a boring nvme device with no special characters
in the id, and the symlinks are unchanged for it by this patch.
(cherry picked from commit d05e1be86e6b14bd22d57af17efcc3b8fb7ecd82)
Related: #2172509
[msekleta: it is not strictly necessary to include this commit in RHEL-9
because the we never had the previous version of non-escaped symlinks in
RHEL-9. However, by including it we are making a life a bit easier for
folks that are doing in-place upgrade from RHEL-8.]
---
rules.d/60-persistent-storage.rules | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/rules.d/60-persistent-storage.rules b/rules.d/60-persistent-storage.rules
index f5178ed6bd..8269c3cfd9 100644
--- a/rules.d/60-persistent-storage.rules
+++ b/rules.d/60-persistent-storage.rules
@@ -38,6 +38,10 @@ KERNEL=="nvme*[0-9]n*[0-9]", ENV{DEVTYPE}=="disk", ATTRS{wwid}=="?*", ENV{ID_WWN
KERNEL=="nvme*[0-9]n*[0-9]", ENV{DEVTYPE}=="disk", ATTRS{model}=="?*", ENV{ID_MODEL}="$attr{model}"
KERNEL=="nvme*[0-9]n*[0-9]", ENV{DEVTYPE}=="disk", ATTRS{firmware_rev}=="?*", ENV{ID_REVISION}="$attr{firmware_rev}"
KERNEL=="nvme*[0-9]n*[0-9]", ENV{DEVTYPE}=="disk", ATTRS{nsid}=="?*", ENV{ID_NSID}="$attr{nsid}"
+# obsolete symlink with non-escaped characters, kept for backward compatiblity
+KERNEL=="nvme*[0-9]n*[0-9]", ENV{DEVTYPE}=="disk", ENV{ID_MODEL}=="?*", ENV{ID_SERIAL_SHORT}=="?*", \
+ ENV{ID_MODEL}!="*/*", ENV{ID_SERIAL_SHORT}!="*/*", \
+ ENV{ID_SERIAL}="$env{ID_MODEL}_$env{ID_SERIAL_SHORT}", SYMLINK+="disk/by-id/nvme-$env{ID_SERIAL}"
# obsolete symlink that might get overridden on adding a new nvme controller, kept for backward compatibility
KERNEL=="nvme*[0-9]n*[0-9]", ENV{DEVTYPE}=="disk", ENV{ID_MODEL}=="?*", ENV{ID_SERIAL_SHORT}=="?*", \
OPTIONS="string_escape=replace", ENV{ID_SERIAL}="$env{ID_MODEL}_$env{ID_SERIAL_SHORT}", SYMLINK+="disk/by-id/nvme-$env{ID_SERIAL}"
@@ -48,6 +52,10 @@ KERNEL=="nvme*[0-9]n*[0-9]p*[0-9]", ENV{DEVTYPE}=="partition", ATTRS{serial}=="?
KERNEL=="nvme*[0-9]n*[0-9]p*[0-9]", ENV{DEVTYPE}=="partition", ATTRS{model}=="?*", ENV{ID_MODEL}="$attr{model}"
KERNEL=="nvme*[0-9]n*[0-9]p*[0-9]", ENV{DEVTYPE}=="partition", ATTRS{firmware_rev}=="?*", ENV{ID_REVISION}="$attr{firmware_rev}"
KERNEL=="nvme*[0-9]n*[0-9]p*[0-9]", ENV{DEVTYPE}=="partition", ATTRS{nsid}=="?*", ENV{ID_NSID}="$attr{nsid}"
+# obsolete symlink with non-escaped characters, kept for backward compatiblity
+KERNEL=="nvme*[0-9]n*[0-9]p*[0-9]", ENV{DEVTYPE}=="partition", ENV{ID_MODEL}=="?*", ENV{ID_SERIAL_SHORT}=="?*", \
+ ENV{ID_MODEL}!="*/*", ENV{ID_SERIAL_SHORT}!="*/*", \
+ ENV{ID_SERIAL}="$env{ID_MODEL}_$env{ID_SERIAL_SHORT}", SYMLINK+="disk/by-id/nvme-$env{ID_SERIAL}-part%n"
# obsolete symlink that might get overridden on adding a new nvme controller, kept for backward compatibility
KERNEL=="nvme*[0-9]n*[0-9]p*[0-9]", ENV{DEVTYPE}=="partition", ENV{ID_MODEL}=="?*", ENV{ID_SERIAL_SHORT}=="?*", \
OPTIONS="string_escape=replace", ENV{ID_SERIAL}="$env{ID_MODEL}_$env{ID_SERIAL_SHORT}", SYMLINK+="disk/by-id/nvme-$env{ID_SERIAL}-part%n"

@ -0,0 +1,25 @@
From 5e92f162bc25197b67d9ffd7669d803a9168b4e6 Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Sat, 8 Apr 2023 03:36:44 +0900
Subject: [PATCH] rules: drop doubled space
(cherry picked from commit 49e3e219b01132ef269297574a9bc7b7b34d9398)
Related: #2172509
---
rules.d/60-persistent-storage.rules | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/rules.d/60-persistent-storage.rules b/rules.d/60-persistent-storage.rules
index 8269c3cfd9..10b347e191 100644
--- a/rules.d/60-persistent-storage.rules
+++ b/rules.d/60-persistent-storage.rules
@@ -59,7 +59,7 @@ KERNEL=="nvme*[0-9]n*[0-9]p*[0-9]", ENV{DEVTYPE}=="partition", ENV{ID_MODEL}=="?
# obsolete symlink that might get overridden on adding a new nvme controller, kept for backward compatibility
KERNEL=="nvme*[0-9]n*[0-9]p*[0-9]", ENV{DEVTYPE}=="partition", ENV{ID_MODEL}=="?*", ENV{ID_SERIAL_SHORT}=="?*", \
OPTIONS="string_escape=replace", ENV{ID_SERIAL}="$env{ID_MODEL}_$env{ID_SERIAL_SHORT}", SYMLINK+="disk/by-id/nvme-$env{ID_SERIAL}-part%n"
-KERNEL=="nvme*[0-9]n*[0-9]p*[0-9]", ENV{DEVTYPE}=="partition", ENV{ID_MODEL}=="?*", ENV{ID_SERIAL_SHORT}=="?*", ENV{ID_NSID}=="?*", \
+KERNEL=="nvme*[0-9]n*[0-9]p*[0-9]", ENV{DEVTYPE}=="partition", ENV{ID_MODEL}=="?*", ENV{ID_SERIAL_SHORT}=="?*", ENV{ID_NSID}=="?*", \
OPTIONS="string_escape=replace", ENV{ID_SERIAL}="$env{ID_MODEL}_$env{ID_SERIAL_SHORT}_$env{ID_NSID}", SYMLINK+="disk/by-id/nvme-$env{ID_SERIAL}-part%n"
# virtio-blk

@ -1,4 +1,4 @@
From 6c4090a8bdf54928e43c21d7443d2e6825ed6d1f Mon Sep 17 00:00:00 2001
From b7b6493dd0a58931afbb7c7d818c1ebb6460b2bc Mon Sep 17 00:00:00 2001
From: Jan Macku <jamacku@redhat.com>
Date: Tue, 9 May 2023 13:15:06 +0200
Subject: [PATCH] manager: don't taint the host if cgroups v1 is used
@ -8,7 +8,7 @@ This is not true for RHEL, don't taint the host when cgroups v1 are enabled.
rhel-only
Resolves: #2196479
Resolves: #2193456
---
man/org.freedesktop.systemd1.xml | 6 ------
src/core/manager.c | 3 ---

@ -0,0 +1,43 @@
From 14d3ca976102d1c013b4b634586a365aadcd94c4 Mon Sep 17 00:00:00 2001
From: Michal Sekletar <msekleta@redhat.com>
Date: Mon, 22 May 2023 17:44:30 +0200
Subject: [PATCH] core/service: when resetting PID also reset known flag
Re-watching pids on cgroup v1 (needed because of unreliability of cgroup
empty notifications in containers) is handled bellow at the end of
service_sigchld_event() and depends on value main_pid_known flag.
In CentOS Stream 8 container on cgroup v1 the stop action would get stuck
indefinitely on unit like this,
$ cat /run/systemd/system/foo.service
[Service]
ExecStart=/bin/bash -c 'trap "nohup sleep 1 & exit 0" TERM; sleep infinity'
ExecStop=/bin/bash -c 'kill -s TERM $MAINPID'
TimeoutSec=0
However, upstream works "fine" because in upstream version of systemd we
actually never wait on processes killed in containers and proceed
immediately to sending SIGKILL hence re-watching of pids in the cgroup
is not necessary. But for the sake of correctness we should merge the
patch also upstream.
(cherry picked from commit ff32060f2ed37b68dc26256b05e2e69013b0ecfe)
Resolves: #2210237
---
src/core/service.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/core/service.c b/src/core/service.c
index 1e14cdc6ca..e5127a4ccf 100644
--- a/src/core/service.c
+++ b/src/core/service.c
@@ -3507,6 +3507,7 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
return;
s->main_pid = 0;
+ s->main_pid_known = false;
exec_status_exit(&s->main_exec_status, &s->exec_context, pid, code, status);
if (s->main_command) {

@ -0,0 +1,28 @@
From 7885b4384b422db6b2d6ad1771dc89c4a3c3461b Mon Sep 17 00:00:00 2001
From: Jan Macku <jamacku@redhat.com>
Date: Thu, 13 Jul 2023 14:21:20 +0200
Subject: [PATCH] ci: drop systemd-stable from advanced-commit-linter config
It's sufficient enough to check only the `systemd/systemd` repo.
Related to https://github.com/redhat-plumbers-in-action/advanced-commit-linter/issues/62
rhel-only
Related: #2170883
---
.github/advanced-commit-linter.yml | 1 -
1 file changed, 1 deletion(-)
diff --git a/.github/advanced-commit-linter.yml b/.github/advanced-commit-linter.yml
index 327af0467a..0fb74a9dc8 100644
--- a/.github/advanced-commit-linter.yml
+++ b/.github/advanced-commit-linter.yml
@@ -2,7 +2,6 @@ policy:
cherry-pick:
upstream:
- github: systemd/systemd
- - github: systemd/systemd-stable
exception:
note:
- rhel-only

@ -0,0 +1,43 @@
From 85631eff66cb440ba253d36ca5b5bd6d131b0f18 Mon Sep 17 00:00:00 2001
From: msizanoen <msizanoen@qtmlabs.xyz>
Date: Mon, 12 Jun 2023 10:30:12 +0700
Subject: [PATCH] Revert "core/service: when resetting PID also reset known
flag"
This reverts commit ff32060f2ed37b68dc26256b05e2e69013b0ecfe.
This change is incorrect as we don't want to mark the PID as invalid but
only mark it as dead.
The change in question also breaks user level socket activation for
`podman.service` as the termination of the main `podman system service`
process is not properly handled, causing any application accessing the
socket to hang.
This is because the user-level `podman.service` unit also hosts two
non-main processes: `rootlessport` and `rootlessport-child` which causes
the `cgroup_good` check to still succeed.
The original submitter of this commit is recommended to find another
more correct way to fix the cgroupsv1 issue on CentOS 8.
(cherry picked from commit 996b00ede87d6a870332e63974a7d4def3c2f1b0)
Resolves: #2225667
Reverts: #2210237
---
src/core/service.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/src/core/service.c b/src/core/service.c
index e5127a4ccf..1e14cdc6ca 100644
--- a/src/core/service.c
+++ b/src/core/service.c
@@ -3507,7 +3507,6 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
return;
s->main_pid = 0;
- s->main_pid_known = false;
exec_status_exit(&s->main_exec_status, &s->exec_context, pid, code, status);
if (s->main_command) {

@ -0,0 +1,42 @@
From 3f2e5cdddd0a11947b493143fbf2ac3c18c9a082 Mon Sep 17 00:00:00 2001
From: Frantisek Sumsal <frantisek@sumsal.cz>
Date: Thu, 27 Jul 2023 13:20:17 +0200
Subject: [PATCH] ci: explicitly install python3-lldb-$COMPILER_VERSION
To avoid apt complaining:
+ apt-get -y install clang-15 lldb-15 lld-15 clangd-15
Reading package lists...
Building dependency tree...
Reading state information...
Some packages could not be installed. This may mean that you have
requested an impossible situation or if you are using the unstable
distribution that some required packages have not yet been created
or been moved out of Incoming.
The following information may help to resolve the situation:
The following packages have unmet dependencies:
python3-lldb-14 : Conflicts: python3-lldb-x.y
python3-lldb-15 : Conflicts: python3-lldb-x.y
E: Error, pkgProblemResolver::Resolve generated breaks, this may be caused by held packages.
(cherry picked from commit c5afbac31bb33e7b1f4d59b253425af991a630a4)
Related: #2225667
---
.github/workflows/build_test.sh | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/build_test.sh b/.github/workflows/build_test.sh
index b60db29efc..745d2e5cbd 100755
--- a/.github/workflows/build_test.sh
+++ b/.github/workflows/build_test.sh
@@ -86,7 +86,7 @@ if [[ "$COMPILER" == clang ]]; then
"$RELEASE" "$RELEASE" "$COMPILER_VERSION" >/etc/apt/sources.list.d/llvm-toolchain.list
fi
- PACKAGES+=("clang-$COMPILER_VERSION" "lldb-$COMPILER_VERSION" "lld-$COMPILER_VERSION" "clangd-$COMPILER_VERSION")
+ PACKAGES+=("clang-$COMPILER_VERSION" "lldb-$COMPILER_VERSION" "python3-lldb-$COMPILER_VERSION" "lld-$COMPILER_VERSION" "clangd-$COMPILER_VERSION")
elif [[ "$COMPILER" == gcc ]]; then
CC="gcc-$COMPILER_VERSION"
CXX="g++-$COMPILER_VERSION"

@ -0,0 +1,83 @@
From df138e1005d2eab39f55aea3bd128b660e1e6a15 Mon Sep 17 00:00:00 2001
From: Jan Macku <jamacku@redhat.com>
Date: Tue, 1 Aug 2023 16:18:06 +0200
Subject: [PATCH] doc: add downstream CONTRIBUTING document
rhel-only
Related: #2170883
---
CONTRIBUTING.md | 64 +++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 64 insertions(+)
create mode 100644 CONTRIBUTING.md
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000000..86a742ea43
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,64 @@
+# Contributing
+
+Welcome to systemd source-git for CentOS Stream and RHEL. When contributing, please follow the guide below.
+
+## Workflow
+
+```mermaid
+flowchart LR
+ A(Issue) --> B{is fixed\nupstream}
+ B -->|YES| C(backport\nupstream patch)
+ B -->|NO| D(upstream\nsubmit issue or PR)
+ D --> E{accepted\nand fixed}
+ E -->|YES| C
+ E -->|NO| F(rhel-only patch) --> G
+ C --> G(submit PR)
+```
+
+## Filing issues
+
+When you find an issue with systemd used in CentOS Stream or RHEL, please file an issue by using Bugzilla ticket systemd - [link](https://bugzilla.redhat.com/enter_bug.cgi?classification=Red%20Hat)
+GitHub Issues are not supported tracking system. If your issue is reproducible using the latest upstream version of systemd, please consider creating [upstream issue](https://github.com/systemd/systemd/issues/new/choose).
+
+## Posting Pull Requests
+
+Every Pull Request has to comply with the following rules:
+
+- Each commit has to reference [upstream](https://github.com/systemd/systemd) commit.
+- Each commit has to reference the approved issue/tracker.
+- Pull requests have to pass mandatory CI validation and testing
+- Pull requests have to be approved by at least one systemd downstream maintainer
+
+### Upstream reference
+
+When doing a back-port of an upstream commit, always use `cherry-pick -x <sha>`. Consider proposing a change upstream first when an upstream commit doesn't exist.
+If the change isn't upstream relevant or accepted by upstream, mark the commit with the `rhel-only` string.
+
+```md
+doc: Fix TYPO
+
+rhel-only
+
+Resolves: #1234567
+```
+
+### Issue reference
+
+Each commit has to reference the relevant approved systemd issue (see: [Filling issues section](#filing-issues)). For referencing issues, we use the following keywords:
+
+- **Resolves** for commits that directly resolve issues described in a referenced tracker
+- **Relates** for commits related to the referenced issue, but they don't fix it. Usually, tests and documentation.
+- **Reverts** for commits that reverts previously merged commit
+
+```md
+doc: Fix TYPO
+
+(cherry picked from commit c5afbac31bb33e7b1f4d59b253425af991a630a4)
+
+Resolves: #1234567
+```
+
+### Validation and testing
+
+Each Pull Request has to pass all enabled tests that are automatically run using GitHub Actions, CentOS Stream CI, and others.
+If CI failure is unrelated to the change introduced in Pull Request, the downstream maintainer will set the `ci-waived` label and explain why CI was waived.

@ -0,0 +1,57 @@
From 2c849b9750ff4978a865e2bb377af69a86038da4 Mon Sep 17 00:00:00 2001
From: Jan Macku <jamacku@redhat.com>
Date: Tue, 8 Aug 2023 11:37:32 +0200
Subject: [PATCH] doc: improve CONTRIBUTING document
based on feedback from: https://github.com/redhat-plumbers/systemd-rhel8/pull/407
rhel-only
Related: #2170883
---
CONTRIBUTING.md | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 86a742ea43..361366d899 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -17,7 +17,8 @@ flowchart LR
## Filing issues
-When you find an issue with systemd used in CentOS Stream or RHEL, please file an issue by using Bugzilla ticket systemd - [link](https://bugzilla.redhat.com/enter_bug.cgi?classification=Red%20Hat)
+When you find an issue with systemd used in CentOS Stream or RHEL, please file an issue in [Jira ticket system](https://issues.redhat.com/secure/CreateIssue!default.jspa) (set Project to **RHEL** and Component to **systemd**).
+
GitHub Issues are not supported tracking system. If your issue is reproducible using the latest upstream version of systemd, please consider creating [upstream issue](https://github.com/systemd/systemd/issues/new/choose).
## Posting Pull Requests
@@ -39,7 +40,7 @@ doc: Fix TYPO
rhel-only
-Resolves: #1234567
+Resolves: RHEL-678
```
### Issue reference
@@ -47,15 +48,17 @@ Resolves: #1234567
Each commit has to reference the relevant approved systemd issue (see: [Filling issues section](#filing-issues)). For referencing issues, we use the following keywords:
- **Resolves** for commits that directly resolve issues described in a referenced tracker
-- **Relates** for commits related to the referenced issue, but they don't fix it. Usually, tests and documentation.
+- **Related** for commits related to the referenced issue, but they don't fix it. Usually, tests and documentation.
- **Reverts** for commits that reverts previously merged commit
+When referencing issues, use following structure: `<keyword>: <issue ID>`. See the example below:
+
```md
doc: Fix TYPO
(cherry picked from commit c5afbac31bb33e7b1f4d59b253425af991a630a4)
-Resolves: #1234567
+Resolves: RHEL-678
```
### Validation and testing

@ -0,0 +1,25 @@
From eff259c8c7677bbbe64890873bd64349871dd6c5 Mon Sep 17 00:00:00 2001
From: Jan Macku <jamacku@redhat.com>
Date: Tue, 8 Aug 2023 13:07:06 +0200
Subject: [PATCH] doc: use link with prefilled Jira issue
rhel-only
Related: #2170883
---
CONTRIBUTING.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 361366d899..1de2b88995 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -17,7 +17,7 @@ flowchart LR
## Filing issues
-When you find an issue with systemd used in CentOS Stream or RHEL, please file an issue in [Jira ticket system](https://issues.redhat.com/secure/CreateIssue!default.jspa) (set Project to **RHEL** and Component to **systemd**).
+When you find an issue with systemd used in CentOS Stream or RHEL, please file an issue in [Jira ticket system](https://issues.redhat.com/secure/CreateIssueDetails!init.jspa?pid=12332745&issuetype=1&components=12380515).
GitHub Issues are not supported tracking system. If your issue is reproducible using the latest upstream version of systemd, please consider creating [upstream issue](https://github.com/systemd/systemd/issues/new/choose).

@ -0,0 +1,52 @@
From 581094db0528e22af351912849474ad322502c28 Mon Sep 17 00:00:00 2001
From: Jan Macku <jamacku@redhat.com>
Date: Thu, 10 Aug 2023 15:16:29 +0200
Subject: [PATCH] docs: link downstream CONTRIBUTING in README
This should increase the visibility of the downstream CONTRIBUTING.
Also fix some wording and update links.
rhel-only
Related: #2170883
---
CONTRIBUTING.md | 4 ++--
README.md | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 1de2b88995..bd17067be2 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -17,7 +17,7 @@ flowchart LR
## Filing issues
-When you find an issue with systemd used in CentOS Stream or RHEL, please file an issue in [Jira ticket system](https://issues.redhat.com/secure/CreateIssueDetails!init.jspa?pid=12332745&issuetype=1&components=12380515).
+When you find an issue with systemd used in **CentOS Stream** or **RHEL**, please file an issue in Red Hat [Jira ticket system](https://issues.redhat.com/secure/CreateIssueDetails!init.jspa?pid=12332745&issuetype=1&components=12380515&priority=10300).
GitHub Issues are not supported tracking system. If your issue is reproducible using the latest upstream version of systemd, please consider creating [upstream issue](https://github.com/systemd/systemd/issues/new/choose).
@@ -51,7 +51,7 @@ Each commit has to reference the relevant approved systemd issue (see: [Filling
- **Related** for commits related to the referenced issue, but they don't fix it. Usually, tests and documentation.
- **Reverts** for commits that reverts previously merged commit
-When referencing issues, use following structure: `<keyword>: <issue ID>`. See the example below:
+When referencing issues, use the following structure: `<keyword>: <issue ID>`. See the example below:
```md
doc: Fix TYPO
diff --git a/README.md b/README.md
index e507c4cb57..11a1b38038 100644
--- a/README.md
+++ b/README.md
@@ -30,7 +30,7 @@ Please see the [Code Map](docs/ARCHITECTURE.md) for information about this repos
Please see the [Hacking guide](docs/HACKING.md) for information on how to hack on systemd and test your modifications.
-Please see our [Contribution Guidelines](docs/CONTRIBUTING.md) for more information about filing GitHub Issues and posting GitHub Pull Requests.
+Please see our [Contribution Guidelines](CONTRIBUTING.md) for more information about filing GitHub Issues and posting GitHub Pull Requests.
When preparing patches for systemd, please follow our [Coding Style Guidelines](docs/CODING_STYLE.md).

@ -0,0 +1,51 @@
From b544c7bfd7812458516d29a11511498ece02b9ee Mon Sep 17 00:00:00 2001
From: Ilya Leoshkevich <iii@linux.ibm.com>
Date: Mon, 30 Jan 2023 21:21:48 +0100
Subject: [PATCH] bpf: fix restrict_fs on s390x
Linux kernel's bpf-next contains BPF LSM support for s390x. systemd's
test-bpf-lsm currently fails with this kernel.
This is an endianness issue: in the restrict_fs bpf program,
magic_number has type unsigned long (64 bits on s390x), but magic_map
keys are uint32_t (32 bits). Accessing magic_map using 64-bit keys may
work by accident on little-endian systems, but fails hard on big-endian
ones.
Fix by casting magic_number to uint32_t.
(cherry picked from commit 907046282c27ee2ced5e22abb80ed8df2e157baf)
Resolves: #2230364
---
src/core/bpf/restrict_fs/restrict-fs.bpf.c | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/src/core/bpf/restrict_fs/restrict-fs.bpf.c b/src/core/bpf/restrict_fs/restrict-fs.bpf.c
index 522a029785..eb5ed3e7fe 100644
--- a/src/core/bpf/restrict_fs/restrict-fs.bpf.c
+++ b/src/core/bpf/restrict_fs/restrict-fs.bpf.c
@@ -39,16 +39,20 @@ struct {
SEC("lsm/file_open")
int BPF_PROG(restrict_filesystems, struct file *file, int ret)
{
- unsigned long magic_number;
+ unsigned long raw_magic_number;
uint64_t cgroup_id;
- uint32_t *value, *magic_map, zero = 0, *is_allow;
+ uint32_t *value, *magic_map, magic_number, zero = 0, *is_allow;
/* ret is the return value from the previous BPF program or 0 if it's
* the first hook */
if (ret != 0)
return ret;
- BPF_CORE_READ_INTO(&magic_number, file, f_inode, i_sb, s_magic);
+ BPF_CORE_READ_INTO(&raw_magic_number, file, f_inode, i_sb, s_magic);
+ /* super_block.s_magic is unsigned long, but magic_map keys are
+ * uint32_t. Using s_magic as-is would fail on big-endian systems,
+ * which have 64-bit unsigned long. So cast it. */
+ magic_number = (uint32_t)raw_magic_number;
cgroup_id = bpf_get_current_cgroup_id();

@ -0,0 +1,24 @@
From fb3db0b1e27b2e60b86677907c761cb6d0a31c5e Mon Sep 17 00:00:00 2001
From: Jan Macku <jamacku@redhat.com>
Date: Mon, 14 Aug 2023 15:44:11 +0200
Subject: [PATCH] udev/net_id: use naming scheme for RHEL-9.3
rhel-only
Resolves: #2231845
---
src/shared/netif-naming-scheme.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/shared/netif-naming-scheme.c b/src/shared/netif-naming-scheme.c
index d846c794a8..0f50533279 100644
--- a/src/shared/netif-naming-scheme.c
+++ b/src/shared/netif-naming-scheme.c
@@ -28,6 +28,7 @@ static const NamingScheme naming_schemes[] = {
{ "rhel-9.0", NAMING_RHEL_9_0 },
{ "rhel-9.1", NAMING_RHEL_9_1 },
{ "rhel-9.2", NAMING_RHEL_9_2 },
+ { "rhel-9.3", NAMING_RHEL_9_3 },
/* … add more schemes here, as the logic to name devices is updated … */
EXTRA_NET_NAMING_MAP

@ -0,0 +1,46 @@
From 87e554ca8567647afef3ba79f75bc98d67716fdb Mon Sep 17 00:00:00 2001
From: Daan De Meyer <daan.j.demeyer@gmail.com>
Date: Tue, 23 May 2023 16:24:47 +0200
Subject: [PATCH] core/timer: Always use inactive_exit_timestamp if it is set
If we're doing a daemon-reload, we'll be going from TIMER_DEAD => TIMER_WAITING,
so we won't use inactive_exit_timestamp because TIMER_DEAD != UNIT_ACTIVE, even
though inactive_exit_timestamp is serialized/deserialized and will be valid after
the daemon-reload.
This issue can lead to timers never firing as we'll always calculate the next
elapse based on the current realtime on daemon-reload, so if daemon-reload happens
often enough, the elapse interval will be moved into the future every time, which
means the timer will never trigger.
To fix the issue, let's always use inactive_exit_timestamp if it is set, and only
fall back to the current realtime if it is not set.
(cherry picked from commit 6546045fa0bf84737bd8b2e1e8bf7dd3941d8352)
Resolves: #2211065
---
src/core/timer.c | 10 ++++------
1 file changed, 4 insertions(+), 6 deletions(-)
diff --git a/src/core/timer.c b/src/core/timer.c
index b6810c8599..711500313d 100644
--- a/src/core/timer.c
+++ b/src/core/timer.c
@@ -401,12 +401,10 @@ static void timer_enter_waiting(Timer *t, bool time_change) {
if (t->last_trigger.realtime > 0)
b = t->last_trigger.realtime;
- else {
- if (state_translation_table[t->state] == UNIT_ACTIVE)
- b = UNIT(t)->inactive_exit_timestamp.realtime;
- else
- b = ts.realtime;
- }
+ else if (dual_timestamp_is_set(&UNIT(t)->inactive_exit_timestamp))
+ b = UNIT(t)->inactive_exit_timestamp.realtime;
+ else
+ b = ts.realtime;
r = calendar_spec_next_usec(v->calendar_spec, b, &v->next_elapse);
if (r < 0)

@ -0,0 +1,25 @@
From 9974ff3bce3b309f086585929b21ac29d4d4f582 Mon Sep 17 00:00:00 2001
From: Daan De Meyer <daan.j.demeyer@gmail.com>
Date: Wed, 24 May 2023 11:41:37 +0200
Subject: [PATCH] timer: Use dual_timestamp_is_set() in one more place
(cherry picked from commit e21f75afcd95a46261a36a2614712eff6bc119f4)
Related: #2211065
---
src/core/timer.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/core/timer.c b/src/core/timer.c
index 711500313d..60e8fea79f 100644
--- a/src/core/timer.c
+++ b/src/core/timer.c
@@ -399,7 +399,7 @@ static void timer_enter_waiting(Timer *t, bool time_change) {
* to that. If we don't, just start from
* the activation time. */
- if (t->last_trigger.realtime > 0)
+ if (dual_timestamp_is_set(&t->last_trigger))
b = t->last_trigger.realtime;
else if (dual_timestamp_is_set(&UNIT(t)->inactive_exit_timestamp))
b = UNIT(t)->inactive_exit_timestamp.realtime;

@ -0,0 +1,77 @@
From 5c1e6fb6440f86d59720d2d3673eb81c9255c5e8 Mon Sep 17 00:00:00 2001
From: Mike Yuan <me@yhndnzj.com>
Date: Thu, 11 May 2023 13:05:39 +0800
Subject: [PATCH] loginctl: list-users: also show state
(cherry picked from commit bae05711b5d06f330423f69d4d6500c907b8d322)
Related: #2209912
---
src/login/loginctl.c | 35 ++++++++++++++++++++++++++++++-----
1 file changed, 30 insertions(+), 5 deletions(-)
diff --git a/src/login/loginctl.c b/src/login/loginctl.c
index 4dbfa0db44..8b72ebae57 100644
--- a/src/login/loginctl.c
+++ b/src/login/loginctl.c
@@ -205,13 +205,15 @@ static int list_users(int argc, char *argv[], void *userdata) {
if (r < 0)
return bus_log_parse_error(r);
- table = table_new("uid", "user", "linger");
+ table = table_new("uid", "user", "linger", "state");
if (!table)
return log_oom();
(void) table_set_align_percent(table, TABLE_HEADER_CELL(0), 100);
for (;;) {
+ _cleanup_(sd_bus_error_free) sd_bus_error error_property = SD_BUS_ERROR_NULL;
+ _cleanup_free_ char *state = NULL;
const char *user, *object;
uint32_t uid;
int linger;
@@ -227,16 +229,39 @@ static int list_users(int argc, char *argv[], void *userdata) {
object,
"org.freedesktop.login1.User",
"Linger",
- &error,
+ &error_property,
'b',
&linger);
- if (r < 0)
- return log_error_errno(r, "Failed to get linger status: %s", bus_error_message(&error, r));
+ if (r < 0) {
+ if (sd_bus_error_has_name(&error_property, SD_BUS_ERROR_UNKNOWN_OBJECT))
+ /* The user logged out when we're querying the property */
+ continue;
+
+ return log_error_errno(r, "Failed to get linger status for user %s: %s",
+ user, bus_error_message(&error_property, r));
+ }
+
+ r = sd_bus_get_property_string(bus,
+ "org.freedesktop.login1",
+ object,
+ "org.freedesktop.login1.User",
+ "State",
+ &error_property,
+ &state);
+ if (r < 0) {
+ if (sd_bus_error_has_name(&error_property, SD_BUS_ERROR_UNKNOWN_OBJECT))
+ /* The user logged out when we're querying the property */
+ continue;
+
+ return log_error_errno(r, "Failed to get state for user %s: %s",
+ user, bus_error_message(&error_property, r));
+ }
r = table_add_many(table,
TABLE_UID, (uid_t) uid,
TABLE_STRING, user,
- TABLE_BOOLEAN, linger);
+ TABLE_BOOLEAN, linger,
+ TABLE_STRING, state);
if (r < 0)
return table_log_add_error(r);
}

@ -0,0 +1,67 @@
From 327f02ddb69c6f908db86e250d240c1036b5c394 Mon Sep 17 00:00:00 2001
From: Mike Yuan <me@yhndnzj.com>
Date: Thu, 11 May 2023 13:17:59 +0800
Subject: [PATCH] loginctl: list-sessions: minor modernization
(cherry picked from commit 486f61a8c908d63c47625c352e456d80c88b4687)
Related: #2209912
---
src/login/loginctl.c | 37 +++++++++++++++++++------------------
1 file changed, 19 insertions(+), 18 deletions(-)
diff --git a/src/login/loginctl.c b/src/login/loginctl.c
index 8b72ebae57..9c21b97bb5 100644
--- a/src/login/loginctl.c
+++ b/src/login/loginctl.c
@@ -141,9 +141,9 @@ static int list_sessions(int argc, char *argv[], void *userdata) {
(void) table_set_align_percent(table, TABLE_HEADER_CELL(1), 100);
for (;;) {
- _cleanup_(sd_bus_error_free) sd_bus_error error_tty = SD_BUS_ERROR_NULL;
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply_tty = NULL;
- const char *id, *user, *seat, *object, *tty = NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error_property = SD_BUS_ERROR_NULL;
+ _cleanup_free_ char *tty = NULL;
+ const char *id, *user, *seat, *object;
uint32_t uid;
r = sd_bus_message_read(reply, "(susso)", &id, &uid, &user, &seat, &object);
@@ -152,21 +152,22 @@ static int list_sessions(int argc, char *argv[], void *userdata) {
if (r == 0)
break;
- r = sd_bus_get_property(
- bus,
- "org.freedesktop.login1",
- object,
- "org.freedesktop.login1.Session",
- "TTY",
- &error_tty,
- &reply_tty,
- "s");
- if (r < 0)
- log_warning_errno(r, "Failed to get TTY for session %s: %s", id, bus_error_message(&error_tty, r));
- else {
- r = sd_bus_message_read(reply_tty, "s", &tty);
- if (r < 0)
- return bus_log_parse_error(r);
+ r = sd_bus_get_property_string(bus,
+ "org.freedesktop.login1",
+ object,
+ "org.freedesktop.login1.Session",
+ "TTY",
+ &error_property,
+ &tty);
+ if (r < 0) {
+ if (sd_bus_error_has_name(&error_property, SD_BUS_ERROR_UNKNOWN_OBJECT))
+ /* The session is already closed when we're querying the property */
+ continue;
+
+ log_warning_errno(r, "Failed to get TTY for session %s, ignoring: %s",
+ id, bus_error_message(&error_property, r));
+
+ sd_bus_error_free(&error_property);
}
r = table_add_many(table,

@ -0,0 +1,65 @@
From a6b868dd39b60199862e306a272b54d2ef617317 Mon Sep 17 00:00:00 2001
From: Mike Yuan <me@yhndnzj.com>
Date: Thu, 11 May 2023 13:21:37 +0800
Subject: [PATCH] loginctl: list-sessions: also show state
(cherry picked from commit 8b6c039a1ac73da006bfe9d5735515bba12ef3c4)
Related: #2209912
---
src/login/loginctl.c | 23 ++++++++++++++++++++---
1 file changed, 20 insertions(+), 3 deletions(-)
diff --git a/src/login/loginctl.c b/src/login/loginctl.c
index 9c21b97bb5..0bea31796d 100644
--- a/src/login/loginctl.c
+++ b/src/login/loginctl.c
@@ -132,7 +132,7 @@ static int list_sessions(int argc, char *argv[], void *userdata) {
if (r < 0)
return bus_log_parse_error(r);
- table = table_new("session", "uid", "user", "seat", "tty");
+ table = table_new("session", "uid", "user", "seat", "tty", "state");
if (!table)
return log_oom();
@@ -142,7 +142,7 @@ static int list_sessions(int argc, char *argv[], void *userdata) {
for (;;) {
_cleanup_(sd_bus_error_free) sd_bus_error error_property = SD_BUS_ERROR_NULL;
- _cleanup_free_ char *tty = NULL;
+ _cleanup_free_ char *tty = NULL, *state = NULL;
const char *id, *user, *seat, *object;
uint32_t uid;
@@ -170,12 +170,29 @@ static int list_sessions(int argc, char *argv[], void *userdata) {
sd_bus_error_free(&error_property);
}
+ r = sd_bus_get_property_string(bus,
+ "org.freedesktop.login1",
+ object,
+ "org.freedesktop.login1.Session",
+ "State",
+ &error_property,
+ &state);
+ if (r < 0) {
+ if (sd_bus_error_has_name(&error_property, SD_BUS_ERROR_UNKNOWN_OBJECT))
+ /* The session is already closed when we're querying the property */
+ continue;
+
+ return log_error_errno(r, "Failed to get state for session %s: %s",
+ id, bus_error_message(&error_property, r));
+ }
+
r = table_add_many(table,
TABLE_STRING, id,
TABLE_UID, (uid_t) uid,
TABLE_STRING, user,
TABLE_STRING, seat,
- TABLE_STRING, strna(tty));
+ TABLE_STRING, strna(tty),
+ TABLE_STRING, state);
if (r < 0)
return table_log_add_error(r);
}

@ -0,0 +1,59 @@
From 89f043cce92c336105e1b36b9eac4ba3bd1333b9 Mon Sep 17 00:00:00 2001
From: Mike Yuan <me@yhndnzj.com>
Date: Mon, 15 May 2023 13:45:33 +0800
Subject: [PATCH] test: add test for state in loginctl list-{users,sessions}
(cherry picked from commit 306ff2e29798f571fba573577abaeb812f7e3166)
Related: #2209912
---
test/units/testsuite-35.sh | 18 ++++++++++++++----
1 file changed, 14 insertions(+), 4 deletions(-)
diff --git a/test/units/testsuite-35.sh b/test/units/testsuite-35.sh
index 85925f2471..c9b2417bb7 100755
--- a/test/units/testsuite-35.sh
+++ b/test/units/testsuite-35.sh
@@ -520,7 +520,7 @@ test_session_properties() {
/usr/lib/systemd/tests/manual/test-session-properties "/org/freedesktop/login1/session/_3${s?}"
}
-test_list_users() {
+test_list_users_sessions() {
if [[ ! -c /dev/tty2 ]]; then
echo "/dev/tty2 does not exist, skipping test ${FUNCNAME[0]}."
return
@@ -531,12 +531,22 @@ test_list_users() {
assert_eq "$(loginctl list-users --no-legend | awk '$2 == "logind-test-user" { print $1 }')" "$(id -ru logind-test-user)"
assert_eq "$(loginctl list-users --no-legend | awk '$2 == "logind-test-user" { print $3 }')" no
+ assert_eq "$(loginctl list-users --no-legend | awk '$2 == "logind-test-user" { print $4 }')" active
+ assert_eq "$(loginctl list-sessions --no-legend | awk '$3 == "logind-test-user" { print $6 }')" active
loginctl enable-linger logind-test-user
-
assert_eq "$(loginctl list-users --no-legend | awk '$2 == "logind-test-user" { print $3 }')" yes
-}
+ for s in $(loginctl list-sessions --no-legend | awk '$3 == "logind-test-user" { print $1 }'); do
+ loginctl terminate-session "$s"
+ done
+ if ! timeout 30 bash -c "while loginctl --no-legend | grep -q logind-test-user; do sleep 1; done"; then
+ echo "WARNING: session for logind-test-user still active, ignoring."
+ return
+ fi
+
+ assert_eq "$(loginctl list-users --no-legend | awk '$2 == "logind-test-user" { print $4 }')" lingering
+}
teardown_stop_idle_session() (
set +eux
@@ -585,7 +595,7 @@ test_sanity_check
test_session
test_lock_idle_action
test_session_properties
-test_list_users
+test_list_users_sessions
test_stop_idle_session
touch /testok

@ -0,0 +1,45 @@
From 3d3681dd81ad5bbae8eab7c1b4487f97678cc875 Mon Sep 17 00:00:00 2001
From: Frantisek Sumsal <frantisek@sumsal.cz>
Date: Mon, 22 May 2023 15:08:29 +0200
Subject: [PATCH] test: add a missing session activation
Otherwise test_list_user_sessions() would fail unless ordered after
test_session(), which activates the session.
(cherry picked from commit 587ae50d5529d4f312cc95ce8f0ece688c9672dc)
Related: #2209912
---
test/units/testsuite-35.sh | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/test/units/testsuite-35.sh b/test/units/testsuite-35.sh
index c9b2417bb7..09009fc257 100755
--- a/test/units/testsuite-35.sh
+++ b/test/units/testsuite-35.sh
@@ -529,6 +529,9 @@ test_list_users_sessions() {
trap cleanup_session RETURN
create_session
+ # Activate the session
+ loginctl activate "$(loginctl --no-legend | awk '$3 == "logind-test-user" { print $1 }')"
+
assert_eq "$(loginctl list-users --no-legend | awk '$2 == "logind-test-user" { print $1 }')" "$(id -ru logind-test-user)"
assert_eq "$(loginctl list-users --no-legend | awk '$2 == "logind-test-user" { print $3 }')" no
assert_eq "$(loginctl list-users --no-legend | awk '$2 == "logind-test-user" { print $4 }')" active
@@ -586,6 +589,7 @@ EOF
: >/failed
setup_test_user
+test_list_users_sessions
test_enable_debug
test_properties
test_started
@@ -595,7 +599,6 @@ test_sanity_check
test_session
test_lock_idle_action
test_session_properties
-test_list_users_sessions
test_stop_idle_session
touch /testok

@ -0,0 +1,57 @@
From f515f2a2182e98a93b669ea744b3809be883d7fa Mon Sep 17 00:00:00 2001
From: David Tardon <dtardon@redhat.com>
Date: Fri, 19 May 2023 14:21:44 +0200
Subject: [PATCH] test: extend test for loginctl list-*
(cherry picked from commit 98a155962d384ad2dd1cd11449a0143b5cfae8ef)
Related: #2209912
---
test/units/testsuite-35.sh | 17 ++++++++++++++---
1 file changed, 14 insertions(+), 3 deletions(-)
diff --git a/test/units/testsuite-35.sh b/test/units/testsuite-35.sh
index 09009fc257..c817bc82bb 100755
--- a/test/units/testsuite-35.sh
+++ b/test/units/testsuite-35.sh
@@ -520,7 +520,9 @@ test_session_properties() {
/usr/lib/systemd/tests/manual/test-session-properties "/org/freedesktop/login1/session/_3${s?}"
}
-test_list_users_sessions() {
+test_list_users_sessions_seats() {
+ local session seat
+
if [[ ! -c /dev/tty2 ]]; then
echo "/dev/tty2 does not exist, skipping test ${FUNCNAME[0]}."
return
@@ -532,10 +534,19 @@ test_list_users_sessions() {
# Activate the session
loginctl activate "$(loginctl --no-legend | awk '$3 == "logind-test-user" { print $1 }')"
+ session=$(loginctl list-sessions --no-legend | awk '$3 == "logind-test-user" { print $1 }')
+ : check that we got a valid session id
+ busctl get-property org.freedesktop.login1 "/org/freedesktop/login1/session/_3${session?}" org.freedesktop.login1.Session Id
+ assert_eq "$(loginctl list-sessions --no-legend | awk '$3 == "logind-test-user" { print $2 }')" "$(id -ru logind-test-user)"
+ seat=$(loginctl list-sessions --no-legend | awk '$3 == "logind-test-user" { print $4 }')
+ assert_eq "$(loginctl list-sessions --no-legend | awk '$3 == "logind-test-user" { print $5 }')" tty2
+ assert_eq "$(loginctl list-sessions --no-legend | awk '$3 == "logind-test-user" { print $6 }')" active
+
+ loginctl list-seats --no-legend | grep -Fwq "${seat?}"
+
assert_eq "$(loginctl list-users --no-legend | awk '$2 == "logind-test-user" { print $1 }')" "$(id -ru logind-test-user)"
assert_eq "$(loginctl list-users --no-legend | awk '$2 == "logind-test-user" { print $3 }')" no
assert_eq "$(loginctl list-users --no-legend | awk '$2 == "logind-test-user" { print $4 }')" active
- assert_eq "$(loginctl list-sessions --no-legend | awk '$3 == "logind-test-user" { print $6 }')" active
loginctl enable-linger logind-test-user
assert_eq "$(loginctl list-users --no-legend | awk '$2 == "logind-test-user" { print $3 }')" yes
@@ -589,7 +600,7 @@ EOF
: >/failed
setup_test_user
-test_list_users_sessions
+test_list_users_sessions_seats
test_enable_debug
test_properties
test_started

@ -0,0 +1,66 @@
From d2a9e9536aa881c130af938ccdc444252fff6412 Mon Sep 17 00:00:00 2001
From: David Tardon <dtardon@redhat.com>
Date: Tue, 23 May 2023 10:48:15 +0200
Subject: [PATCH] loginctl: shorten variable name
(cherry picked from commit 86f128558d57586bd28c55eb63968eab3dc4b36e)
Related: #2209912
---
src/login/loginctl.c | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/src/login/loginctl.c b/src/login/loginctl.c
index 0bea31796d..fad09cbe55 100644
--- a/src/login/loginctl.c
+++ b/src/login/loginctl.c
@@ -141,7 +141,7 @@ static int list_sessions(int argc, char *argv[], void *userdata) {
(void) table_set_align_percent(table, TABLE_HEADER_CELL(1), 100);
for (;;) {
- _cleanup_(sd_bus_error_free) sd_bus_error error_property = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error e = SD_BUS_ERROR_NULL;
_cleanup_free_ char *tty = NULL, *state = NULL;
const char *id, *user, *seat, *object;
uint32_t uid;
@@ -157,17 +157,17 @@ static int list_sessions(int argc, char *argv[], void *userdata) {
object,
"org.freedesktop.login1.Session",
"TTY",
- &error_property,
+ &e,
&tty);
if (r < 0) {
- if (sd_bus_error_has_name(&error_property, SD_BUS_ERROR_UNKNOWN_OBJECT))
+ if (sd_bus_error_has_name(&e, SD_BUS_ERROR_UNKNOWN_OBJECT))
/* The session is already closed when we're querying the property */
continue;
log_warning_errno(r, "Failed to get TTY for session %s, ignoring: %s",
- id, bus_error_message(&error_property, r));
+ id, bus_error_message(&e, r));
- sd_bus_error_free(&error_property);
+ sd_bus_error_free(&e);
}
r = sd_bus_get_property_string(bus,
@@ -175,15 +175,15 @@ static int list_sessions(int argc, char *argv[], void *userdata) {
object,
"org.freedesktop.login1.Session",
"State",
- &error_property,
+ &e,
&state);
if (r < 0) {
- if (sd_bus_error_has_name(&error_property, SD_BUS_ERROR_UNKNOWN_OBJECT))
+ if (sd_bus_error_has_name(&e, SD_BUS_ERROR_UNKNOWN_OBJECT))
/* The session is already closed when we're querying the property */
continue;
return log_error_errno(r, "Failed to get state for session %s: %s",
- id, bus_error_message(&error_property, r));
+ id, bus_error_message(&e, r));
}
r = table_add_many(table,

@ -0,0 +1,150 @@
From f8a5e518f0bfd44b37d3b52a8e88e67ced716889 Mon Sep 17 00:00:00 2001
From: David Tardon <dtardon@redhat.com>
Date: Fri, 19 May 2023 13:33:58 +0200
Subject: [PATCH] loginctl: use bus_map_all_properties
(cherry picked from commit 5b7d1536d0c2ccf0b7688490f31c92c1e766ea44)
Related: #2209912
---
src/login/loginctl.c | 84 ++++++++++++++++++--------------------------
1 file changed, 34 insertions(+), 50 deletions(-)
diff --git a/src/login/loginctl.c b/src/login/loginctl.c
index fad09cbe55..9a09bfc82c 100644
--- a/src/login/loginctl.c
+++ b/src/login/loginctl.c
@@ -53,6 +53,27 @@ static OutputMode arg_output = OUTPUT_SHORT;
STATIC_DESTRUCTOR_REGISTER(arg_property, strv_freep);
+typedef struct SessionStatusInfo {
+ const char *id;
+ uid_t uid;
+ const char *name;
+ struct dual_timestamp timestamp;
+ unsigned vtnr;
+ const char *seat;
+ const char *tty;
+ const char *display;
+ bool remote;
+ const char *remote_host;
+ const char *remote_user;
+ const char *service;
+ pid_t leader;
+ const char *type;
+ const char *class;
+ const char *state;
+ const char *scope;
+ const char *desktop;
+} SessionStatusInfo;
+
static OutputFlags get_output_flags(void) {
return
@@ -114,6 +135,13 @@ static int show_table(Table *table, const char *word) {
}
static int list_sessions(int argc, char *argv[], void *userdata) {
+
+ static const struct bus_properties_map map[] = {
+ { "State", "s", NULL, offsetof(SessionStatusInfo, state) },
+ { "TTY", "s", NULL, offsetof(SessionStatusInfo, tty) },
+ {},
+ };
+
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
_cleanup_(table_unrefp) Table *table = NULL;
@@ -142,9 +170,10 @@ static int list_sessions(int argc, char *argv[], void *userdata) {
for (;;) {
_cleanup_(sd_bus_error_free) sd_bus_error e = SD_BUS_ERROR_NULL;
- _cleanup_free_ char *tty = NULL, *state = NULL;
const char *id, *user, *seat, *object;
uint32_t uid;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
+ SessionStatusInfo i = {};
r = sd_bus_message_read(reply, "(susso)", &id, &uid, &user, &seat, &object);
if (r < 0)
@@ -152,38 +181,14 @@ static int list_sessions(int argc, char *argv[], void *userdata) {
if (r == 0)
break;
- r = sd_bus_get_property_string(bus,
- "org.freedesktop.login1",
- object,
- "org.freedesktop.login1.Session",
- "TTY",
- &e,
- &tty);
+ r = bus_map_all_properties(bus, "org.freedesktop.login1", object, map, BUS_MAP_BOOLEAN_AS_BOOL, &e, &m, &i);
if (r < 0) {
if (sd_bus_error_has_name(&e, SD_BUS_ERROR_UNKNOWN_OBJECT))
/* The session is already closed when we're querying the property */
continue;
- log_warning_errno(r, "Failed to get TTY for session %s, ignoring: %s",
+ log_warning_errno(r, "Failed to get properties of session %s, ignoring: %s",
id, bus_error_message(&e, r));
-
- sd_bus_error_free(&e);
- }
-
- r = sd_bus_get_property_string(bus,
- "org.freedesktop.login1",
- object,
- "org.freedesktop.login1.Session",
- "State",
- &e,
- &state);
- if (r < 0) {
- if (sd_bus_error_has_name(&e, SD_BUS_ERROR_UNKNOWN_OBJECT))
- /* The session is already closed when we're querying the property */
- continue;
-
- return log_error_errno(r, "Failed to get state for session %s: %s",
- id, bus_error_message(&e, r));
}
r = table_add_many(table,
@@ -191,8 +196,8 @@ static int list_sessions(int argc, char *argv[], void *userdata) {
TABLE_UID, (uid_t) uid,
TABLE_STRING, user,
TABLE_STRING, seat,
- TABLE_STRING, strna(tty),
- TABLE_STRING, state);
+ TABLE_STRING, strna(i.tty),
+ TABLE_STRING, i.state);
if (r < 0)
return table_log_add_error(r);
}
@@ -375,27 +380,6 @@ static int show_unit_cgroup(sd_bus *bus, const char *interface, const char *unit
return 0;
}
-typedef struct SessionStatusInfo {
- const char *id;
- uid_t uid;
- const char *name;
- struct dual_timestamp timestamp;
- unsigned vtnr;
- const char *seat;
- const char *tty;
- const char *display;
- bool remote;
- const char *remote_host;
- const char *remote_user;
- const char *service;
- pid_t leader;
- const char *type;
- const char *class;
- const char *state;
- const char *scope;
- const char *desktop;
-} SessionStatusInfo;
-
typedef struct UserStatusInfo {
uid_t uid;
bool linger;

@ -0,0 +1,96 @@
From b4e164914c66eb8aeb71170c1d7615589783f467 Mon Sep 17 00:00:00 2001
From: David Tardon <dtardon@redhat.com>
Date: Fri, 19 May 2023 14:03:09 +0200
Subject: [PATCH] loginctl: show session idle status in list-sessions
(cherry picked from commit 556723e738b96a5c2b2d45a96b87b7b80e0c5664)
Resolves: #2209912
---
src/login/loginctl.c | 31 +++++++++++++++++++++----------
test/units/testsuite-35.sh | 2 ++
2 files changed, 23 insertions(+), 10 deletions(-)
diff --git a/src/login/loginctl.c b/src/login/loginctl.c
index 9a09bfc82c..967ae230ab 100644
--- a/src/login/loginctl.c
+++ b/src/login/loginctl.c
@@ -72,6 +72,8 @@ typedef struct SessionStatusInfo {
const char *state;
const char *scope;
const char *desktop;
+ bool idle_hint;
+ dual_timestamp idle_hint_timestamp;
} SessionStatusInfo;
static OutputFlags get_output_flags(void) {
@@ -137,8 +139,10 @@ static int show_table(Table *table, const char *word) {
static int list_sessions(int argc, char *argv[], void *userdata) {
static const struct bus_properties_map map[] = {
- { "State", "s", NULL, offsetof(SessionStatusInfo, state) },
- { "TTY", "s", NULL, offsetof(SessionStatusInfo, tty) },
+ { "IdleHint", "b", NULL, offsetof(SessionStatusInfo, idle_hint) },
+ { "IdleSinceHintMonotonic", "t", NULL, offsetof(SessionStatusInfo, idle_hint_timestamp.monotonic) },
+ { "State", "s", NULL, offsetof(SessionStatusInfo, state) },
+ { "TTY", "s", NULL, offsetof(SessionStatusInfo, tty) },
{},
};
@@ -160,7 +164,7 @@ static int list_sessions(int argc, char *argv[], void *userdata) {
if (r < 0)
return bus_log_parse_error(r);
- table = table_new("session", "uid", "user", "seat", "tty", "state");
+ table = table_new("session", "uid", "user", "seat", "tty", "state", "idle", "since");
if (!table)
return log_oom();
@@ -183,12 +187,11 @@ static int list_sessions(int argc, char *argv[], void *userdata) {
r = bus_map_all_properties(bus, "org.freedesktop.login1", object, map, BUS_MAP_BOOLEAN_AS_BOOL, &e, &m, &i);
if (r < 0) {
- if (sd_bus_error_has_name(&e, SD_BUS_ERROR_UNKNOWN_OBJECT))
- /* The session is already closed when we're querying the property */
- continue;
-
- log_warning_errno(r, "Failed to get properties of session %s, ignoring: %s",
- id, bus_error_message(&e, r));
+ log_full_errno(sd_bus_error_has_name(&e, SD_BUS_ERROR_UNKNOWN_OBJECT) ? LOG_DEBUG : LOG_WARNING,
+ r,
+ "Failed to get properties of session %s, ignoring: %s",
+ id, bus_error_message(&e, r));
+ continue;
}
r = table_add_many(table,
@@ -197,7 +200,15 @@ static int list_sessions(int argc, char *argv[], void *userdata) {
TABLE_STRING, user,
TABLE_STRING, seat,
TABLE_STRING, strna(i.tty),
- TABLE_STRING, i.state);
+ TABLE_STRING, i.state,
+ TABLE_BOOLEAN, i.idle_hint);
+ if (r < 0)
+ return table_log_add_error(r);
+
+ if (i.idle_hint)
+ r = table_add_cell(table, NULL, TABLE_TIMESTAMP_RELATIVE, &i.idle_hint_timestamp.monotonic);
+ else
+ r = table_add_cell(table, NULL, TABLE_EMPTY, NULL);
if (r < 0)
return table_log_add_error(r);
}
diff --git a/test/units/testsuite-35.sh b/test/units/testsuite-35.sh
index c817bc82bb..1863c535a4 100755
--- a/test/units/testsuite-35.sh
+++ b/test/units/testsuite-35.sh
@@ -541,6 +541,8 @@ test_list_users_sessions_seats() {
seat=$(loginctl list-sessions --no-legend | awk '$3 == "logind-test-user" { print $4 }')
assert_eq "$(loginctl list-sessions --no-legend | awk '$3 == "logind-test-user" { print $5 }')" tty2
assert_eq "$(loginctl list-sessions --no-legend | awk '$3 == "logind-test-user" { print $6 }')" active
+ assert_eq "$(loginctl list-sessions --no-legend | awk '$3 == "logind-test-user" { print $7 }')" no
+ assert_eq "$(loginctl list-sessions --no-legend | awk '$3 == "logind-test-user" { print $8 }')" ''
loginctl list-seats --no-legend | grep -Fwq "${seat?}"

@ -0,0 +1,184 @@
From 1cb097a7c664b253556b3b63b7899d76d7e4cba5 Mon Sep 17 00:00:00 2001
From: Mike Yuan <me@yhndnzj.com>
Date: Wed, 24 May 2023 19:42:03 +0800
Subject: [PATCH] loginctl: some modernizations
(cherry picked from commit c9443393b5a1e6f8941e04e2641135ab3936a8a0)
Related: #2209912
---
src/login/loginctl.c | 85 +++++++++++++++++++++++---------------------
1 file changed, 44 insertions(+), 41 deletions(-)
diff --git a/src/login/loginctl.c b/src/login/loginctl.c
index 967ae230ab..25e5787c11 100644
--- a/src/login/loginctl.c
+++ b/src/login/loginctl.c
@@ -57,7 +57,7 @@ typedef struct SessionStatusInfo {
const char *id;
uid_t uid;
const char *name;
- struct dual_timestamp timestamp;
+ dual_timestamp timestamp;
unsigned vtnr;
const char *seat;
const char *tty;
@@ -76,8 +76,36 @@ typedef struct SessionStatusInfo {
dual_timestamp idle_hint_timestamp;
} SessionStatusInfo;
-static OutputFlags get_output_flags(void) {
+typedef struct UserStatusInfo {
+ uid_t uid;
+ bool linger;
+ const char *name;
+ dual_timestamp timestamp;
+ const char *state;
+ char **sessions;
+ const char *display;
+ const char *slice;
+} UserStatusInfo;
+typedef struct SeatStatusInfo {
+ const char *id;
+ const char *active_session;
+ char **sessions;
+} SeatStatusInfo;
+
+static void user_status_info_done(UserStatusInfo *info) {
+ assert(info);
+
+ strv_free(info->sessions);
+}
+
+static void seat_status_info_done(SeatStatusInfo *info) {
+ assert(info);
+
+ strv_free(info->sessions);
+}
+
+static OutputFlags get_output_flags(void) {
return
FLAGS_SET(arg_print_flags, BUS_PRINT_PROPERTY_SHOW_EMPTY) * OUTPUT_SHOW_ALL |
(arg_full || !on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
@@ -86,8 +114,13 @@ static OutputFlags get_output_flags(void) {
static int get_session_path(sd_bus *bus, const char *session_id, sd_bus_error *error, char **path) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
- int r;
char *ans;
+ int r;
+
+ assert(bus);
+ assert(session_id);
+ assert(error);
+ assert(path);
r = bus_call_method(bus, bus_login_mgr, "GetSession", error, &reply, "s", session_id);
if (r < 0)
@@ -391,41 +424,13 @@ static int show_unit_cgroup(sd_bus *bus, const char *interface, const char *unit
return 0;
}
-typedef struct UserStatusInfo {
- uid_t uid;
- bool linger;
- const char *name;
- struct dual_timestamp timestamp;
- const char *state;
- char **sessions;
- const char *display;
- const char *slice;
-} UserStatusInfo;
-
-typedef struct SeatStatusInfo {
- const char *id;
- const char *active_session;
- char **sessions;
-} SeatStatusInfo;
-
-static void user_status_info_clear(UserStatusInfo *info) {
- if (info) {
- strv_free(info->sessions);
- zero(*info);
- }
-}
-
-static void seat_status_info_clear(SeatStatusInfo *info) {
- if (info) {
- strv_free(info->sessions);
- zero(*info);
- }
-}
-
static int prop_map_first_of_struct(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
const char *contents;
int r;
+ assert(bus);
+ assert(m);
+
r = sd_bus_message_peek_type(m, NULL, &contents);
if (r < 0)
return r;
@@ -473,7 +478,7 @@ static int prop_map_sessions_strv(sd_bus *bus, const char *member, sd_bus_messag
static int print_session_status_info(sd_bus *bus, const char *path, bool *new_line) {
- static const struct bus_properties_map map[] = {
+ static const struct bus_properties_map map[] = {
{ "Id", "s", NULL, offsetof(SessionStatusInfo, id) },
{ "Name", "s", NULL, offsetof(SessionStatusInfo, name) },
{ "TTY", "s", NULL, offsetof(SessionStatusInfo, tty) },
@@ -608,7 +613,7 @@ static int print_session_status_info(sd_bus *bus, const char *path, bool *new_li
static int print_user_status_info(sd_bus *bus, const char *path, bool *new_line) {
- static const struct bus_properties_map map[] = {
+ static const struct bus_properties_map map[] = {
{ "Name", "s", NULL, offsetof(UserStatusInfo, name) },
{ "Linger", "b", NULL, offsetof(UserStatusInfo, linger) },
{ "Slice", "s", NULL, offsetof(UserStatusInfo, slice) },
@@ -623,7 +628,7 @@ static int print_user_status_info(sd_bus *bus, const char *path, bool *new_line)
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
- _cleanup_(user_status_info_clear) UserStatusInfo i = {};
+ _cleanup_(user_status_info_done) UserStatusInfo i = {};
int r;
r = bus_map_all_properties(bus, "org.freedesktop.login1", path, map, BUS_MAP_BOOLEAN_AS_BOOL, &error, &m, &i);
@@ -685,7 +690,7 @@ static int print_user_status_info(sd_bus *bus, const char *path, bool *new_line)
static int print_seat_status_info(sd_bus *bus, const char *path, bool *new_line) {
- static const struct bus_properties_map map[] = {
+ static const struct bus_properties_map map[] = {
{ "Id", "s", NULL, offsetof(SeatStatusInfo, id) },
{ "ActiveSession", "(so)", prop_map_first_of_struct, offsetof(SeatStatusInfo, active_session) },
{ "Sessions", "a(so)", prop_map_sessions_strv, offsetof(SeatStatusInfo, sessions) },
@@ -694,7 +699,7 @@ static int print_seat_status_info(sd_bus *bus, const char *path, bool *new_line)
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
- _cleanup_(seat_status_info_clear) SeatStatusInfo i = {};
+ _cleanup_(seat_status_info_done) SeatStatusInfo i = {};
int r;
r = bus_map_all_properties(bus, "org.freedesktop.login1", path, map, 0, &error, &m, &i);
@@ -1009,7 +1014,6 @@ static int activate(int argc, char *argv[], void *userdata) {
}
for (int i = 1; i < argc; i++) {
-
r = bus_call_method(
bus,
bus_login_mgr,
@@ -1039,7 +1043,6 @@ static int kill_session(int argc, char *argv[], void *userdata) {
arg_kill_whom = "all";
for (int i = 1; i < argc; i++) {
-
r = bus_call_method(
bus,
bus_login_mgr,

@ -0,0 +1,55 @@
From 0884a1675b2ad20fdf7f98849ad6592a10b893e4 Mon Sep 17 00:00:00 2001
From: Mike Yuan <me@yhndnzj.com>
Date: Thu, 25 May 2023 01:20:45 +0800
Subject: [PATCH] loginctl: list-sessions: fix timestamp for idle hint
Follow-up for 556723e738b96a5c2b2d45a96b87b7b80e0c5664
TABLE_TIMESTAMP_RELATIVE takes a realtime timestamp.
(cherry picked from commit be88af3d9646c8bd1aaea3d4a00520e97ee8674d)
Related: #2209912
---
src/login/loginctl.c | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/src/login/loginctl.c b/src/login/loginctl.c
index 25e5787c11..598acf766d 100644
--- a/src/login/loginctl.c
+++ b/src/login/loginctl.c
@@ -73,7 +73,7 @@ typedef struct SessionStatusInfo {
const char *scope;
const char *desktop;
bool idle_hint;
- dual_timestamp idle_hint_timestamp;
+ usec_t idle_hint_timestamp;
} SessionStatusInfo;
typedef struct UserStatusInfo {
@@ -171,11 +171,11 @@ static int show_table(Table *table, const char *word) {
static int list_sessions(int argc, char *argv[], void *userdata) {
- static const struct bus_properties_map map[] = {
- { "IdleHint", "b", NULL, offsetof(SessionStatusInfo, idle_hint) },
- { "IdleSinceHintMonotonic", "t", NULL, offsetof(SessionStatusInfo, idle_hint_timestamp.monotonic) },
- { "State", "s", NULL, offsetof(SessionStatusInfo, state) },
- { "TTY", "s", NULL, offsetof(SessionStatusInfo, tty) },
+ static const struct bus_properties_map map[] = {
+ { "IdleHint", "b", NULL, offsetof(SessionStatusInfo, idle_hint) },
+ { "IdleSinceHint", "t", NULL, offsetof(SessionStatusInfo, idle_hint_timestamp) },
+ { "State", "s", NULL, offsetof(SessionStatusInfo, state) },
+ { "TTY", "s", NULL, offsetof(SessionStatusInfo, tty) },
{},
};
@@ -239,7 +239,7 @@ static int list_sessions(int argc, char *argv[], void *userdata) {
return table_log_add_error(r);
if (i.idle_hint)
- r = table_add_cell(table, NULL, TABLE_TIMESTAMP_RELATIVE, &i.idle_hint_timestamp.monotonic);
+ r = table_add_cell(table, NULL, TABLE_TIMESTAMP_RELATIVE, &i.idle_hint_timestamp);
else
r = table_add_cell(table, NULL, TABLE_EMPTY, NULL);
if (r < 0)

@ -0,0 +1,103 @@
From 837b3a3ba22efd133c8b39e142994405cc1aa322 Mon Sep 17 00:00:00 2001
From: Mike Yuan <me@yhndnzj.com>
Date: Tue, 23 May 2023 18:27:05 +0800
Subject: [PATCH] loginctl: list-users: use bus_map_all_properties
(cherry picked from commit 8b0da9971afabd47e2e0b72be82dc37c06caabee)
Related: #2209912
---
src/login/loginctl.c | 58 ++++++++++++++++++--------------------------
1 file changed, 24 insertions(+), 34 deletions(-)
diff --git a/src/login/loginctl.c b/src/login/loginctl.c
index 598acf766d..98bb87bd87 100644
--- a/src/login/loginctl.c
+++ b/src/login/loginctl.c
@@ -254,6 +254,13 @@ static int list_sessions(int argc, char *argv[], void *userdata) {
}
static int list_users(int argc, char *argv[], void *userdata) {
+
+ static const struct bus_properties_map property_map[] = {
+ { "Linger", "b", NULL, offsetof(UserStatusInfo, linger) },
+ { "State", "s", NULL, offsetof(UserStatusInfo, state) },
+ {},
+ };
+
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
_cleanup_(table_unrefp) Table *table = NULL;
@@ -280,10 +287,10 @@ static int list_users(int argc, char *argv[], void *userdata) {
for (;;) {
_cleanup_(sd_bus_error_free) sd_bus_error error_property = SD_BUS_ERROR_NULL;
- _cleanup_free_ char *state = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply_property = NULL;
+ _cleanup_(user_status_info_done) UserStatusInfo info = {};
const char *user, *object;
uint32_t uid;
- int linger;
r = sd_bus_message_read(reply, "(uso)", &uid, &user, &object);
if (r < 0)
@@ -291,44 +298,27 @@ static int list_users(int argc, char *argv[], void *userdata) {
if (r == 0)
break;
- r = sd_bus_get_property_trivial(bus,
- "org.freedesktop.login1",
- object,
- "org.freedesktop.login1.User",
- "Linger",
- &error_property,
- 'b',
- &linger);
+ r = bus_map_all_properties(bus,
+ "org.freedesktop.login1",
+ object,
+ property_map,
+ BUS_MAP_BOOLEAN_AS_BOOL,
+ &error_property,
+ &reply_property,
+ &info);
if (r < 0) {
- if (sd_bus_error_has_name(&error_property, SD_BUS_ERROR_UNKNOWN_OBJECT))
- /* The user logged out when we're querying the property */
- continue;
-
- return log_error_errno(r, "Failed to get linger status for user %s: %s",
- user, bus_error_message(&error_property, r));
- }
-
- r = sd_bus_get_property_string(bus,
- "org.freedesktop.login1",
- object,
- "org.freedesktop.login1.User",
- "State",
- &error_property,
- &state);
- if (r < 0) {
- if (sd_bus_error_has_name(&error_property, SD_BUS_ERROR_UNKNOWN_OBJECT))
- /* The user logged out when we're querying the property */
- continue;
-
- return log_error_errno(r, "Failed to get state for user %s: %s",
- user, bus_error_message(&error_property, r));
+ log_full_errno(sd_bus_error_has_name(&error_property, SD_BUS_ERROR_UNKNOWN_OBJECT) ? LOG_DEBUG : LOG_WARNING,
+ r,
+ "Failed to get properties of user %s, ignoring: %s",
+ user, bus_error_message(&error_property, r));
+ continue;
}
r = table_add_many(table,
TABLE_UID, (uid_t) uid,
TABLE_STRING, user,
- TABLE_BOOLEAN, linger,
- TABLE_STRING, state);
+ TABLE_BOOLEAN, info.linger,
+ TABLE_STRING, info.state);
if (r < 0)
return table_log_add_error(r);
}

@ -0,0 +1,78 @@
From e9d8b5a3d251007444f7722e34cd43ca4c1d628b Mon Sep 17 00:00:00 2001
From: Mike Yuan <me@yhndnzj.com>
Date: Tue, 23 May 2023 18:54:30 +0800
Subject: [PATCH] loginctl: also show idle hint in session-status
(cherry picked from commit 82449055af97cf92466dbe132a89c9d889440c3d)
Related: #2209912
---
src/login/loginctl.c | 48 ++++++++++++++++++++++++++------------------
1 file changed, 29 insertions(+), 19 deletions(-)
diff --git a/src/login/loginctl.c b/src/login/loginctl.c
index 98bb87bd87..e2eda66da7 100644
--- a/src/login/loginctl.c
+++ b/src/login/loginctl.c
@@ -469,25 +469,27 @@ static int prop_map_sessions_strv(sd_bus *bus, const char *member, sd_bus_messag
static int print_session_status_info(sd_bus *bus, const char *path, bool *new_line) {
static const struct bus_properties_map map[] = {
- { "Id", "s", NULL, offsetof(SessionStatusInfo, id) },
- { "Name", "s", NULL, offsetof(SessionStatusInfo, name) },
- { "TTY", "s", NULL, offsetof(SessionStatusInfo, tty) },
- { "Display", "s", NULL, offsetof(SessionStatusInfo, display) },
- { "RemoteHost", "s", NULL, offsetof(SessionStatusInfo, remote_host) },
- { "RemoteUser", "s", NULL, offsetof(SessionStatusInfo, remote_user) },
- { "Service", "s", NULL, offsetof(SessionStatusInfo, service) },
- { "Desktop", "s", NULL, offsetof(SessionStatusInfo, desktop) },
- { "Type", "s", NULL, offsetof(SessionStatusInfo, type) },
- { "Class", "s", NULL, offsetof(SessionStatusInfo, class) },
- { "Scope", "s", NULL, offsetof(SessionStatusInfo, scope) },
- { "State", "s", NULL, offsetof(SessionStatusInfo, state) },
- { "VTNr", "u", NULL, offsetof(SessionStatusInfo, vtnr) },
- { "Leader", "u", NULL, offsetof(SessionStatusInfo, leader) },
- { "Remote", "b", NULL, offsetof(SessionStatusInfo, remote) },
- { "Timestamp", "t", NULL, offsetof(SessionStatusInfo, timestamp.realtime) },
- { "TimestampMonotonic", "t", NULL, offsetof(SessionStatusInfo, timestamp.monotonic) },
- { "User", "(uo)", prop_map_first_of_struct, offsetof(SessionStatusInfo, uid) },
- { "Seat", "(so)", prop_map_first_of_struct, offsetof(SessionStatusInfo, seat) },
+ { "Id", "s", NULL, offsetof(SessionStatusInfo, id) },
+ { "Name", "s", NULL, offsetof(SessionStatusInfo, name) },
+ { "TTY", "s", NULL, offsetof(SessionStatusInfo, tty) },
+ { "Display", "s", NULL, offsetof(SessionStatusInfo, display) },
+ { "RemoteHost", "s", NULL, offsetof(SessionStatusInfo, remote_host) },
+ { "RemoteUser", "s", NULL, offsetof(SessionStatusInfo, remote_user) },
+ { "Service", "s", NULL, offsetof(SessionStatusInfo, service) },
+ { "Desktop", "s", NULL, offsetof(SessionStatusInfo, desktop) },
+ { "Type", "s", NULL, offsetof(SessionStatusInfo, type) },
+ { "Class", "s", NULL, offsetof(SessionStatusInfo, class) },
+ { "Scope", "s", NULL, offsetof(SessionStatusInfo, scope) },
+ { "State", "s", NULL, offsetof(SessionStatusInfo, state) },
+ { "VTNr", "u", NULL, offsetof(SessionStatusInfo, vtnr) },
+ { "Leader", "u", NULL, offsetof(SessionStatusInfo, leader) },
+ { "Remote", "b", NULL, offsetof(SessionStatusInfo, remote) },
+ { "Timestamp", "t", NULL, offsetof(SessionStatusInfo, timestamp.realtime) },
+ { "TimestampMonotonic", "t", NULL, offsetof(SessionStatusInfo, timestamp.monotonic) },
+ { "IdleHint", "b", NULL, offsetof(SessionStatusInfo, idle_hint) },
+ { "IdleSinceHint", "t", NULL, offsetof(SessionStatusInfo, idle_hint_timestamp) },
+ { "User", "(uo)", prop_map_first_of_struct, offsetof(SessionStatusInfo, uid) },
+ { "Seat", "(so)", prop_map_first_of_struct, offsetof(SessionStatusInfo, seat) },
{}
};
@@ -578,6 +580,14 @@ static int print_session_status_info(sd_bus *bus, const char *path, bool *new_li
if (i.state)
printf("\t State: %s\n", i.state);
+ if (i.idle_hint && timestamp_is_set(i.idle_hint_timestamp))
+ printf("\t Idle: %s since %s (%s)\n",
+ yes_no(i.idle_hint),
+ FORMAT_TIMESTAMP(i.idle_hint_timestamp),
+ FORMAT_TIMESTAMP_RELATIVE(i.idle_hint_timestamp));
+ else
+ printf("\t Idle: %s\n", yes_no(i.idle_hint));
+
if (i.scope) {
printf("\t Unit: %s\n", i.scope);
show_unit_cgroup(bus, "org.freedesktop.systemd1.Scope", i.scope, i.leader);

@ -0,0 +1,45 @@
From 0b4518d1f00543a25b5fc30a6203cd59c84cf8c4 Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Sun, 7 May 2023 18:34:35 +0900
Subject: [PATCH] memory-util: make ArrayCleanup passed to array_cleanup()
const
Should not change any behavior, preparation for later commits.
(cherry picked from commit 3facdc7da8ad424a38ce9c673fbb94a41e070a7d)
Related: #2190226
---
src/basic/memory-util.h | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/src/basic/memory-util.h b/src/basic/memory-util.h
index 8d75befed5..eea9c0e92f 100644
--- a/src/basic/memory-util.h
+++ b/src/basic/memory-util.h
@@ -123,13 +123,13 @@ static inline void erase_char(char *p) {
}
/* An automatic _cleanup_-like logic for destroy arrays (i.e. pointers + size) when leaving scope */
-struct ArrayCleanup {
+typedef struct ArrayCleanup {
void **parray;
size_t *pn;
free_array_func_t pfunc;
-};
+} ArrayCleanup;
-static inline void array_cleanup(struct ArrayCleanup *c) {
+static inline void array_cleanup(const ArrayCleanup *c) {
assert(c);
assert(!c->parray == !c->pn);
@@ -147,7 +147,7 @@ static inline void array_cleanup(struct ArrayCleanup *c) {
}
#define CLEANUP_ARRAY(array, n, func) \
- _cleanup_(array_cleanup) _unused_ struct ArrayCleanup CONCATENATE(_cleanup_array_, UNIQ) = { \
+ _cleanup_(array_cleanup) _unused_ const ArrayCleanup CONCATENATE(_cleanup_array_, UNIQ) = { \
.parray = (void**) &(array), \
.pn = &(n), \
.pfunc = (free_array_func_t) ({ \

@ -0,0 +1,87 @@
From 8d45c6b730d7c56e970708767301700397756b52 Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Sun, 7 May 2023 18:37:13 +0900
Subject: [PATCH] static-destruct: several cleanups
No functional changes, preparation for later commits.
(cherry picked from commit 555ead898539183a435e18c6e1e4d5fb89499231)
Related: #2190226
---
src/basic/static-destruct.h | 42 ++++++++++++++++++-------------------
1 file changed, 21 insertions(+), 21 deletions(-)
diff --git a/src/basic/static-destruct.h b/src/basic/static-destruct.h
index 97baac7abb..4bc82889be 100644
--- a/src/basic/static-destruct.h
+++ b/src/basic/static-destruct.h
@@ -10,6 +10,21 @@
* feel a bit like the gcc cleanup attribute, but for static variables. Note that this does not work for static
* variables declared in .so's, as the list is private to the same linking unit. But maybe that's a good thing. */
+#define _common_static_destruct_attrs_ \
+ /* Older compilers don't know "retain" attribute. */ \
+ _Pragma("GCC diagnostic ignored \"-Wattributes\"") \
+ /* The actual destructor structure we place in a special section to find it. */ \
+ _section_("SYSTEMD_STATIC_DESTRUCT") \
+ /* Use pointer alignment, since that is apparently what gcc does for static variables. */ \
+ _alignptr_ \
+ /* Make sure this is not dropped from the image despite not being explicitly referenced. */ \
+ _used_ \
+ /* Prevent garbage collection by the linker. */ \
+ _retain_ \
+ /* Make sure that AddressSanitizer doesn't pad this variable: we want everything in this section
+ * packed next to each other so that we can enumerate it. */ \
+ _variable_no_sanitize_address_
+
typedef struct StaticDestructor {
void *data;
free_func_t destroy;
@@ -24,19 +39,7 @@ typedef struct StaticDestructor {
typeof(variable) *q = p; \
func(q); \
} \
- /* Older compilers don't know "retain" attribute. */ \
- _Pragma("GCC diagnostic ignored \"-Wattributes\"") \
- /* The actual destructor structure we place in a special section to find it. */ \
- _section_("SYSTEMD_STATIC_DESTRUCT") \
- /* Use pointer alignment, since that is apparently what gcc does for static variables. */ \
- _alignptr_ \
- /* Make sure this is not dropped from the image despite not being explicitly referenced. */ \
- _used_ \
- /* Prevent garbage collection by the linker. */ \
- _retain_ \
- /* Make sure that AddressSanitizer doesn't pad this variable: we want everything in this section
- * packed next to each other so that we can enumerate it. */ \
- _variable_no_sanitize_address_ \
+ _common_static_destruct_attrs_ \
static const StaticDestructor UNIQ_T(static_destructor_entry, uq) = { \
.data = &(variable), \
.destroy = UNIQ_T(static_destructor_wrapper, uq), \
@@ -44,20 +47,17 @@ typedef struct StaticDestructor {
/* Beginning and end of our section listing the destructors. We define these as weak as we want this to work
* even if no destructors are defined and the section is missing. */
-extern const struct StaticDestructor _weak_ __start_SYSTEMD_STATIC_DESTRUCT[];
-extern const struct StaticDestructor _weak_ __stop_SYSTEMD_STATIC_DESTRUCT[];
+extern const StaticDestructor _weak_ __start_SYSTEMD_STATIC_DESTRUCT[];
+extern const StaticDestructor _weak_ __stop_SYSTEMD_STATIC_DESTRUCT[];
/* The function to destroy everything. (Note that this must be static inline, as it's key that it remains in
* the same linking unit as the variables we want to destroy.) */
static inline void static_destruct(void) {
- const StaticDestructor *d;
-
if (!__start_SYSTEMD_STATIC_DESTRUCT)
return;
- d = ALIGN_PTR(__start_SYSTEMD_STATIC_DESTRUCT);
- while (d < __stop_SYSTEMD_STATIC_DESTRUCT) {
+ for (const StaticDestructor *d = ALIGN_PTR(__start_SYSTEMD_STATIC_DESTRUCT);
+ d < __stop_SYSTEMD_STATIC_DESTRUCT;
+ d = ALIGN_PTR(d + 1))
d->destroy(d->data);
- d = ALIGN_PTR(d + 1);
- }
}

@ -0,0 +1,172 @@
From a8f31096dcd402b4c8d57c2a8f86b52146077ce3 Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Tue, 9 May 2023 06:44:27 +0900
Subject: [PATCH] static-destruct: introduce STATIC_ARRAY_DESTRUCTOR_REGISTER()
(cherry picked from commit 9695b0c01bf3d4b260432fb6754c7fbe9173c7db)
Related: #2190226
---
src/basic/static-destruct.h | 50 ++++++++++++++++++++++++++++++---
src/test/test-static-destruct.c | 41 ++++++++++++++++++++++++---
2 files changed, 83 insertions(+), 8 deletions(-)
diff --git a/src/basic/static-destruct.h b/src/basic/static-destruct.h
index 4bc82889be..2ffc6516f8 100644
--- a/src/basic/static-destruct.h
+++ b/src/basic/static-destruct.h
@@ -4,6 +4,7 @@
#include "alloc-util.h"
#include "macro.h"
+#include "memory-util.h"
/* A framework for registering static variables that shall be freed on shutdown of a process. It's a bit like gcc's
* destructor attribute, but allows us to precisely schedule when we want to free the variables. This is supposed to
@@ -25,9 +26,24 @@
* packed next to each other so that we can enumerate it. */ \
_variable_no_sanitize_address_
-typedef struct StaticDestructor {
+typedef enum StaticDestructorType {
+ STATIC_DESTRUCTOR_SIMPLE,
+ STATIC_DESTRUCTOR_ARRAY,
+ _STATIC_DESTRUCTOR_TYPE_MAX,
+ _STATIC_DESTRUCTOR_INVALID = -EINVAL,
+} StaticDestructorType;
+
+typedef struct SimpleCleanup {
void *data;
free_func_t destroy;
+} SimpleCleanup;
+
+typedef struct StaticDestructor {
+ StaticDestructorType type;
+ union {
+ SimpleCleanup simple;
+ ArrayCleanup array;
+ };
} StaticDestructor;
#define STATIC_DESTRUCTOR_REGISTER(variable, func) \
@@ -41,10 +57,25 @@ typedef struct StaticDestructor {
} \
_common_static_destruct_attrs_ \
static const StaticDestructor UNIQ_T(static_destructor_entry, uq) = { \
- .data = &(variable), \
- .destroy = UNIQ_T(static_destructor_wrapper, uq), \
+ .type = STATIC_DESTRUCTOR_SIMPLE, \
+ .simple.data = &(variable), \
+ .simple.destroy = UNIQ_T(static_destructor_wrapper, uq), \
}
+#define STATIC_ARRAY_DESTRUCTOR_REGISTER(a, n, func) \
+ _STATIC_ARRAY_DESTRUCTOR_REGISTER(UNIQ, a, n, func)
+
+#define _STATIC_ARRAY_DESTRUCTOR_REGISTER(uq, a, n, func) \
+ /* Type-safety check */ \
+ _unused_ static void (* UNIQ_T(static_destructor_wrapper, uq))(typeof(a[0]) *x, size_t y) = (func); \
+ _common_static_destruct_attrs_ \
+ static const StaticDestructor UNIQ_T(static_destructor_entry, uq) = { \
+ .type = STATIC_DESTRUCTOR_ARRAY, \
+ .array.parray = (void**) &(a), \
+ .array.pn = &(n), \
+ .array.pfunc = (free_array_func_t) (func), \
+ };
+
/* Beginning and end of our section listing the destructors. We define these as weak as we want this to work
* even if no destructors are defined and the section is missing. */
extern const StaticDestructor _weak_ __start_SYSTEMD_STATIC_DESTRUCT[];
@@ -59,5 +90,16 @@ static inline void static_destruct(void) {
for (const StaticDestructor *d = ALIGN_PTR(__start_SYSTEMD_STATIC_DESTRUCT);
d < __stop_SYSTEMD_STATIC_DESTRUCT;
d = ALIGN_PTR(d + 1))
- d->destroy(d->data);
+ switch (d->type) {
+ case STATIC_DESTRUCTOR_SIMPLE:
+ d->simple.destroy(d->simple.data);
+ break;
+
+ case STATIC_DESTRUCTOR_ARRAY:
+ array_cleanup(&d->array);
+ break;
+
+ default:
+ assert_not_reached();
+ }
}
diff --git a/src/test/test-static-destruct.c b/src/test/test-static-destruct.c
index cb518ea362..ef8648f588 100644
--- a/src/test/test-static-destruct.c
+++ b/src/test/test-static-destruct.c
@@ -2,17 +2,38 @@
#include "alloc-util.h"
#include "static-destruct.h"
+#include "strv.h"
#include "tests.h"
static int foo = 0;
static int bar = 0;
static int baz = 0;
-static char* memory = NULL;
+static char *memory = NULL;
+static char **strings = NULL;
+static size_t n_strings = 0;
+static int *integers = NULL;
+static size_t n_integers = 0;
static void test_destroy(int *b) {
(*b)++;
}
+static void test_strings_destroy(char **array, size_t n) {
+ assert_se(n == 3);
+ assert_se(strv_equal(array, STRV_MAKE("a", "bbb", "ccc")));
+
+ strv_free(array);
+}
+
+static void test_integers_destroy(int *array, size_t n) {
+ assert_se(n == 10);
+
+ for (size_t i = 0; i < n; i++)
+ assert_se(array[i] == (int)(i * i));
+
+ free(array);
+}
+
STATIC_DESTRUCTOR_REGISTER(foo, test_destroy);
STATIC_DESTRUCTOR_REGISTER(bar, test_destroy);
STATIC_DESTRUCTOR_REGISTER(bar, test_destroy);
@@ -20,15 +41,27 @@ STATIC_DESTRUCTOR_REGISTER(baz, test_destroy);
STATIC_DESTRUCTOR_REGISTER(baz, test_destroy);
STATIC_DESTRUCTOR_REGISTER(baz, test_destroy);
STATIC_DESTRUCTOR_REGISTER(memory, freep);
+STATIC_ARRAY_DESTRUCTOR_REGISTER(strings, n_strings, test_strings_destroy);
+STATIC_ARRAY_DESTRUCTOR_REGISTER(integers, n_integers, test_integers_destroy);
TEST(static_destruct) {
+ assert_se(foo == 0 && bar == 0 && baz == 0);
assert_se(memory = strdup("hallo"));
+ assert_se(strings = strv_new("a", "bbb", "ccc"));
+ n_strings = strv_length(strings);
+ n_integers = 10;
+ assert_se(integers = new(int, n_integers));
+ for (size_t i = 0; i < n_integers; i++)
+ integers[i] = i * i;
- assert_se(foo == 0 && bar == 0 && baz == 0);
static_destruct();
- assert_se(foo == 1 && bar == 2 && baz == 3);
- assert_se(memory == NULL);
+ assert_se(foo == 1 && bar == 2 && baz == 3);
+ assert_se(!memory);
+ assert_se(!strings);
+ assert_se(n_strings == 0);
+ assert_se(!integers);
+ assert_se(n_integers == 0);
}
DEFINE_TEST_MAIN(LOG_INFO);

@ -0,0 +1,40 @@
From 7ca6eafaa28848cb917a2cd4af78a9c85c3fd51a Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Thu, 9 Mar 2023 13:14:12 +0900
Subject: [PATCH] macro: support the case that the number of elements has const
qualifier
Follow-up for 5716c27e1f52d2aba9dd02916c01d6271d9d0b16.
Addresses https://github.com/systemd/systemd/pull/26303#issuecomment-1460712007.
(cherry picked from commit b9872fe1ddb61a7f930c652887c04e2f82b43be4)
Related: #2190226
---
src/basic/macro.h | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/src/basic/macro.h b/src/basic/macro.h
index b977730e54..72a2c7267e 100644
--- a/src/basic/macro.h
+++ b/src/basic/macro.h
@@ -329,12 +329,14 @@ static inline int __coverity_check_and_return__(int condition) {
#endif
#endif
-#define _FOREACH_ARRAY(i, array, num, m, s) \
- for (typeof(num) m = (num); m > 0; m = 0) \
- for (typeof(array[0]) *s = (array), *i = s; s && i < s + m; i++)
+#define _FOREACH_ARRAY(i, array, num, m, end) \
+ for (typeof(array[0]) *i = (array), *end = ({ \
+ typeof(num) m = (num); \
+ (i && m > 0) ? i + m : NULL; \
+ }); end && i < end; i++)
#define FOREACH_ARRAY(i, array, num) \
- _FOREACH_ARRAY(i, array, num, UNIQ_T(m, UNIQ), UNIQ_T(s, UNIQ))
+ _FOREACH_ARRAY(i, array, num, UNIQ_T(m, UNIQ), UNIQ_T(end, UNIQ))
#define DEFINE_TRIVIAL_DESTRUCTOR(name, type, func) \
static inline void name(type *p) { \

@ -0,0 +1,74 @@
From b663e9f1256c62fa0e1c0fb80e6cd4a3c055716d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
Date: Wed, 28 Sep 2022 13:38:56 +0200
Subject: [PATCH] shared/generator: apply similar config reordering of
generated units
(cherry picked from commit ce37fb0d92ca8af31215c81b573ebaac81ed6fd2)
Related: #2190226
---
src/shared/generator.c | 18 ++++++++++++------
1 file changed, 12 insertions(+), 6 deletions(-)
diff --git a/src/shared/generator.c b/src/shared/generator.c
index 5d019f4f4e..4c684fc3e7 100644
--- a/src/shared/generator.c
+++ b/src/shared/generator.c
@@ -116,6 +116,7 @@ static int write_fsck_sysroot_service(
"[Unit]\n"
"Description=File System Check on %2$s\n"
"Documentation=man:%3$s(8)\n"
+ "\n"
"DefaultDependencies=no\n"
"BindsTo=%4$s\n"
"Conflicts=shutdown.target\n"
@@ -409,11 +410,13 @@ int generator_hook_up_mkswap(
"[Unit]\n"
"Description=Make Swap on %%f\n"
"Documentation=man:systemd-mkswap@.service(8)\n"
+ "\n"
"DefaultDependencies=no\n"
"BindsTo=%%i.device\n"
- "Conflicts=shutdown.target\n"
"After=%%i.device\n"
- "Before=shutdown.target %s\n"
+ "Before=%s\n"
+ "Conflicts=shutdown.target\n"
+ "Before=shutdown.target\n"
"\n"
"[Service]\n"
"Type=oneshot\n"
@@ -486,13 +489,15 @@ int generator_hook_up_mkfs(
"[Unit]\n"
"Description=Make File System on %%f\n"
"Documentation=man:systemd-makefs@.service(8)\n"
+ "\n"
"DefaultDependencies=no\n"
"BindsTo=%%i.device\n"
- "Conflicts=shutdown.target\n"
"After=%%i.device\n"
/* fsck might or might not be used, so let's be safe and order
* ourselves before both systemd-fsck@.service and the mount unit. */
- "Before=shutdown.target systemd-fsck@%%i.service %s\n"
+ "Before=systemd-fsck@%%i.service %s\n"
+ "Conflicts=shutdown.target\n"
+ "Before=shutdown.target\n"
"\n"
"[Service]\n"
"Type=oneshot\n"
@@ -624,11 +629,12 @@ int generator_write_cryptsetup_unit_section(
fprintf(f, "SourcePath=%s\n", source);
fprintf(f,
+ "\n"
"DefaultDependencies=no\n"
- "IgnoreOnIsolate=true\n"
"After=cryptsetup-pre.target systemd-udevd-kernel.socket\n"
"Before=blockdev@dev-mapper-%%i.target\n"
- "Wants=blockdev@dev-mapper-%%i.target\n");
+ "Wants=blockdev@dev-mapper-%%i.target\n"
+ "IgnoreOnIsolate=true\n");
return 0;
}

@ -0,0 +1,34 @@
From 0770b3b7af5f11a65bc11307789c2ed45e5c8155 Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Mon, 8 May 2023 20:06:33 +0900
Subject: [PATCH] nulstr-util: make ret_size in strv_make_nulstr() optional
(cherry picked from commit 16cda99c737714d6d259e45808e39f94408d90bd)
Related: #2190226
---
src/basic/strv.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/basic/strv.c b/src/basic/strv.c
index 24fc56a1a5..66b70befd6 100644
--- a/src/basic/strv.c
+++ b/src/basic/strv.c
@@ -706,7 +706,6 @@ int strv_make_nulstr(char * const *l, char **ret, size_t *ret_size) {
size_t n = 0;
assert(ret);
- assert(ret_size);
STRV_FOREACH(i, l) {
size_t z;
@@ -731,7 +730,8 @@ int strv_make_nulstr(char * const *l, char **ret, size_t *ret_size) {
assert(n > 0);
*ret = TAKE_PTR(m);
- *ret_size = n - 1;
+ if (ret_size)
+ *ret_size = n - 1;
return 0;
}

@ -0,0 +1,105 @@
From d175d6d2260cd4b2116669953058fa9bef7ae478 Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Sun, 16 Oct 2022 22:39:31 +0200
Subject: [PATCH] generator: teach generator_add_symlink() to instantiate
specified unit
if we want generators to instantiate a template service, we need to
teach generator_add_symlink() the concept.
Just some preparation for a later commit.
While we are at it, modernize the function around
path_extract_filename() + path_extract_directory()
(cherry picked from commit 0ba07f907721941f611eaca9521937c467bdfff2)
Related: #2190226
---
src/shared/generator.c | 51 ++++++++++++++++++++++++++++++++++--------
src/shared/generator.h | 6 ++++-
2 files changed, 47 insertions(+), 10 deletions(-)
diff --git a/src/shared/generator.c b/src/shared/generator.c
index 4c684fc3e7..6001b2778c 100644
--- a/src/shared/generator.c
+++ b/src/shared/generator.c
@@ -59,19 +59,52 @@ int generator_open_unit_file(
return 0;
}
-int generator_add_symlink(const char *dir, const char *dst, const char *dep_type, const char *src) {
- /* Adds a symlink from <dst>.<dep_type>/ to <src> (if src is absolute)
- * or ../<src> (otherwise). */
+int generator_add_symlink_full(
+ const char *dir,
+ const char *dst,
+ const char *dep_type,
+ const char *src,
+ const char *instance) {
+
+ _cleanup_free_ char *dn = NULL, *fn = NULL, *instantiated = NULL, *to = NULL, *from = NULL;
+ int r;
+
+ assert(dir);
+ assert(dst);
+ assert(dep_type);
+ assert(src);
+
+ /* Adds a symlink from <dst>.<dep_type>/ to <src> (if src is absolute) or ../<src> (otherwise). If
+ * <instance> is specified, then <src> must be a template unit name, and we'll instantiate it. */
- const char *from, *to;
+ r = path_extract_directory(src, &dn);
+ if (r < 0 && r != -EDESTADDRREQ) /* EDESTADDRREQ → just a file name was passed */
+ return log_error_errno(r, "Failed to extract directory name from '%s': %m", src);
- from = path_is_absolute(src) ? src : strjoina("../", src);
- to = strjoina(dir, "/", dst, ".", dep_type, "/", basename(src));
+ r = path_extract_filename(src, &fn);
+ if (r < 0)
+ return log_error_errno(r, "Failed to extract file name from '%s': %m", src);
+ if (r == O_DIRECTORY)
+ return log_error_errno(SYNTHETIC_ERRNO(EISDIR), "Expected path to regular file name, but got '%s', refusing.", src);
+
+ if (instance) {
+ r = unit_name_replace_instance(fn, instance, &instantiated);
+ if (r < 0)
+ return log_error_errno(r, "Failed to instantiate '%s' for '%s': %m", fn, instance);
+ }
+
+ from = path_join(dn ?: "..", fn);
+ if (!from)
+ return log_oom();
+
+ to = strjoin(dir, "/", dst, ".", dep_type, "/", instantiated ?: fn);
+ if (!to)
+ return log_oom();
(void) mkdir_parents_label(to, 0755);
- if (symlink(from, to) < 0)
- if (errno != EEXIST)
- return log_error_errno(errno, "Failed to create symlink \"%s\": %m", to);
+
+ if (symlink(from, to) < 0 && errno != EEXIST)
+ return log_error_errno(errno, "Failed to create symlink \"%s\": %m", to);
return 0;
}
diff --git a/src/shared/generator.h b/src/shared/generator.h
index 1b4f36ac53..a4049dbd8f 100644
--- a/src/shared/generator.h
+++ b/src/shared/generator.h
@@ -12,7 +12,11 @@ int generator_open_unit_file(
const char *name,
FILE **file);
-int generator_add_symlink(const char *dir, const char *dst, const char *dep_type, const char *src);
+int generator_add_symlink_full(const char *dir, const char *dst, const char *dep_type, const char *src, const char *instance);
+
+static inline int generator_add_symlink(const char *dir, const char *dst, const char *dep_type, const char *src) {
+ return generator_add_symlink_full(dir, dst, dep_type, src, NULL);
+}
int generator_write_fsck_deps(
FILE *f,

@ -0,0 +1,270 @@
From 09fd7becfe7bd05ea354fdd9326cd6175ca7143d Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Sun, 16 Oct 2022 22:45:17 +0200
Subject: [PATCH] units: rework growfs units to be just a regular unit that is
instantiated
The systemd-growfs@.service units are currently written in full for each
file system to grow. Which is kinda pointless given that (besides an
optional ordering dep) they contain always the same definition. Let's
fix that and add a static template for this logic, that the generator
simply instantiates (and adds an ordering dep for).
This mimics how systemd-fsck@.service is handled. Similar to the wait
that for root fs there's a special instance systemd-fsck-root.service
we also add a special instance systemd-growfs-root.service for the root
fs, since it has slightly different deps.
Fixes: #20788
See: #10014
(cherry picked from commit 50072ccf1bfee8a53563a083a3a52b26f0d5678f)
Related: #2190226
---
src/basic/special.h | 2 +
src/shared/generator.c | 126 ++++++++++++++++-----------
units/meson.build | 2 +
units/systemd-growfs-root.service.in | 22 +++++
units/systemd-growfs@.service.in | 23 +++++
5 files changed, 126 insertions(+), 49 deletions(-)
create mode 100644 units/systemd-growfs-root.service.in
create mode 100644 units/systemd-growfs@.service.in
diff --git a/src/basic/special.h b/src/basic/special.h
index 5d1111fd71..9bb36c5732 100644
--- a/src/basic/special.h
+++ b/src/basic/special.h
@@ -87,6 +87,8 @@
#define SPECIAL_REMOUNT_FS_SERVICE "systemd-remount-fs.service"
#define SPECIAL_VOLATILE_ROOT_SERVICE "systemd-volatile-root.service"
#define SPECIAL_UDEVD_SERVICE "systemd-udevd.service"
+#define SPECIAL_GROWFS_SERVICE "systemd-growfs@.service"
+#define SPECIAL_GROWFS_ROOT_SERVICE "systemd-growfs-root.service"
/* Services systemd relies on */
#define SPECIAL_DBUS_SERVICE "dbus.service"
diff --git a/src/shared/generator.c b/src/shared/generator.c
index 6001b2778c..5d617bbe99 100644
--- a/src/shared/generator.c
+++ b/src/shared/generator.c
@@ -109,6 +109,64 @@ int generator_add_symlink_full(
return 0;
}
+static int generator_add_ordering(
+ const char *dir,
+ const char *src,
+ const char *order,
+ const char *dst,
+ const char *instance) {
+
+ _cleanup_free_ char *instantiated = NULL, *p = NULL, *fn = NULL;
+ _cleanup_fclose_ FILE *f = NULL;
+ const char *to;
+ int r;
+
+ assert(dir);
+ assert(src);
+ assert(order);
+ assert(dst);
+
+ /* Adds in an explicit ordering dependency of type <order> from <src> to <dst>. If <instance> is
+ * specified, it is inserted into <dst>. */
+
+ if (instance) {
+ r = unit_name_replace_instance(dst, instance, &instantiated);
+ if (r < 0)
+ return log_error_errno(r, "Failed to instantiate '%s' for '%s': %m", dst, instance);
+
+ to = instantiated;
+ } else
+ to = dst;
+
+ fn = strjoin(src, ".d/50-order-", to, ".conf");
+ if (!fn)
+ return log_oom();
+
+ p = path_join(dir, fn);
+ if (!p)
+ return log_oom();
+
+ (void) mkdir_parents_label(p, 0755);
+
+ r = fopen_unlocked(p, "wxe", &f);
+ if (r < 0)
+ return log_error_errno(r, "Failed to create '%s': %m", p);
+
+ fprintf(f,
+ "# Automatically generated by %s\n\n"
+ "[Unit]\n"
+ "%s=%s\n",
+ program_invocation_short_name,
+ order,
+ to);
+
+ r = fflush_and_check(f);
+ if (r < 0)
+ return log_error_errno(r, "Failed to write drop-in '%s': %m", p);
+
+ return 0;
+}
+
static int write_fsck_sysroot_service(
const char *unit, /* Either SPECIAL_FSCK_ROOT_SERVICE or SPECIAL_FSCK_USR_SERVICE */
const char *dir,
@@ -555,66 +613,36 @@ int generator_hook_up_growfs(
const char *where,
const char *target) {
- _cleanup_free_ char *unit = NULL, *escaped = NULL, *where_unit = NULL, *unit_file = NULL;
- _cleanup_fclose_ FILE *f = NULL;
+ const char *growfs_unit, *growfs_unit_path;
+ _cleanup_free_ char *where_unit = NULL, *instance = NULL;
int r;
assert(dir);
assert(where);
- escaped = cescape(where);
- if (!escaped)
- return log_oom();
-
- r = unit_name_from_path_instance("systemd-growfs", where, ".service", &unit);
- if (r < 0)
- return log_error_errno(r, "Failed to make unit instance name from path \"%s\": %m",
- where);
-
r = unit_name_from_path(where, ".mount", &where_unit);
if (r < 0)
- return log_error_errno(r, "Failed to make unit name from path \"%s\": %m",
- where);
-
- unit_file = path_join(dir, unit);
- if (!unit_file)
- return log_oom();
-
- log_debug("Creating %s", unit_file);
-
- f = fopen(unit_file, "wxe");
- if (!f)
- return log_error_errno(errno, "Failed to create unit file %s: %m",
- unit_file);
+ return log_error_errno(r, "Failed to make unit name from path '%s': %m", where);
- fprintf(f,
- "# Automatically generated by %s\n\n"
- "[Unit]\n"
- "Description=Grow File System on %%f\n"
- "Documentation=man:systemd-growfs@.service(8)\n"
- "DefaultDependencies=no\n"
- "BindsTo=%%i.mount\n"
- "Conflicts=shutdown.target\n"
- "After=systemd-repart.service %%i.mount\n"
- "Before=shutdown.target%s%s\n",
- program_invocation_short_name,
- target ? " " : "",
- strempty(target));
+ if (empty_or_root(where)) {
+ growfs_unit = SPECIAL_GROWFS_ROOT_SERVICE;
+ growfs_unit_path = SYSTEM_DATA_UNIT_DIR "/" SPECIAL_GROWFS_ROOT_SERVICE;
+ } else {
+ growfs_unit = SPECIAL_GROWFS_SERVICE;
+ growfs_unit_path = SYSTEM_DATA_UNIT_DIR "/" SPECIAL_GROWFS_SERVICE;
- if (empty_or_root(where)) /* Make sure the root fs is actually writable before we resize it */
- fprintf(f,
- "After=systemd-remount-fs.service\n");
+ r = unit_name_path_escape(where, &instance);
+ if (r < 0)
+ return log_error_errno(r, "Failed to escape path '%s': %m", where);
+ }
- fprintf(f,
- "\n"
- "[Service]\n"
- "Type=oneshot\n"
- "RemainAfterExit=yes\n"
- "ExecStart="SYSTEMD_GROWFS_PATH " %s\n"
- "TimeoutSec=0\n",
- escaped);
+ if (target) {
+ r = generator_add_ordering(dir, target, "After", growfs_unit, instance);
+ if (r < 0)
+ return r;
+ }
- return generator_add_symlink(dir, where_unit, "wants", unit);
+ return generator_add_symlink_full(dir, where_unit, "wants", growfs_unit_path, instance);
}
int generator_enable_remount_fs_service(const char *dir) {
diff --git a/units/meson.build b/units/meson.build
index eae7394731..a99f27adc5 100644
--- a/units/meson.build
+++ b/units/meson.build
@@ -264,6 +264,8 @@ in_units = [
'sysinit.target.wants/'],
['systemd-pcrphase.service', 'HAVE_GNU_EFI HAVE_OPENSSL HAVE_TPM2',
'sysinit.target.wants/'],
+ ['systemd-growfs-root.service', ''],
+ ['systemd-growfs@.service', ''],
]
add_wants = []
diff --git a/units/systemd-growfs-root.service.in b/units/systemd-growfs-root.service.in
new file mode 100644
index 0000000000..295bafd5af
--- /dev/null
+++ b/units/systemd-growfs-root.service.in
@@ -0,0 +1,22 @@
+# SPDX-License-Identifier: LGPL-2.1-or-later
+#
+# This file is part of systemd.
+#
+# systemd is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 2.1 of the License, or
+# (at your option) any later version.
+
+[Unit]
+Description=Grow Root File System
+Documentation=man:systemd-growfs-root.service(8)
+DefaultDependencies=no
+Conflicts=shutdown.target
+After=systemd-repart.service systemd-remount-fs.service
+Before=shutdown.target
+
+[Service]
+Type=oneshot
+RemainAfterExit=yes
+ExecStart={{ROOTLIBEXECDIR}}/systemd-growfs /
+TimeoutSec=0
diff --git a/units/systemd-growfs@.service.in b/units/systemd-growfs@.service.in
new file mode 100644
index 0000000000..7154e4ca76
--- /dev/null
+++ b/units/systemd-growfs@.service.in
@@ -0,0 +1,23 @@
+# SPDX-License-Identifier: LGPL-2.1-or-later
+#
+# This file is part of systemd.
+#
+# systemd is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 2.1 of the License, or
+# (at your option) any later version.
+
+[Unit]
+Description=Grow File System on %f
+Documentation=man:systemd-growfs@.service(8)
+DefaultDependencies=no
+BindsTo=%i.mount
+Conflicts=shutdown.target
+After=systemd-repart.service %i.mount
+Before=shutdown.target
+
+[Service]
+Type=oneshot
+RemainAfterExit=yes
+ExecStart={{ROOTLIBEXECDIR}}/systemd-growfs %f
+TimeoutSec=0

@ -0,0 +1,159 @@
From 2739a62abe692e9ca5792fc46f03cd4618a65000 Mon Sep 17 00:00:00 2001
From: Lily Foster <lily@lily.flowers>
Date: Wed, 25 Jan 2023 19:05:08 -0500
Subject: [PATCH] fstab-generator: use correct targets when /sysroot is
specificied in fstab only
(cherry picked from commit dfce61dda7b7b15b910221e5ca1673b371554368)
Related: #2190226
---
man/systemd-fstab-generator.xml | 7 ++-
src/fstab-generator/fstab-generator.c | 63 +++++++++++++++++++++------
2 files changed, 54 insertions(+), 16 deletions(-)
diff --git a/man/systemd-fstab-generator.xml b/man/systemd-fstab-generator.xml
index b7908377a4..30204f5d8a 100644
--- a/man/systemd-fstab-generator.xml
+++ b/man/systemd-fstab-generator.xml
@@ -81,12 +81,15 @@
<listitem><para>Configures the operating system's root filesystem to mount when running in the
initrd. This accepts a device node path (usually <filename>/dev/disk/by-uuid/…</filename> or
- <filename>/dev/disk/by-label/…</filename> or similar), or the special values <literal>gpt-auto</literal>
- and <literal>tmpfs</literal>.</para>
+ <filename>/dev/disk/by-label/…</filename> or similar), or the special values <literal>gpt-auto</literal>,
+ <literal>fstab</literal>, and <literal>tmpfs</literal>.</para>
<para>Use <literal>gpt-auto</literal> to explicitly request automatic root file system discovery via
<citerefentry><refentrytitle>systemd-gpt-auto-generator</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
+ <para>Use <literal>fstab</literal> to explicitly request automatic root file system discovery via
+ the initrd <filename>/etc/fstab</filename> rather than via kernel command line.</para>
+
<para>Use <literal>tmpfs</literal> in order to mount a <citerefentry
project='man-pages'><refentrytitle>tmpfs</refentrytitle><manvolnum>5</manvolnum></citerefentry> file
system as root file system of the OS. This is useful in combination with
diff --git a/src/fstab-generator/fstab-generator.c b/src/fstab-generator/fstab-generator.c
index e76de45a0f..9bf5f04d1d 100644
--- a/src/fstab-generator/fstab-generator.c
+++ b/src/fstab-generator/fstab-generator.c
@@ -633,6 +633,19 @@ static const char* sysroot_fstab_path(void) {
return getenv("SYSTEMD_SYSROOT_FSTAB") ?: "/sysroot/etc/fstab";
}
+static int add_sysusr_sysroot_usr_bind_mount(const char *source) {
+ return add_mount(source,
+ arg_dest,
+ "/sysusr/usr",
+ "/sysroot/usr",
+ NULL,
+ NULL,
+ "bind",
+ 0,
+ 0,
+ SPECIAL_INITRD_FS_TARGET);
+}
+
static int parse_fstab(bool initrd) {
_cleanup_endmntent_ FILE *f = NULL;
const char *fstab;
@@ -734,7 +747,7 @@ static int parse_fstab(bool initrd) {
if (streq(me->mnt_type, "swap"))
k = add_swap(fstab, what, me, flags);
else {
- bool rw_only, automount;
+ bool rw_only, automount, is_sysroot, is_sysroot_usr;
rw_only = fstab_test_option(me->mnt_opts, "x-systemd.rw-only\0");
automount = fstab_test_option(me->mnt_opts,
@@ -744,21 +757,43 @@ static int parse_fstab(bool initrd) {
flags |= rw_only * MOUNT_RW_ONLY |
automount * MOUNT_AUTOMOUNT;
+ is_sysroot = in_initrd() && path_equal(where, "/sysroot");
+ /* See comment from add_sysroot_usr_mount about the need for extra indirection
+ * in case /usr needs to be mounted in order for the root fs to be synthesized
+ * based on configuration included in /usr/, e.g. systemd-repart. */
+ is_sysroot_usr = in_initrd() && path_equal(where, "/sysroot/usr");
+
const char *target_unit =
initrd ? SPECIAL_INITRD_FS_TARGET :
+ is_sysroot ? SPECIAL_INITRD_ROOT_FS_TARGET :
+ is_sysroot_usr ? SPECIAL_INITRD_USR_FS_TARGET :
mount_is_network(me) ? SPECIAL_REMOTE_FS_TARGET :
SPECIAL_LOCAL_FS_TARGET;
+ if (is_sysroot && is_device_path(what)) {
+ r = generator_write_initrd_root_device_deps(arg_dest, what);
+ if (r < 0)
+ return r;
+ }
+
k = add_mount(fstab,
arg_dest,
what,
- canonical_where ?: where,
- canonical_where ? where: NULL,
+ is_sysroot_usr ? "/sysusr/usr" : canonical_where ?: where,
+ !is_sysroot_usr && canonical_where ? where : NULL,
me->mnt_type,
me->mnt_opts,
me->mnt_passno,
flags,
target_unit);
+
+ if (is_sysroot_usr && k >= 0) {
+ log_debug("Synthesizing fstab entry what=/sysusr/usr where=/sysroot/usr opts=bind");
+
+ r = add_sysusr_sysroot_usr_bind_mount(fstab);
+ if (r != 0)
+ k = r;
+ }
}
if (arg_sysroot_check && k > 0)
@@ -836,6 +871,10 @@ static int add_sysroot_mount(void) {
/* This is handled by gpt-auto-generator */
log_debug("Skipping root directory handling, as gpt-auto was requested.");
return 0;
+ } else if (streq(arg_root_what, "fstab")) {
+ /* This is handled by parse_fstab */
+ log_debug("Using initrd's fstab for /sysroot/ configuration.");
+ return 0;
}
r = sysroot_is_nfsroot();
@@ -951,6 +990,11 @@ static int add_sysroot_usr_mount(void) {
log_debug("Skipping /usr/ directory handling, as gpt-auto was requested.");
return 1; /* systemd-gpt-auto-generator will generate a unit for this, hence report that a
* unit file is being created for the host /usr/ mount. */
+ } else if (streq(arg_usr_what, "fstab")) {
+ /* This is handled by parse_fstab */
+ log_debug("Using initrd's fstab for /sysroot/usr/ configuration.");
+ return 1; /* parse_fstab will generate a unit for this, hence report that a
+ * unit file is being created for the host /usr/ mount. */
}
if (path_equal(arg_usr_what, "/dev/nfs")) {
@@ -992,18 +1036,9 @@ static int add_sysroot_usr_mount(void) {
if (r < 0)
return r;
- log_debug("Synthesizing entry what=/sysusr/usr where=/sysrootr/usr opts=bind");
+ log_debug("Synthesizing entry what=/sysusr/usr where=/sysroot/usr opts=bind");
- r = add_mount("/proc/cmdline",
- arg_dest,
- "/sysusr/usr",
- "/sysroot/usr",
- NULL,
- NULL,
- "bind",
- 0,
- 0,
- SPECIAL_INITRD_FS_TARGET);
+ r = add_sysusr_sysroot_usr_bind_mount("/proc/cmdline");
if (r < 0)
return r;

@ -0,0 +1,70 @@
From 77a8682a6ee41a92aa1e07b557607c65e94d904b Mon Sep 17 00:00:00 2001
From: Lily Foster <lily@lily.flowers>
Date: Wed, 25 Jan 2023 18:52:06 -0500
Subject: [PATCH] fstab-generator: add SYSTEMD_SYSFS_CHECK env var
This forces processing of /dev entries in fstab when running in a
container is detected (checked as the existence of read-only /sys).
(cherry picked from commit 905dd992f8fbfe486e68808ce88e1662c970ab35)
Related: #2190226
---
docs/ENVIRONMENT.md | 4 ++++
src/fstab-generator/fstab-generator.c | 14 +++++++++++---
2 files changed, 15 insertions(+), 3 deletions(-)
diff --git a/docs/ENVIRONMENT.md b/docs/ENVIRONMENT.md
index 70fac2e361..f1a4692b59 100644
--- a/docs/ENVIRONMENT.md
+++ b/docs/ENVIRONMENT.md
@@ -54,6 +54,10 @@ All tools:
* `$SYSTEMD_SYSROOT_FSTAB` — if set, use this path instead of
`/sysroot/etc/fstab`. Only useful for debugging `systemd-fstab-generator`.
+* `$SYSTEMD_SYSFS_CHECK` — takes a boolean. If set, overrides sysfs container
+ detection that ignores `/dev/` entries in fstab. Only useful for debugging
+ `systemd-fstab-generator`.
+
* `$SYSTEMD_CRYPTTAB` — if set, use this path instead of `/etc/crypttab`. Only
useful for debugging. Currently only supported by
`systemd-cryptsetup-generator`.
diff --git a/src/fstab-generator/fstab-generator.c b/src/fstab-generator/fstab-generator.c
index 9bf5f04d1d..bbd669e477 100644
--- a/src/fstab-generator/fstab-generator.c
+++ b/src/fstab-generator/fstab-generator.c
@@ -8,6 +8,7 @@
#include "bus-error.h"
#include "bus-locator.h"
#include "chase-symlinks.h"
+#include "env-util.h"
#include "fd-util.h"
#include "fileio.h"
#include "fstab-util.h"
@@ -650,7 +651,7 @@ static int parse_fstab(bool initrd) {
_cleanup_endmntent_ FILE *f = NULL;
const char *fstab;
struct mntent *me;
- int r = 0;
+ int r = 0, sysfs_check = -1;
if (initrd)
fstab = sysroot_fstab_path();
@@ -688,8 +689,15 @@ static int parse_fstab(bool initrd) {
continue;
}
- if (is_device_path(what)) {
- log_info("Running in a container, ignoring fstab device entry for %s.", what);
+ if (sysfs_check < 0) {
+ r = getenv_bool_secure("SYSTEMD_SYSFS_CHECK");
+ if (r < 0 && r != -ENXIO)
+ log_debug_errno(r, "Failed to parse $SYSTEMD_SYSFS_CHECK, ignoring: %m");
+ sysfs_check = r != 0;
+ }
+
+ if (sysfs_check && is_device_path(what)) {
+ log_info("/sys/ is read-only (running in a container?), ignoring fstab device entry for %s.", what);
continue;
}
}

@ -0,0 +1,155 @@
From 337826320020e4e1e8f6be62c3c65d5b157bb58d Mon Sep 17 00:00:00 2001
From: Lily Foster <lily@lily.flowers>
Date: Wed, 25 Jan 2023 18:52:30 -0500
Subject: [PATCH] test: add fstab file support for fstab-generator tests
(cherry picked from commit ef0c7ab6ac1ad2a38988fd4aa959aaa0408f2f4b)
Related: #2190226
---
test/test-fstab-generator.sh | 6 +++++-
.../initrd-fs.target.requires/sysroot-usr.mount | 0
.../50-root-device.conf | 5 +++++
.../initrd-root-fs.target.requires/sysroot.mount | 0
.../initrd-usr-fs.target.requires/sysroot.mount | 0
.../sysusr-usr.mount | 0
.../sysroot-usr.mount | 11 +++++++++++
.../sysroot.mount | 13 +++++++++++++
.../systemd-fsck-root.service | 16 ++++++++++++++++
.../sysusr-usr.mount | 11 +++++++++++
.../test-17-initrd-sysroot.fstab.input | 2 ++
11 files changed, 63 insertions(+), 1 deletion(-)
create mode 100644 test/test-fstab-generator/test-17-initrd-sysroot.fstab.expected/initrd-fs.target.requires/sysroot-usr.mount
create mode 100644 test/test-fstab-generator/test-17-initrd-sysroot.fstab.expected/initrd-root-device.target.d/50-root-device.conf
create mode 100644 test/test-fstab-generator/test-17-initrd-sysroot.fstab.expected/initrd-root-fs.target.requires/sysroot.mount
create mode 100644 test/test-fstab-generator/test-17-initrd-sysroot.fstab.expected/initrd-usr-fs.target.requires/sysroot.mount
create mode 100644 test/test-fstab-generator/test-17-initrd-sysroot.fstab.expected/initrd-usr-fs.target.requires/sysusr-usr.mount
create mode 100644 test/test-fstab-generator/test-17-initrd-sysroot.fstab.expected/sysroot-usr.mount
create mode 100644 test/test-fstab-generator/test-17-initrd-sysroot.fstab.expected/sysroot.mount
create mode 100644 test/test-fstab-generator/test-17-initrd-sysroot.fstab.expected/systemd-fsck-root.service
create mode 100644 test/test-fstab-generator/test-17-initrd-sysroot.fstab.expected/sysusr-usr.mount
create mode 100644 test/test-fstab-generator/test-17-initrd-sysroot.fstab.input
diff --git a/test/test-fstab-generator.sh b/test/test-fstab-generator.sh
index 7c060dfac7..c86914a107 100755
--- a/test/test-fstab-generator.sh
+++ b/test/test-fstab-generator.sh
@@ -26,7 +26,11 @@ for f in "$src"/test-*.input; do
trap "rm -rf '$out'" EXIT INT QUIT PIPE
# shellcheck disable=SC2046
- SYSTEMD_LOG_LEVEL=debug SYSTEMD_IN_INITRD=yes SYSTEMD_PROC_CMDLINE="fstab=no $(cat "$f")" $generator "$out" "$out" "$out"
+ if [[ "$f" == *.fstab.input ]]; then
+ SYSTEMD_LOG_LEVEL=debug SYSTEMD_IN_INITRD=yes SYSTEMD_SYSFS_CHECK=no SYSTEMD_PROC_CMDLINE="fstab=yes root=fstab" SYSTEMD_FSTAB="$f" SYSTEMD_SYSROOT_FSTAB="/dev/null" $generator "$out" "$out" "$out"
+ else
+ SYSTEMD_LOG_LEVEL=debug SYSTEMD_IN_INITRD=yes SYSTEMD_PROC_CMDLINE="fstab=no $(cat "$f")" $generator "$out" "$out" "$out"
+ fi
if [[ -f "$out"/systemd-fsck-root.service ]]; then
# For split-usr system
diff --git a/test/test-fstab-generator/test-17-initrd-sysroot.fstab.expected/initrd-fs.target.requires/sysroot-usr.mount b/test/test-fstab-generator/test-17-initrd-sysroot.fstab.expected/initrd-fs.target.requires/sysroot-usr.mount
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/test/test-fstab-generator/test-17-initrd-sysroot.fstab.expected/initrd-root-device.target.d/50-root-device.conf b/test/test-fstab-generator/test-17-initrd-sysroot.fstab.expected/initrd-root-device.target.d/50-root-device.conf
new file mode 100644
index 0000000000..47c4232223
--- /dev/null
+++ b/test/test-fstab-generator/test-17-initrd-sysroot.fstab.expected/initrd-root-device.target.d/50-root-device.conf
@@ -0,0 +1,5 @@
+# Automatically generated by systemd-fstab-generator
+
+[Unit]
+Requires=dev-sdx1.device
+After=dev-sdx1.device
diff --git a/test/test-fstab-generator/test-17-initrd-sysroot.fstab.expected/initrd-root-fs.target.requires/sysroot.mount b/test/test-fstab-generator/test-17-initrd-sysroot.fstab.expected/initrd-root-fs.target.requires/sysroot.mount
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/test/test-fstab-generator/test-17-initrd-sysroot.fstab.expected/initrd-usr-fs.target.requires/sysroot.mount b/test/test-fstab-generator/test-17-initrd-sysroot.fstab.expected/initrd-usr-fs.target.requires/sysroot.mount
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/test/test-fstab-generator/test-17-initrd-sysroot.fstab.expected/initrd-usr-fs.target.requires/sysusr-usr.mount b/test/test-fstab-generator/test-17-initrd-sysroot.fstab.expected/initrd-usr-fs.target.requires/sysusr-usr.mount
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/test/test-fstab-generator/test-17-initrd-sysroot.fstab.expected/sysroot-usr.mount b/test/test-fstab-generator/test-17-initrd-sysroot.fstab.expected/sysroot-usr.mount
new file mode 100644
index 0000000000..69be9c17d4
--- /dev/null
+++ b/test/test-fstab-generator/test-17-initrd-sysroot.fstab.expected/sysroot-usr.mount
@@ -0,0 +1,11 @@
+# Automatically generated by systemd-fstab-generator
+
+[Unit]
+Documentation=man:fstab(5) man:systemd-fstab-generator(8)
+SourcePath=/etc/fstab
+Before=initrd-fs.target
+
+[Mount]
+What=/sysusr/usr
+Where=/sysroot/usr
+Options=bind
diff --git a/test/test-fstab-generator/test-17-initrd-sysroot.fstab.expected/sysroot.mount b/test/test-fstab-generator/test-17-initrd-sysroot.fstab.expected/sysroot.mount
new file mode 100644
index 0000000000..0e8a701be9
--- /dev/null
+++ b/test/test-fstab-generator/test-17-initrd-sysroot.fstab.expected/sysroot.mount
@@ -0,0 +1,13 @@
+# Automatically generated by systemd-fstab-generator
+
+[Unit]
+Documentation=man:fstab(5) man:systemd-fstab-generator(8)
+SourcePath=/etc/fstab
+Before=initrd-root-fs.target
+Requires=systemd-fsck-root.service
+After=systemd-fsck-root.service
+After=blockdev@dev-sdx1.target
+
+[Mount]
+What=/dev/sdx1
+Where=/sysroot
diff --git a/test/test-fstab-generator/test-17-initrd-sysroot.fstab.expected/systemd-fsck-root.service b/test/test-fstab-generator/test-17-initrd-sysroot.fstab.expected/systemd-fsck-root.service
new file mode 100644
index 0000000000..7f914fdd14
--- /dev/null
+++ b/test/test-fstab-generator/test-17-initrd-sysroot.fstab.expected/systemd-fsck-root.service
@@ -0,0 +1,16 @@
+# Automatically generated by systemd-fstab-generator
+
+[Unit]
+Description=File System Check on /dev/sdx1
+Documentation=man:systemd-fsck-root.service(8)
+DefaultDependencies=no
+BindsTo=dev-sdx1.device
+Conflicts=shutdown.target
+After=initrd-root-device.target local-fs-pre.target dev-sdx1.device
+Before=shutdown.target
+
+[Service]
+Type=oneshot
+RemainAfterExit=yes
+ExecStart=/usr/lib/systemd/systemd-fsck /dev/sdx1
+TimeoutSec=0
diff --git a/test/test-fstab-generator/test-17-initrd-sysroot.fstab.expected/sysusr-usr.mount b/test/test-fstab-generator/test-17-initrd-sysroot.fstab.expected/sysusr-usr.mount
new file mode 100644
index 0000000000..63fcb10340
--- /dev/null
+++ b/test/test-fstab-generator/test-17-initrd-sysroot.fstab.expected/sysusr-usr.mount
@@ -0,0 +1,11 @@
+# Automatically generated by systemd-fstab-generator
+
+[Unit]
+Documentation=man:fstab(5) man:systemd-fstab-generator(8)
+SourcePath=/etc/fstab
+Before=initrd-usr-fs.target
+After=blockdev@dev-sdx2.target
+
+[Mount]
+What=/dev/sdx2
+Where=/sysusr/usr
diff --git a/test/test-fstab-generator/test-17-initrd-sysroot.fstab.input b/test/test-fstab-generator/test-17-initrd-sysroot.fstab.input
new file mode 100644
index 0000000000..1ba9b0624e
--- /dev/null
+++ b/test/test-fstab-generator/test-17-initrd-sysroot.fstab.input
@@ -0,0 +1,2 @@
+/dev/sdx1 /sysroot auto defaults 0 1
+/dev/sdx2 /sysroot/usr auto defaults 0 0

@ -0,0 +1,345 @@
From 8a964936a2c117b3e6706781026a239dd5727975 Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Fri, 12 May 2023 03:54:13 +0900
Subject: [PATCH] test-fstab-generator: also check file contents
Since e683878c0f03a4ffa123e37b27933fbf7e144901, only filenames are
checked. Let's check contents of generated unit files.
(cherry picked from commit 70bf9f62b9f3c46bb7d111342889bfac7c9ca45e)
Related: #2190226
---
test/test-fstab-generator.sh | 55 ++++++++++++++++---
.../sysroot.mount | 1 +
.../sysroot.mount | 1 +
.../systemd-fsck-root.service | 1 +
.../sysroot.mount | 1 +
.../sysroot.mount | 1 +
.../systemd-fsck-root.service | 1 +
.../sysroot.mount | 1 +
.../sysroot.mount | 1 +
.../systemd-fsck-root.service | 1 +
.../sysroot.mount | 1 +
.../sysroot.mount | 1 +
.../systemd-fsck-root.service | 1 +
.../sysroot.mount | 1 +
.../sysroot.mount | 1 +
.../sysroot-usr.mount | 1 +
.../sysroot.mount | 1 +
.../sysroot.mount | 1 +
.../sysusr-usr.mount | 1 +
.../systemd-fsck-root.service | 1 +
20 files changed, 67 insertions(+), 7 deletions(-)
mode change 100644 => 120000 test/test-fstab-generator/test-12-dev-sdx.expected/initrd-root-fs.target.requires/sysroot.mount
mode change 100644 => 120000 test/test-fstab-generator/test-12-dev-sdx.expected/initrd-usr-fs.target.requires/sysroot.mount
mode change 100644 => 120000 test/test-fstab-generator/test-13-label.expected/initrd-root-fs.target.requires/sysroot.mount
mode change 100644 => 120000 test/test-fstab-generator/test-13-label.expected/initrd-usr-fs.target.requires/sysroot.mount
mode change 100644 => 120000 test/test-fstab-generator/test-14-uuid.expected/initrd-root-fs.target.requires/sysroot.mount
mode change 100644 => 120000 test/test-fstab-generator/test-14-uuid.expected/initrd-usr-fs.target.requires/sysroot.mount
mode change 100644 => 120000 test/test-fstab-generator/test-15-partuuid.expected/initrd-root-fs.target.requires/sysroot.mount
mode change 100644 => 120000 test/test-fstab-generator/test-15-partuuid.expected/initrd-usr-fs.target.requires/sysroot.mount
mode change 100644 => 120000 test/test-fstab-generator/test-16-tmpfs.expected/initrd-root-fs.target.requires/sysroot.mount
mode change 100644 => 120000 test/test-fstab-generator/test-16-tmpfs.expected/initrd-usr-fs.target.requires/sysroot.mount
mode change 100644 => 120000 test/test-fstab-generator/test-17-initrd-sysroot.fstab.expected/initrd-fs.target.requires/sysroot-usr.mount
mode change 100644 => 120000 test/test-fstab-generator/test-17-initrd-sysroot.fstab.expected/initrd-root-fs.target.requires/sysroot.mount
mode change 100644 => 120000 test/test-fstab-generator/test-17-initrd-sysroot.fstab.expected/initrd-usr-fs.target.requires/sysroot.mount
mode change 100644 => 120000 test/test-fstab-generator/test-17-initrd-sysroot.fstab.expected/initrd-usr-fs.target.requires/sysusr-usr.mount
diff --git a/test/test-fstab-generator.sh b/test/test-fstab-generator.sh
index c86914a107..c844d0dae1 100755
--- a/test/test-fstab-generator.sh
+++ b/test/test-fstab-generator.sh
@@ -1,6 +1,8 @@
#!/usr/bin/env bash
# SPDX-License-Identifier: LGPL-2.1-or-later
set -e
+shopt -s nullglob
+shopt -s globstar
if [[ -n "$1" ]]; then
generator=$1
@@ -25,23 +27,62 @@ for f in "$src"/test-*.input; do
# shellcheck disable=SC2064
trap "rm -rf '$out'" EXIT INT QUIT PIPE
- # shellcheck disable=SC2046
- if [[ "$f" == *.fstab.input ]]; then
+ exp="${f%.input}.expected"
+
+ if [[ "${f##*/}" =~ \.fstab\.input ]]; then
SYSTEMD_LOG_LEVEL=debug SYSTEMD_IN_INITRD=yes SYSTEMD_SYSFS_CHECK=no SYSTEMD_PROC_CMDLINE="fstab=yes root=fstab" SYSTEMD_FSTAB="$f" SYSTEMD_SYSROOT_FSTAB="/dev/null" $generator "$out" "$out" "$out"
else
SYSTEMD_LOG_LEVEL=debug SYSTEMD_IN_INITRD=yes SYSTEMD_PROC_CMDLINE="fstab=no $(cat "$f")" $generator "$out" "$out" "$out"
fi
- if [[ -f "$out"/systemd-fsck-root.service ]]; then
- # For split-usr system
- sed -i -e 's:ExecStart=/lib/systemd/systemd-fsck:ExecStart=/usr/lib/systemd/systemd-fsck:' "$out"/systemd-fsck-root.service
+ # For split-usr system
+ for i in "$out"/systemd-*.service; do
+ sed -i -e 's:ExecStart=/lib/systemd/:ExecStart=/usr/lib/systemd/:' "$i"
+ done
+
+ if [[ "${f##*/}" =~ \.fstab\.input ]]; then
+ for i in "$out"/*.{automount,mount,swap}; do
+ sed -i -e 's:SourcePath=.*$:SourcePath=/etc/fstab:' "$i"
+ done
fi
- # We store empty files rather than symlinks, so that they don't get pruned when packaged up, so compare
+ # We store empty files rather than dead symlinks, so that they don't get pruned when packaged up, so compare
# the list of filenames rather than their content
- if ! diff -u <(find "$out" -printf '%P\n' | sort) <(find "${f%.input}.expected" -printf '%P\n' | sort); then
+ if ! diff -u <(find "$out" -printf '%P\n' | sort) <(find "$exp" -printf '%P\n' | sort); then
+ echo "**** Unexpected output for $f"
+ exit 1
+ fi
+
+ # Check the main units.
+ if ! diff -u "$out" "$exp"; then
echo "**** Unexpected output for $f"
exit 1
fi
+
+ # Also check drop-ins.
+ for i in "$out"/*; do
+ [[ -d "$i" ]] || continue
+
+ dir="${i##*/}"
+
+ for j in "$i"/*; do
+ fname="${j##*/}"
+ expf="$exp/$dir/$fname"
+
+ if [[ -L "$j" && ! -e "$j" ]]; then
+ # For dead symlink, we store an empty file.
+ if [[ ! -e "$expf" || -n "$(cat "$expf")" ]]; then
+ echo "**** Unexpected symlink $j created by $f"
+ exit 1
+ fi
+ continue
+ fi
+
+ if ! diff -u "$j" "$expf"; then
+ echo "**** Unexpected output in $j for $f"
+ exit 1
+ fi
+ done
+ done
) || exit 1
done
diff --git a/test/test-fstab-generator/test-12-dev-sdx.expected/initrd-root-fs.target.requires/sysroot.mount b/test/test-fstab-generator/test-12-dev-sdx.expected/initrd-root-fs.target.requires/sysroot.mount
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/test/test-fstab-generator/test-12-dev-sdx.expected/initrd-root-fs.target.requires/sysroot.mount b/test/test-fstab-generator/test-12-dev-sdx.expected/initrd-root-fs.target.requires/sysroot.mount
new file mode 120000
index 0000000000..0c969cdbd4
--- /dev/null
+++ b/test/test-fstab-generator/test-12-dev-sdx.expected/initrd-root-fs.target.requires/sysroot.mount
@@ -0,0 +1 @@
+../sysroot.mount
\ No newline at end of file
diff --git a/test/test-fstab-generator/test-12-dev-sdx.expected/initrd-usr-fs.target.requires/sysroot.mount b/test/test-fstab-generator/test-12-dev-sdx.expected/initrd-usr-fs.target.requires/sysroot.mount
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/test/test-fstab-generator/test-12-dev-sdx.expected/initrd-usr-fs.target.requires/sysroot.mount b/test/test-fstab-generator/test-12-dev-sdx.expected/initrd-usr-fs.target.requires/sysroot.mount
new file mode 120000
index 0000000000..0c969cdbd4
--- /dev/null
+++ b/test/test-fstab-generator/test-12-dev-sdx.expected/initrd-usr-fs.target.requires/sysroot.mount
@@ -0,0 +1 @@
+../sysroot.mount
\ No newline at end of file
diff --git a/test/test-fstab-generator/test-12-dev-sdx.expected/systemd-fsck-root.service b/test/test-fstab-generator/test-12-dev-sdx.expected/systemd-fsck-root.service
index 7f914fdd14..95d943b87a 100644
--- a/test/test-fstab-generator/test-12-dev-sdx.expected/systemd-fsck-root.service
+++ b/test/test-fstab-generator/test-12-dev-sdx.expected/systemd-fsck-root.service
@@ -3,6 +3,7 @@
[Unit]
Description=File System Check on /dev/sdx1
Documentation=man:systemd-fsck-root.service(8)
+
DefaultDependencies=no
BindsTo=dev-sdx1.device
Conflicts=shutdown.target
diff --git a/test/test-fstab-generator/test-13-label.expected/initrd-root-fs.target.requires/sysroot.mount b/test/test-fstab-generator/test-13-label.expected/initrd-root-fs.target.requires/sysroot.mount
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/test/test-fstab-generator/test-13-label.expected/initrd-root-fs.target.requires/sysroot.mount b/test/test-fstab-generator/test-13-label.expected/initrd-root-fs.target.requires/sysroot.mount
new file mode 120000
index 0000000000..0c969cdbd4
--- /dev/null
+++ b/test/test-fstab-generator/test-13-label.expected/initrd-root-fs.target.requires/sysroot.mount
@@ -0,0 +1 @@
+../sysroot.mount
\ No newline at end of file
diff --git a/test/test-fstab-generator/test-13-label.expected/initrd-usr-fs.target.requires/sysroot.mount b/test/test-fstab-generator/test-13-label.expected/initrd-usr-fs.target.requires/sysroot.mount
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/test/test-fstab-generator/test-13-label.expected/initrd-usr-fs.target.requires/sysroot.mount b/test/test-fstab-generator/test-13-label.expected/initrd-usr-fs.target.requires/sysroot.mount
new file mode 120000
index 0000000000..0c969cdbd4
--- /dev/null
+++ b/test/test-fstab-generator/test-13-label.expected/initrd-usr-fs.target.requires/sysroot.mount
@@ -0,0 +1 @@
+../sysroot.mount
\ No newline at end of file
diff --git a/test/test-fstab-generator/test-13-label.expected/systemd-fsck-root.service b/test/test-fstab-generator/test-13-label.expected/systemd-fsck-root.service
index a1327396ca..d6c59ff608 100644
--- a/test/test-fstab-generator/test-13-label.expected/systemd-fsck-root.service
+++ b/test/test-fstab-generator/test-13-label.expected/systemd-fsck-root.service
@@ -3,6 +3,7 @@
[Unit]
Description=File System Check on /dev/disk/by-label/Root
Documentation=man:systemd-fsck-root.service(8)
+
DefaultDependencies=no
BindsTo=dev-disk-by\x2dlabel-Root.device
Conflicts=shutdown.target
diff --git a/test/test-fstab-generator/test-14-uuid.expected/initrd-root-fs.target.requires/sysroot.mount b/test/test-fstab-generator/test-14-uuid.expected/initrd-root-fs.target.requires/sysroot.mount
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/test/test-fstab-generator/test-14-uuid.expected/initrd-root-fs.target.requires/sysroot.mount b/test/test-fstab-generator/test-14-uuid.expected/initrd-root-fs.target.requires/sysroot.mount
new file mode 120000
index 0000000000..0c969cdbd4
--- /dev/null
+++ b/test/test-fstab-generator/test-14-uuid.expected/initrd-root-fs.target.requires/sysroot.mount
@@ -0,0 +1 @@
+../sysroot.mount
\ No newline at end of file
diff --git a/test/test-fstab-generator/test-14-uuid.expected/initrd-usr-fs.target.requires/sysroot.mount b/test/test-fstab-generator/test-14-uuid.expected/initrd-usr-fs.target.requires/sysroot.mount
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/test/test-fstab-generator/test-14-uuid.expected/initrd-usr-fs.target.requires/sysroot.mount b/test/test-fstab-generator/test-14-uuid.expected/initrd-usr-fs.target.requires/sysroot.mount
new file mode 120000
index 0000000000..0c969cdbd4
--- /dev/null
+++ b/test/test-fstab-generator/test-14-uuid.expected/initrd-usr-fs.target.requires/sysroot.mount
@@ -0,0 +1 @@
+../sysroot.mount
\ No newline at end of file
diff --git a/test/test-fstab-generator/test-14-uuid.expected/systemd-fsck-root.service b/test/test-fstab-generator/test-14-uuid.expected/systemd-fsck-root.service
index 5945560287..cd9583c4dd 100644
--- a/test/test-fstab-generator/test-14-uuid.expected/systemd-fsck-root.service
+++ b/test/test-fstab-generator/test-14-uuid.expected/systemd-fsck-root.service
@@ -3,6 +3,7 @@
[Unit]
Description=File System Check on /dev/disk/by-uuid/3f5ad593-4546-4a94-a374-bcfb68aa11f7
Documentation=man:systemd-fsck-root.service(8)
+
DefaultDependencies=no
BindsTo=dev-disk-by\x2duuid-3f5ad593\x2d4546\x2d4a94\x2da374\x2dbcfb68aa11f7.device
Conflicts=shutdown.target
diff --git a/test/test-fstab-generator/test-15-partuuid.expected/initrd-root-fs.target.requires/sysroot.mount b/test/test-fstab-generator/test-15-partuuid.expected/initrd-root-fs.target.requires/sysroot.mount
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/test/test-fstab-generator/test-15-partuuid.expected/initrd-root-fs.target.requires/sysroot.mount b/test/test-fstab-generator/test-15-partuuid.expected/initrd-root-fs.target.requires/sysroot.mount
new file mode 120000
index 0000000000..0c969cdbd4
--- /dev/null
+++ b/test/test-fstab-generator/test-15-partuuid.expected/initrd-root-fs.target.requires/sysroot.mount
@@ -0,0 +1 @@
+../sysroot.mount
\ No newline at end of file
diff --git a/test/test-fstab-generator/test-15-partuuid.expected/initrd-usr-fs.target.requires/sysroot.mount b/test/test-fstab-generator/test-15-partuuid.expected/initrd-usr-fs.target.requires/sysroot.mount
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/test/test-fstab-generator/test-15-partuuid.expected/initrd-usr-fs.target.requires/sysroot.mount b/test/test-fstab-generator/test-15-partuuid.expected/initrd-usr-fs.target.requires/sysroot.mount
new file mode 120000
index 0000000000..0c969cdbd4
--- /dev/null
+++ b/test/test-fstab-generator/test-15-partuuid.expected/initrd-usr-fs.target.requires/sysroot.mount
@@ -0,0 +1 @@
+../sysroot.mount
\ No newline at end of file
diff --git a/test/test-fstab-generator/test-15-partuuid.expected/systemd-fsck-root.service b/test/test-fstab-generator/test-15-partuuid.expected/systemd-fsck-root.service
index aa1d455ecd..650ed8070a 100644
--- a/test/test-fstab-generator/test-15-partuuid.expected/systemd-fsck-root.service
+++ b/test/test-fstab-generator/test-15-partuuid.expected/systemd-fsck-root.service
@@ -3,6 +3,7 @@
[Unit]
Description=File System Check on /dev/disk/by-partuuid/3f5ad593-4546-4a94-a374-bcfb68aa11f7
Documentation=man:systemd-fsck-root.service(8)
+
DefaultDependencies=no
BindsTo=dev-disk-by\x2dpartuuid-3f5ad593\x2d4546\x2d4a94\x2da374\x2dbcfb68aa11f7.device
Conflicts=shutdown.target
diff --git a/test/test-fstab-generator/test-16-tmpfs.expected/initrd-root-fs.target.requires/sysroot.mount b/test/test-fstab-generator/test-16-tmpfs.expected/initrd-root-fs.target.requires/sysroot.mount
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/test/test-fstab-generator/test-16-tmpfs.expected/initrd-root-fs.target.requires/sysroot.mount b/test/test-fstab-generator/test-16-tmpfs.expected/initrd-root-fs.target.requires/sysroot.mount
new file mode 120000
index 0000000000..0c969cdbd4
--- /dev/null
+++ b/test/test-fstab-generator/test-16-tmpfs.expected/initrd-root-fs.target.requires/sysroot.mount
@@ -0,0 +1 @@
+../sysroot.mount
\ No newline at end of file
diff --git a/test/test-fstab-generator/test-16-tmpfs.expected/initrd-usr-fs.target.requires/sysroot.mount b/test/test-fstab-generator/test-16-tmpfs.expected/initrd-usr-fs.target.requires/sysroot.mount
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/test/test-fstab-generator/test-16-tmpfs.expected/initrd-usr-fs.target.requires/sysroot.mount b/test/test-fstab-generator/test-16-tmpfs.expected/initrd-usr-fs.target.requires/sysroot.mount
new file mode 120000
index 0000000000..0c969cdbd4
--- /dev/null
+++ b/test/test-fstab-generator/test-16-tmpfs.expected/initrd-usr-fs.target.requires/sysroot.mount
@@ -0,0 +1 @@
+../sysroot.mount
\ No newline at end of file
diff --git a/test/test-fstab-generator/test-17-initrd-sysroot.fstab.expected/initrd-fs.target.requires/sysroot-usr.mount b/test/test-fstab-generator/test-17-initrd-sysroot.fstab.expected/initrd-fs.target.requires/sysroot-usr.mount
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/test/test-fstab-generator/test-17-initrd-sysroot.fstab.expected/initrd-fs.target.requires/sysroot-usr.mount b/test/test-fstab-generator/test-17-initrd-sysroot.fstab.expected/initrd-fs.target.requires/sysroot-usr.mount
new file mode 120000
index 0000000000..8bcbb16eae
--- /dev/null
+++ b/test/test-fstab-generator/test-17-initrd-sysroot.fstab.expected/initrd-fs.target.requires/sysroot-usr.mount
@@ -0,0 +1 @@
+../sysroot-usr.mount
\ No newline at end of file
diff --git a/test/test-fstab-generator/test-17-initrd-sysroot.fstab.expected/initrd-root-fs.target.requires/sysroot.mount b/test/test-fstab-generator/test-17-initrd-sysroot.fstab.expected/initrd-root-fs.target.requires/sysroot.mount
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/test/test-fstab-generator/test-17-initrd-sysroot.fstab.expected/initrd-root-fs.target.requires/sysroot.mount b/test/test-fstab-generator/test-17-initrd-sysroot.fstab.expected/initrd-root-fs.target.requires/sysroot.mount
new file mode 120000
index 0000000000..0c969cdbd4
--- /dev/null
+++ b/test/test-fstab-generator/test-17-initrd-sysroot.fstab.expected/initrd-root-fs.target.requires/sysroot.mount
@@ -0,0 +1 @@
+../sysroot.mount
\ No newline at end of file
diff --git a/test/test-fstab-generator/test-17-initrd-sysroot.fstab.expected/initrd-usr-fs.target.requires/sysroot.mount b/test/test-fstab-generator/test-17-initrd-sysroot.fstab.expected/initrd-usr-fs.target.requires/sysroot.mount
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/test/test-fstab-generator/test-17-initrd-sysroot.fstab.expected/initrd-usr-fs.target.requires/sysroot.mount b/test/test-fstab-generator/test-17-initrd-sysroot.fstab.expected/initrd-usr-fs.target.requires/sysroot.mount
new file mode 120000
index 0000000000..0c969cdbd4
--- /dev/null
+++ b/test/test-fstab-generator/test-17-initrd-sysroot.fstab.expected/initrd-usr-fs.target.requires/sysroot.mount
@@ -0,0 +1 @@
+../sysroot.mount
\ No newline at end of file
diff --git a/test/test-fstab-generator/test-17-initrd-sysroot.fstab.expected/initrd-usr-fs.target.requires/sysusr-usr.mount b/test/test-fstab-generator/test-17-initrd-sysroot.fstab.expected/initrd-usr-fs.target.requires/sysusr-usr.mount
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/test/test-fstab-generator/test-17-initrd-sysroot.fstab.expected/initrd-usr-fs.target.requires/sysusr-usr.mount b/test/test-fstab-generator/test-17-initrd-sysroot.fstab.expected/initrd-usr-fs.target.requires/sysusr-usr.mount
new file mode 120000
index 0000000000..8fb2e18647
--- /dev/null
+++ b/test/test-fstab-generator/test-17-initrd-sysroot.fstab.expected/initrd-usr-fs.target.requires/sysusr-usr.mount
@@ -0,0 +1 @@
+../sysusr-usr.mount
\ No newline at end of file
diff --git a/test/test-fstab-generator/test-17-initrd-sysroot.fstab.expected/systemd-fsck-root.service b/test/test-fstab-generator/test-17-initrd-sysroot.fstab.expected/systemd-fsck-root.service
index 7f914fdd14..95d943b87a 100644
--- a/test/test-fstab-generator/test-17-initrd-sysroot.fstab.expected/systemd-fsck-root.service
+++ b/test/test-fstab-generator/test-17-initrd-sysroot.fstab.expected/systemd-fsck-root.service
@@ -3,6 +3,7 @@
[Unit]
Description=File System Check on /dev/sdx1
Documentation=man:systemd-fsck-root.service(8)
+
DefaultDependencies=no
BindsTo=dev-sdx1.device
Conflicts=shutdown.target

@ -0,0 +1,667 @@
From 9afc07262dd2b37a20094909ab0a8cddb29cefc8 Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Fri, 19 May 2023 09:31:51 +0900
Subject: [PATCH] test-fstab-generator: add tests for mount options
(cherry picked from commit 82c29dbee0ae4c438d25482083facc75f84bc5ee)
Related: #2190226
---
test/test-fstab-generator.sh | 9 +++++++++
.../foo.service.requires/mnt-requiredby.mount | 1 +
.../foo.service.wants/mnt-wantedby.mount | 1 +
.../50-root-device.conf | 5 +++++
.../sysroot.mount | 1 +
.../sysroot.mount | 1 +
...rder-systemd-growfs@mnt-growfs.service.conf | 4 ++++
.../local-fs.target.requires/mnt-after.mount | 1 +
.../mnt-automount1.automount | 1 +
.../local-fs.target.requires/mnt-before.mount | 1 +
.../local-fs.target.requires/mnt-growfs.mount | 1 +
.../local-fs.target.requires/mnt-mkfs.mount | 1 +
.../local-fs.target.requires/mnt-pcrfs.mount | 1 +
.../mnt-reqmounts.mount | 1 +
.../mnt-requires.mount | 1 +
.../local-fs.target.requires/mnt-rwonly.mount | 1 +
.../local-fs.target.requires/mnt-timeout.mount | 1 +
.../mnt-automount2.automount | 1 +
.../local-fs.target.wants/mnt-nofail.mount | 1 +
.../mnt-after.mount | 13 +++++++++++++
.../mnt-automount1.automount | 9 +++++++++
.../mnt-automount1.mount | 12 ++++++++++++
.../mnt-automount2.automount | 8 ++++++++
.../mnt-automount2.mount | 11 +++++++++++
.../mnt-before.mount | 13 +++++++++++++
.../mnt-growfs.mount | 12 ++++++++++++
.../systemd-growfs@mnt-growfs.service | 0
.../mnt-mkfs.mount | 13 +++++++++++++
.../systemd-makefs@dev-sdx12.service | 1 +
.../mnt-noauto.mount | 12 ++++++++++++
.../mnt-nofail.mount | 11 +++++++++++
.../mnt-pcrfs.mount | 12 ++++++++++++
.../mnt-reqmounts.mount | 13 +++++++++++++
.../mnt-requiredby.mount | 12 ++++++++++++
.../mnt-requires.mount | 14 ++++++++++++++
.../mnt-rwonly.mount | 13 +++++++++++++
.../mnt-timeout.mount | 13 +++++++++++++
.../mnt-wantedby.mount | 12 ++++++++++++
.../sysroot.mount | 13 +++++++++++++
.../systemd-fsck-root.service | 17 +++++++++++++++++
.../systemd-makefs@dev-sdx12.service | 18 ++++++++++++++++++
.../test-18-options.fstab.input | 16 ++++++++++++++++
42 files changed, 302 insertions(+)
create mode 120000 test/test-fstab-generator/test-18-options.fstab.expected/foo.service.requires/mnt-requiredby.mount
create mode 120000 test/test-fstab-generator/test-18-options.fstab.expected/foo.service.wants/mnt-wantedby.mount
create mode 100644 test/test-fstab-generator/test-18-options.fstab.expected/initrd-root-device.target.d/50-root-device.conf
create mode 120000 test/test-fstab-generator/test-18-options.fstab.expected/initrd-root-fs.target.requires/sysroot.mount
create mode 120000 test/test-fstab-generator/test-18-options.fstab.expected/initrd-usr-fs.target.requires/sysroot.mount
create mode 100644 test/test-fstab-generator/test-18-options.fstab.expected/local-fs.target.d/50-order-systemd-growfs@mnt-growfs.service.conf
create mode 120000 test/test-fstab-generator/test-18-options.fstab.expected/local-fs.target.requires/mnt-after.mount
create mode 120000 test/test-fstab-generator/test-18-options.fstab.expected/local-fs.target.requires/mnt-automount1.automount
create mode 120000 test/test-fstab-generator/test-18-options.fstab.expected/local-fs.target.requires/mnt-before.mount
create mode 120000 test/test-fstab-generator/test-18-options.fstab.expected/local-fs.target.requires/mnt-growfs.mount
create mode 120000 test/test-fstab-generator/test-18-options.fstab.expected/local-fs.target.requires/mnt-mkfs.mount
create mode 120000 test/test-fstab-generator/test-18-options.fstab.expected/local-fs.target.requires/mnt-pcrfs.mount
create mode 120000 test/test-fstab-generator/test-18-options.fstab.expected/local-fs.target.requires/mnt-reqmounts.mount
create mode 120000 test/test-fstab-generator/test-18-options.fstab.expected/local-fs.target.requires/mnt-requires.mount
create mode 120000 test/test-fstab-generator/test-18-options.fstab.expected/local-fs.target.requires/mnt-rwonly.mount
create mode 120000 test/test-fstab-generator/test-18-options.fstab.expected/local-fs.target.requires/mnt-timeout.mount
create mode 120000 test/test-fstab-generator/test-18-options.fstab.expected/local-fs.target.wants/mnt-automount2.automount
create mode 120000 test/test-fstab-generator/test-18-options.fstab.expected/local-fs.target.wants/mnt-nofail.mount
create mode 100644 test/test-fstab-generator/test-18-options.fstab.expected/mnt-after.mount
create mode 100644 test/test-fstab-generator/test-18-options.fstab.expected/mnt-automount1.automount
create mode 100644 test/test-fstab-generator/test-18-options.fstab.expected/mnt-automount1.mount
create mode 100644 test/test-fstab-generator/test-18-options.fstab.expected/mnt-automount2.automount
create mode 100644 test/test-fstab-generator/test-18-options.fstab.expected/mnt-automount2.mount
create mode 100644 test/test-fstab-generator/test-18-options.fstab.expected/mnt-before.mount
create mode 100644 test/test-fstab-generator/test-18-options.fstab.expected/mnt-growfs.mount
create mode 100644 test/test-fstab-generator/test-18-options.fstab.expected/mnt-growfs.mount.wants/systemd-growfs@mnt-growfs.service
create mode 100644 test/test-fstab-generator/test-18-options.fstab.expected/mnt-mkfs.mount
create mode 120000 test/test-fstab-generator/test-18-options.fstab.expected/mnt-mkfs.mount.requires/systemd-makefs@dev-sdx12.service
create mode 100644 test/test-fstab-generator/test-18-options.fstab.expected/mnt-noauto.mount
create mode 100644 test/test-fstab-generator/test-18-options.fstab.expected/mnt-nofail.mount
create mode 100644 test/test-fstab-generator/test-18-options.fstab.expected/mnt-pcrfs.mount
create mode 100644 test/test-fstab-generator/test-18-options.fstab.expected/mnt-reqmounts.mount
create mode 100644 test/test-fstab-generator/test-18-options.fstab.expected/mnt-requiredby.mount
create mode 100644 test/test-fstab-generator/test-18-options.fstab.expected/mnt-requires.mount
create mode 100644 test/test-fstab-generator/test-18-options.fstab.expected/mnt-rwonly.mount
create mode 100644 test/test-fstab-generator/test-18-options.fstab.expected/mnt-timeout.mount
create mode 100644 test/test-fstab-generator/test-18-options.fstab.expected/mnt-wantedby.mount
create mode 100644 test/test-fstab-generator/test-18-options.fstab.expected/sysroot.mount
create mode 100644 test/test-fstab-generator/test-18-options.fstab.expected/systemd-fsck-root.service
create mode 100644 test/test-fstab-generator/test-18-options.fstab.expected/systemd-makefs@dev-sdx12.service
create mode 100644 test/test-fstab-generator/test-18-options.fstab.input
diff --git a/test/test-fstab-generator.sh b/test/test-fstab-generator.sh
index c844d0dae1..7df67ce305 100755
--- a/test/test-fstab-generator.sh
+++ b/test/test-fstab-generator.sh
@@ -35,6 +35,15 @@ for f in "$src"/test-*.input; do
SYSTEMD_LOG_LEVEL=debug SYSTEMD_IN_INITRD=yes SYSTEMD_PROC_CMDLINE="fstab=no $(cat "$f")" $generator "$out" "$out" "$out"
fi
+ # The option x-systemd.growfs creates symlink to system's systemd-growfs@.service in .mount.wants directory.
+ # The system that the test is currently running on may not have or may have outdated unit file.
+ # Let's replace the symlink with an empty file.
+ for i in "$out"/*/systemd-growfs@*.service; do
+ [[ -L "$i" ]] || continue
+ rm "$i"
+ touch "$i"
+ done
+
# For split-usr system
for i in "$out"/systemd-*.service; do
sed -i -e 's:ExecStart=/lib/systemd/:ExecStart=/usr/lib/systemd/:' "$i"
diff --git a/test/test-fstab-generator/test-18-options.fstab.expected/foo.service.requires/mnt-requiredby.mount b/test/test-fstab-generator/test-18-options.fstab.expected/foo.service.requires/mnt-requiredby.mount
new file mode 120000
index 0000000000..6b012b09ef
--- /dev/null
+++ b/test/test-fstab-generator/test-18-options.fstab.expected/foo.service.requires/mnt-requiredby.mount
@@ -0,0 +1 @@
+../mnt-requiredby.mount
\ No newline at end of file
diff --git a/test/test-fstab-generator/test-18-options.fstab.expected/foo.service.wants/mnt-wantedby.mount b/test/test-fstab-generator/test-18-options.fstab.expected/foo.service.wants/mnt-wantedby.mount
new file mode 120000
index 0000000000..cdf21276b6
--- /dev/null
+++ b/test/test-fstab-generator/test-18-options.fstab.expected/foo.service.wants/mnt-wantedby.mount
@@ -0,0 +1 @@
+../mnt-wantedby.mount
\ No newline at end of file
diff --git a/test/test-fstab-generator/test-18-options.fstab.expected/initrd-root-device.target.d/50-root-device.conf b/test/test-fstab-generator/test-18-options.fstab.expected/initrd-root-device.target.d/50-root-device.conf
new file mode 100644
index 0000000000..47c4232223
--- /dev/null
+++ b/test/test-fstab-generator/test-18-options.fstab.expected/initrd-root-device.target.d/50-root-device.conf
@@ -0,0 +1,5 @@
+# Automatically generated by systemd-fstab-generator
+
+[Unit]
+Requires=dev-sdx1.device
+After=dev-sdx1.device
diff --git a/test/test-fstab-generator/test-18-options.fstab.expected/initrd-root-fs.target.requires/sysroot.mount b/test/test-fstab-generator/test-18-options.fstab.expected/initrd-root-fs.target.requires/sysroot.mount
new file mode 120000
index 0000000000..0c969cdbd4
--- /dev/null
+++ b/test/test-fstab-generator/test-18-options.fstab.expected/initrd-root-fs.target.requires/sysroot.mount
@@ -0,0 +1 @@
+../sysroot.mount
\ No newline at end of file
diff --git a/test/test-fstab-generator/test-18-options.fstab.expected/initrd-usr-fs.target.requires/sysroot.mount b/test/test-fstab-generator/test-18-options.fstab.expected/initrd-usr-fs.target.requires/sysroot.mount
new file mode 120000
index 0000000000..0c969cdbd4
--- /dev/null
+++ b/test/test-fstab-generator/test-18-options.fstab.expected/initrd-usr-fs.target.requires/sysroot.mount
@@ -0,0 +1 @@
+../sysroot.mount
\ No newline at end of file
diff --git a/test/test-fstab-generator/test-18-options.fstab.expected/local-fs.target.d/50-order-systemd-growfs@mnt-growfs.service.conf b/test/test-fstab-generator/test-18-options.fstab.expected/local-fs.target.d/50-order-systemd-growfs@mnt-growfs.service.conf
new file mode 100644
index 0000000000..ac770bcb51
--- /dev/null
+++ b/test/test-fstab-generator/test-18-options.fstab.expected/local-fs.target.d/50-order-systemd-growfs@mnt-growfs.service.conf
@@ -0,0 +1,4 @@
+# Automatically generated by systemd-fstab-generator
+
+[Unit]
+After=systemd-growfs@mnt-growfs.service
diff --git a/test/test-fstab-generator/test-18-options.fstab.expected/local-fs.target.requires/mnt-after.mount b/test/test-fstab-generator/test-18-options.fstab.expected/local-fs.target.requires/mnt-after.mount
new file mode 120000
index 0000000000..68364ef19c
--- /dev/null
+++ b/test/test-fstab-generator/test-18-options.fstab.expected/local-fs.target.requires/mnt-after.mount
@@ -0,0 +1 @@
+../mnt-after.mount
\ No newline at end of file
diff --git a/test/test-fstab-generator/test-18-options.fstab.expected/local-fs.target.requires/mnt-automount1.automount b/test/test-fstab-generator/test-18-options.fstab.expected/local-fs.target.requires/mnt-automount1.automount
new file mode 120000
index 0000000000..3638a8c90e
--- /dev/null
+++ b/test/test-fstab-generator/test-18-options.fstab.expected/local-fs.target.requires/mnt-automount1.automount
@@ -0,0 +1 @@
+../mnt-automount1.automount
\ No newline at end of file
diff --git a/test/test-fstab-generator/test-18-options.fstab.expected/local-fs.target.requires/mnt-before.mount b/test/test-fstab-generator/test-18-options.fstab.expected/local-fs.target.requires/mnt-before.mount
new file mode 120000
index 0000000000..3a50a40d5f
--- /dev/null
+++ b/test/test-fstab-generator/test-18-options.fstab.expected/local-fs.target.requires/mnt-before.mount
@@ -0,0 +1 @@
+../mnt-before.mount
\ No newline at end of file
diff --git a/test/test-fstab-generator/test-18-options.fstab.expected/local-fs.target.requires/mnt-growfs.mount b/test/test-fstab-generator/test-18-options.fstab.expected/local-fs.target.requires/mnt-growfs.mount
new file mode 120000
index 0000000000..cb05081e45
--- /dev/null
+++ b/test/test-fstab-generator/test-18-options.fstab.expected/local-fs.target.requires/mnt-growfs.mount
@@ -0,0 +1 @@
+../mnt-growfs.mount
\ No newline at end of file
diff --git a/test/test-fstab-generator/test-18-options.fstab.expected/local-fs.target.requires/mnt-mkfs.mount b/test/test-fstab-generator/test-18-options.fstab.expected/local-fs.target.requires/mnt-mkfs.mount
new file mode 120000
index 0000000000..51f897e419
--- /dev/null
+++ b/test/test-fstab-generator/test-18-options.fstab.expected/local-fs.target.requires/mnt-mkfs.mount
@@ -0,0 +1 @@
+../mnt-mkfs.mount
\ No newline at end of file
diff --git a/test/test-fstab-generator/test-18-options.fstab.expected/local-fs.target.requires/mnt-pcrfs.mount b/test/test-fstab-generator/test-18-options.fstab.expected/local-fs.target.requires/mnt-pcrfs.mount
new file mode 120000
index 0000000000..276dfc0731
--- /dev/null
+++ b/test/test-fstab-generator/test-18-options.fstab.expected/local-fs.target.requires/mnt-pcrfs.mount
@@ -0,0 +1 @@
+../mnt-pcrfs.mount
\ No newline at end of file
diff --git a/test/test-fstab-generator/test-18-options.fstab.expected/local-fs.target.requires/mnt-reqmounts.mount b/test/test-fstab-generator/test-18-options.fstab.expected/local-fs.target.requires/mnt-reqmounts.mount
new file mode 120000
index 0000000000..7efce8da9a
--- /dev/null
+++ b/test/test-fstab-generator/test-18-options.fstab.expected/local-fs.target.requires/mnt-reqmounts.mount
@@ -0,0 +1 @@
+../mnt-reqmounts.mount
\ No newline at end of file
diff --git a/test/test-fstab-generator/test-18-options.fstab.expected/local-fs.target.requires/mnt-requires.mount b/test/test-fstab-generator/test-18-options.fstab.expected/local-fs.target.requires/mnt-requires.mount
new file mode 120000
index 0000000000..34a6aad26f
--- /dev/null
+++ b/test/test-fstab-generator/test-18-options.fstab.expected/local-fs.target.requires/mnt-requires.mount
@@ -0,0 +1 @@
+../mnt-requires.mount
\ No newline at end of file
diff --git a/test/test-fstab-generator/test-18-options.fstab.expected/local-fs.target.requires/mnt-rwonly.mount b/test/test-fstab-generator/test-18-options.fstab.expected/local-fs.target.requires/mnt-rwonly.mount
new file mode 120000
index 0000000000..d03abd2353
--- /dev/null
+++ b/test/test-fstab-generator/test-18-options.fstab.expected/local-fs.target.requires/mnt-rwonly.mount
@@ -0,0 +1 @@
+../mnt-rwonly.mount
\ No newline at end of file
diff --git a/test/test-fstab-generator/test-18-options.fstab.expected/local-fs.target.requires/mnt-timeout.mount b/test/test-fstab-generator/test-18-options.fstab.expected/local-fs.target.requires/mnt-timeout.mount
new file mode 120000
index 0000000000..b0ec730825
--- /dev/null
+++ b/test/test-fstab-generator/test-18-options.fstab.expected/local-fs.target.requires/mnt-timeout.mount
@@ -0,0 +1 @@
+../mnt-timeout.mount
\ No newline at end of file
diff --git a/test/test-fstab-generator/test-18-options.fstab.expected/local-fs.target.wants/mnt-automount2.automount b/test/test-fstab-generator/test-18-options.fstab.expected/local-fs.target.wants/mnt-automount2.automount
new file mode 120000
index 0000000000..a30481ec1f
--- /dev/null
+++ b/test/test-fstab-generator/test-18-options.fstab.expected/local-fs.target.wants/mnt-automount2.automount
@@ -0,0 +1 @@
+../mnt-automount2.automount
\ No newline at end of file
diff --git a/test/test-fstab-generator/test-18-options.fstab.expected/local-fs.target.wants/mnt-nofail.mount b/test/test-fstab-generator/test-18-options.fstab.expected/local-fs.target.wants/mnt-nofail.mount
new file mode 120000
index 0000000000..b82bbad730
--- /dev/null
+++ b/test/test-fstab-generator/test-18-options.fstab.expected/local-fs.target.wants/mnt-nofail.mount
@@ -0,0 +1 @@
+../mnt-nofail.mount
\ No newline at end of file
diff --git a/test/test-fstab-generator/test-18-options.fstab.expected/mnt-after.mount b/test/test-fstab-generator/test-18-options.fstab.expected/mnt-after.mount
new file mode 100644
index 0000000000..2aebb686a7
--- /dev/null
+++ b/test/test-fstab-generator/test-18-options.fstab.expected/mnt-after.mount
@@ -0,0 +1,13 @@
+# Automatically generated by systemd-fstab-generator
+
+[Unit]
+Documentation=man:fstab(5) man:systemd-fstab-generator(8)
+SourcePath=/etc/fstab
+After=foo.service
+Before=local-fs.target
+After=blockdev@dev-sdx3.target
+
+[Mount]
+What=/dev/sdx3
+Where=/mnt/after
+Options=x-systemd.after=foo.service
diff --git a/test/test-fstab-generator/test-18-options.fstab.expected/mnt-automount1.automount b/test/test-fstab-generator/test-18-options.fstab.expected/mnt-automount1.automount
new file mode 100644
index 0000000000..e376689b67
--- /dev/null
+++ b/test/test-fstab-generator/test-18-options.fstab.expected/mnt-automount1.automount
@@ -0,0 +1,9 @@
+# Automatically generated by systemd-fstab-generator
+
+[Unit]
+SourcePath=/etc/fstab
+Documentation=man:fstab(5) man:systemd-fstab-generator(8)
+
+[Automount]
+Where=/mnt/automount1
+TimeoutIdleSec=30min
diff --git a/test/test-fstab-generator/test-18-options.fstab.expected/mnt-automount1.mount b/test/test-fstab-generator/test-18-options.fstab.expected/mnt-automount1.mount
new file mode 100644
index 0000000000..1413292c79
--- /dev/null
+++ b/test/test-fstab-generator/test-18-options.fstab.expected/mnt-automount1.mount
@@ -0,0 +1,12 @@
+# Automatically generated by systemd-fstab-generator
+
+[Unit]
+Documentation=man:fstab(5) man:systemd-fstab-generator(8)
+SourcePath=/etc/fstab
+Before=local-fs.target
+After=blockdev@dev-sdx9.target
+
+[Mount]
+What=/dev/sdx9
+Where=/mnt/automount1
+Options=x-systemd.automount,x-systemd.idle-timeout=30m
diff --git a/test/test-fstab-generator/test-18-options.fstab.expected/mnt-automount2.automount b/test/test-fstab-generator/test-18-options.fstab.expected/mnt-automount2.automount
new file mode 100644
index 0000000000..e05d3976ef
--- /dev/null
+++ b/test/test-fstab-generator/test-18-options.fstab.expected/mnt-automount2.automount
@@ -0,0 +1,8 @@
+# Automatically generated by systemd-fstab-generator
+
+[Unit]
+SourcePath=/etc/fstab
+Documentation=man:fstab(5) man:systemd-fstab-generator(8)
+
+[Automount]
+Where=/mnt/automount2
diff --git a/test/test-fstab-generator/test-18-options.fstab.expected/mnt-automount2.mount b/test/test-fstab-generator/test-18-options.fstab.expected/mnt-automount2.mount
new file mode 100644
index 0000000000..1eba08c9f7
--- /dev/null
+++ b/test/test-fstab-generator/test-18-options.fstab.expected/mnt-automount2.mount
@@ -0,0 +1,11 @@
+# Automatically generated by systemd-fstab-generator
+
+[Unit]
+Documentation=man:fstab(5) man:systemd-fstab-generator(8)
+SourcePath=/etc/fstab
+After=blockdev@dev-sdx10.target
+
+[Mount]
+What=/dev/sdx10
+Where=/mnt/automount2
+Options=x-systemd.automount,nofail
diff --git a/test/test-fstab-generator/test-18-options.fstab.expected/mnt-before.mount b/test/test-fstab-generator/test-18-options.fstab.expected/mnt-before.mount
new file mode 100644
index 0000000000..eea084b7b6
--- /dev/null
+++ b/test/test-fstab-generator/test-18-options.fstab.expected/mnt-before.mount
@@ -0,0 +1,13 @@
+# Automatically generated by systemd-fstab-generator
+
+[Unit]
+Documentation=man:fstab(5) man:systemd-fstab-generator(8)
+SourcePath=/etc/fstab
+Before=foo.service
+Before=local-fs.target
+After=blockdev@dev-sdx4.target
+
+[Mount]
+What=/dev/sdx4
+Where=/mnt/before
+Options=x-systemd.before=foo.service
diff --git a/test/test-fstab-generator/test-18-options.fstab.expected/mnt-growfs.mount b/test/test-fstab-generator/test-18-options.fstab.expected/mnt-growfs.mount
new file mode 100644
index 0000000000..bbe958c076
--- /dev/null
+++ b/test/test-fstab-generator/test-18-options.fstab.expected/mnt-growfs.mount
@@ -0,0 +1,12 @@
+# Automatically generated by systemd-fstab-generator
+
+[Unit]
+Documentation=man:fstab(5) man:systemd-fstab-generator(8)
+SourcePath=/etc/fstab
+Before=local-fs.target
+After=blockdev@dev-sdx13.target
+
+[Mount]
+What=/dev/sdx13
+Where=/mnt/growfs
+Options=x-systemd.growfs
diff --git a/test/test-fstab-generator/test-18-options.fstab.expected/mnt-growfs.mount.wants/systemd-growfs@mnt-growfs.service b/test/test-fstab-generator/test-18-options.fstab.expected/mnt-growfs.mount.wants/systemd-growfs@mnt-growfs.service
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/test/test-fstab-generator/test-18-options.fstab.expected/mnt-mkfs.mount b/test/test-fstab-generator/test-18-options.fstab.expected/mnt-mkfs.mount
new file mode 100644
index 0000000000..be4c8fa17f
--- /dev/null
+++ b/test/test-fstab-generator/test-18-options.fstab.expected/mnt-mkfs.mount
@@ -0,0 +1,13 @@
+# Automatically generated by systemd-fstab-generator
+
+[Unit]
+Documentation=man:fstab(5) man:systemd-fstab-generator(8)
+SourcePath=/etc/fstab
+Before=local-fs.target
+After=blockdev@dev-sdx12.target
+
+[Mount]
+What=/dev/sdx12
+Where=/mnt/mkfs
+Type=ext4
+Options=x-systemd.makefs
diff --git a/test/test-fstab-generator/test-18-options.fstab.expected/mnt-mkfs.mount.requires/systemd-makefs@dev-sdx12.service b/test/test-fstab-generator/test-18-options.fstab.expected/mnt-mkfs.mount.requires/systemd-makefs@dev-sdx12.service
new file mode 120000
index 0000000000..fe80548a68
--- /dev/null
+++ b/test/test-fstab-generator/test-18-options.fstab.expected/mnt-mkfs.mount.requires/systemd-makefs@dev-sdx12.service
@@ -0,0 +1 @@
+../systemd-makefs@dev-sdx12.service
\ No newline at end of file
diff --git a/test/test-fstab-generator/test-18-options.fstab.expected/mnt-noauto.mount b/test/test-fstab-generator/test-18-options.fstab.expected/mnt-noauto.mount
new file mode 100644
index 0000000000..4d52a6e698
--- /dev/null
+++ b/test/test-fstab-generator/test-18-options.fstab.expected/mnt-noauto.mount
@@ -0,0 +1,12 @@
+# Automatically generated by systemd-fstab-generator
+
+[Unit]
+Documentation=man:fstab(5) man:systemd-fstab-generator(8)
+SourcePath=/etc/fstab
+Before=local-fs.target
+After=blockdev@dev-sdx15.target
+
+[Mount]
+What=/dev/sdx15
+Where=/mnt/noauto
+Options=noauto
diff --git a/test/test-fstab-generator/test-18-options.fstab.expected/mnt-nofail.mount b/test/test-fstab-generator/test-18-options.fstab.expected/mnt-nofail.mount
new file mode 100644
index 0000000000..3c20b652b0
--- /dev/null
+++ b/test/test-fstab-generator/test-18-options.fstab.expected/mnt-nofail.mount
@@ -0,0 +1,11 @@
+# Automatically generated by systemd-fstab-generator
+
+[Unit]
+Documentation=man:fstab(5) man:systemd-fstab-generator(8)
+SourcePath=/etc/fstab
+After=blockdev@dev-sdx16.target
+
+[Mount]
+What=/dev/sdx16
+Where=/mnt/nofail
+Options=nofail
diff --git a/test/test-fstab-generator/test-18-options.fstab.expected/mnt-pcrfs.mount b/test/test-fstab-generator/test-18-options.fstab.expected/mnt-pcrfs.mount
new file mode 100644
index 0000000000..2c070e695a
--- /dev/null
+++ b/test/test-fstab-generator/test-18-options.fstab.expected/mnt-pcrfs.mount
@@ -0,0 +1,12 @@
+# Automatically generated by systemd-fstab-generator
+
+[Unit]
+Documentation=man:fstab(5) man:systemd-fstab-generator(8)
+SourcePath=/etc/fstab
+Before=local-fs.target
+After=blockdev@dev-sdx14.target
+
+[Mount]
+What=/dev/sdx14
+Where=/mnt/pcrfs
+Options=x-systemd.pcrfs
diff --git a/test/test-fstab-generator/test-18-options.fstab.expected/mnt-reqmounts.mount b/test/test-fstab-generator/test-18-options.fstab.expected/mnt-reqmounts.mount
new file mode 100644
index 0000000000..c21ccd27ba
--- /dev/null
+++ b/test/test-fstab-generator/test-18-options.fstab.expected/mnt-reqmounts.mount
@@ -0,0 +1,13 @@
+# Automatically generated by systemd-fstab-generator
+
+[Unit]
+Documentation=man:fstab(5) man:systemd-fstab-generator(8)
+SourcePath=/etc/fstab
+RequiresMountsFor=/hoge
+Before=local-fs.target
+After=blockdev@dev-sdx6.target
+
+[Mount]
+What=/dev/sdx6
+Where=/mnt/reqmounts
+Options=x-systemd.requires-mounts-for=/hoge
diff --git a/test/test-fstab-generator/test-18-options.fstab.expected/mnt-requiredby.mount b/test/test-fstab-generator/test-18-options.fstab.expected/mnt-requiredby.mount
new file mode 100644
index 0000000000..5edc4ddf22
--- /dev/null
+++ b/test/test-fstab-generator/test-18-options.fstab.expected/mnt-requiredby.mount
@@ -0,0 +1,12 @@
+# Automatically generated by systemd-fstab-generator
+
+[Unit]
+Documentation=man:fstab(5) man:systemd-fstab-generator(8)
+SourcePath=/etc/fstab
+Before=local-fs.target
+After=blockdev@dev-sdx8.target
+
+[Mount]
+What=/dev/sdx8
+Where=/mnt/requiredby
+Options=x-systemd.required-by=foo.service
diff --git a/test/test-fstab-generator/test-18-options.fstab.expected/mnt-requires.mount b/test/test-fstab-generator/test-18-options.fstab.expected/mnt-requires.mount
new file mode 100644
index 0000000000..8386616593
--- /dev/null
+++ b/test/test-fstab-generator/test-18-options.fstab.expected/mnt-requires.mount
@@ -0,0 +1,14 @@
+# Automatically generated by systemd-fstab-generator
+
+[Unit]
+Documentation=man:fstab(5) man:systemd-fstab-generator(8)
+SourcePath=/etc/fstab
+After=foo.service
+Requires=foo.service
+Before=local-fs.target
+After=blockdev@dev-sdx5.target
+
+[Mount]
+What=/dev/sdx5
+Where=/mnt/requires
+Options=x-systemd.requires=foo.service
diff --git a/test/test-fstab-generator/test-18-options.fstab.expected/mnt-rwonly.mount b/test/test-fstab-generator/test-18-options.fstab.expected/mnt-rwonly.mount
new file mode 100644
index 0000000000..8649734386
--- /dev/null
+++ b/test/test-fstab-generator/test-18-options.fstab.expected/mnt-rwonly.mount
@@ -0,0 +1,13 @@
+# Automatically generated by systemd-fstab-generator
+
+[Unit]
+Documentation=man:fstab(5) man:systemd-fstab-generator(8)
+SourcePath=/etc/fstab
+Before=local-fs.target
+After=blockdev@dev-sdx11.target
+
+[Mount]
+What=/dev/sdx11
+Where=/mnt/rwonly
+Options=x-systemd.rw-only
+ReadWriteOnly=yes
diff --git a/test/test-fstab-generator/test-18-options.fstab.expected/mnt-timeout.mount b/test/test-fstab-generator/test-18-options.fstab.expected/mnt-timeout.mount
new file mode 100644
index 0000000000..09d772a52b
--- /dev/null
+++ b/test/test-fstab-generator/test-18-options.fstab.expected/mnt-timeout.mount
@@ -0,0 +1,13 @@
+# Automatically generated by systemd-fstab-generator
+
+[Unit]
+Documentation=man:fstab(5) man:systemd-fstab-generator(8)
+SourcePath=/etc/fstab
+Before=local-fs.target
+After=blockdev@dev-sdx2.target
+
+[Mount]
+What=/dev/sdx2
+Where=/mnt/timeout
+TimeoutSec=10min
+Options=x-systemd.mount-timeout=10m
diff --git a/test/test-fstab-generator/test-18-options.fstab.expected/mnt-wantedby.mount b/test/test-fstab-generator/test-18-options.fstab.expected/mnt-wantedby.mount
new file mode 100644
index 0000000000..e12df820d4
--- /dev/null
+++ b/test/test-fstab-generator/test-18-options.fstab.expected/mnt-wantedby.mount
@@ -0,0 +1,12 @@
+# Automatically generated by systemd-fstab-generator
+
+[Unit]
+Documentation=man:fstab(5) man:systemd-fstab-generator(8)
+SourcePath=/etc/fstab
+Before=local-fs.target
+After=blockdev@dev-sdx7.target
+
+[Mount]
+What=/dev/sdx7
+Where=/mnt/wantedby
+Options=x-systemd.wanted-by=foo.service
diff --git a/test/test-fstab-generator/test-18-options.fstab.expected/sysroot.mount b/test/test-fstab-generator/test-18-options.fstab.expected/sysroot.mount
new file mode 100644
index 0000000000..0e8a701be9
--- /dev/null
+++ b/test/test-fstab-generator/test-18-options.fstab.expected/sysroot.mount
@@ -0,0 +1,13 @@
+# Automatically generated by systemd-fstab-generator
+
+[Unit]
+Documentation=man:fstab(5) man:systemd-fstab-generator(8)
+SourcePath=/etc/fstab
+Before=initrd-root-fs.target
+Requires=systemd-fsck-root.service
+After=systemd-fsck-root.service
+After=blockdev@dev-sdx1.target
+
+[Mount]
+What=/dev/sdx1
+Where=/sysroot
diff --git a/test/test-fstab-generator/test-18-options.fstab.expected/systemd-fsck-root.service b/test/test-fstab-generator/test-18-options.fstab.expected/systemd-fsck-root.service
new file mode 100644
index 0000000000..95d943b87a
--- /dev/null
+++ b/test/test-fstab-generator/test-18-options.fstab.expected/systemd-fsck-root.service
@@ -0,0 +1,17 @@
+# Automatically generated by systemd-fstab-generator
+
+[Unit]
+Description=File System Check on /dev/sdx1
+Documentation=man:systemd-fsck-root.service(8)
+
+DefaultDependencies=no
+BindsTo=dev-sdx1.device
+Conflicts=shutdown.target
+After=initrd-root-device.target local-fs-pre.target dev-sdx1.device
+Before=shutdown.target
+
+[Service]
+Type=oneshot
+RemainAfterExit=yes
+ExecStart=/usr/lib/systemd/systemd-fsck /dev/sdx1
+TimeoutSec=0
diff --git a/test/test-fstab-generator/test-18-options.fstab.expected/systemd-makefs@dev-sdx12.service b/test/test-fstab-generator/test-18-options.fstab.expected/systemd-makefs@dev-sdx12.service
new file mode 100644
index 0000000000..303c1ee680
--- /dev/null
+++ b/test/test-fstab-generator/test-18-options.fstab.expected/systemd-makefs@dev-sdx12.service
@@ -0,0 +1,18 @@
+# Automatically generated by systemd-fstab-generator
+
+[Unit]
+Description=Make File System on %f
+Documentation=man:systemd-makefs@.service(8)
+
+DefaultDependencies=no
+BindsTo=%i.device
+After=%i.device
+Before=systemd-fsck@%i.service mnt-mkfs.mount
+Conflicts=shutdown.target
+Before=shutdown.target
+
+[Service]
+Type=oneshot
+RemainAfterExit=yes
+ExecStart=/usr/lib/systemd/systemd-makefs ext4 /dev/sdx12
+TimeoutSec=0
diff --git a/test/test-fstab-generator/test-18-options.fstab.input b/test/test-fstab-generator/test-18-options.fstab.input
new file mode 100644
index 0000000000..98ef0b9fba
--- /dev/null
+++ b/test/test-fstab-generator/test-18-options.fstab.input
@@ -0,0 +1,16 @@
+/dev/sdx1 /sysroot auto defaults 0 1
+/dev/sdx2 /mnt/timeout auto x-systemd.mount-timeout=10m 0 0
+/dev/sdx3 /mnt/after auto x-systemd.after=foo.service 0 0
+/dev/sdx4 /mnt/before auto x-systemd.before=foo.service 0 0
+/dev/sdx5 /mnt/requires auto x-systemd.requires=foo.service 0 0
+/dev/sdx6 /mnt/reqmounts auto x-systemd.requires-mounts-for=/hoge 0 0
+/dev/sdx7 /mnt/wantedby auto x-systemd.wanted-by=foo.service 0 0
+/dev/sdx8 /mnt/requiredby auto x-systemd.required-by=foo.service 0 0
+/dev/sdx9 /mnt/automount1 auto x-systemd.automount,x-systemd.idle-timeout=30m 0 0
+/dev/sdx10 /mnt/automount2 auto x-systemd.automount,nofail 0 0
+/dev/sdx11 /mnt/rwonly auto x-systemd.rw-only 0 0
+/dev/sdx12 /mnt/mkfs ext4 x-systemd.makefs 0 0
+/dev/sdx13 /mnt/growfs auto x-systemd.growfs 0 0
+/dev/sdx14 /mnt/pcrfs auto x-systemd.pcrfs 0 0
+/dev/sdx15 /mnt/noauto auto noauto 0 0
+/dev/sdx16 /mnt/nofail auto nofail 0 0

@ -0,0 +1,408 @@
From ddcdc462b935fc210677f664d61cf556fb2abe0f Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Mon, 8 May 2023 19:45:34 +0900
Subject: [PATCH] fstab-generator: split out several functions from
parse_fstab()
No functional changes, just refactoring and preparation for later
commits.
(cherry picked from commit cfeb4d378ecd1ea50c0a0248c384e49983511fa8)
Related: #2190226
---
src/fstab-generator/fstab-generator.c | 323 ++++++++++++++------------
1 file changed, 171 insertions(+), 152 deletions(-)
diff --git a/src/fstab-generator/fstab-generator.c b/src/fstab-generator/fstab-generator.c
index bbd669e477..4ea95f29eb 100644
--- a/src/fstab-generator/fstab-generator.c
+++ b/src/fstab-generator/fstab-generator.c
@@ -99,7 +99,7 @@ static int write_what(FILE *f, const char *what) {
static int add_swap(
const char *source,
const char *what,
- struct mntent *me,
+ const char *options,
MountPointFlags flags) {
_cleanup_free_ char *name = NULL;
@@ -107,7 +107,6 @@ static int add_swap(
int r;
assert(what);
- assert(me);
if (!arg_swap_enabled) {
log_info("Swap unit generation disabled on kernel command line, ignoring fstab swap entry for %s.", what);
@@ -155,7 +154,7 @@ static int add_swap(
if (r < 0)
return r;
- r = write_options(f, me->mnt_opts);
+ r = write_options(f, options);
if (r < 0)
return r;
@@ -164,7 +163,7 @@ static int add_swap(
return log_error_errno(r, "Failed to write unit file %s: %m", name);
/* use what as where, to have a nicer error message */
- r = generator_write_timeouts(arg_dest, what, what, me->mnt_opts, NULL);
+ r = generator_write_timeouts(arg_dest, what, what, options, NULL);
if (r < 0)
return r;
@@ -188,18 +187,14 @@ static int add_swap(
return true;
}
-static bool mount_is_network(struct mntent *me) {
- assert(me);
-
- return fstab_test_option(me->mnt_opts, "_netdev\0") ||
- fstype_is_network(me->mnt_type);
+static bool mount_is_network(const char *fstype, const char *options) {
+ return fstab_test_option(options, "_netdev\0") ||
+ (fstype && fstype_is_network(fstype));
}
-static bool mount_in_initrd(struct mntent *me) {
- assert(me);
-
- return fstab_test_option(me->mnt_opts, "x-initrd.mount\0") ||
- path_equal(me->mnt_dir, "/usr");
+static bool mount_in_initrd(const char *where, const char *options) {
+ return fstab_test_option(options, "x-initrd.mount\0") ||
+ (where && path_equal(where, "/usr"));
}
static int write_timeout(
@@ -634,6 +629,20 @@ static const char* sysroot_fstab_path(void) {
return getenv("SYSTEMD_SYSROOT_FSTAB") ?: "/sysroot/etc/fstab";
}
+static bool sysfs_check(void) {
+ static int cached = -1;
+ int r;
+
+ if (cached < 0) {
+ r = getenv_bool_secure("SYSTEMD_SYSFS_CHECK");
+ if (r < 0 && r != -ENXIO)
+ log_debug_errno(r, "Failed to parse $SYSTEMD_SYSFS_CHECK, ignoring: %m");
+ cached = r != 0;
+ }
+
+ return cached;
+}
+
static int add_sysusr_sysroot_usr_bind_mount(const char *source) {
return add_mount(source,
arg_dest,
@@ -647,11 +656,153 @@ static int add_sysusr_sysroot_usr_bind_mount(const char *source) {
SPECIAL_INITRD_FS_TARGET);
}
+static MountPointFlags fstab_options_to_flags(const char *options, bool is_swap) {
+ MountPointFlags flags = 0;
+
+ if (fstab_test_option(options, "x-systemd.makefs\0"))
+ flags |= MOUNT_MAKEFS;
+ if (fstab_test_option(options, "x-systemd.growfs\0"))
+ flags |= MOUNT_GROWFS;
+ if (fstab_test_yes_no_option(options, "noauto\0" "auto\0"))
+ flags |= MOUNT_NOAUTO;
+ if (fstab_test_yes_no_option(options, "nofail\0" "fail\0"))
+ flags |= MOUNT_NOFAIL;
+
+ if (!is_swap) {
+ if (fstab_test_option(options, "x-systemd.rw-only\0"))
+ flags |= MOUNT_RW_ONLY;
+ if (fstab_test_option(options,
+ "comment=systemd.automount\0"
+ "x-systemd.automount\0"))
+ flags |= MOUNT_AUTOMOUNT;
+ }
+
+ return flags;
+}
+
+static int parse_fstab_one(
+ const char *source,
+ const char *what_original,
+ const char *where_original,
+ const char *fstype,
+ const char *options,
+ int passno,
+ bool initrd) {
+
+ _cleanup_free_ char *what = NULL, *where = NULL, *canonical_where = NULL;
+ MountPointFlags flags;
+ int r;
+
+ assert(what_original);
+ assert(where_original);
+ assert(fstype);
+ assert(options);
+
+ if (initrd && !mount_in_initrd(where_original, options))
+ return 0;
+
+ what = fstab_node_to_udev_node(what_original);
+ if (!what)
+ return log_oom();
+
+ if (path_is_read_only_fs("/sys") > 0 &&
+ (streq(what, "sysfs") ||
+ (sysfs_check() && is_device_path(what)))) {
+ log_info("/sys/ is read-only (running in a container?), ignoring mount for %s.", what);
+ return 0;
+ }
+
+ where = strdup(where_original);
+ if (!where)
+ return log_oom();
+
+ if (is_path(where)) {
+ path_simplify(where);
+
+ /* Follow symlinks here; see 5261ba901845c084de5a8fd06500ed09bfb0bd80 which makes sense for
+ * mount units, but causes problems since it historically worked to have symlinks in e.g.
+ * /etc/fstab. So we canonicalize here. Note that we use CHASE_NONEXISTENT to handle the case
+ * where a symlink refers to another mount target; this works assuming the sub-mountpoint
+ * target is the final directory.
+ *
+ * FIXME: when chase() learns to chase non-existent paths, use this here and
+ * drop the prefixing with /sysroot on error below.
+ */
+ r = chase_symlinks(where, initrd ? "/sysroot" : NULL, CHASE_PREFIX_ROOT | CHASE_NONEXISTENT,
+ &canonical_where, NULL);
+ if (r < 0) {
+ /* If we can't canonicalize, continue as if it wasn't a symlink */
+ log_debug_errno(r, "Failed to read symlink target for %s, using as-is: %m", where);
+
+ if (initrd) {
+ canonical_where = path_join("/sysroot", where);
+ if (!canonical_where)
+ return log_oom();
+ }
+
+ } else if (streq(canonical_where, where)) /* If it was fully canonicalized, suppress the change */
+ canonical_where = mfree(canonical_where);
+ else
+ log_debug("Canonicalized what=%s where=%s to %s", what, where, canonical_where);
+ }
+
+ flags = fstab_options_to_flags(options, streq_ptr(fstype, "swap"));
+
+ log_debug("Found entry what=%s where=%s type=%s makefs=%s growfs=%s noauto=%s nofail=%s",
+ what, where, strna(fstype),
+ yes_no(flags & MOUNT_MAKEFS), yes_no(flags & MOUNT_GROWFS),
+ yes_no(flags & MOUNT_NOAUTO), yes_no(flags & MOUNT_NOFAIL));
+
+ if (streq_ptr(fstype, "swap"))
+ return add_swap(source, what, options, flags);
+
+ bool is_sysroot = in_initrd() && path_equal(where, "/sysroot");
+ /* See comment from add_sysroot_usr_mount() about the need for extra indirection in case /usr needs
+ * to be mounted in order for the root fs to be synthesized based on configuration included in /usr/,
+ * e.g. systemd-repart. */
+ bool is_sysroot_usr = in_initrd() && path_equal(where, "/sysroot/usr");
+
+ const char *target_unit =
+ initrd ? SPECIAL_INITRD_FS_TARGET :
+ is_sysroot ? SPECIAL_INITRD_ROOT_FS_TARGET :
+ is_sysroot_usr ? SPECIAL_INITRD_USR_FS_TARGET :
+ mount_is_network(fstype, options) ? SPECIAL_REMOTE_FS_TARGET :
+ SPECIAL_LOCAL_FS_TARGET;
+
+ if (is_sysroot && is_device_path(what)) {
+ r = generator_write_initrd_root_device_deps(arg_dest, what);
+ if (r < 0)
+ return r;
+ }
+
+ r = add_mount(source,
+ arg_dest,
+ what,
+ is_sysroot_usr ? "/sysusr/usr" : canonical_where ?: where,
+ !is_sysroot_usr && canonical_where ? where : NULL,
+ fstype,
+ options,
+ passno,
+ flags,
+ target_unit);
+ if (r <= 0)
+ return r;
+
+ if (is_sysroot_usr) {
+ log_debug("Synthesizing fstab entry what=/sysusr/usr where=/sysroot/usr opts=bind");
+ r = add_sysusr_sysroot_usr_bind_mount(source);
+ if (r < 0)
+ return r;
+ }
+
+ return true;
+}
+
static int parse_fstab(bool initrd) {
_cleanup_endmntent_ FILE *f = NULL;
const char *fstab;
struct mntent *me;
- int r = 0, sysfs_check = -1;
+ int r, ret = 0;
if (initrd)
fstab = sysroot_fstab_path();
@@ -671,146 +822,14 @@ static int parse_fstab(bool initrd) {
}
while ((me = getmntent(f))) {
- _cleanup_free_ char *where = NULL, *what = NULL, *canonical_where = NULL;
- bool makefs, growfs, noauto, nofail;
- MountPointFlags flags;
- int k;
-
- if (initrd && !mount_in_initrd(me))
- continue;
-
- what = fstab_node_to_udev_node(me->mnt_fsname);
- if (!what)
- return log_oom();
-
- if (path_is_read_only_fs("/sys") > 0) {
- if (streq(what, "sysfs")) {
- log_info("Running in a container, ignoring fstab entry for %s.", what);
- continue;
- }
-
- if (sysfs_check < 0) {
- r = getenv_bool_secure("SYSTEMD_SYSFS_CHECK");
- if (r < 0 && r != -ENXIO)
- log_debug_errno(r, "Failed to parse $SYSTEMD_SYSFS_CHECK, ignoring: %m");
- sysfs_check = r != 0;
- }
-
- if (sysfs_check && is_device_path(what)) {
- log_info("/sys/ is read-only (running in a container?), ignoring fstab device entry for %s.", what);
- continue;
- }
- }
-
- where = strdup(me->mnt_dir);
- if (!where)
- return log_oom();
-
- if (is_path(where)) {
- path_simplify(where);
-
- /* Follow symlinks here; see 5261ba901845c084de5a8fd06500ed09bfb0bd80 which makes sense for
- * mount units, but causes problems since it historically worked to have symlinks in e.g.
- * /etc/fstab. So we canonicalize here. Note that we use CHASE_NONEXISTENT to handle the case
- * where a symlink refers to another mount target; this works assuming the sub-mountpoint
- * target is the final directory.
- *
- * FIXME: when chase_symlinks() learns to chase non-existent paths, use this here and
- * drop the prefixing with /sysroot on error below.
- */
- k = chase_symlinks(where, initrd ? "/sysroot" : NULL,
- CHASE_PREFIX_ROOT | CHASE_NONEXISTENT,
- &canonical_where, NULL);
- if (k < 0) {
- /* If we can't canonicalize, continue as if it wasn't a symlink */
- log_debug_errno(k, "Failed to read symlink target for %s, using as-is: %m", where);
-
- if (initrd) {
- canonical_where = path_join("/sysroot", where);
- if (!canonical_where)
- return log_oom();
- }
-
- } else if (streq(canonical_where, where)) /* If it was fully canonicalized, suppress the change */
- canonical_where = mfree(canonical_where);
- else
- log_debug("Canonicalized what=%s where=%s to %s", what, where, canonical_where);
- }
-
- makefs = fstab_test_option(me->mnt_opts, "x-systemd.makefs\0");
- growfs = fstab_test_option(me->mnt_opts, "x-systemd.growfs\0");
- noauto = fstab_test_yes_no_option(me->mnt_opts, "noauto\0" "auto\0");
- nofail = fstab_test_yes_no_option(me->mnt_opts, "nofail\0" "fail\0");
-
- log_debug("Found entry what=%s where=%s type=%s makefs=%s growfs=%s noauto=%s nofail=%s",
- what, where, me->mnt_type,
- yes_no(makefs), yes_no(growfs),
- yes_no(noauto), yes_no(nofail));
-
- flags = makefs * MOUNT_MAKEFS |
- growfs * MOUNT_GROWFS |
- noauto * MOUNT_NOAUTO |
- nofail * MOUNT_NOFAIL;
-
- if (streq(me->mnt_type, "swap"))
- k = add_swap(fstab, what, me, flags);
- else {
- bool rw_only, automount, is_sysroot, is_sysroot_usr;
-
- rw_only = fstab_test_option(me->mnt_opts, "x-systemd.rw-only\0");
- automount = fstab_test_option(me->mnt_opts,
- "comment=systemd.automount\0"
- "x-systemd.automount\0");
-
- flags |= rw_only * MOUNT_RW_ONLY |
- automount * MOUNT_AUTOMOUNT;
-
- is_sysroot = in_initrd() && path_equal(where, "/sysroot");
- /* See comment from add_sysroot_usr_mount about the need for extra indirection
- * in case /usr needs to be mounted in order for the root fs to be synthesized
- * based on configuration included in /usr/, e.g. systemd-repart. */
- is_sysroot_usr = in_initrd() && path_equal(where, "/sysroot/usr");
-
- const char *target_unit =
- initrd ? SPECIAL_INITRD_FS_TARGET :
- is_sysroot ? SPECIAL_INITRD_ROOT_FS_TARGET :
- is_sysroot_usr ? SPECIAL_INITRD_USR_FS_TARGET :
- mount_is_network(me) ? SPECIAL_REMOTE_FS_TARGET :
- SPECIAL_LOCAL_FS_TARGET;
-
- if (is_sysroot && is_device_path(what)) {
- r = generator_write_initrd_root_device_deps(arg_dest, what);
- if (r < 0)
- return r;
- }
-
- k = add_mount(fstab,
- arg_dest,
- what,
- is_sysroot_usr ? "/sysusr/usr" : canonical_where ?: where,
- !is_sysroot_usr && canonical_where ? where : NULL,
- me->mnt_type,
- me->mnt_opts,
- me->mnt_passno,
- flags,
- target_unit);
-
- if (is_sysroot_usr && k >= 0) {
- log_debug("Synthesizing fstab entry what=/sysusr/usr where=/sysroot/usr opts=bind");
-
- r = add_sysusr_sysroot_usr_bind_mount(fstab);
- if (r != 0)
- k = r;
- }
- }
-
- if (arg_sysroot_check && k > 0)
+ r = parse_fstab_one(fstab, me->mnt_fsname, me->mnt_dir, me->mnt_type, me->mnt_opts, me->mnt_passno, initrd);
+ if (r < 0 && ret >= 0)
+ ret = r;
+ if (arg_sysroot_check && r > 0)
return true; /* We found a mount or swap that would be started… */
- if (r >= 0 && k < 0)
- r = k;
}
- return r;
+ return ret;
}
static int sysroot_is_nfsroot(void) {

@ -0,0 +1,81 @@
From 90c66a0982b41c38cfd027a2bb3e6b33d0744e68 Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Fri, 12 May 2023 16:08:32 +0900
Subject: [PATCH] fstab-generator: call add_swap() earlier
As 'where' field will be ignored for swap entry.
(cherry picked from commit 256604ccddd41a16de329ff792c5f49d6750e510)
Related: #2190226
---
src/fstab-generator/fstab-generator.c | 21 +++++++++++++++------
1 file changed, 15 insertions(+), 6 deletions(-)
diff --git a/src/fstab-generator/fstab-generator.c b/src/fstab-generator/fstab-generator.c
index 4ea95f29eb..742a84b485 100644
--- a/src/fstab-generator/fstab-generator.c
+++ b/src/fstab-generator/fstab-generator.c
@@ -128,6 +128,11 @@ static int add_swap(
return true;
}
+ log_debug("Found swap entry what=%s makefs=%s growfs=%s noauto=%s nofail=%s",
+ what,
+ yes_no(flags & MOUNT_MAKEFS), yes_no(flags & MOUNT_GROWFS),
+ yes_no(flags & MOUNT_NOAUTO), yes_no(flags & MOUNT_NOFAIL));
+
r = unit_name_from_path(what, ".swap", &name);
if (r < 0)
return log_error_errno(r, "Failed to generate unit name: %m");
@@ -691,16 +696,18 @@ static int parse_fstab_one(
_cleanup_free_ char *what = NULL, *where = NULL, *canonical_where = NULL;
MountPointFlags flags;
+ bool is_swap;
int r;
assert(what_original);
- assert(where_original);
assert(fstype);
assert(options);
if (initrd && !mount_in_initrd(where_original, options))
return 0;
+ is_swap = streq_ptr(fstype, "swap");
+
what = fstab_node_to_udev_node(what_original);
if (!what)
return log_oom();
@@ -712,6 +719,13 @@ static int parse_fstab_one(
return 0;
}
+ flags = fstab_options_to_flags(options, is_swap);
+
+ if (is_swap)
+ return add_swap(source, what, options, flags);
+
+ assert(where_original); /* 'where' is not necessary for swap entry. */
+
where = strdup(where_original);
if (!where)
return log_oom();
@@ -746,16 +760,11 @@ static int parse_fstab_one(
log_debug("Canonicalized what=%s where=%s to %s", what, where, canonical_where);
}
- flags = fstab_options_to_flags(options, streq_ptr(fstype, "swap"));
-
log_debug("Found entry what=%s where=%s type=%s makefs=%s growfs=%s noauto=%s nofail=%s",
what, where, strna(fstype),
yes_no(flags & MOUNT_MAKEFS), yes_no(flags & MOUNT_GROWFS),
yes_no(flags & MOUNT_NOAUTO), yes_no(flags & MOUNT_NOFAIL));
- if (streq_ptr(fstype, "swap"))
- return add_swap(source, what, options, flags);
-
bool is_sysroot = in_initrd() && path_equal(where, "/sysroot");
/* See comment from add_sysroot_usr_mount() about the need for extra indirection in case /usr needs
* to be mounted in order for the root fs to be synthesized based on configuration included in /usr/,

@ -0,0 +1,41 @@
From 6858b1611dd198607c246b835d8840d15d8f09e5 Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Wed, 24 May 2023 07:24:52 +0900
Subject: [PATCH] fstab-generator: refuse to add swap earlier if disabled
No functional change, preparation for later commits.
(cherry picked from commit 9445623363fc47ee5a9265adeb9f4ca1a80ebfe4)
Related: #2190226
---
src/fstab-generator/fstab-generator.c | 9 ++++-----
1 file changed, 4 insertions(+), 5 deletions(-)
diff --git a/src/fstab-generator/fstab-generator.c b/src/fstab-generator/fstab-generator.c
index 742a84b485..2cd4de29f0 100644
--- a/src/fstab-generator/fstab-generator.c
+++ b/src/fstab-generator/fstab-generator.c
@@ -108,11 +108,6 @@ static int add_swap(
assert(what);
- if (!arg_swap_enabled) {
- log_info("Swap unit generation disabled on kernel command line, ignoring fstab swap entry for %s.", what);
- return 0;
- }
-
if (access("/proc/swaps", F_OK) < 0) {
log_info("Swap not supported, ignoring fstab swap entry for %s.", what);
return 0;
@@ -707,6 +702,10 @@ static int parse_fstab_one(
return 0;
is_swap = streq_ptr(fstype, "swap");
+ if (is_swap && !arg_swap_enabled) {
+ log_info("Swap unit generation disabled on kernel command line, ignoring swap entry for %s.", what);
+ return 0;
+ }
what = fstab_node_to_udev_node(what_original);
if (!what)

@ -0,0 +1,119 @@
From 38d81fc89f325801922971229a894038fe207eae Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Wed, 24 May 2023 07:04:06 +0900
Subject: [PATCH] fstab-generator: refuse invalid mount point path in fstab
earlier
(cherry picked from commit 6742eca13497dd9dd548ba3e2ced2588d82720ac)
Related: #2190226
---
src/fstab-generator/fstab-generator.c | 68 +++++++++++++--------------
1 file changed, 34 insertions(+), 34 deletions(-)
diff --git a/src/fstab-generator/fstab-generator.c b/src/fstab-generator/fstab-generator.c
index 2cd4de29f0..bd1508bc30 100644
--- a/src/fstab-generator/fstab-generator.c
+++ b/src/fstab-generator/fstab-generator.c
@@ -689,7 +689,7 @@ static int parse_fstab_one(
int passno,
bool initrd) {
- _cleanup_free_ char *what = NULL, *where = NULL, *canonical_where = NULL;
+ _cleanup_free_ char *what = NULL, *where = NULL;
MountPointFlags flags;
bool is_swap;
int r;
@@ -725,50 +725,50 @@ static int parse_fstab_one(
assert(where_original); /* 'where' is not necessary for swap entry. */
- where = strdup(where_original);
- if (!where)
- return log_oom();
-
- if (is_path(where)) {
- path_simplify(where);
+ if (!is_path(where_original)) {
+ log_warning("Mount point %s is not a valid path, ignoring.", where);
+ return 0;
+ }
- /* Follow symlinks here; see 5261ba901845c084de5a8fd06500ed09bfb0bd80 which makes sense for
- * mount units, but causes problems since it historically worked to have symlinks in e.g.
- * /etc/fstab. So we canonicalize here. Note that we use CHASE_NONEXISTENT to handle the case
- * where a symlink refers to another mount target; this works assuming the sub-mountpoint
- * target is the final directory.
- *
- * FIXME: when chase() learns to chase non-existent paths, use this here and
- * drop the prefixing with /sysroot on error below.
- */
- r = chase_symlinks(where, initrd ? "/sysroot" : NULL, CHASE_PREFIX_ROOT | CHASE_NONEXISTENT,
- &canonical_where, NULL);
- if (r < 0) {
- /* If we can't canonicalize, continue as if it wasn't a symlink */
- log_debug_errno(r, "Failed to read symlink target for %s, using as-is: %m", where);
-
- if (initrd) {
- canonical_where = path_join("/sysroot", where);
- if (!canonical_where)
- return log_oom();
- }
+ /* Follow symlinks here; see 5261ba901845c084de5a8fd06500ed09bfb0bd80 which makes sense for
+ * mount units, but causes problems since it historically worked to have symlinks in e.g.
+ * /etc/fstab. So we canonicalize here. Note that we use CHASE_NONEXISTENT to handle the case
+ * where a symlink refers to another mount target; this works assuming the sub-mountpoint
+ * target is the final directory.
+ *
+ * FIXME: when chase() learns to chase non-existent paths, use this here and
+ * drop the prefixing with /sysroot on error below.
+ */
+ r = chase_symlinks(where_original, initrd ? "/sysroot" : NULL, CHASE_PREFIX_ROOT | CHASE_NONEXISTENT, &where, NULL);
+ if (r < 0) {
+ /* If we can't canonicalize, continue as if it wasn't a symlink */
+ log_debug_errno(r, "Failed to read symlink target for %s, using as-is: %m", where_original);
- } else if (streq(canonical_where, where)) /* If it was fully canonicalized, suppress the change */
- canonical_where = mfree(canonical_where);
+ if (initrd)
+ where = path_join("/sysroot", where_original);
else
- log_debug("Canonicalized what=%s where=%s to %s", what, where, canonical_where);
+ where = strdup(where_original);
+ if (!where)
+ return log_oom();
+
+ path_simplify(where);
}
+ if (streq(where, where_original)) /* If it was fully canonicalized, suppress the change */
+ where = mfree(where);
+ else
+ log_debug("Canonicalized what=%s where=%s to %s", what, where_original, where);
+
log_debug("Found entry what=%s where=%s type=%s makefs=%s growfs=%s noauto=%s nofail=%s",
what, where, strna(fstype),
yes_no(flags & MOUNT_MAKEFS), yes_no(flags & MOUNT_GROWFS),
yes_no(flags & MOUNT_NOAUTO), yes_no(flags & MOUNT_NOFAIL));
- bool is_sysroot = in_initrd() && path_equal(where, "/sysroot");
+ bool is_sysroot = in_initrd() && path_equal(where ?: where_original, "/sysroot");
/* See comment from add_sysroot_usr_mount() about the need for extra indirection in case /usr needs
* to be mounted in order for the root fs to be synthesized based on configuration included in /usr/,
* e.g. systemd-repart. */
- bool is_sysroot_usr = in_initrd() && path_equal(where, "/sysroot/usr");
+ bool is_sysroot_usr = in_initrd() && path_equal(where ?: where_original, "/sysroot/usr");
const char *target_unit =
initrd ? SPECIAL_INITRD_FS_TARGET :
@@ -786,8 +786,8 @@ static int parse_fstab_one(
r = add_mount(source,
arg_dest,
what,
- is_sysroot_usr ? "/sysusr/usr" : canonical_where ?: where,
- !is_sysroot_usr && canonical_where ? where : NULL,
+ is_sysroot_usr ? "/sysusr/usr" : where ?: where_original,
+ !is_sysroot_usr && where ? where_original : NULL,
fstype,
options,
passno,

@ -0,0 +1,75 @@
From 00f65b3c9b052007857558ec0776944ffe3979d4 Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Mon, 8 May 2023 19:47:17 +0900
Subject: [PATCH] fstab-generator: fix error code propagation in
run_generator()
Previously, some errors might be ignored.
(cherry picked from commit 2646f1844553b5d9c6109ad6b1b86da0b6b1f248)
Related: #2190226
---
src/fstab-generator/fstab-generator.c | 29 +++++++++++++++++++--------
1 file changed, 21 insertions(+), 8 deletions(-)
diff --git a/src/fstab-generator/fstab-generator.c b/src/fstab-generator/fstab-generator.c
index bd1508bc30..c53feb6154 100644
--- a/src/fstab-generator/fstab-generator.c
+++ b/src/fstab-generator/fstab-generator.c
@@ -1265,7 +1265,7 @@ static int determine_usr(void) {
* with /sysroot/etc/fstab available, and then we can write additional units based
* on that file. */
static int run_generator(void) {
- int r, r2 = 0, r3 = 0;
+ int r, ret = 0;
r = proc_cmdline_parse(parse_proc_cmdline_item, NULL, 0);
if (r < 0)
@@ -1286,26 +1286,39 @@ static int run_generator(void) {
/* Always honour root= and usr= in the kernel command line if we are in an initrd */
if (in_initrd()) {
r = add_sysroot_mount();
+ if (r < 0 && ret >= 0)
+ ret = r;
- r2 = add_sysroot_usr_mount_or_fallback();
+ r = add_sysroot_usr_mount_or_fallback();
+ if (r < 0 && ret >= 0)
+ ret = r;
- r3 = add_volatile_root();
- } else
+ r = add_volatile_root();
+ if (r < 0 && ret >= 0)
+ ret = r;
+ } else {
r = add_volatile_var();
+ if (r < 0 && ret >= 0)
+ ret = r;
+ }
/* Honour /etc/fstab only when that's enabled */
if (arg_fstab_enabled) {
/* Parse the local /etc/fstab, possibly from the initrd */
- r2 = parse_fstab(false);
+ r = parse_fstab(false);
+ if (r < 0 && ret >= 0)
+ ret = r;
/* If running in the initrd also parse the /etc/fstab from the host */
if (in_initrd())
- r3 = parse_fstab(true);
+ r = parse_fstab(true);
else
- r3 = generator_enable_remount_fs_service(arg_dest);
+ r = generator_enable_remount_fs_service(arg_dest);
+ if (r < 0 && ret >= 0)
+ ret = r;
}
- return r < 0 ? r : r2 < 0 ? r2 : r3;
+ return ret;
}
static int run(int argc, char **argv) {

@ -0,0 +1,307 @@
From 752ce62315bb38bd1267bd49dccc4dad2e9d05ee Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Mon, 8 May 2023 19:49:33 +0900
Subject: [PATCH] fstab-generator: support defining mount units through kernel
command line
Now, the following kernel command line options are supported:
systemd.mount-extra=what:where:fstype:options
systemd.swap-extra=what:options
Closes #27260.
(cherry picked from commit 55365b0a233ae3024411fd0815ad930e20f6a3d6)
Resolves: #2190226
---
man/systemd-fstab-generator.xml | 27 +++++
src/fstab-generator/fstab-generator.c | 164 +++++++++++++++++++++++++-
2 files changed, 186 insertions(+), 5 deletions(-)
diff --git a/man/systemd-fstab-generator.xml b/man/systemd-fstab-generator.xml
index 30204f5d8a..b29022fab7 100644
--- a/man/systemd-fstab-generator.xml
+++ b/man/systemd-fstab-generator.xml
@@ -239,6 +239,33 @@
any swap devices configured in <filename>/etc/fstab</filename>.
Defaults to enabled.</para></listitem>
</varlistentry>
+
+ <varlistentry>
+ <term><varname>systemd.mount-extra=<replaceable>WHAT</replaceable>:<replaceable>WHERE</replaceable>[:<replaceable>FSTYPE</replaceable>[:<replaceable>OPTIONS</replaceable>]]</varname></term>
+
+ <listitem>
+ <para>Specifies the mount unit. Takes at least two and at most four fields separated with a colon
+ (<literal>:</literal>). Each field is handled as the corresponding fstab field. This option can be
+ specified multiple times.</para>
+ <para>Example:
+ <programlisting>
+systemd.mount-extra=/dev/sda1:/mount-point:ext4:rw,noatime</programlisting>
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>systemd.swap-extra=<replaceable>WHAT</replaceable>[:<replaceable>OPTIONS</replaceable>]</varname></term>
+
+ <listitem>
+ <para>Specifies the swap unit. Takes the block device to be used as a swap device, and optionally
+ takes mount options followed by a colon (<literal>:</literal>).</para>
+ <para>Example:
+ <programlisting>
+systemd.swap=/dev/sda2:x-systemd.makefs</programlisting>
+ </para>
+ </listitem>
+ </varlistentry>
</variablelist>
</refsect1>
diff --git a/src/fstab-generator/fstab-generator.c b/src/fstab-generator/fstab-generator.c
index c53feb6154..910e29d26b 100644
--- a/src/fstab-generator/fstab-generator.c
+++ b/src/fstab-generator/fstab-generator.c
@@ -20,6 +20,7 @@
#include "mount-setup.h"
#include "mount-util.h"
#include "mountpoint-util.h"
+#include "nulstr-util.h"
#include "parse-util.h"
#include "path-util.h"
#include "proc-cmdline.h"
@@ -43,6 +44,15 @@ typedef enum MountPointFlags {
MOUNT_RW_ONLY = 1 << 5,
} MountPointFlags;
+typedef struct Mount {
+ char *what;
+ char *where;
+ char *fstype;
+ char *options;
+} Mount;
+
+static void mount_array_free(Mount *mounts, size_t n);
+
static bool arg_sysroot_check = false;
static const char *arg_dest = NULL;
static const char *arg_dest_late = NULL;
@@ -58,6 +68,8 @@ static char *arg_usr_fstype = NULL;
static char *arg_usr_options = NULL;
static char *arg_usr_hash = NULL;
static VolatileMode arg_volatile_mode = _VOLATILE_MODE_INVALID;
+static Mount *arg_mounts = NULL;
+static size_t arg_n_mounts = 0;
STATIC_DESTRUCTOR_REGISTER(arg_root_what, freep);
STATIC_DESTRUCTOR_REGISTER(arg_root_fstype, freep);
@@ -67,6 +79,101 @@ STATIC_DESTRUCTOR_REGISTER(arg_usr_what, freep);
STATIC_DESTRUCTOR_REGISTER(arg_usr_fstype, freep);
STATIC_DESTRUCTOR_REGISTER(arg_usr_options, freep);
STATIC_DESTRUCTOR_REGISTER(arg_usr_hash, freep);
+STATIC_ARRAY_DESTRUCTOR_REGISTER(arg_mounts, arg_n_mounts, mount_array_free);
+
+static void mount_done(Mount *m) {
+ assert(m);
+
+ free(m->what);
+ free(m->where);
+ free(m->fstype);
+ free(m->options);
+}
+
+static void mount_array_free(Mount *mounts, size_t n) {
+ FOREACH_ARRAY(m, mounts, n)
+ mount_done(m);
+
+ free(mounts);
+}
+
+static int mount_array_add_internal(char *in_what, char *in_where, const char *in_fstype, const char *in_options) {
+ _cleanup_free_ char *what = NULL, *where = NULL, *fstype = NULL, *options = NULL;
+ int r;
+
+ /* This takes what and where. */
+
+ what = ASSERT_PTR(in_what);
+ where = in_where;
+
+ fstype = strdup(isempty(in_fstype) ? "auto" : in_fstype);
+ if (!fstype)
+ return -ENOMEM;
+
+ if (streq(fstype, "swap"))
+ where = mfree(where);
+
+ if (!isempty(in_options)) {
+ _cleanup_strv_free_ char **options_strv = NULL;
+
+ r = strv_split_full(&options_strv, in_options, ",", 0);
+ if (r < 0)
+ return r;
+
+ r = strv_make_nulstr(options_strv, &options, NULL);
+ } else
+ r = strv_make_nulstr(STRV_MAKE("defaults"), &options, NULL);
+ if (r < 0)
+ return r;
+
+ if (!GREEDY_REALLOC(arg_mounts, arg_n_mounts + 1))
+ return -ENOMEM;
+
+ arg_mounts[arg_n_mounts++] = (Mount) {
+ .what = TAKE_PTR(what),
+ .where = TAKE_PTR(where),
+ .fstype = TAKE_PTR(fstype),
+ .options = TAKE_PTR(options),
+ };
+
+ return 0;
+}
+
+static int mount_array_add(const char *str) {
+ _cleanup_free_ char *what = NULL, *where = NULL, *fstype = NULL, *options = NULL;
+ int r;
+
+ assert(str);
+
+ r = extract_many_words(&str, ":", EXTRACT_CUNESCAPE | EXTRACT_DONT_COALESCE_SEPARATORS,
+ &what, &where, &fstype, &options, NULL);
+ if (r < 0)
+ return r;
+ if (r < 2)
+ return -EINVAL;
+ if (!isempty(str))
+ return -EINVAL;
+
+ return mount_array_add_internal(TAKE_PTR(what), TAKE_PTR(where), fstype, options);
+}
+
+static int mount_array_add_swap(const char *str) {
+ _cleanup_free_ char *what = NULL, *options = NULL;
+ int r;
+
+ assert(str);
+
+ r = extract_many_words(&str, ":", EXTRACT_CUNESCAPE | EXTRACT_DONT_COALESCE_SEPARATORS,
+ &what, &options, NULL);
+ if (r < 0)
+ return r;
+ if (r < 1)
+ return -EINVAL;
+ if (!isempty(str))
+ return -EINVAL;
+
+ return mount_array_add_internal(TAKE_PTR(what), NULL, "swap", options);
+}
static int write_options(FILE *f, const char *options) {
_cleanup_free_ char *o = NULL;
@@ -109,12 +216,12 @@ static int add_swap(
assert(what);
if (access("/proc/swaps", F_OK) < 0) {
- log_info("Swap not supported, ignoring fstab swap entry for %s.", what);
+ log_info("Swap not supported, ignoring swap entry for %s.", what);
return 0;
}
if (detect_container() > 0) {
- log_info("Running in a container, ignoring fstab swap entry for %s.", what);
+ log_info("Running in a container, ignoring swap entry for %s.", what);
return 0;
}
@@ -687,7 +794,8 @@ static int parse_fstab_one(
const char *fstype,
const char *options,
int passno,
- bool initrd) {
+ bool initrd,
+ bool use_swap_enabled) {
_cleanup_free_ char *what = NULL, *where = NULL;
MountPointFlags flags;
@@ -702,7 +810,7 @@ static int parse_fstab_one(
return 0;
is_swap = streq_ptr(fstype, "swap");
- if (is_swap && !arg_swap_enabled) {
+ if (is_swap && use_swap_enabled && !arg_swap_enabled) {
log_info("Swap unit generation disabled on kernel command line, ignoring swap entry for %s.", what);
return 0;
}
@@ -830,7 +938,9 @@ static int parse_fstab(bool initrd) {
}
while ((me = getmntent(f))) {
- r = parse_fstab_one(fstab, me->mnt_fsname, me->mnt_dir, me->mnt_type, me->mnt_opts, me->mnt_passno, initrd);
+ r = parse_fstab_one(fstab,
+ me->mnt_fsname, me->mnt_dir, me->mnt_type, me->mnt_opts, me->mnt_passno,
+ initrd, /* use_swap_enabled = */ true);
if (r < 0 && ret >= 0)
ret = r;
if (arg_sysroot_check && r > 0)
@@ -1129,6 +1239,28 @@ static int add_volatile_var(void) {
SPECIAL_LOCAL_FS_TARGET);
}
+static int add_mounts_from_cmdline(void) {
+ int r, ret = 0;
+
+ /* Handle each entries found in cmdline as a fstab entry. */
+
+ FOREACH_ARRAY(m, arg_mounts, arg_n_mounts) {
+ r = parse_fstab_one(
+ "/proc/cmdline",
+ m->what,
+ m->where,
+ m->fstype,
+ m->options,
+ /* passno = */ 0,
+ /* initrd = */ false,
+ /* use_swap_enabled = */ false);
+ if (r < 0 && ret >= 0)
+ ret = r;
+ }
+
+ return ret;
+}
+
static int parse_proc_cmdline_item(const char *key, const char *value, void *data) {
int r;
@@ -1225,6 +1357,24 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
log_warning("Failed to parse systemd.swap switch %s. Ignoring.", value);
else
arg_swap_enabled = r;
+
+ } else if (streq(key, "systemd.mount-extra")) {
+
+ if (proc_cmdline_value_missing(key, value))
+ return 0;
+
+ r = mount_array_add(value);
+ if (r < 0)
+ log_warning("Failed to parse systemd.mount-extra= option, ignoring: %s", value);
+
+ } else if (streq(key, "systemd.swap-extra")) {
+
+ if (proc_cmdline_value_missing(key, value))
+ return 0;
+
+ r = mount_array_add_swap(value);
+ if (r < 0)
+ log_warning("Failed to parse systemd.swap-extra= option, ignoring: %s", value);
}
return 0;
@@ -1318,6 +1468,10 @@ static int run_generator(void) {
ret = r;
}
+ r = add_mounts_from_cmdline();
+ if (r < 0 && ret >= 0)
+ ret = r;
+
return ret;
}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save