ab0e4d
From 1e7a27bd5f463409392d34816a10bf108ee896c6 Mon Sep 17 00:00:00 2001
ab0e4d
From: Jonathan Lebon <jonathan@jlebon.com>
ab0e4d
Date: Fri, 9 Oct 2020 19:44:35 -0400
ab0e4d
Subject: [PATCH] 98dracut-systemd: don't wait for root device if remote
ab0e4d
 cryptsetup active
ab0e4d
ab0e4d
This is a plain and simple hack around dependency issues between dracut
ab0e4d
and systemd.
ab0e4d
ab0e4d
When using Tang-pinned LUKS root devices, we want to rely on
ab0e4d
`systemd-cryptsetup@.service` to unlock it. However, that service only
ab0e4d
runs `After=remote-fs-pre.target`, while `dracut-initqueue.service` has
ab0e4d
`Before=remote-fs-pre.target` (which makes sense because we don't want
ab0e4d
to attempt networked root devices before networking is up).
ab0e4d
ab0e4d
However, the rootfs-generator here wants to make sure that the root
ab0e4d
device exists *before* exiting the initqueue via an initqueue/finished
ab0e4d
"devexists" hook. This will never work though because by design
ab0e4d
`systemd-cryptsetup@.service`, which unlocks the root device, won't run
ab0e4d
until after we exit.
ab0e4d
ab0e4d
So we have a dependency cycle:
ab0e4d
ab0e4d
    initqueue -> devexists hook -> root device ->
ab0e4d
        systemd-cryptsetup@.service -> remote-fs-pre.target -> initqueue
ab0e4d
ab0e4d
There's no clean way to break this. The root issue is that there's no
ab0e4d
way right now to split sequencing of systemd services across the
ab0e4d
initqueue/online and initqueue/finished events because it's all bundled
ab0e4d
in a single service. (The deeper root issue of course is that we have
ab0e4d
two init systems. :) ).
ab0e4d
ab0e4d
Here we do a tactical fix: if there's a `systemd-cryptsetup@.service`
ab0e4d
instance, let's assume it's for the root device and skip waiting for it
ab0e4d
to show up if it depends on `remote-fs-pre.target`.
ab0e4d
ab0e4d
(cherry picked from commit 512c51d2677dd1637cc203e3676fefb50a3d73d0)
ab0e4d
ab0e4d
Resolves: #1897384
ab0e4d
---
ab0e4d
 modules.d/98dracut-systemd/rootfs-generator.sh | 11 +++++++++--
ab0e4d
 1 file changed, 9 insertions(+), 2 deletions(-)
ab0e4d
ab0e4d
diff --git a/modules.d/98dracut-systemd/rootfs-generator.sh b/modules.d/98dracut-systemd/rootfs-generator.sh
ab0e4d
index 4ae693bb..bb376c0f 100755
ab0e4d
--- a/modules.d/98dracut-systemd/rootfs-generator.sh
ab0e4d
+++ b/modules.d/98dracut-systemd/rootfs-generator.sh
ab0e4d
@@ -13,8 +13,15 @@ generator_wait_for_dev()
ab0e4d
 
ab0e4d
     if ! [ -e "$hookdir/initqueue/finished/devexists-${_name}.sh" ]; then
ab0e4d
 
ab0e4d
-        printf '[ -e "%s" ]\n' $1 \
ab0e4d
-            >> "$hookdir/initqueue/finished/devexists-${_name}.sh"
ab0e4d
+        # If a LUKS device needs unlocking via systemd in the initrd, assume
ab0e4d
+        # it's for the root device. In that case, don't block on it if it's
ab0e4d
+        # after remote-fs-pre.target since the initqueue is ordered before it so
ab0e4d
+        # it will never actually show up (think Tang-pinned rootfs).
ab0e4d
+        cat > "$hookdir/initqueue/finished/devexists-${_name}.sh" << EOF
ab0e4d
+if ! grep -q After=remote-fs-pre.target /run/systemd/generator/systemd-cryptsetup@*.service 2>/dev/null; then
ab0e4d
+    [ -e "$1" ]
ab0e4d
+fi
ab0e4d
+EOF
ab0e4d
         {
ab0e4d
             printf '[ -e "%s" ] || ' $1
ab0e4d
             printf 'warn "\"%s\" does not exist"\n' $1
ab0e4d