Add --no-bookmark flag

This prevents the use bookmarks when trying to find the latest common
snapshot. This forces a rollback when the latest snapshot on the source
was deleted but a common and older snapshot was found.

Signed-off-by: Felix Matouschek <felix@matouschek.org>
This commit is contained in:
Felix Matouschek 2026-01-10 11:03:31 +00:00 committed by Felix Matouschek
parent e49d52de4a
commit 0d6b368158
2 changed files with 76 additions and 11 deletions

View File

@ -24,7 +24,7 @@ my %args = ('sshconfig' => '', 'sshkey' => '', 'sshport' => '', 'sshcipher' => '
GetOptions(\%args, "no-command-checks", "monitor-version", "compress=s", "dumpsnaps", "recursive|r", "sendoptions=s", "recvoptions=s",
"source-bwlimit=s", "target-bwlimit=s", "sshconfig=s", "sshkey=s", "sshport=i", "sshcipher|c=s", "sshoption|o=s@",
"debug", "quiet", "no-stream", "no-sync-snap", "no-resume", "exclude=s@", "skip-parent", "identifier=s",
"no-clone-handling", "no-privilege-elevation", "force-delete", "no-rollback", "create-bookmark", "use-hold",
"no-clone-handling", "no-privilege-elevation", "force-delete", "no-rollback", "create-bookmark", "no-bookmark", "use-hold",
"pv-options=s" => \$pvoptions, "keep-sync-snap", "preserve-recordsize", "mbuffer-size=s" => \$mbuffer_size,
"delete-target-snapshots", "insecure-direct-connection=s", "preserve-properties",
"include-snaps=s@", "exclude-snaps=s@", "exclude-datasets=s@")
@ -609,6 +609,7 @@ sub syncdataset {
my %bookmark = ();
my $bookmarksnap = 0;
if (! defined $args{'no-bookmark'}) {
# find most recent matching bookmark
my %bookmarks = getbookmarks($sourcehost,$sourcefs,$sourceisroot);
@ -623,6 +624,7 @@ sub syncdataset {
last;
}
}
}
$matchingsnap = getmatchingsnapshot($sourcefs, $targetfs, \%snaps);
if (! $matchingsnap) {
@ -2439,6 +2441,7 @@ Options:
--no-sync-snap Does not create new snapshot, only transfers existing
--keep-sync-snap Don't destroy created sync snapshots
--create-bookmark Creates a zfs bookmark for the newest snapshot on the source after replication succeeds (only works with --no-sync-snap)
--no-bookmark Do not use bookmarks when trying to find the latest common snapshot. This forces a rollback when the latest snapshot on the source was deleted but a common and older snapshot was found.
--use-hold Adds a hold to the newest snapshot on the source and target after replication succeeds and removes the hold after the next successful replication. The hold name includes the identifier if set. This allows for separate holds in case of multiple targets
--preserve-recordsize Preserves the recordsize on initial sends to the target
--preserve-properties Preserves locally set dataset properties similar to the zfs send -p flag but this one will also work for encrypted datasets in non raw sends

View File

@ -0,0 +1,62 @@
#!/bin/bash
# test that a rollback is required when not using bookmarks
set -x
set -e
. ../../common/lib.sh
POOL_IMAGE="/tmp/syncoid-test-016.zpool"
MOUNT_TARGET="/tmp/syncoid-test-016.mount"
POOL_SIZE="1000M"
POOL_NAME="syncoid-test-016"
TARGET_CHECKSUM="0ed2eed1488bbba5c35c2b24beee9e6e8a76f8de10aa1e3710dc737cf626635a -"
truncate -s "${POOL_SIZE}" "${POOL_IMAGE}"
zpool create -m "${MOUNT_TARGET}" -f "${POOL_NAME}" "${POOL_IMAGE}"
function cleanUp {
zpool export "${POOL_NAME}"
}
# export pool in any case
trap cleanUp EXIT
zfs create "${POOL_NAME}"/a
zfs snapshot "${POOL_NAME}"/a@s0
# This fully replicates a to b
../../../syncoid --debug --no-sync-snap --no-rollback --create-bookmark "${POOL_NAME}"/a "${POOL_NAME}"/b
echo "Test 1" > "${MOUNT_TARGET}"/a/file1
zfs snapshot "${POOL_NAME}"/a@s1
# This incrementally replicates from a@s0 to a@s1
../../../syncoid --debug --no-sync-snap --no-rollback --create-bookmark "${POOL_NAME}"/a "${POOL_NAME}"/b
echo "Test 2" > "${MOUNT_TARGET}"/a/file2
zfs snapshot "${POOL_NAME}"/a@s2
# Destroy latest common snap between a and b
zfs destroy "${POOL_NAME}"/a@s1
# This uses a@s0 and rolls b back to it although common and newer bookmark a#s1 exists
../../../syncoid --debug --no-sync-snap --no-bookmark --create-bookmark "${POOL_NAME}"/a "${POOL_NAME}"/b
echo "Test 3" > "${MOUNT_TARGET}"/a/file3
zfs snapshot "${POOL_NAME}"/a@s3
# This uses a@s2 as base snap again
../../../syncoid --debug --no-sync-snap --no-rollback --create-bookmark "${POOL_NAME}"/a "${POOL_NAME}"/b
# verify
output=$(zfs list -t snapshot -r -H -o name "${POOL_NAME}")
checksum=$(echo "${output}" | shasum -a 256)
if [ "${checksum}" != "${TARGET_CHECKSUM}" ]; then
exit 1
fi
exit 0