You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
271 lines
9.6 KiB
271 lines
9.6 KiB
1 year ago
|
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
|