diff options
-rw-r--r-- | src/basic/special.h | 2 | ||||
-rw-r--r-- | src/shared/generator.c | 126 | ||||
-rw-r--r-- | units/meson.build | 2 | ||||
-rw-r--r-- | units/systemd-growfs-root.service.in | 22 | ||||
-rw-r--r-- | units/systemd-growfs@.service.in | 23 |
5 files changed, 126 insertions, 49 deletions
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 ec0182d05e..6c82d0f0ef 100644 --- a/src/shared/generator.c +++ b/src/shared/generator.c @@ -110,6 +110,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, @@ -560,66 +618,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 48b24f05c1..62ce438a3f 100644 --- a/units/meson.build +++ b/units/meson.build @@ -267,6 +267,8 @@ in_units = [ 'sysinit.target.wants/'], ['systemd-pcrmachine.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 |