diff --git a/clone-backup.sh b/clone-backup.sh index caecb1e7..3dfe222b 100755 --- a/clone-backup.sh +++ b/clone-backup.sh @@ -350,6 +350,17 @@ transfer_backup() { echo "No metadata file found, using normal extraction" fi + + # AFTER SLOWDISK_TRANSFORMS: rewrite remaining var/lib/docker/ members onto + # the target's real docker root when it is a cross-device symlink (see + # docker_root_transform in volume-utils.sh). + local _drt + _drt=$(docker_root_transform) + if [[ -n "$_drt" ]]; then + echo "Target /var/lib/docker is a symlink; appending docker-root --transform (after slowdisk)" + tar_extract_opts="${tar_extract_opts}${_drt}" + fi + local file_size=$(stat -f%z "$backup_file" 2>/dev/null || stat -c%s "$backup_file" 2>/dev/null) # Find an available port @@ -529,6 +540,17 @@ transfer_backup_ssh() { fi fi + + # AFTER SLOWDISK_TRANSFORMS: rewrite remaining var/lib/docker/ members onto + # the target's real docker root when it is a cross-device symlink (see + # docker_root_transform in volume-utils.sh). + local _drt + _drt=$(docker_root_transform) + if [[ -n "$_drt" ]]; then + echo "Target /var/lib/docker is a symlink; appending docker-root --transform (after slowdisk)" + tar_extract_opts="${tar_extract_opts}${_drt}" + fi + echo "Using direct SSH transfer for $key (file: $(basename "$backup_file"), size: $((file_size / 1048576))MB)" pv -pterb -s "$file_size" -N "$key" < "$backup_file" | \ diff --git a/clone-node.sh b/clone-node.sh index ce16def5..d8a076d9 100755 --- a/clone-node.sh +++ b/clone-node.sh @@ -319,6 +319,17 @@ transfer_volume() { fi fi + + # AFTER SLOWDISK_TRANSFORMS: rewrite remaining var/lib/docker/ members onto + # the target's real docker root when it is a cross-device symlink (see + # docker_root_transform in volume-utils.sh). + local _drt + _drt=$(docker_root_transform) + if [[ -n "$_drt" ]]; then + echo "Target /var/lib/docker is a symlink; appending docker-root --transform (after slowdisk)" + tar_extract_opts="${tar_extract_opts}${_drt}" + fi + # Find an available port local port=$(find_available_port) if [[ $? -ne 0 ]]; then @@ -500,6 +511,17 @@ transfer_volume_ssh() { fi fi + + # AFTER SLOWDISK_TRANSFORMS: rewrite remaining var/lib/docker/ members onto + # the target's real docker root when it is a cross-device symlink (see + # docker_root_transform in volume-utils.sh). + local _drt + _drt=$(docker_root_transform) + if [[ -n "$_drt" ]]; then + echo "Target /var/lib/docker is a symlink; appending docker-root --transform (after slowdisk)" + tar_extract_opts="${tar_extract_opts}${_drt}" + fi + echo "Using direct SSH transfer for $key (size: $((folder_size / 1048576))MB)" tar -cf - --dereference "$source_folder" 2>/dev/null | \ diff --git a/volume-utils.sh b/volume-utils.sh index b4f73202..6a99fc9b 100755 --- a/volume-utils.sh +++ b/volume-utils.sh @@ -294,3 +294,32 @@ delete_slowdisk_targets_for_key() { done shopt -u nullglob } + +# Echo a tar --transform fragment (leading space + quoted --transform=...) that +# rewrites archive members from var/lib/docker/volumes/... onto the TARGET's +# real volumes root when that path is a cross-device symlink (EXDEV under +# tar -C /). Key on the DEEPEST static prefix — readlink -f +# /var/lib/docker/volumes — so we cover symlinks at /var, /var/lib, +# /var/lib/docker, OR /var/lib/docker/volumes itself (canonicalizing only +# /var/lib/docker misses a real dir with volumes/ as the symlink). +# Reproduced rpc-us-32 2026-07-15/18: /var on sda4, /var/lib/docker -> /docker +# on md0 → volumes resolves to /docker/volumes. Empty when readlink -f +# returns /var/lib/docker/volumes itself (no-op). +# Requires SSH_CMD + DEST_HOST (set by clone-*/cache-deploy after multiplexing). +# Must be appended AFTER any SLOWDISK_TRANSFORMS — tar applies transforms in +# order; slowdisk-rewritten members start with slowdisk/ and must not be +# re-touched, while remaining var/lib/docker/volumes/... members still need +# the rewrite. Per-volume _data static-file symlinks onto /slowdisk remain the +# SLOWDISK_TRANSFORMS mechanism — this helper only relocates the volumes root. +# Quoting follows the SLOWDISK_TRANSFORMS '|'-delimiter + single-quote pattern +# so the script-file listener heredoc expands once without mangling the regex. +docker_root_transform() { + local real + real=$($SSH_CMD "$DEST_HOST" "readlink -f /var/lib/docker/volumes" 2>/dev/null || true) + real="${real%/}" + if [[ -z "$real" || "$real" == "/var/lib/docker/volumes" ]]; then + return 0 + fi + local rel="${real#/}" + echo " --transform='s|^\\(\\./\\)\\?var/lib/docker/volumes/|${rel}/|'" +}