]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
Merge pull request #26038 from lilyinstarlight/fix/fstab-generator-sysroot-without...
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Thu, 9 Mar 2023 07:51:31 +0000 (08:51 +0100)
committerGitHub <noreply@github.com>
Thu, 9 Mar 2023 07:51:31 +0000 (08:51 +0100)
fstab-generator: use correct targets when /sysroot is specificied in fstab only

14 files changed:
docs/ENVIRONMENT.md
man/systemd-fstab-generator.xml
src/fstab-generator/fstab-generator.c
test/test-fstab-generator.sh
test/test-fstab-generator/test-17-initrd-sysroot.fstab.expected/initrd-fs.target.requires/sysroot-usr.mount [new file with mode: 0644]
test/test-fstab-generator/test-17-initrd-sysroot.fstab.expected/initrd-root-device.target.d/50-root-device.conf [new file with mode: 0644]
test/test-fstab-generator/test-17-initrd-sysroot.fstab.expected/initrd-root-fs.target.requires/sysroot.mount [new file with mode: 0644]
test/test-fstab-generator/test-17-initrd-sysroot.fstab.expected/initrd-usr-fs.target.requires/sysroot.mount [new file with mode: 0644]
test/test-fstab-generator/test-17-initrd-sysroot.fstab.expected/initrd-usr-fs.target.requires/sysusr-usr.mount [new file with mode: 0644]
test/test-fstab-generator/test-17-initrd-sysroot.fstab.expected/sysroot-usr.mount [new file with mode: 0644]
test/test-fstab-generator/test-17-initrd-sysroot.fstab.expected/sysroot.mount [new file with mode: 0644]
test/test-fstab-generator/test-17-initrd-sysroot.fstab.expected/systemd-fsck-root.service [new file with mode: 0644]
test/test-fstab-generator/test-17-initrd-sysroot.fstab.expected/sysusr-usr.mount [new file with mode: 0644]
test/test-fstab-generator/test-17-initrd-sysroot.fstab.input [new file with mode: 0644]

index 30ef1e7e42ad96d3f4d7944eb6835b5babaffc59..3e957113e74c04ef4ca4fb50831cc6af9104f668 100644 (file)
@@ -54,6 +54,10 @@ All tools:
 * `$SYSTEMD_SYSROOT_FSTAB` — if set, use this path instead of
   `/sysroot/etc/fstab`. Only useful for debugging `systemd-fstab-generator`.
 
+* `$SYSTEMD_SYSFS_CHECK` — takes a boolean. If set, overrides sysfs container
+  detection that ignores `/dev/` entries in fstab. Only useful for debugging
+  `systemd-fstab-generator`.
+
 * `$SYSTEMD_CRYPTTAB` — if set, use this path instead of `/etc/crypttab`. Only
   useful for debugging. Currently only supported by
   `systemd-cryptsetup-generator`.
index b7908377a4f00ccf969dcbadf6e619f44342f0d1..30204f5d8aec4f5eb9235901184c5e614e8fe213 100644 (file)
 
         <listitem><para>Configures the operating system's root filesystem to mount when running in the
         initrd. This accepts a device node path (usually <filename>/dev/disk/by-uuid/…</filename> or
-        <filename>/dev/disk/by-label/…</filename> or similar), or the special values <literal>gpt-auto</literal>
-        and <literal>tmpfs</literal>.</para>
+        <filename>/dev/disk/by-label/…</filename> or similar), or the special values <literal>gpt-auto</literal>,
+        <literal>fstab</literal>, and <literal>tmpfs</literal>.</para>
 
         <para>Use <literal>gpt-auto</literal> to explicitly request automatic root file system discovery via
         <citerefentry><refentrytitle>systemd-gpt-auto-generator</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
 
+        <para>Use <literal>fstab</literal> to explicitly request automatic root file system discovery via
+        the initrd <filename>/etc/fstab</filename> rather than via kernel command line.</para>
+
         <para>Use <literal>tmpfs</literal> in order to mount a <citerefentry
         project='man-pages'><refentrytitle>tmpfs</refentrytitle><manvolnum>5</manvolnum></citerefentry> file
         system as root file system of the OS. This is useful in combination with
