]> git.ipfire.org Git - thirdparty/dracut.git/commitdiff
98dracut-systemd: don't wait for root device if remote cryptsetup active
authorJonathan Lebon <jonathan@jlebon.com>
Fri, 9 Oct 2020 23:44:35 +0000 (19:44 -0400)
committerHarald Hoyer <harald@hoyer.xyz>
Mon, 12 Oct 2020 09:07:41 +0000 (11:07 +0200)
This is a plain and simple hack around dependency issues between dracut
and systemd.

When using Tang-pinned LUKS root devices, we want to rely on
`systemd-cryptsetup@.service` to unlock it. However, that service only
runs `After=remote-fs-pre.target`, while `dracut-initqueue.service` has
`Before=remote-fs-pre.target` (which makes sense because we don't want
to attempt networked root devices before networking is up).

However, the rootfs-generator here wants to make sure that the root
device exists *before* exiting the initqueue via an initqueue/finished
"devexists" hook. This will never work though because by design
`systemd-cryptsetup@.service`, which unlocks the root device, won't run
until after we exit.

So we have a dependency cycle:

    initqueue -> devexists hook -> root device ->
        systemd-cryptsetup@.service -> remote-fs-pre.target -> initqueue

There's no clean way to break this. The root issue is that there's no
way right now to split sequencing of systemd services across the
initqueue/online and initqueue/finished events because it's all bundled
in a single service. (The deeper root issue of course is that we have
two init systems. :) ).

Here we do a tactical fix: if there's a `systemd-cryptsetup@.service`
instance, let's assume it's for the root device and skip waiting for it
to show up if it depends on `remote-fs-pre.target`.

modules.d/98dracut-systemd/rootfs-generator.sh

index 4ae693bbc22aa584c5cb2cbb8cef074e7dbb1440..bb376c0f6c77f3ec367d6fc4cc6fb90714caa184 100755 (executable)
@@ -13,8 +13,15 @@ generator_wait_for_dev()
 
     if ! [ -e "$hookdir/initqueue/finished/devexists-${_name}.sh" ]; then
 
-        printf '[ -e "%s" ]\n' $1 \
-            >> "$hookdir/initqueue/finished/devexists-${_name}.sh"
+        # If a LUKS device needs unlocking via systemd in the initrd, assume
+        # it's for the root device. In that case, don't block on it if it's
+        # after remote-fs-pre.target since the initqueue is ordered before it so
+        # it will never actually show up (think Tang-pinned rootfs).
+        cat > "$hookdir/initqueue/finished/devexists-${_name}.sh" << EOF
+if ! grep -q After=remote-fs-pre.target /run/systemd/generator/systemd-cryptsetup@*.service 2>/dev/null; then
+    [ -e "$1" ]
+fi
+EOF
         {
             printf '[ -e "%s" ] || ' $1
             printf 'warn "\"%s\" does not exist"\n' $1