gpt-auto-generator: optionally, set up root fs via dissection logic

This introduces root=dissect, which is a lot like root=gpt-auto, but
uses the image dissection logic to find the root partition. It's also
based on the GPT efi var telling us about the root disk, but instead of
just picking some suitable root disk manually it uses the dissection
logic.

This is a big step forward, since it means we can actually make
use of the image policy logic for the root fs too.
This commit is contained in:
Lennart Poettering
2025-03-14 15:44:50 +01:00
parent 1e6f03a45d
commit 198f7badaa
3 changed files with 41 additions and 13 deletions

View File

@@ -656,19 +656,27 @@ static int add_partition_root_flags(DissectedPartition *p) {
static int add_root_cryptsetup(void) {
#if HAVE_LIBCRYPTSETUP
/* 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. */
assert(arg_auto_root != GPT_AUTO_ROOT_OFF);
const char *bdev = "/dev/gpt-auto-root-luks";
/* If a device /dev/gpt-auto-root-luks or /dev/disk/by-designator/root-luks appears, then make it
* pull in systemd-cryptsetup@root.service, which sets it up, and causes /dev/gpt-auto-root or
* /dev/disk/by-designator/root to appear which is all we are looking for. */
if (arg_auto_root == GPT_AUTO_ROOT_FORCE) {
const char *bdev =
IN_SET(arg_auto_root, GPT_AUTO_ROOT_DISSECT, GPT_AUTO_ROOT_DISSECT_FORCE) ?
"/dev/disk/by-designator/root-luks" : "/dev/gpt-auto-root-luks";
if (IN_SET(arg_auto_root, GPT_AUTO_ROOT_FORCE, GPT_AUTO_ROOT_DISSECT_FORCE)) {
/* Similar logic as in add_root_mount(), see below */
FactoryResetMode f = factory_reset_mode();
if (f < 0)
log_warning_errno(f, "Failed to determine whether we are in factory reset mode, assuming not: %m");
if (IN_SET(f, FACTORY_RESET_ON, FACTORY_RESET_COMPLETE))
bdev = "/dev/gpt-auto-root-luks-ignore-factory-reset";
bdev =
IN_SET(arg_auto_root, GPT_AUTO_ROOT_DISSECT, GPT_AUTO_ROOT_DISSECT_FORCE) ?
"/dev/disk/by-designator/root-luks-ignore-factory-reset" :
"/dev/gpt-auto-root-luks-ignore-factory-reset";
}
return add_cryptsetup("root", bdev, arg_root_options, MOUNT_RW|MOUNT_MEASURE, /* require= */ false, NULL);
@@ -715,14 +723,19 @@ static int add_root_mount(void) {
* factory reset the latter is the link to use, otherwise the former (so that we don't accidentally
* mount a root partition too early that is about to be wiped and replaced by another one). */
const char *bdev = "/dev/gpt-auto-root";
if (arg_auto_root == GPT_AUTO_ROOT_FORCE) {
const char *bdev =
IN_SET(arg_auto_root, GPT_AUTO_ROOT_DISSECT, GPT_AUTO_ROOT_DISSECT_FORCE) ?
"/dev/disk/by-designator/root" : "/dev/gpt-auto-root";
if (IN_SET(arg_auto_root, GPT_AUTO_ROOT_FORCE, GPT_AUTO_ROOT_DISSECT_FORCE)) {
FactoryResetMode f = factory_reset_mode();
if (f < 0)
log_warning_errno(f, "Failed to determine whether we are in factory reset mode, assuming not: %m");
if (IN_SET(f, FACTORY_RESET_ON, FACTORY_RESET_COMPLETE))
bdev = "/dev/gpt-auto-root-ignore-factory-reset";
bdev =
IN_SET(arg_auto_root, GPT_AUTO_ROOT_DISSECT, GPT_AUTO_ROOT_DISSECT_FORCE) ?
"/dev/disk/by-designator/root-ignore-factory-reset" :
"/dev/gpt-auto-root-ignore-factory-reset";
}
if (in_initrd()) {

View File

@@ -1089,7 +1089,10 @@ bool generator_soft_rebooted(void) {
GptAutoRoot parse_gpt_auto_root(const char *value) {
assert(value);
/* Parses the 'gpt-auto'/'gpt-auto-root' parameters to root= */
/* Parses the 'gpt-auto'/'gpt-auto-root'/'dissect'/'dissect-force' parameters to root=
*
* note that we are not using a regular string table here, because the mode names don't fully match
* 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'.");
@@ -1101,6 +1104,16 @@ GptAutoRoot parse_gpt_auto_root(const char *value) {
return GPT_AUTO_ROOT_FORCE;
}
log_debug("Disabling root partition auto-detection, root= is neither unset, nor set to 'gpt-auto' or 'gpt-auto-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'.");
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'.");
return GPT_AUTO_ROOT_DISSECT_FORCE;
}
log_debug("Disabling root partition auto-detection, root= is neither unset, nor set to 'gpt-auto', 'gpt-auto-force', 'dissect' or 'dissect-force'.");
return GPT_AUTO_ROOT_OFF;
}

View File

@@ -122,9 +122,11 @@ bool generator_soft_rebooted(void);
exit_failure_if_negative)
typedef enum GptAutoRoot {
GPT_AUTO_ROOT_OFF = 0, /* root= set to something else */
GPT_AUTO_ROOT_ON, /* root= set explicitly to "gpt-auto" */
GPT_AUTO_ROOT_FORCE, /* root= set explicitly to "gpt-auto-force" → ignores factory reset mode */
GPT_AUTO_ROOT_OFF = 0, /* root= set to something else */
GPT_AUTO_ROOT_ON, /* root= set explicitly to "gpt-auto" */
GPT_AUTO_ROOT_FORCE, /* root= set explicitly to "gpt-auto-force" → ignores factory reset mode */
GPT_AUTO_ROOT_DISSECT, /* root= set to "dissect" */
GPT_AUTO_ROOT_DISSECT_FORCE, /* root= set to "dissect-force" → ignores factory reset mode */
_GPT_AUTO_ROOT_MAX,
_GPT_AUTO_ROOT_INVALID = -EINVAL,
} GptAutoRoot;