index efc553b698923e1a526632a4a9daf26aae1193c3..138321680d7f6a707aca351f37e27a5aeb2ffdb4 100644 (file)
@@ -9,6 +9,7 @@
 #include "bus-locator.h"
 #include "chase-symlinks.h"
 #include "efi-loader.h"
+#include "env-util.h"
 #include "fd-util.h"
 #include "fileio.h"
 #include "fstab-util.h"
@@ -648,11 +649,24 @@ static const char* sysroot_fstab_path(void) {
         return getenv("SYSTEMD_SYSROOT_FSTAB") ?: "/sysroot/etc/fstab";
 }
 
+static int add_sysusr_sysroot_usr_bind_mount(const char *source) {
+        return add_mount(source,
+                        arg_dest,
+                        "/sysusr/usr",
+                        "/sysroot/usr",
+                        NULL,
+                        NULL,
+                        "bind",
+                        0,
+                        0,
+                        SPECIAL_INITRD_FS_TARGET);
+}
+
 static int parse_fstab(bool initrd) {
         _cleanup_endmntent_ FILE *f = NULL;
         const char *fstab;
         struct mntent *me;
-        int r = 0;
+        int r = 0, sysfs_check = -1;
 
         if (initrd)
                 fstab = sysroot_fstab_path();
@@ -690,7 +704,14 @@ static int parse_fstab(bool initrd) {
                                 continue;
                         }
 
-                        if (is_device_path(what)) {
+                        if (sysfs_check < 0) {
+                                r = getenv_bool_secure("SYSTEMD_SYSFS_CHECK");
+                                if (r < 0 && r != -ENXIO)
+                                        log_debug_errno(r, "Failed to parse $SYSTEMD_SYSFS_CHECK, ignoring: %m");
+                                sysfs_check = r != 0;
+                        }
+
+                        if (sysfs_check && is_device_path(what)) {
                                 log_info("/sys/ is read-only (running in a container?), ignoring fstab device entry for %s.", what);
                                 continue;
                         }
@@ -751,7 +772,7 @@ static int parse_fstab(bool initrd) {
                 if (streq(me->mnt_type, "swap"))
                         k = add_swap(fstab, what, me, flags);
                 else {
-                        bool rw_only, automount;
+                        bool rw_only, automount, is_sysroot, is_sysroot_usr;
 
                         rw_only = fstab_test_option(me->mnt_opts, "x-systemd.rw-only\0");
                         automount = fstab_test_option(me->mnt_opts,
@@ -761,21 +782,43 @@ static int parse_fstab(bool initrd) {
                         flags |= rw_only * MOUNT_RW_ONLY |
                                  automount * MOUNT_AUTOMOUNT;
 
+                        is_sysroot = in_initrd() && path_equal(where, "/sysroot");
+                        /* See comment from add_sysroot_usr_mount about the need for extra indirection
+                         * in case /usr needs to be mounted in order for the root fs to be synthesized
+                         * based on configuration included in /usr/, e.g. systemd-repart. */
+                        is_sysroot_usr = in_initrd() && path_equal(where, "/sysroot/usr");
+
                         const char *target_unit =
                                 initrd ?               SPECIAL_INITRD_FS_TARGET :
+                                is_sysroot ?           SPECIAL_INITRD_ROOT_FS_TARGET :
+                                is_sysroot_usr ?       SPECIAL_INITRD_USR_FS_TARGET :
                                 mount_is_network(me) ? SPECIAL_REMOTE_FS_TARGET :
                                                        SPECIAL_LOCAL_FS_TARGET;
 
+                        if (is_sysroot && is_device_path(what)) {
+                                r = generator_write_initrd_root_device_deps(arg_dest, what);
+                                if (r < 0)
+                                        return r;
+                        }
+
                         k = add_mount(fstab,
                                       arg_dest,
                                       what,
-                                      canonical_where ?: where,
-                                      canonical_where ? where: NULL,
+                                      is_sysroot_usr ? "/sysusr/usr" : canonical_where ?: where,
+                                      !is_sysroot_usr && canonical_where ? where : NULL,
                                       me->mnt_type,
                                       me->mnt_opts,
                                       me->mnt_passno,
                                       flags,
                                       target_unit);
+
+                        if (is_sysroot_usr && k >= 0) {
+                                log_debug("Synthesizing fstab entry what=/sysusr/usr where=/sysroot/usr opts=bind");
+
+                                r = add_sysusr_sysroot_usr_bind_mount(fstab);
+                                if (r != 0)
+                                        k = r;
+                        }
                 }
 
                 if (arg_sysroot_check && k > 0)
@@ -854,6 +897,10 @@ static int add_sysroot_mount(void) {
                 /* This is handled by gpt-auto-generator */
                 log_debug("Skipping root directory handling, as gpt-auto was requested.");
                 return 0;
+        } else if (streq(arg_root_what, "fstab")) {
+                /* This is handled by parse_fstab */
+                log_debug("Using initrd's fstab for /sysroot/ configuration.");
+                return 0;
         }
 
         r = sysroot_is_nfsroot();
@@ -974,6 +1021,11 @@ static int add_sysroot_usr_mount(void) {
                 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. */
+        } else if (streq(arg_usr_what, "fstab")) {
+                /* This is handled by parse_fstab */
+                log_debug("Using initrd's fstab for /sysroot/usr/ configuration.");
+                return 1; /* parse_fstab 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")) {
@@ -1018,18 +1070,9 @@ static int add_sysroot_usr_mount(void) {
         if (r < 0)
                 return r;
 
-        log_debug("Synthesizing entry what=/sysusr/usr where=/sysrootr/usr opts=bind");
+        log_debug("Synthesizing entry what=/sysusr/usr where=/sysroot/usr opts=bind");
 
-        r = add_mount("/proc/cmdline",
-                      arg_dest,
-                      "/sysusr/usr",
-                      "/sysroot/usr",
-                      NULL,
-                      NULL,
-                      "bind",
-                      0,
-                      0,
-                      SPECIAL_INITRD_FS_TARGET);
+        r = add_sysusr_sysroot_usr_bind_mount("/proc/cmdline");
         if (r < 0)
                 return r;
 
index 7c060dfac79b789dc68d348879dab1cbb960c6f7..c86914a10774d9080e5382a27708f9a8706b8ac5 100755 (executable)
@@ -26,7 +26,11 @@ for f in "$src"/test-*.input; do
         trap "rm -rf '$out'" EXIT INT QUIT PIPE
 
         # shellcheck disable=SC2046
-        SYSTEMD_LOG_LEVEL=debug SYSTEMD_IN_INITRD=yes SYSTEMD_PROC_CMDLINE="fstab=no $(cat "$f")" $generator "$out" "$out" "$out"
+        if [[ "$f" == *.fstab.input ]]; then
+            SYSTEMD_LOG_LEVEL=debug SYSTEMD_IN_INITRD=yes SYSTEMD_SYSFS_CHECK=no SYSTEMD_PROC_CMDLINE="fstab=yes root=fstab" SYSTEMD_FSTAB="$f" SYSTEMD_SYSROOT_FSTAB="/dev/null" $generator "$out" "$out" "$out"
+        else
+            SYSTEMD_LOG_LEVEL=debug SYSTEMD_IN_INITRD=yes SYSTEMD_PROC_CMDLINE="fstab=no $(cat "$f")" $generator "$out" "$out" "$out"
+        fi
 
         if [[ -f "$out"/systemd-fsck-root.service ]]; then
             # For split-usr system
diff --git a/test/test-fstab-generator/test-17-initrd-sysroot.fstab.expected/initrd-fs.target.requires/sysroot-usr.mount b/test/test-fstab-generator/test-17-initrd-sysroot.fstab.expected/initrd-fs.target.requires/sysroot-usr.mount
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/test/test-fstab-generator/test-17-initrd-sysroot.fstab.expected/initrd-root-device.target.d/50-root-device.conf b/test/test-fstab-generator/test-17-initrd-sysroot.fstab.expected/initrd-root-device.target.d/50-root-device.conf
new file mode 100644 (file)
index 0000000..47c4232
--- /dev/null
@@ -0,0 +1,5 @@
+# Automatically generated by systemd-fstab-generator
+
+[Unit]
+Requires=dev-sdx1.device
+After=dev-sdx1.device
diff --git a/test/test-fstab-generator/test-17-initrd-sysroot.fstab.expected/initrd-root-fs.target.requires/sysroot.mount b/test/test-fstab-generator/test-17-initrd-sysroot.fstab.expected/initrd-root-fs.target.requires/sysroot.mount
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/test/test-fstab-generator/test-17-initrd-sysroot.fstab.expected/initrd-usr-fs.target.requires/sysroot.mount b/test/test-fstab-generator/test-17-initrd-sysroot.fstab.expected/initrd-usr-fs.target.requires/sysroot.mount
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/test/test-fstab-generator/test-17-initrd-sysroot.fstab.expected/initrd-usr-fs.target.requires/sysusr-usr.mount b/test/test-fstab-generator/test-17-initrd-sysroot.fstab.expected/initrd-usr-fs.target.requires/sysusr-usr.mount
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/test/test-fstab-generator/test-17-initrd-sysroot.fstab.expected/sysroot-usr.mount b/test/test-fstab-generator/test-17-initrd-sysroot.fstab.expected/sysroot-usr.mount
new file mode 100644 (file)
index 0000000..69be9c1
--- /dev/null
@@ -0,0 +1,11 @@
+# Automatically generated by systemd-fstab-generator
+
+[Unit]
+Documentation=man:fstab(5) man:systemd-fstab-generator(8)
+SourcePath=/etc/fstab
+Before=initrd-fs.target
+
+[Mount]
+What=/sysusr/usr
+Where=/sysroot/usr
+Options=bind
diff --git a/test/test-fstab-generator/test-17-initrd-sysroot.fstab.expected/sysroot.mount b/test/test-fstab-generator/test-17-initrd-sysroot.fstab.expected/sysroot.mount
new file mode 100644 (file)
index 0000000..0e8a701
--- /dev/null
@@ -0,0 +1,13 @@
+# Automatically generated by systemd-fstab-generator
+
+[Unit]
+Documentation=man:fstab(5) man:systemd-fstab-generator(8)
+SourcePath=/etc/fstab
+Before=initrd-root-fs.target
+Requires=systemd-fsck-root.service
+After=systemd-fsck-root.service
+After=blockdev@dev-sdx1.target
+
+[Mount]
+What=/dev/sdx1
+Where=/sysroot
diff --git a/test/test-fstab-generator/test-17-initrd-sysroot.fstab.expected/systemd-fsck-root.service b/test/test-fstab-generator/test-17-initrd-sysroot.fstab.expected/systemd-fsck-root.service
new file mode 100644 (file)
index 0000000..7f914fd
--- /dev/null
@@ -0,0 +1,16 @@
+# Automatically generated by systemd-fstab-generator
+
+[Unit]
+Description=File System Check on /dev/sdx1
+Documentation=man:systemd-fsck-root.service(8)
+DefaultDependencies=no
+BindsTo=dev-sdx1.device
+Conflicts=shutdown.target
+After=initrd-root-device.target local-fs-pre.target dev-sdx1.device
+Before=shutdown.target
+
+[Service]
+Type=oneshot
+RemainAfterExit=yes
+ExecStart=/usr/lib/systemd/systemd-fsck /dev/sdx1
+TimeoutSec=0
diff --git a/test/test-fstab-generator/test-17-initrd-sysroot.fstab.expected/sysusr-usr.mount b/test/test-fstab-generator/test-17-initrd-sysroot.fstab.expected/sysusr-usr.mount
new file mode 100644 (file)
index 0000000..63fcb10
--- /dev/null
@@ -0,0 +1,11 @@
+# Automatically generated by systemd-fstab-generator
+
+[Unit]
+Documentation=man:fstab(5) man:systemd-fstab-generator(8)
+SourcePath=/etc/fstab
+Before=initrd-usr-fs.target
+After=blockdev@dev-sdx2.target
+
+[Mount]
+What=/dev/sdx2
+Where=/sysusr/usr
diff --git a/test/test-fstab-generator/test-17-initrd-sysroot.fstab.input b/test/test-fstab-generator/test-17-initrd-sysroot.fstab.input
new file mode 100644 (file)
index 0000000..1ba9b06
--- /dev/null
@@ -0,0 +1,2 @@
+/dev/sdx1 /sysroot auto defaults 0 1
+/dev/sdx2 /sysroot/usr auto defaults 0 0