From 7852e301e0eb839adf4bf45aa41e39c0dfc03403 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 17 Mar 2025 17:01:49 +0100 Subject: [PATCH] gpt-auto-generator: add support for mount.usr=dissect So far, we did not support auto-discovery the /usr/ partition at boot. Change that: on explicit request (i.e. mount.usr=dissect) automatically discover the /usr/ partition based on our usual dissection logic. --- src/fstab-generator/fstab-generator.c | 2 +- src/gpt-auto-generator/gpt-auto-generator.c | 125 +++++++++++++++++++- src/shared/generator.c | 21 ++-- src/shared/generator.h | 2 +- 4 files changed, 136 insertions(+), 14 deletions(-) diff --git a/src/fstab-generator/fstab-generator.c b/src/fstab-generator/fstab-generator.c index ab009e8b212..5adf48f20c7 100644 --- a/src/fstab-generator/fstab-generator.c +++ b/src/fstab-generator/fstab-generator.c @@ -1137,7 +1137,7 @@ static bool validate_root_or_usr_mount_source(const char *what, const char *swit return false; } - if (parse_gpt_auto_root(what) > 0) { + if (parse_gpt_auto_root(switch_name, what) > 0) { /* This is handled by gpt-auto-generator */ log_debug("Skipping %s directory handling, as gpt-auto was requested.", switch_name); return false; diff --git a/src/gpt-auto-generator/gpt-auto-generator.c b/src/gpt-auto-generator/gpt-auto-generator.c index 28242850ac1..c7acbcb2b0c 100644 --- a/src/gpt-auto-generator/gpt-auto-generator.c +++ b/src/gpt-auto-generator/gpt-auto-generator.c @@ -48,15 +48,20 @@ typedef enum MountPointFlags { static const char *arg_dest = NULL; static bool arg_enabled = true; static GptAutoRoot arg_auto_root = _GPT_AUTO_ROOT_INVALID; +static GptAutoRoot arg_auto_usr = _GPT_AUTO_ROOT_INVALID; static bool arg_swap_enabled = true; static char *arg_root_fstype = NULL; static char *arg_root_options = NULL; static int arg_root_rw = -1; +static char *arg_usr_fstype = NULL; +static char *arg_usr_options = NULL; static ImagePolicy *arg_image_policy = NULL; STATIC_DESTRUCTOR_REGISTER(arg_image_policy, image_policy_freep); STATIC_DESTRUCTOR_REGISTER(arg_root_fstype, freep); STATIC_DESTRUCTOR_REGISTER(arg_root_options, freep); +STATIC_DESTRUCTOR_REGISTER(arg_usr_fstype, freep); +STATIC_DESTRUCTOR_REGISTER(arg_usr_options, freep); #define LOADER_PARTITION_IDLE_USEC (120 * USEC_PER_SEC) @@ -679,7 +684,13 @@ static int add_root_cryptsetup(void) { "/dev/gpt-auto-root-luks-ignore-factory-reset"; } - return add_cryptsetup("root", bdev, arg_root_options, MOUNT_RW|MOUNT_MEASURE, /* require= */ false, NULL); + return add_cryptsetup( + "root", + bdev, + arg_root_options, + MOUNT_RW|MOUNT_MEASURE, + /* require= */ false, + /* ret_device= */ NULL); #else return 0; #endif @@ -782,6 +793,84 @@ static int add_root_mount(void) { #endif } + +static int add_usr_mount(void) { +#if ENABLE_EFI + int r; + + /* /usr/ discovery must be enabled explicitly. */ + if (arg_auto_usr == GPT_AUTO_ROOT_OFF || + arg_auto_usr < 0) + return 0; + + /* We do not support the other gpt-auto modes for /usr/, but the parser should already have checked that. */ + assert(arg_auto_usr == GPT_AUTO_ROOT_DISSECT); + + if (arg_root_fstype && !arg_usr_fstype) { + arg_usr_fstype = strdup(arg_root_fstype); + if (!arg_usr_fstype) + return log_oom(); + } + + if (arg_root_options && !arg_usr_options) { + arg_usr_options = strdup(arg_root_options); + if (!arg_usr_options) + return log_oom(); + } + + if (in_initrd()) { + r = add_cryptsetup( + "usr", + "/dev/disk/by-designator/usr-luks", + arg_usr_options, + MOUNT_RW|MOUNT_MEASURE, + /* require= */ false, + /* ret_device= */ NULL); + if (r < 0) + return r; + } + + _cleanup_free_ char *options = NULL; + r = partition_pick_mount_options( + PARTITION_USR, + arg_usr_fstype, + /* rw= */ false, + /* discard= */ true, + &options, + /* ret_ms_flags= */ NULL); + if (r < 0) + return log_error_errno(r, "Failed to pick /usr/ mount options: %m"); + + if (arg_usr_options) + if (!strextend_with_separator(&options, ",", arg_usr_options)) + return log_oom(); + + r = add_mount("usr", + "/dev/disk/by-designator/usr", + in_initrd() ? "/sysusr/usr" : "/usr", + arg_usr_fstype, + (in_initrd() ? MOUNT_VALIDATEFS : 0), + options, + "/usr/ Partition", + in_initrd() ? SPECIAL_INITRD_USR_FS_TARGET : SPECIAL_LOCAL_FS_TARGET); + if (r < 0) + return r; + + log_debug("Synthesizing entry what=/sysusr/usr where=/sysroot/usr opts=bind"); + + return add_mount("usr-bind", + "/sysusr/usr", + "/sysroot/usr", + /* fstype= */ NULL, + /* flags= */ 0, + "bind", + "/usr/ Partition (Final)", + in_initrd() ? SPECIAL_INITRD_FS_TARGET : SPECIAL_LOCAL_FS_TARGET); +#else + return 0; +#endif +} + static int process_loader_partitions(DissectedPartition *esp, DissectedPartition *xbootldr) { sd_id128_t loader_uuid; int r; @@ -973,7 +1062,7 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat /* Disable root disk logic if there's a root= value specified (unless it happens to be * "gpt-auto" or "gpt-auto-force") */ - arg_auto_root = parse_gpt_auto_root(value); + arg_auto_root = parse_gpt_auto_root("root=", value); assert(arg_auto_root >= 0); } else if (streq(key, "roothash")) { @@ -1001,6 +1090,37 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat if (!strextend_with_separator(&arg_root_options, ",", value)) return log_oom(); + } else if (streq(key, "mount.usr")) { + + if (proc_cmdline_value_missing(key, value)) + return 0; + + /* Disable root disk logic if there's a root= value specified (unless it happens to be + * "gpt-auto" or "gpt-auto-force") */ + + arg_auto_usr = parse_gpt_auto_root("mount.usr=", value); + assert(arg_auto_usr >= 0); + + if (IN_SET(arg_auto_usr, GPT_AUTO_ROOT_ON, GPT_AUTO_ROOT_FORCE, GPT_AUTO_ROOT_DISSECT_FORCE)) { + log_warning("'gpt-auto', 'gpt-auto-force' and 'dissect-force' are not supported for mount.usr=. Automatically resorting to mount.usr=dissect mode instead."); + arg_auto_usr = GPT_AUTO_ROOT_DISSECT; + } + + } else if (streq(key, "mount.usrfstype")) { + + if (proc_cmdline_value_missing(key, value)) + return 0; + + return free_and_strdup_warn(&arg_usr_fstype, empty_to_null(value)); + + } else if (streq(key, "mount.usrflags")) { + + if (proc_cmdline_value_missing(key, value)) + return 0; + + if (!strextend_with_separator(&arg_usr_options, ",", value)) + return log_oom(); + } else if (streq(key, "rw") && !value) arg_root_rw = true; else if (streq(key, "ro") && !value) @@ -1045,6 +1165,7 @@ static int run(const char *dest, const char *dest_early, const char *dest_late) r = 0; RET_GATHER(r, add_root_mount()); + RET_GATHER(r, add_usr_mount()); RET_GATHER(r, add_mounts()); return r; diff --git a/src/shared/generator.c b/src/shared/generator.c index d1c643b9231..90568e3ec94 100644 --- a/src/shared/generator.c +++ b/src/shared/generator.c @@ -216,8 +216,8 @@ static int write_fsck_sysroot_service( /* Writes out special versions of systemd-fsck-root.service and systemd-fsck-usr.service for use in * the initrd. The regular statically shipped versions of these unit files use / and /usr for as - * paths, which doesn't match what we need for the initrd (where the dirs are /sysroot + - * /sysusr/usr), hence we overwrite those versions here. */ + * paths, which doesn't match what we need for the initrd (where the dirs are /sysroot/ + + * /sysusr/usr/), hence we overwrite those versions here. */ escaped = specifier_escape(what); if (!escaped) @@ -281,7 +281,7 @@ int generator_write_fsck_deps( assert(where); /* Let's do an early exit if we are invoked for the root and /usr/ trees in the initrd, to avoid - * generating confusing log messages */ + * generating confusing log messages. */ if (in_initrd() && PATH_IN_SET(where, "/", "/usr")) { log_debug("Skipping fsck for %s in initrd.", where); return 0; @@ -1086,7 +1086,8 @@ bool generator_soft_rebooted(void) { return (cached = (u > 0)); } -GptAutoRoot parse_gpt_auto_root(const char *value) { +GptAutoRoot parse_gpt_auto_root(const char *switch_name, const char *value) { + assert(switch_name); assert(value); /* Parses the 'gpt-auto'/'gpt-auto-root'/'dissect'/'dissect-force' parameters to root= @@ -1095,29 +1096,29 @@ GptAutoRoot parse_gpt_auto_root(const char *value) { * the parameter names. And root= being something else is not an error. */ if (streq(value, "gpt-auto")) { - log_debug("Enabling root partition auto-detection (respecting factory reset mode), root= is explicitly set to 'gpt-auto'."); + log_debug("Enabling partition auto-detection (respecting factory reset mode), %s is explicitly set to 'gpt-auto'.", switch_name); return GPT_AUTO_ROOT_ON; } if (streq(value, "gpt-auto-force")) { - log_debug("Enabling root partition auto-detection (ignoring factory reset mode), root= is explicitly set to 'gpt-auto-force'."); + log_debug("Enabling partition auto-detection (ignoring factory reset mode), %s is explicitly set to 'gpt-auto-force'.", switch_name); return GPT_AUTO_ROOT_FORCE; } if (streq(value, "dissect")) { - log_debug("Enabling root partition auto-detection via full image dissection (respecting factory reset mode), root= is explicitly set to 'dissect'."); + log_debug("Enabling partition auto-detection via full image dissection (respecting factory reset mode), %s is explicitly set to 'dissect'.", switch_name); return GPT_AUTO_ROOT_DISSECT; } if (streq(value, "dissect-force")) { - log_debug("Enabling root partition auto-detection via full image dissection (ignoring factory reset mode), root= is explicitly set to 'dissect-force'."); + log_debug("Enabling partition auto-detection via full image dissection (ignoring factory reset mode), %s is explicitly set to 'dissect-force'.", switch_name); return GPT_AUTO_ROOT_DISSECT_FORCE; } if (streq(value, "off")) - log_debug("Disabling root partition auto-detection, root= handling is explicitly turned off."); + log_debug("Disabling partition auto-detection, %s handling is explicitly turned off.", switch_name); else - log_debug("Disabling root partition auto-detection, root= is neither unset, nor set to 'gpt-auto', 'gpt-auto-force', 'dissect' or 'dissect-force'."); + log_debug("Disabling partition auto-detection, %s is neither unset, nor set to 'gpt-auto', 'gpt-auto-force', 'dissect' or 'dissect-force'.", switch_name); return GPT_AUTO_ROOT_OFF; } diff --git a/src/shared/generator.h b/src/shared/generator.h index 4ded62d011e..68ea9b376ff 100644 --- a/src/shared/generator.h +++ b/src/shared/generator.h @@ -131,4 +131,4 @@ typedef enum GptAutoRoot { _GPT_AUTO_ROOT_INVALID = -EINVAL, } GptAutoRoot; -GptAutoRoot parse_gpt_auto_root(const char *value); +GptAutoRoot parse_gpt_auto_root(const char *switch_name, const char *value); -- 2.47.3