From: Benjamin Drung <benjamin.drung@canonical.com>
Date: Thu, 4 Sep 2025 21:11:51 +0200
Subject: dracut: Open and mount luks keystore

Booting an encrypted ZFS system with dracut fails:

```
dracut-pre-mount[817]: Warning: ZFS: Key /run/keystore/rpool/system.key for rpool hasn't appeared. Trying anyway.
dracut-pre-mount[863]: Key load error: Failed to open key material file: No such file or directory
[FAILED] Failed to mount sysroot.mount - /sysroot.
```

4000-zsys-support.patch enhances `contrib/initramfs/scripts/zfs` to open
and mount luks keystore for any pools using one. Port this Ubuntu
keystore convention to Dracut.

Bug-Ubuntu: https://launchpad.net/bugs/2070066
---
 contrib/dracut/90zfs/module-setup.sh.in |  2 +-
 contrib/dracut/90zfs/zfs-load-key.sh.in | 29 +++++++++++++++++++++++++++++
 2 files changed, 30 insertions(+), 1 deletion(-)

diff --git a/contrib/dracut/90zfs/module-setup.sh.in b/contrib/dracut/90zfs/module-setup.sh.in
index c77efad..0dbe049 100755
--- a/contrib/dracut/90zfs/module-setup.sh.in
+++ b/contrib/dracut/90zfs/module-setup.sh.in
@@ -12,7 +12,7 @@ check() {
 }
 
 depends() {
-	echo udev-rules
+	echo systemd-cryptsetup udev-rules
 }
 
 installkernel() {
diff --git a/contrib/dracut/90zfs/zfs-load-key.sh.in b/contrib/dracut/90zfs/zfs-load-key.sh.in
index 8e68468..1932100 100755
--- a/contrib/dracut/90zfs/zfs-load-key.sh.in
+++ b/contrib/dracut/90zfs/zfs-load-key.sh.in
@@ -22,6 +22,29 @@ fi
 
 [ "$(zpool get -Ho value feature@encryption "${BOOTFS%%/*}")" = 'active' ] || return 0
 
+_open_and_mount_luks_keystore() {
+    pool="$1"
+    keyfile="$2"
+
+    ks="/dev/zvol/$pool/keystore"
+    if [ ! -e "$ks" ]; then
+        echo "Error: $ks does not exist." >&2
+        return 1
+    fi
+
+    systemd-cryptsetup attach "keystore-${pool}" "${ks}"
+
+    dev="/dev/mapper/keystore-${pool}"
+    if [ ! -e "$dev" ]; then
+        echo "Error: $dev does not exist." >&2
+        return 1
+    fi
+
+    keypath="${keyfile%/*}"
+    mkdir -p "${keypath}"
+    mount -o discard "${dev}" "${keypath}"
+}
+
 _load_key_cb() {
     dataset="$1"
 
@@ -31,6 +54,12 @@ _load_key_cb() {
     [ "$(zfs get -Ho value keystatus "${ENCRYPTIONROOT}")" = "unavailable" ] || return 0
 
     KEYLOCATION="$(zfs get -Ho value keylocation "${ENCRYPTIONROOT}")"
+    case "$KEYLOCATION" in
+        "file:///run/keystore/${ENCRYPTIONROOT}/"*)
+            _open_and_mount_luks_keystore "${ENCRYPTIONROOT}" "${KEYLOCATION#file://}"
+            ;;
+    esac
+
     case "${KEYLOCATION%%://*}" in
         prompt)
             for _ in 1 2 3; do
