fix: rewrite tar extract onto target volumes root when it is a cross-device symlink

Hosts like rpc-us-32 put /var/lib/docker (or volumes/) on another mount;
tar -C / then EXDEV on every var/lib/docker/volumes/... member. Canonicalize
the deepest static prefix (readlink -f /var/lib/docker/volumes) and append a
--transform after SLOWDISK_TRANSFORMS. Keying only on /var/lib/docker misses
a real docker root with volumes/ as the symlink. No-op on normal hosts.
Per-volume _data static-file offload stays on SLOWDISK_TRANSFORMS.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
rob
2026-07-19 02:24:56 +00:00
parent 38c43345f6
commit 95360bd238
3 changed files with 73 additions and 0 deletions

View File

@@ -350,6 +350,17 @@ transfer_backup() {
echo "No metadata file found, using normal extraction" echo "No metadata file found, using normal extraction"
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
local file_size=$(stat -f%z "$backup_file" 2>/dev/null || stat -c%s "$backup_file" 2>/dev/null) local file_size=$(stat -f%z "$backup_file" 2>/dev/null || stat -c%s "$backup_file" 2>/dev/null)
# Find an available port # Find an available port
@@ -529,6 +540,17 @@ transfer_backup_ssh() {
fi fi
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)" 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" | \ pv -pterb -s "$file_size" -N "$key" < "$backup_file" | \

View File

@@ -319,6 +319,17 @@ transfer_volume() {
fi fi
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 # Find an available port
local port=$(find_available_port) local port=$(find_available_port)
if [[ $? -ne 0 ]]; then if [[ $? -ne 0 ]]; then
@@ -500,6 +511,17 @@ transfer_volume_ssh() {
fi fi
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)" echo "Using direct SSH transfer for $key (size: $((folder_size / 1048576))MB)"
tar -cf - --dereference "$source_folder" 2>/dev/null | \ tar -cf - --dereference "$source_folder" 2>/dev/null | \

View File

@@ -294,3 +294,32 @@ delete_slowdisk_targets_for_key() {
done done
shopt -u nullglob 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}/|'"
}