From 956c028435853faf22f058943d30b3de9f40a021 Mon Sep 17 00:00:00 2001 From: Axel Burri Date: Tue, 31 Mar 2015 21:45:21 +0200 Subject: [PATCH] btrbk: find correct latest common snapshot when resuming backups. Note that we then chain the backups, assuming that the previous snapshot is automatically the parent for the next one, which is not always true --- btrbk | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/btrbk b/btrbk index 5cca8db..5c57982 100755 --- a/btrbk +++ b/btrbk @@ -931,18 +931,26 @@ sub get_receive_targets_by_uuid($$) } -sub get_latest_common($$$) +sub get_latest_common($$$;$) { my $sroot = shift || die; my $svol = shift || die; my $droot = shift || die; + my $threshold_gen = shift; # skip all snapshot children with generation >= $threshold_gen die("source subvolume info not present: $sroot") unless($vol_info{$sroot}); die("target subvolume info not present: $droot") unless($vol_info{$droot}); + TRACE "get_latest_common: threshold_gen=$threshold_gen" if($threshold_gen); + # sort children of svol descending by generation foreach my $child (sort { $b->{node}->{gen} <=> $a->{node}->{gen} } get_snapshot_children($sroot, $svol)) { TRACE "get_latest_common: checking source snapshot: $child->{SUBVOL_PATH}"; + if($threshold_gen && ($child->{node}->{gen} >= $threshold_gen)) { + TRACE "get_latest_common: skipped gen=$child->{node}->{gen} >= $threshold_gen: $child->{SUBVOL_PATH}"; + next; + } + if($vol_btrfs_progs_compat{$droot}) { # guess matches by subvolume name (node->received_uuid is not available if BTRFS_PROGS_COMPAT is set) my $child_name = $child->{node}->{REL_PATH}; @@ -1585,16 +1593,15 @@ MAIN: WARN "Ignoring deprecated option \"receive_log\" for target: $droot" } - my ($latest_common_src, $latest_common_target) = get_latest_common($sroot, $svol, $droot); - my $parent_snap; - $parent_snap = $latest_common_src->{FS_PATH} if($latest_common_src); + my $parent_snap = ""; # resume missing backups (resume_missing) if(config_key($config_target, "resume_missing")) { INFO "Checking for missing backups of subvolume \"$sroot/$svol\" in: $droot/"; my $found_missing = 0; - foreach my $child (sort { $a->{SUBVOL_PATH} cmp $b->{SUBVOL_PATH} } get_snapshot_children($sroot, $svol)) + # sort children of svol ascending by generation + foreach my $child (sort { $a->{node}->{gen} <=> $b->{node}->{gen} } get_snapshot_children($sroot, $svol)) { last if($config_target->{ABORTED}); @@ -1621,6 +1628,13 @@ MAIN: else { $found_missing++; + + unless($parent_snap) { + my ($latest_common_src, $latest_common_target) = get_latest_common($sroot, $svol, $droot, $child->{node}->{gen}); + $parent_snap = $latest_common_src->{FS_PATH} if($latest_common_src); + DEBUG("Set latest common snapshots for: $child->{FS_PATH}: src=$parent_snap"); + } + INFO "Resuming subvolume backup (send-receive) for: $child->{FS_PATH}"; if(macro_send_receive($config_target, src => $child->{FS_PATH}, @@ -1628,6 +1642,8 @@ MAIN: parent => $parent_snap, resume => 1, # propagated to $config_target->{subvol_received} )) { + + # NOTE: we assume that the previous snapshot is automatically the parent for the next one. $parent_snap = $child->{FS_PATH}; DEBUG("Updated latest common snapshots for: $sroot/$svol: src=$parent_snap"); }