slowdisk offload: fix EXDEV - extract statics via tar --transform, not through symlinks

tar cannot create files through a directory symlink whose target is on
another device: open() fails with 'Invalid cross-device link' even under
--keep-directory-symlink (reproduced, GNU tar 1.34 and 1.35). This killed
the katana->uk-4 provision (place-provision-katana-EU-NorthWest-p1) and
means the slowdisk EXTRACT path never worked on hosts with a separate
/slowdisk device. Rewrite member paths with --transform so tar writes
directly into /slowdisk/rpc_<key>__data_<rel>; the symlink stays for the
container's runtime view. Also aligns restore-volumes' nested-path target
naming to the double-underscore convention clone-backup already uses.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
rob
2026-07-11 01:50:08 +00:00
parent defb9133ea
commit fccf279262
2 changed files with 20 additions and 6 deletions

View File

@@ -137,10 +137,17 @@ prep_static_offload() {
[ -z "$rel" ] && continue
rel="${rel#/}"
case "$rel" in *..*) echo " skip unsafe static path '$rel'"; continue;; esac
target="/slowdisk/rpc_${key}__data_${rel//\//_}"
target="/slowdisk/rpc_${key}__data_${rel//\//__}"
echo " offload static '$rel' -> $target"
mkdir -p "$target" "$data_dir/$(dirname "$rel")" || { echo " WARN: mkdir failed for '$rel', skipping"; continue; }
ln -sfn "$target" "$data_dir/$rel"
# tar CANNOT extract through a symlink whose target is on another device -
# open() fails with EXDEV "Invalid cross-device link" even with
# --keep-directory-symlink (reproduced GNU tar 1.34 + 1.35, 2026-07-11;
# killed the katana->uk-4 provision). Rewrite the member paths so tar
# writes DIRECTLY into the /slowdisk target; the symlink stays for the
# container's runtime view.
static_transform_args+=(--transform "s|^\\(\\./\\)\\?var/lib/docker/volumes/rpc_${key}/_data/${rel}|slowdisk/rpc_${key}__data_${rel//\//__}|")
done < <(awk 'NR>3 && NF>=2 {print $NF}' "$meta")
}
@@ -167,6 +174,7 @@ while IFS= read -r key; do
meta_file="${newest_file%.tar.zst}.txt"
echo "=== restoring rpc_$key <- $newest_file ==="
static_offload_used=0
static_transform_args=()
# 1) wipe live data AND any /slowdisk static targets for this key (no leak on re-restore)
delete_slowdisk_targets_for_key "$key"
@@ -193,7 +201,7 @@ while IFS= read -r key; do
if [[ -n "$remote_source" ]]; then
if [ ! -d "$backup_dir" ]; then
echo "No /backup cache: streaming + extracting $newest_file directly"
curl --ipv4 -# "${remote_source}${newest_file}" | zstd -d | tar -xf - --keep-directory-symlink -C /
curl --ipv4 -# "${remote_source}${newest_file}" | zstd -d | tar -xf - --keep-directory-symlink "${static_transform_args[@]}" -C /
if [ $? -ne 0 ]; then
echo "Error processing $newest_file" >&2
exit 1
@@ -203,14 +211,14 @@ while IFS= read -r key; do
if [ ! -e "$backup_file" ] || [ -e "${backup_file}.aria2" ]; then
aria2c -c -Z -x8 -j8 -s8 -d "$backup_dir" "${remote_source}${newest_file}"
fi
tar -I zstd -xf "$backup_file" --keep-directory-symlink -C /
tar -I zstd -xf "$backup_file" --keep-directory-symlink "${static_transform_args[@]}" -C /
if [ $? -ne 0 ]; then
echo "Error processing $newest_file" >&2
exit 1
fi
fi
else
tar -I zstd -xf "$newest_file" --keep-directory-symlink -C /
tar -I zstd -xf "$newest_file" --keep-directory-symlink "${static_transform_args[@]}" -C /
if [ $? -ne 0 ]; then
echo "Error processing $newest_file" >&2
exit 1