From 0707cc1be8c201a0f57730464361d0c8dbb3d632 Mon Sep 17 00:00:00 2001 From: Claude Code Bot Date: Thu, 14 May 2026 11:49:59 -0700 Subject: [PATCH] =?UTF-8?q?fix(podman):=20prevent=20VirtioFS=E2=86=92NFS?= =?UTF-8?q?=20data=20loss=20and=20boot-order=20race?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cross-directory renames (incomplete/ → pending-move/) through VirtioFS over a soft NFS mount can silently lose data: the source is unlinked from the VirtioFS cache while the NFS rename fails, leaving files in neither directory. Disable Transmission's incomplete-dir so downloads go directly to pending-move/ (same-directory .part rename only). Also add wait_for_nfs() before starting the Podman VM, closing a boot-order race where the VM could start before the NFS mount was ready (observed 7-second gap on 2026-05-14 reboot). Co-Authored-By: Claude Opus 4.6 --- app-setup/podman-transmission-setup.sh | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/app-setup/podman-transmission-setup.sh b/app-setup/podman-transmission-setup.sh index 3338724..a5b3131 100755 --- a/app-setup/podman-transmission-setup.sh +++ b/app-setup/podman-transmission-setup.sh @@ -512,6 +512,22 @@ log_ts() { echo "[\${ts}] \$*" } +wait_for_nfs() { + local mount_point="${NFS_MOUNT_POINT}" + local max_wait=120 + local elapsed=0 + while ! /sbin/mount | grep -q " on \${mount_point} "; do + log_ts "waiting for NFS mount at \${mount_point} (\${elapsed}/\${max_wait}s)..." + sleep 5 + elapsed=\$((elapsed + 5)) + if (( elapsed >= max_wait )); then + log_ts "FATAL: NFS mount not available at \${mount_point} after \${max_wait}s" + return 1 + fi + done + log_ts "NFS mount ready at \${mount_point}" +} + ensure_machine() { local state state=\$(podman machine inspect transmission-vm --format '{{.State}}' 2>/dev/null || echo unknown) @@ -563,7 +579,7 @@ ensure_container() { -e "PGID=${PGID}" \\ -e "TZ=${TZ_VALUE}" \\ -e TRANSMISSION_DOWNLOAD_DIR=/data/Media/Torrents/pending-move \\ - -e TRANSMISSION_INCOMPLETE_DIR=/data/Media/Torrents/incomplete \\ + -e TRANSMISSION_INCOMPLETE_DIR_ENABLED=false \\ -e TRANSMISSION_WATCH_DIR=/watch \\ -e TRANSMISSION_WATCH_DIR_ENABLED=true \\ -e TRANSMISSION_RATIO_LIMIT_ENABLED=false \\ @@ -579,6 +595,7 @@ ensure_container() { haugene/transmission-openvpn:latest } +wait_for_nfs || exit 1 ensure_machine ensure_container @@ -790,7 +807,7 @@ else -e "PGID=${PGID}" \ -e "TZ=${TZ_VALUE}" \ -e TRANSMISSION_DOWNLOAD_DIR=/data/Media/Torrents/pending-move \ - -e TRANSMISSION_INCOMPLETE_DIR=/data/Media/Torrents/incomplete \ + -e TRANSMISSION_INCOMPLETE_DIR_ENABLED=false \ -e TRANSMISSION_WATCH_DIR=/watch \ -e TRANSMISSION_WATCH_DIR_ENABLED=true \ -e TRANSMISSION_RATIO_LIMIT_ENABLED=false \