split out hash because rocky doesnt support it inline

This commit is contained in:
Audiobuzz
2026-06-15 12:52:27 +00:00
parent 2037531771
commit 72d3f49369
6 changed files with 116 additions and 57 deletions
+28 -22
View File
@@ -1,29 +1,32 @@
#!/usr/bin/env bash
# Configure SPDK nvmf_tgt to serve the diskless root filesystem as a single
# READ-ONLY NVMe/TCP namespace (design doc §5, §7).
# Configure SPDK nvmf_tgt to serve the diskless root filesystem as TWO READ-ONLY
# NVMe/TCP namespaces — erofs DATA and the dm-verity HASH tree (design doc §5, §7).
#
# rootfs.erofs is the erofs image with the dm-verity hash tree appended in-file;
# we expose the WHOLE file as one namespace, and the host splits data/hash with
# systemd.verity_root_options=hash-offset= from the kernel cmdline. Integrity is
# enforced end-to-end by dm-verity on the host; the target serves it read-only.
# Two namespaces (not one with an in-file hash-offset): the target Rocky 9
# systemd-veritysetup does not support the hash-offset layout, so the host needs
# the verity data and hash on separate block devices. Integrity is enforced
# end-to-end by dm-verity on the host; the target serves both read-only.
set -euo pipefail
ROOTFS="/artifacts/rootfs.erofs"
ROOTHASH="/artifacts/rootfs.hash"
SUBNQN="${SUBNQN:-nqn.2026-06.org.example.fleet:rootfs}"
# Fixed, fleet-generic namespace UUID. The host references the root device as
# /dev/disk/by-id/nvme-uuid.$ROOT_NS_UUID on the kernel cmdline, which is stable
# regardless of NVMe controller enumeration order (the I/O controller can land
# on nvme0/nvme1/... depending on whether a transient discovery controller took
# a slot first — so a hardcoded /dev/nvme0n1 is unsafe). MUST match
# ROOT_NS_UUID in scripts/extract-artifacts.sh, which bakes it into the UKI
# cmdline. NOTE: for multi-version serving (TODO #6) make this version-specific
# alongside the per-version NQN, so a host can't connect the wrong rootfs.
ROOT_NS_UUID="${ROOT_NS_UUID:-f1ee7000-0000-4000-8000-000000000001}"
# Fixed, fleet-generic namespace UUIDs. The host references each device as
# /dev/disk/by-id/nvme-uuid.<uuid> on the kernel cmdline, stable regardless of
# NVMe controller/namespace enumeration order (a transient discovery controller
# can shift indices — so a hardcoded /dev/nvmeNnM is unsafe). MUST match
# ROOT_DATA_UUID / ROOT_HASH_UUID in scripts/extract-artifacts.sh, which bake
# them into the UKI cmdline. NOTE: for multi-version serving (TODO #6) make
# these version-specific alongside the per-version NQN, so a host can't connect
# the wrong rootfs.
ROOT_DATA_UUID="${ROOT_DATA_UUID:-f1ee7000-0000-4000-8000-000000000001}"
ROOT_HASH_UUID="${ROOT_HASH_UUID:-f1ee7000-0000-4000-8000-000000000002}"
TADDR="${TARGET_ADDR:-0.0.0.0}"
TPORT="${TARGET_PORT:-4420}"
CPUMASK="${SPDK_CPUMASK:-0x1}"
[ -s "$ROOTFS" ] || { echo "ERROR: $ROOTFS not found/empty — is ARTIFACT_SRC populated?" >&2; exit 1; }
[ -s "$ROOTFS" ] || { echo "ERROR: $ROOTFS not found/empty — is ARTIFACT_SRC populated?" >&2; exit 1; }
[ -s "$ROOTHASH" ] || { echo "ERROR: $ROOTHASH not found/empty — rebuild artifacts with the two-namespace layout." >&2; exit 1; }
# Binary locations differ across SPDK images; fall back to the common path.
TGT=$(command -v nvmf_tgt || echo /usr/libexec/spdk/spdk/build/bin/nvmf_tgt)
@@ -59,21 +62,24 @@ done
echo "==> creating TCP transport"
"$RPC" nvmf_create_transport -t TCP -u 16384 -m 8 -c 8192
echo "==> exposing $ROOTFS as bdev 'rootfs' (4 KiB blocks)"
echo "==> exposing $ROOTFS (data) + $ROOTHASH (verity hash) as bdevs (4 KiB blocks)"
# -r opens the backing file read-only where supported; harmless if ignored.
"$RPC" bdev_aio_create "$ROOTFS" rootfs 4096 -r \
|| "$RPC" bdev_aio_create "$ROOTFS" rootfs 4096
"$RPC" bdev_aio_create "$ROOTHASH" roothash 4096 -r \
|| "$RPC" bdev_aio_create "$ROOTHASH" roothash 4096
echo "==> creating subsystem $SUBNQN (allow any host — lab/no-auth)"
"$RPC" nvmf_create_subsystem "$SUBNQN" -a -s SPDKLAB0000000001 -d FleetRootfs
echo "==> adding namespace 1 (uuid $ROOT_NS_UUID)"
# Read-only is enforced by the bdev_aio '-r' open above (this SPDK's add_ns has
# no --read-only flag), plus the :ro image-volume mount and the client's erofs
# ro + dm-verity.
# -u pins the namespace UUID so the host can reference it as
# /dev/disk/by-id/nvme-uuid.$ROOT_NS_UUID (stable across controller indices).
"$RPC" nvmf_subsystem_add_ns "$SUBNQN" rootfs -u "$ROOT_NS_UUID"
# ro + dm-verity. -u pins each namespace UUID so the host references them as
# /dev/disk/by-id/nvme-uuid.<uuid> (stable across controller indices).
echo "==> adding namespace 1: data (uuid $ROOT_DATA_UUID)"
"$RPC" nvmf_subsystem_add_ns "$SUBNQN" rootfs -u "$ROOT_DATA_UUID"
echo "==> adding namespace 2: verity hash (uuid $ROOT_HASH_UUID)"
"$RPC" nvmf_subsystem_add_ns "$SUBNQN" roothash -u "$ROOT_HASH_UUID"
echo "==> adding TCP listener ${TADDR}:${TPORT} to $SUBNQN"
"$RPC" nvmf_subsystem_add_listener "$SUBNQN" -t tcp -a "$TADDR" -s "$TPORT"