From ce85b778f40dc0275a52f5c37048dc65f4a7474d Mon Sep 17 00:00:00 2001 From: Denys Fedoryshchenko Date: Thu, 23 Jul 2026 02:46:52 +0300 Subject: [PATCH] config/rootfs: support NFSv4 in debos initramfs The klibc nfsmount helper only supports NFSv2 and NFSv3, so it rejects LAVA's v4.2 mount option before reaching the server. Extract mount.nfs from nfs-common while creating the initramfs, copy only its runtime dependency closure, and replace nfsmount with a compatibility wrapper that normalizes v4.x options. Keep the temporary helper and packages out of the final rootfs. Link: https://bugs.debian.org/409271 Signed-off-by: Denys Fedoryshchenko --- .../etc/initramfs-tools/hooks/zz-kernelci-nfs | 24 +++++ .../nfs-initramfs/usr/lib/kernelci/nfsmount | 100 ++++++++++++++++++ config/rootfs/debos/rootfs.yaml | 4 + .../debos/scripts/create_initrd_ramdisk.sh | 54 ++++++++++ 4 files changed, 182 insertions(+) create mode 100755 config/rootfs/debos/overlays/nfs-initramfs/etc/initramfs-tools/hooks/zz-kernelci-nfs create mode 100755 config/rootfs/debos/overlays/nfs-initramfs/usr/lib/kernelci/nfsmount diff --git a/config/rootfs/debos/overlays/nfs-initramfs/etc/initramfs-tools/hooks/zz-kernelci-nfs b/config/rootfs/debos/overlays/nfs-initramfs/etc/initramfs-tools/hooks/zz-kernelci-nfs new file mode 100755 index 0000000000..4650699d9b --- /dev/null +++ b/config/rootfs/debos/overlays/nfs-initramfs/etc/initramfs-tools/hooks/zz-kernelci-nfs @@ -0,0 +1,24 @@ +#!/bin/sh + +PREREQ="klibc-utils" + +prereqs() +{ + echo "$PREREQ" +} + +case "$1" in +prereqs) + prereqs + exit 0 + ;; +esac + +# shellcheck source=/dev/null +. /usr/share/initramfs-tools/hook-functions + +copy_exec /usr/lib/kernelci/mount.nfs /usr/sbin/mount.nfs + +# Replace klibc's NFSv2/v3-only helper after its hook has installed it. +rm -f "${DESTDIR}/bin/nfsmount" "${DESTDIR}/usr/bin/nfsmount" +copy_file script /usr/lib/kernelci/nfsmount /bin/nfsmount diff --git a/config/rootfs/debos/overlays/nfs-initramfs/usr/lib/kernelci/nfsmount b/config/rootfs/debos/overlays/nfs-initramfs/usr/lib/kernelci/nfsmount new file mode 100755 index 0000000000..c742f647dc --- /dev/null +++ b/config/rootfs/debos/overlays/nfs-initramfs/usr/lib/kernelci/nfsmount @@ -0,0 +1,100 @@ +#!/bin/sh + +# Compatibility wrapper for initramfs-tools. Its NFS boot script calls the +# klibc nfsmount interface using one or more "-o options" pairs. Collect those +# options for mount.nfs and translate LAVA's legacy v4.x spelling. +# +# Replacing klibc's NFSv2/v3-only nfsmount with mount.nfs follows the workaround +# discussed in Debian bug #409271. The argument translation here is needed for +# the initramfs-tools call interface and KernelCI's LAVA boot arguments. +# https://bugs.debian.org/409271 + +normalize_options() +{ + input=$1 + output= + + while [ -n "$input" ]; do + case "$input" in + *,*) + option=${input%%,*} + input=${input#*,} + ;; + *) + option=$input + input= + ;; + esac + + case "$option" in + v4) + option=vers=4 + ;; + v4.0) + option=vers=4.0 + ;; + v4.1) + option=vers=4.1 + ;; + v4.2) + option=vers=4.2 + ;; + esac + + if [ -n "$output" ]; then + output="$output,$option" + else + output=$option + fi + done + + printf '%s' "$output" +} + +mount_options= +mount_source= +mount_target= + +while [ "$#" -gt 0 ]; do + case "$1" in + -o) + shift + if [ "$#" -eq 0 ]; then + echo "nfsmount: option requires an argument -- 'o'" >&2 + exit 1 + fi + options=$(normalize_options "$1") + if [ -n "$mount_options" ]; then + mount_options="$mount_options,$options" + else + mount_options=$options + fi + ;; + -*) + echo "nfsmount: unsupported option '$1'" >&2 + exit 1 + ;; + *) + if [ -z "$mount_source" ]; then + mount_source=$1 + elif [ -z "$mount_target" ]; then + mount_target=$1 + else + echo "nfsmount: too many paths" >&2 + exit 1 + fi + ;; + esac + shift +done + +if [ -z "$mount_source" ] || [ -z "$mount_target" ]; then + echo "nfsmount: need a server path and mount point" >&2 + exit 1 +fi + +if [ -n "$mount_options" ]; then + exec /usr/sbin/mount.nfs -o "$mount_options" "$mount_source" "$mount_target" +else + exec /usr/sbin/mount.nfs "$mount_source" "$mount_target" +fi diff --git a/config/rootfs/debos/rootfs.yaml b/config/rootfs/debos/rootfs.yaml index c6fc5f7828..f4d4f2325d 100644 --- a/config/rootfs/debos/rootfs.yaml +++ b/config/rootfs/debos/rootfs.yaml @@ -174,6 +174,10 @@ actions: command: xz -9 -T0 -f ${ARTIFACTDIR}/{{ $basename -}}/rootfs.ext4 postprocess: true + - action: overlay + description: Add NFSv4 initramfs mount helper + source: overlays/nfs-initramfs + - action: run description: update-initramfs step chroot: true diff --git a/config/rootfs/debos/scripts/create_initrd_ramdisk.sh b/config/rootfs/debos/scripts/create_initrd_ramdisk.sh index d97909c4e7..6a677e2ad8 100755 --- a/config/rootfs/debos/scripts/create_initrd_ramdisk.sh +++ b/config/rootfs/debos/scripts/create_initrd_ramdisk.sh @@ -1,5 +1,7 @@ #!/bin/bash +set -euo pipefail + patch -p1 << 'EOF' --- a/usr/share/initramfs-tools/scripts/nfs-premount/wait_ethernet 1970-01-01 02:00:00.000000000 +0200 +++ b/usr/share/initramfs-tools/scripts/nfs-premount/wait_ethernet 2022-11-25 12:38:46.037498198 +0200 @@ -29,9 +31,61 @@ EOF chmod +x /usr/share/initramfs-tools/scripts/nfs-premount/wait_ethernet +nfs_packages_before=$(mktemp) +dpkg-query -W -f='${binary:Package}\t${db:Status-Status}\n' \ + | sed -n 's/\tinstalled$//p' \ + | sort -u > "$nfs_packages_before" + +# mount.nfs only needs libtirpc and its shared-library dependencies. Extract +# the helper without installing nfs-common, whose unrelated device-mapper hook +# would otherwise make the initramfs larger. +if ! dpkg-query -W -f='${db:Status-Status}' libtirpc3t64 2>/dev/null \ + | grep -qx installed; then + DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ + libtirpc3t64 +fi +nfs_package_dir=$(mktemp -d) +chown _apt:root "$nfs_package_dir" +( + cd "$nfs_package_dir" + apt-get download nfs-common +) +nfs_common_deb=$(find "$nfs_package_dir" -maxdepth 1 -type f \ + -name 'nfs-common_*.deb' -print -quit) +if [[ -z "$nfs_common_deb" ]]; then + echo "Unable to download nfs-common" >&2 + exit 1 +fi +dpkg-deb --extract "$nfs_common_deb" "$nfs_package_dir/root" +install -m 0755 "$nfs_package_dir/root/usr/sbin/mount.nfs" \ + /usr/lib/kernelci/mount.nfs +rm -rf -- "$nfs_package_dir" + KVER=min # update-initramfs uses kernel config to decide how to compress ramdisk echo "CONFIG_RD_GZIP=y" > /boot/config-$KVER update-initramfs -c -k $KVER + +# These files are only needed while constructing the initramfs. +rm -f /etc/initramfs-tools/hooks/zz-kernelci-nfs \ + /usr/lib/kernelci/nfsmount \ + /usr/lib/kernelci/mount.nfs +rmdir --ignore-fail-on-non-empty /usr/lib/kernelci + +nfs_packages_after=$(mktemp) +nfs_packages_remove_file=$(mktemp) +dpkg-query -W -f='${binary:Package}\t${db:Status-Status}\n' \ + | sed -n 's/\tinstalled$//p' \ + | sort -u > "$nfs_packages_after" +comm -13 "$nfs_packages_before" "$nfs_packages_after" \ + > "$nfs_packages_remove_file" +mapfile -t nfs_packages_to_remove < "$nfs_packages_remove_file" +rm -f "$nfs_packages_before" "$nfs_packages_after" \ + "$nfs_packages_remove_file" +if ((${#nfs_packages_to_remove[@]})); then + DEBIAN_FRONTEND=noninteractive apt-get purge -y \ + "${nfs_packages_to_remove[@]}" +fi +apt-get clean