diff --git a/src/cryptsetup/cryptsetup-generator.c b/src/cryptsetup/cryptsetup-generator.c index 6a3ff961fc8..12b6044d8c5 100644 --- a/src/cryptsetup/cryptsetup-generator.c +++ b/src/cryptsetup/cryptsetup-generator.c @@ -518,7 +518,7 @@ static int create_disk( "After=modprobe@loop.service\n", u_escaped); - r = generator_write_timeouts(arg_dest, device, name, options, &filtered); + r = generator_write_device_timeout(arg_dest, device, options, &filtered); if (r < 0) log_warning_errno(r, "Failed to write device timeout drop-in: %m"); diff --git a/src/fstab-generator/fstab-generator.c b/src/fstab-generator/fstab-generator.c index 6b7445b201d..4dfe9fea897 100644 --- a/src/fstab-generator/fstab-generator.c +++ b/src/fstab-generator/fstab-generator.c @@ -289,7 +289,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, options, NULL); + r = generator_write_device_timeout(arg_dest, what, options, NULL); if (r < 0) return r; @@ -325,47 +325,9 @@ static bool mount_in_initrd(const char *where, const char *options, bool accept_ (where && PATH_IN_SET(where, "/usr", accept_root ? "/" : NULL)); } -static int write_timeout( - FILE *f, - const char *where, - const char *opts, - const char *filter, - const char *unit_setting) { - - _cleanup_free_ char *timeout = NULL; - usec_t u; - int r; - - assert(f); - assert(where); - assert(filter); - assert(unit_setting); - - r = fstab_filter_options(opts, filter, NULL, &timeout, NULL, NULL); - if (r < 0) - return log_error_errno(r, "Failed to parse options for '%s': %m", where); - if (r == 0) - return 0; - - r = parse_sec_fix_0(timeout, &u); - if (r < 0) { - log_warning_errno(r, "Failed to parse timeout '%s' for '%s', ignoring: %m", timeout, where); - return 0; - } - - fprintf(f, "%s=%s\n", unit_setting, FORMAT_TIMESPAN(u, 0)); - - return 0; -} - static int write_idle_timeout(FILE *f, const char *where, const char *opts) { - return write_timeout(f, where, opts, - "x-systemd.idle-timeout\0", "TimeoutIdleSec"); -} - -static int write_mount_timeout(FILE *f, const char *where, const char *opts) { - return write_timeout(f, where, opts, - "x-systemd.mount-timeout\0", "TimeoutSec"); + return generator_write_unit_timeout(f, where, opts, + "x-systemd.idle-timeout\0", "TimeoutIdleSec"); } static int write_dependency( @@ -670,11 +632,11 @@ static int add_mount( fprintf(f, "Type=%s\n", t); } - r = generator_write_timeouts(dest, what, where, opts, &filtered); + r = generator_write_device_timeout(dest, what, opts, &filtered); if (r < 0) return r; - r = generator_write_device_deps(dest, what, where, opts); + r = generator_write_network_device_deps(dest, what, where, opts); if (r < 0) return r; @@ -684,7 +646,7 @@ static int add_mount( return r; } - r = write_mount_timeout(f, where, opts); + r = generator_write_mount_timeout(f, where, opts); if (r < 0) return r; diff --git a/src/gpt-auto-generator/gpt-auto-generator.c b/src/gpt-auto-generator/gpt-auto-generator.c index 8bb32afb279..dbcef3b0a92 100644 --- a/src/gpt-auto-generator/gpt-auto-generator.c +++ b/src/gpt-auto-generator/gpt-auto-generator.c @@ -51,9 +51,12 @@ STATIC_DESTRUCTOR_REGISTER(arg_image_policy, image_policy_freep); STATIC_DESTRUCTOR_REGISTER(arg_root_fstype, freep); STATIC_DESTRUCTOR_REGISTER(arg_root_options, freep); +#define LOADER_PARTITION_IDLE_USEC (120 * USEC_PER_SEC) + static int add_cryptsetup( const char *id, const char *what, + const char *mount_opts, bool rw, bool require, bool measure, @@ -126,6 +129,10 @@ static int add_cryptsetup( if (r < 0) return log_error_errno(r, "Failed to write file %s: %m", n); + r = generator_write_device_timeout(arg_dest, what, mount_opts, /* filtered = */ NULL); + if (r < 0) + return r; + r = generator_add_symlink(arg_dest, d, "wants", n); if (r < 0) return r; @@ -178,7 +185,7 @@ static int add_mount( const char *description, const char *post) { - _cleanup_free_ char *unit = NULL, *crypto_what = NULL; + _cleanup_free_ char *unit = NULL, *crypto_what = NULL, *opts_filtered = NULL; _cleanup_fclose_ FILE *f = NULL; int r; @@ -194,7 +201,9 @@ static int add_mount( log_debug("Adding %s: %s fstype=%s", where, what, fstype ?: "(any)"); if (streq_ptr(fstype, "crypto_LUKS")) { - r = add_cryptsetup(id, what, rw, /* require= */ true, measure, &crypto_what); + /* Mount options passed are determined by partition_pick_mount_options(), whose result + * is known to not contain timeout options. */ + r = add_cryptsetup(id, what, /* mount_opts = */ NULL, rw, /* require= */ true, measure, &crypto_what); if (r < 0) return r; @@ -211,6 +220,10 @@ static int add_mount( fstype, where); } + r = generator_write_device_timeout(arg_dest, what, options, &opts_filtered); + if (r < 0) + return r; + r = unit_name_from_path(where, ".mount", &unit); if (r < 0) return log_error_errno(r, "Failed to generate unit name: %m"); @@ -246,8 +259,12 @@ static int add_mount( if (fstype) fprintf(f, "Type=%s\n", fstype); - if (options) - fprintf(f, "Options=%s\n", options); + if (opts_filtered) + fprintf(f, "Options=%s\n", opts_filtered); + + r = generator_write_mount_timeout(f, where, opts_filtered); + if (r < 0) + return r; r = fflush_and_check(f); if (r < 0) @@ -366,7 +383,7 @@ static int add_partition_swap(DissectedPartition *p) { } if (streq_ptr(p->fstype, "crypto_LUKS")) { - r = add_cryptsetup("swap", p->node, /* rw= */ true, /* require= */ true, /* measure= */ false, &crypto_what); + r = add_cryptsetup("swap", p->node, /* mount_opts = */ NULL, /* rw= */ true, /* require= */ true, /* measure= */ false, &crypto_what); if (r < 0) return r; what = crypto_what; @@ -499,7 +516,7 @@ static int add_partition_xbootldr(DissectedPartition *p) { /* growfs= */ false, options, "Boot Loader Partition", - 120 * USEC_PER_SEC); + LOADER_PARTITION_IDLE_USEC); } #if ENABLE_EFI @@ -566,7 +583,7 @@ static int add_partition_esp(DissectedPartition *p, bool has_xbootldr) { /* growfs= */ false, options, "EFI System Partition Automount", - 120 * USEC_PER_SEC); + LOADER_PARTITION_IDLE_USEC); } #else static int add_partition_esp(DissectedPartition *p, bool has_xbootldr) { @@ -644,7 +661,7 @@ static int add_root_cryptsetup(void) { /* If a device /dev/gpt-auto-root-luks appears, then make it pull in systemd-cryptsetup-root.service, which * sets it up, and causes /dev/gpt-auto-root to appear which is all we are looking for. */ - return add_cryptsetup("root", "/dev/gpt-auto-root-luks", /* rw= */ true, /* require= */ false, /* measure= */ true, NULL); + return add_cryptsetup("root", "/dev/gpt-auto-root-luks", arg_root_options, /* rw= */ true, /* require= */ false, /* measure= */ true, NULL); #else return 0; #endif diff --git a/src/hibernate-resume/hibernate-resume-generator.c b/src/hibernate-resume/hibernate-resume-generator.c index 2b175342c14..666cd52e477 100644 --- a/src/hibernate-resume/hibernate-resume-generator.c +++ b/src/hibernate-resume/hibernate-resume-generator.c @@ -64,24 +64,21 @@ static int process_resume(const HibernateInfo *info) { if (r < 0) return log_error_errno(r, "Failed to generate device unit name from path '%s': %m", info->device); - /* If hibernate info is acquired from EFI variable, don't wait forever by default. Otherwise, if - * swap device is not present and HibernateLocation was not correctly cleared, we end up blocking - * the boot process infinitely. */ - r = write_drop_in_format(arg_dest, device_unit, 40, "device-timeout", - "# Automatically generated by systemd-hibernate-resume-generator\n\n" - "[Unit]\n" - "JobTimeoutSec=%s\n", - info->cmdline ? "infinity" : "2min"); - if (r < 0) - log_warning_errno(r, "Failed to write device timeout drop-in, ignoring: %m"); - - r = generator_write_timeouts(arg_dest, - info->device, - info->device, - arg_resume_options ?: arg_root_options, - NULL); + r = generator_write_device_timeout(arg_dest, info->device, arg_resume_options ?: arg_root_options, NULL); if (r < 0) log_warning_errno(r, "Failed to write device timeout drop-in, ignoring: %m"); + if (r <= 0) { + /* No timeout explicitly defined? Wait infinitely if resume= is specified, 2min if from EFI + * HibernateLocation variable. In the latter case, we avoid blocking the boot process forever + * if a stale var is detected while the swap device is not present. */ + r = write_drop_in_format(arg_dest, device_unit, 40, "device-timeout", + "# Automatically generated by systemd-hibernate-resume-generator\n\n" + "[Unit]\n" + "JobTimeoutSec=%s\n", + info->cmdline ? "infinity" : "2min"); + if (r < 0) + log_warning_errno(r, "Failed to write fallback device timeout drop-in, ignoring: %m"); + } r = write_drop_in_format(arg_dest, SPECIAL_HIBERNATE_RESUME_SERVICE, 90, "device-dependency", "# Automatically generated by systemd-hibernate-resume-generator\n\n" diff --git a/src/shared/generator.c b/src/shared/generator.c index b3e57770aa7..738f1892797 100644 --- a/src/shared/generator.c +++ b/src/shared/generator.c @@ -368,10 +368,9 @@ int generator_write_fsck_deps( return 0; } -int generator_write_timeouts( +int generator_write_device_timeout( const char *dir, const char *what, - const char *where, const char *opts, char **filtered) { @@ -383,6 +382,9 @@ int generator_write_timeouts( usec_t u; int r; + assert(dir); + assert(what); + r = fstab_filter_options(opts, "comment=systemd.device-timeout\0" "x-systemd.device-timeout\0", NULL, &timeout, NULL, filtered); @@ -395,7 +397,7 @@ int generator_write_timeouts( r = parse_sec_fix_0(timeout, &u); if (r < 0) { - log_warning("Failed to parse timeout for %s, ignoring: %s", where, timeout); + log_warning("Failed to parse timeout for device '%s', ignoring: %s", what, timeout); return 0; } @@ -403,25 +405,62 @@ int generator_write_timeouts( if (!node) return log_oom(); if (!is_device_path(node)) { - log_warning("x-systemd.device-timeout ignored for %s", what); + log_warning("'%s' is not a device path, ignoring x-systemd.device-timeout= option.", node); return 0; } r = unit_name_from_path(node, ".device", &unit); if (r < 0) - return log_error_errno(r, "Failed to make unit name from path: %m"); + return log_error_errno(r, "Failed to make unit name from device path '%s': %m", node); - return write_drop_in_format(dir, unit, 50, "device-timeout", - "# Automatically generated by %s\n" - "# from supplied options \"%s\"\n\n" - "[Unit]\n" - "JobRunningTimeoutSec=%s", - program_invocation_short_name, - opts, - timeout); + r = write_drop_in_format(dir, unit, 50, "device-timeout", + "# Automatically generated by %s\n" + "# from supplied options \"%s\"\n\n" + "[Unit]\n" + "JobRunningTimeoutSec=%s", + program_invocation_short_name, + opts, + timeout); + if (r < 0) + return r; + + return 1; } -int generator_write_device_deps( +int generator_write_unit_timeout( + FILE *f, + const char *where, + const char *opts, + const char *filter, + const char *unit_setting) { + + _cleanup_free_ char *timeout = NULL; + usec_t u; + int r; + + assert(f); + assert(where); + assert(filter); + assert(unit_setting); + + r = fstab_filter_options(opts, filter, NULL, &timeout, NULL, NULL); + if (r < 0) + return log_error_errno(r, "Failed to parse options for '%s': %m", where); + if (r == 0) + return 0; + + r = parse_sec_fix_0(timeout, &u); + if (r < 0) { + log_warning_errno(r, "Failed to parse timeout '%s' for '%s', ignoring: %m", timeout, where); + return 0; + } + + fprintf(f, "%s=%s\n", unit_setting, FORMAT_TIMESPAN(u, 0)); + + return 0; +} + +int generator_write_network_device_deps( const char *dir, const char *what, const char *where, @@ -435,6 +474,10 @@ int generator_write_device_deps( _cleanup_free_ char *node = NULL, *unit = NULL; int r; + assert(dir); + assert(what); + assert(where); + if (fstab_is_extrinsic(where, opts)) return 0; @@ -451,8 +494,7 @@ int generator_write_device_deps( r = unit_name_from_path(node, ".device", &unit); if (r < 0) - return log_error_errno(r, "Failed to make unit name from path \"%s\": %m", - node); + return log_error_errno(r, "Failed to make unit name from path \"%s\": %m", node); /* See mount_add_default_dependencies for explanation why we create such * dependencies. */ @@ -787,10 +829,7 @@ int generator_enable_remount_fs_service(const char *dir) { SYSTEM_DATA_UNIT_DIR "/" SPECIAL_REMOUNT_FS_SERVICE); } -int generator_write_blockdev_dependency( - FILE *f, - const char *what) { - +int generator_write_blockdev_dependency(FILE *f, const char *what) { _cleanup_free_ char *escaped = NULL; int r; @@ -811,10 +850,7 @@ int generator_write_blockdev_dependency( return 0; } -int generator_write_cryptsetup_unit_section( - FILE *f, - const char *source) { - +int generator_write_cryptsetup_unit_section(FILE *f, const char *source) { assert(f); fprintf(f, @@ -886,10 +922,7 @@ int generator_write_cryptsetup_service_section( return 0; } -int generator_write_veritysetup_unit_section( - FILE *f, - const char *source) { - +int generator_write_veritysetup_unit_section(FILE *f, const char *source) { assert(f); fprintf(f, diff --git a/src/shared/generator.h b/src/shared/generator.h index f07d7d6b3ae..5879e34ea25 100644 --- a/src/shared/generator.h +++ b/src/shared/generator.h @@ -7,13 +7,11 @@ #include "main-func.h" int generator_open_unit_file_full(const char *dest, const char *source, const char *name, FILE **ret_file, char **ret_final_path, char **ret_temp_path); - static inline int generator_open_unit_file(const char *dest, const char *source, const char *name, FILE **ret_file) { return generator_open_unit_file_full(dest, source, name, ret_file, NULL, NULL); } 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); } @@ -25,49 +23,32 @@ int generator_write_fsck_deps( const char *where, const char *type); -int generator_write_timeouts( +int generator_write_device_timeout( const char *dir, const char *what, - const char *where, const char *opts, char **filtered); -int generator_write_blockdev_dependency( +int generator_write_unit_timeout( FILE *f, - const char *what); + const char *where, + const char *opts, + const char *filter, + const char *unit_setting); +static inline int generator_write_mount_timeout(FILE *f, const char *where, const char *opts) { + return generator_write_unit_timeout(f, where, opts, + "x-systemd.mount-timeout\0", "TimeoutSec"); +} -int generator_write_cryptsetup_unit_section( - FILE *f, - const char *source); +int generator_write_blockdev_dependency(FILE *f, const char *what); -int generator_write_cryptsetup_service_section( - FILE *f, - const char *name, - const char *what, - const char *password, - const char *options); - -int generator_write_veritysetup_unit_section( - FILE *f, - const char *source); - -int generator_write_veritysetup_service_section( - FILE *f, - const char *name, - const char *data_what, - const char *hash_what, - const char *roothash, - const char *options); - -int generator_write_device_deps( +int generator_write_network_device_deps( const char *dir, const char *what, const char *where, const char *opts); -int generator_write_initrd_root_device_deps( - const char *dir, - const char *what); +int generator_write_initrd_root_device_deps(const char *dir, const char *what); int generator_hook_up_mkswap( const char *dir, @@ -96,6 +77,23 @@ int generator_hook_up_quotaon( const char *where, const char *target); +int generator_write_cryptsetup_unit_section(FILE *f, const char *source); +int generator_write_cryptsetup_service_section( + FILE *f, + const char *name, + const char *what, + const char *password, + const char *options); + +int generator_write_veritysetup_unit_section(FILE *f, const char *source); +int generator_write_veritysetup_service_section( + FILE *f, + const char *name, + const char *data_what, + const char *hash_what, + const char *roothash, + const char *options); + int generator_enable_remount_fs_service(const char *dir); void log_setup_generator(void);