diff options
author | Lennart Poettering <lennart@poettering.net> | 2021-03-26 22:40:40 +0100 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2021-04-20 18:26:17 +0200 |
commit | 29a24ab28e9790680348b1ffab653a321fa49a67 (patch) | |
tree | 6bf35850f80c21a86728106ed767e88a72bc4658 /src/fstab-generator | |
parent | update TODO (diff) | |
download | systemd-29a24ab28e9790680348b1ffab653a321fa49a67.tar.xz systemd-29a24ab28e9790680348b1ffab653a321fa49a67.zip |
fstab-generator: if usr= is specified, mount it to /sysusr/usr/ first
This changes the fstab-generator to handle mounting of /usr/ a bit
differently than before. Instead of immediately mounting the fs to
/sysroot/usr/ we'll first mount it to /sysusr/usr/ and then add a
separate bind mount that mounts it from /sysusr/usr/ to /sysroot/usr/.
This way we can access /usr independently of the root fs, without for
waiting to be mounted via the /sysusr/ hierarchy. This is useful for
invoking systemd-repart while a root fs doesn't exist yet and for
creating it, with partition data read from the /usr/ hierarchy.
This introduces a new generic target initrd-usr-fs.target that may be
used to generically order services against /sysusr/ to become available.
Diffstat (limited to 'src/fstab-generator')
-rw-r--r-- | src/fstab-generator/fstab-generator.c | 90 |
1 files changed, 77 insertions, 13 deletions
diff --git a/src/fstab-generator/fstab-generator.c b/src/fstab-generator/fstab-generator.c index 69ba4bfc64..4e4121550d 100644 --- a/src/fstab-generator/fstab-generator.c +++ b/src/fstab-generator/fstab-generator.c @@ -744,6 +744,10 @@ static int add_sysroot_mount(void) { static int add_sysroot_usr_mount(void) { _cleanup_free_ char *what = NULL; const char *opts; + int r; + + /* Returns 0 if we didn't do anything, > 0 if we either generated a unit for the /usr/ mount, or we + * know for sure something else did */ if (!arg_usr_what && !arg_usr_fstype && !arg_usr_options) return 0; @@ -767,8 +771,23 @@ static int add_sysroot_usr_mount(void) { return log_oom(); } - if (!arg_usr_what) + if (isempty(arg_usr_what)) { + log_debug("Could not find a usr= entry on the kernel command line."); return 0; + } + + if (streq(arg_usr_what, "gpt-auto")) { + /* This is handled by the gpt-auto generator */ + log_debug("Skipping /usr/ directory handling, as gpt-auto was requested."); + return 1; /* systemd-gpt-auto-generator will generate a unit for this, hence report that a + * unit file is being created for the host /usr/ mount. */ + } + + if (path_equal(arg_usr_what, "/dev/nfs")) { + /* This is handled by the initrd (if at all supported, that is) */ + log_debug("Skipping /usr/ directory handling, as /dev/nfs was requested."); + return 1; /* As above, report that NFS code will create the unit */ + } what = fstab_node_to_udev_node(arg_usr_what); if (!what) @@ -781,17 +800,62 @@ static int add_sysroot_usr_mount(void) { else opts = arg_usr_options; - log_debug("Found entry what=%s where=/sysroot/usr type=%s", what, strna(arg_usr_fstype)); - return add_mount(arg_dest, - what, - "/sysroot/usr", - NULL, - arg_usr_fstype, - opts, - is_device_path(what) ? 1 : 0, /* passno */ - 0, - SPECIAL_INITRD_FS_TARGET, - "/proc/cmdline"); + /* When mounting /usr from the initrd, we add an extra level of indirection: we first mount the /usr/ + * partition to /sysusr/usr/, and then afterwards bind mount that to /sysroot/usr/. We do this so + * that we can cover for systems that initially only have a /usr/ around and where the root fs needs + * to be synthesized, based on configuration included in /usr/, e.g. systemd-repart. Software like + * this should order itself after initrd-usr-fs.target and before initrd-fs.target; and it should + * look into both /sysusr/ and /sysroot/ for the configuration data to apply. */ + + log_debug("Found entry what=%s where=/sysusr/usr type=%s opts=%s", what, strna(arg_usr_fstype), strempty(opts)); + + r = add_mount(arg_dest, + what, + "/sysusr/usr", + NULL, + arg_usr_fstype, + opts, + is_device_path(what) ? 1 : 0, /* passno */ + 0, + SPECIAL_INITRD_USR_FS_TARGET, + "/proc/cmdline"); + if (r < 0) + return r; + + log_debug("Synthesizing entry what=/sysusr/usr where=/sysrootr/usr opts=bind"); + + r = add_mount(arg_dest, + "/sysusr/usr", + "/sysroot/usr", + NULL, + NULL, + "bind", + 0, + 0, + SPECIAL_INITRD_FS_TARGET, + "/proc/cmdline"); + if (r < 0) + return r; + + return 1; +} + +static int add_sysroot_usr_mount_or_fallback(void) { + int r; + + r = add_sysroot_usr_mount(); + if (r != 0) + return r; + + /* OK, so we didn't write anything out for /sysusr/usr/ nor /sysroot/usr/. In this case, let's make + * sure that initrd-usr-fs.target is at least ordered after sysroot.mount so that services that order + * themselves get the guarantee that /usr/ is definitely mounted somewhere. */ + + return generator_add_symlink( + arg_dest, + SPECIAL_INITRD_USR_FS_TARGET, + "requires", + "sysroot.mount"); } static int add_volatile_root(void) { @@ -953,7 +1017,7 @@ static int run(const char *dest, const char *dest_early, const char *dest_late) if (in_initrd()) { r = add_sysroot_mount(); - r2 = add_sysroot_usr_mount(); + r2 = add_sysroot_usr_mount_or_fallback(); r3 = add_volatile_root(); } else |