From 3a1a19b39bb79cb76483538c1acbb7aa94a9064a Mon Sep 17 00:00:00 2001 From: Christoph Klaffl Date: Wed, 18 Feb 2026 14:57:38 +0100 Subject: [PATCH] fix replication with '0' named bookmarks --- syncoid | 8 ++-- .../013_bookmark_replication_0_named/run.sh | 48 +++++++++++++++++++ 2 files changed, 52 insertions(+), 4 deletions(-) create mode 100755 tests/syncoid/013_bookmark_replication_0_named/run.sh diff --git a/syncoid b/syncoid index 8c9c2f2..945e095 100755 --- a/syncoid +++ b/syncoid @@ -575,7 +575,7 @@ sub syncdataset { my $targetsize = getzfsvalue($targethost,$targetfs,$targetisroot,'-p used'); - my $bookmark = 0; + my $bookmark = ''; my $bookmarkcreation = 0; $matchingsnap = getmatchingsnapshot($sourcefs, $targetfs, \%snaps); @@ -596,7 +596,7 @@ sub syncdataset { } } - if (! $bookmark) { + if ($bookmark eq '') { # force delete is not possible for the root dataset if ($args{'force-delete'} && index($targetfs, '/') != -1) { writelog('INFO', "Removing $targetfs because no matching snapshots were found"); @@ -669,7 +669,7 @@ sub syncdataset { my $nextsnapshot = 0; - if ($bookmark) { + if ($bookmark ne '') { my $bookmarkescaped = escapeshellparam($bookmark); if (!defined $args{'no-stream'}) { @@ -727,7 +727,7 @@ sub syncdataset { # do a normal replication if bookmarks aren't used or if previous # bookmark replication was only done to the next oldest snapshot # edge case: skip repilcation if bookmark replication used the latest snapshot - if ((!$bookmark || $nextsnapshot) && !($matchingsnap eq $newsyncsnap)) { + if (($bookmark eq '' || $nextsnapshot) && !($matchingsnap eq $newsyncsnap)) { ($exit, $stdout) = syncincremental($sourcehost, $sourcefs, $targethost, $targetfs, $matchingsnap, $newsyncsnap, defined($args{'no-stream'})); diff --git a/tests/syncoid/013_bookmark_replication_0_named/run.sh b/tests/syncoid/013_bookmark_replication_0_named/run.sh new file mode 100755 index 0000000..f811e56 --- /dev/null +++ b/tests/syncoid/013_bookmark_replication_0_named/run.sh @@ -0,0 +1,48 @@ +#!/bin/bash + +# test replication with fallback to bookmarks and special named snapshot/bookmark '0' + +set -x +set -e + +. ../../common/lib.sh + +POOL_IMAGE="/tmp/syncoid-test-013.zpool" +POOL_SIZE="200M" +POOL_NAME="syncoid-test-013" +TARGET_CHECKSUM="b927125d2113c8da1a7f0181516e8f57fee5d268bdd5386d6ff7ddf31d6d6a35 -" + +truncate -s "${POOL_SIZE}" "${POOL_IMAGE}" + +zpool create -m none -f "${POOL_NAME}" "${POOL_IMAGE}" + +function cleanUp { + zpool export "${POOL_NAME}" +} + +# export pool in any case +trap cleanUp EXIT + +zfs create "${POOL_NAME}"/src +zfs snapshot "${POOL_NAME}"/src@0 + +# initial replication +../../../syncoid --no-sync-snap --create-bookmark --debug --compress=none "${POOL_NAME}"/src "${POOL_NAME}"/dst + +# destroy last common snapshot on source +zfs destroy "${POOL_NAME}"/src@0 + +zfs snapshot "${POOL_NAME}"/src@1 + +# replicate which should fallback to bookmarks +../../../syncoid --no-sync-snap --create-bookmark --debug --compress=none "${POOL_NAME}"/src "${POOL_NAME}"/dst + +# verify +output=$(zfs list -t snapshot -r -H -o name "${POOL_NAME}"; zfs list -t bookmark -r -H -o name "${POOL_NAME}") +checksum=$(echo "${output}" | grep -v syncoid_ | shasum -a 256) + +if [ "${checksum}" != "${TARGET_CHECKSUM}" ]; then + exit 1 +fi + +exit 0