]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
fstab-generator: if usr= is specified, mount it to /sysusr/usr/ first
authorLennart Poettering <lennart@poettering.net>
Fri, 26 Mar 2021 21:40:40 +0000 (22:40 +0100)
committerLennart Poettering <lennart@poettering.net>
Tue, 20 Apr 2021 16:26:17 +0000 (18:26 +0200)
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.

src/basic/special.h
src/fstab-generator/fstab-generator.c
units/initrd-usr-fs.target [new file with mode: 0644]
units/initrd.target
units/meson.build
units/systemd-repart.service.in
units/systemd-volatile-root.service.in

index b9b7be7a7dda98c0b0840bacabcda882c75ed150..841e8ad132355326127c385b3f3be9ea67dc269b 100644 (file)
@@ -37,6 +37,7 @@
 #define SPECIAL_INITRD_FS_TARGET "initrd-fs.target"
 #define SPECIAL_INITRD_ROOT_DEVICE_TARGET "initrd-root-device.target"
 #define SPECIAL_INITRD_ROOT_FS_TARGET "initrd-root-fs.target"
+#define SPECIAL_INITRD_USR_FS_TARGET "initrd-usr-fs.target"
 #define SPECIAL_REMOTE_FS_TARGET "remote-fs.target"       /* LSB's $remote_fs */
 #define SPECIAL_REMOTE_FS_PRE_TARGET "remote-fs-pre.target"
 #define SPECIAL_SWAP_TARGET "swap.target"
index 69ba4bfc647083459ea0a1892fd9cbb7559a2cb1..4e4121550d324664d9ea4456c4374fc36ffb6a3c 100644 (file)
@@ -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
diff --git a/units/initrd-usr-fs.target b/units/initrd-usr-fs.target
new file mode 100644 (file)
index 0000000..7219655
--- /dev/null
@@ -0,0 +1,17 @@
+#  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=Initrd /usr File System
+Documentation=man:systemd.special(7)
+AssertPathExists=/etc/initrd-release
+OnFailure=emergency.target
+OnFailureJobMode=replace-irreversibly
+DefaultDependencies=no
+Conflicts=shutdown.target
index 655158a58bca3daa98d5d95f878f1cd75030effb..fc8fbff4bded60a3534cc0b5e20a3b3972f98832 100644 (file)
@@ -14,6 +14,6 @@ OnFailure=emergency.target
 OnFailureJobMode=replace-irreversibly
 AssertPathExists=/etc/initrd-release
 Requires=basic.target
-Wants=initrd-root-fs.target initrd-root-device.target initrd-fs.target initrd-parse-etc.service
-After=initrd-root-fs.target initrd-root-device.target initrd-fs.target basic.target rescue.service rescue.target
+Wants=initrd-root-fs.target initrd-root-device.target initrd-fs.target initrd-usr-fs.target initrd-parse-etc.service
+After=initrd-root-fs.target initrd-root-device.target initrd-fs.target initrd-usr-fs.target basic.target rescue.service rescue.target
 AllowIsolate=yes
index 15463760c6796d6f93670bb25e3be6bbc8515c6d..fe8e95ff91dc824f7fa8d3da18f9da43089e4c52 100644 (file)
@@ -38,6 +38,7 @@ units = [
         ['initrd-switch-root.service',          'ENABLE_INITRD'],
         ['initrd-switch-root.target',           'ENABLE_INITRD'],
         ['initrd-udevadm-cleanup-db.service',   'ENABLE_INITRD'],
+        ['initrd-usr-fs.target',                'ENABLE_INITRD'],
         ['initrd.target',                       'ENABLE_INITRD'],
         ['kexec.target',                        ''],
         ['ldconfig.service',                    'ENABLE_LDCONFIG',
index a5565834ebbe3129e6feb71ad579ebab0abbb1a7..60dc7783b3bfe03e81893b3fe6d2f10a05819aeb 100644 (file)
@@ -12,7 +12,7 @@ Description=Repartition Root Disk
 Documentation=man:systemd-repart.service(8)
 DefaultDependencies=no
 Conflicts=shutdown.target
-After=sysroot.mount
+After=initrd-usr-fs.target
 Before=initrd-root-fs.target shutdown.target
 ConditionVirtualization=!container
 ConditionDirectoryNotEmpty=|/usr/lib/repart.d
index 5ecc702b6d109c3dbe7f04ef7bf40f300dd9b839..468d85f968315365d820d66f15713c1c4328f075 100644 (file)
@@ -12,7 +12,7 @@ Description=Enforce Volatile Root File Systems
 Documentation=man:systemd-volatile-root.service(8)
 DefaultDependencies=no
 Conflicts=shutdown.target
-After=sysroot.mount systemd-repart.service
+After=sysroot.mount sysroot-usr.mount systemd-repart.service
 Before=initrd-root-fs.target shutdown.target
 AssertPathExists=/etc/initrd-release