makechrootpkg: sync_chroot: Make more general.
This is inspired by the thought that went in to the delete_chroot is_subvolume commit. sync_chroot($chrootdir, $copydir) copies `$chrootdir/root` to `$copydir`. That seems a little silly; why do we care about "$chrootdir"? Have it just be sync_chroot(source, destination) like every other sync/copy command. Where this becomes tricky is check to decide if we are going to use btrfs subvolumes or not. We don't care if "$source/.." is on btrfs; the root could be a directly-mounted subvolume, but and the destination could be another subvolume of the same btrfs mounted somewhere else. The things we do care about are: - The source is a btrfs subvolume (so that we can snapshot it) - The source is on the same filesystem as the directory that the copy will be created in. - If the destination exists: * that it is not a mountpoint (so that we can delete and recreate it) * that it is a btrfs subvolume (so that we can quickly delete it) On the last point, it isn't necessary for creating the new snapshot, just for quick deletion. That can be a separate check, where we use regular `rm` for deleting the existing copy, but use subvolume snapshots for creating the new one.
This commit is contained in:
parent
928744cbc4
commit
6d1992909c
|
@ -33,6 +33,14 @@ is_subvolume() {
|
||||||
[[ -e "$1" && "$(stat -f -c %T "$1")" == btrfs && "$(stat -c %i "$1")" == 256 ]]
|
[[ -e "$1" && "$(stat -f -c %T "$1")" == btrfs && "$(stat -c %i "$1")" == 256 ]]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
##
|
||||||
|
# usage : is_same_fs( $path_a, $path_b )
|
||||||
|
# return : whether $path_a and $path_b are on the same filesystem
|
||||||
|
##
|
||||||
|
is_same_fs() {
|
||||||
|
[[ "$(stat -c %d "$1")" == "$(stat -c %d "$1")" ]]
|
||||||
|
}
|
||||||
|
|
||||||
##
|
##
|
||||||
# usage : subvolume_delete_recursive( $path )
|
# usage : subvolume_delete_recursive( $path )
|
||||||
#
|
#
|
||||||
|
|
|
@ -98,31 +98,37 @@ load_vars() {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
# Usage: sync_chroot $chrootdir $copydir [$copy]
|
# Usage: sync_chroot $rootdir $copydir [$copy]
|
||||||
sync_chroot() {
|
sync_chroot() {
|
||||||
local chrootdir=$1
|
local rootdir=$1
|
||||||
local copydir=$2
|
local copydir=$2
|
||||||
local copy=${3:-$2}
|
local copy=${3:-$2}
|
||||||
|
|
||||||
if [[ "$chrootdir/root" -ef "$copydir" ]]; then
|
if [[ "$rootdir" -ef "$copydir" ]]; then
|
||||||
error 'Cannot sync copy with itself: %s' "$copydir"
|
error 'Cannot sync copy with itself: %s' "$copydir"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Get a read lock on the root chroot to make
|
# Get a read lock on the root chroot to make
|
||||||
# sure we don't clone a half-updated chroot
|
# sure we don't clone a half-updated chroot
|
||||||
slock 8 "$chrootdir/root.lock" \
|
slock 8 "$rootdir.lock" \
|
||||||
"Locking clean chroot [%s]" "$chrootdir/root"
|
"Locking clean chroot [%s]" "$rootdir"
|
||||||
|
|
||||||
stat_busy "Synchronizing chroot copy [%s] -> [%s]" "$chrootdir/root" "$copy"
|
stat_busy "Synchronizing chroot copy [%s] -> [%s]" "$rootdir" "$copy"
|
||||||
if is_btrfs "$chrootdir" && ! mountpoint -q "$copydir"; then
|
if is_subvolume "$rootdir" && is_same_fs "$rootdir" "$(dirname -- "$copydir")" && ! mountpoint -q "$copydir"; then
|
||||||
subvolume_delete_recursive "$copydir" ||
|
if is_subvolume "$copydir"; then
|
||||||
die "Unable to delete subvolume %s" "$copydir"
|
subvolume_delete_recursive "$copydir" ||
|
||||||
btrfs subvolume snapshot "$chrootdir/root" "$copydir" >/dev/null ||
|
die "Unable to delete subvolume %s" "$copydir"
|
||||||
|
else
|
||||||
|
# avoid change of filesystem in case of an umount failure
|
||||||
|
rm --recursive --force --one-file-system "$copydir" ||
|
||||||
|
die "Unable to delete %s" "$copydir"
|
||||||
|
fi
|
||||||
|
btrfs subvolume snapshot "$rootdir" "$copydir" >/dev/null ||
|
||||||
die "Unable to create subvolume %s" "$copydir"
|
die "Unable to create subvolume %s" "$copydir"
|
||||||
else
|
else
|
||||||
mkdir -p "$copydir"
|
mkdir -p "$copydir"
|
||||||
rsync -a --delete -q -W -x "$chrootdir/root/" "$copydir"
|
rsync -a --delete -q -W -x "$rootdir/" "$copydir"
|
||||||
fi
|
fi
|
||||||
stat_done
|
stat_done
|
||||||
|
|
||||||
|
@ -374,7 +380,7 @@ main() {
|
||||||
lock 9 "$copydir.lock" "Locking chroot copy [%s]" "$copy"
|
lock 9 "$copydir.lock" "Locking chroot copy [%s]" "$copy"
|
||||||
|
|
||||||
if [[ ! -d $copydir ]] || $clean_first; then
|
if [[ ! -d $copydir ]] || $clean_first; then
|
||||||
sync_chroot "$chrootdir" "$copydir" "$copy"
|
sync_chroot "$chrootdir/root" "$copydir" "$copy"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
$update_first && arch-nspawn "$copydir" \
|
$update_first && arch-nspawn "$copydir" \
|
||||||
|
|
Loading…
Reference in New Issue