Skip to content

Commit

Permalink
btrbk: find correct latest common snapshot when resuming backups. Not…
Browse files Browse the repository at this point in the history
…e that we then chain the backups, assuming that the previous snapshot is automatically the parent for the next one, which is not always true
  • Loading branch information
digint committed Mar 31, 2015
1 parent 679a964 commit 956c028
Showing 1 changed file with 21 additions and 5 deletions.
26 changes: 21 additions & 5 deletions btrbk
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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});

Expand All @@ -1621,13 +1628,22 @@ 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},
target => $droot,
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");
}
Expand Down

0 comments on commit 956c028

Please sign in to comment.