btrbk: no more copy of node information in vinfo by vinfo_set_detail(); always use vinfo->{node}{key}; cleanup

pull/73/head
Axel Burri 2016-03-14 16:39:13 +01:00
parent 9a68ab6519
commit 207e8868da
1 changed files with 114 additions and 170 deletions

284
btrbk
View File

@ -525,44 +525,6 @@ sub vinfo_child($$;$)
}
sub vinfo_init_root($)
{
my $vol = shift;
# read the subvolume list, and update %url_cache
my $subvol_list = vinfo_subvol_list($vol, fill_cache => 1);
TRACE "vinfo_init_root: created vinfo root: $vol->{PRINT}";
return $subvol_list;
}
sub vinfo_set_detail($$)
{
my $vol = shift || die;
my $detail = shift || die;
my @vinfo_detail_keys = qw(id is_root gen cgen uuid parent_uuid received_uuid readonly node);
# TRACE "updating vinfo detail for: $vol->{PRINT}";
# VINFO($detail) if($loglevel >= 4);
# copy only from keys in @vinfo_detail_keys
foreach(@vinfo_detail_keys) {
next unless(exists($detail->{$_}));
# die if already present matches new
die if(exists($vol->{$_}) && ($vol->{$_} ne $detail->{$_}));
$vol->{$_} = $detail->{$_};
}
# be very paranoid, this should never happen
die if(defined($detail->{URL}) && ($detail->{URL} ne $vol->{URL}));
die if(defined($detail->{NAME}) && ($detail->{NAME} ne $vol->{NAME}));
die if(defined($detail->{SUBVOL_PATH}) && defined($vol->{SUBVOL_PATH}) && ($detail->{SUBVOL_PATH} ne $vol->{SUBVOL_PATH}));
return $vol;
}
# returns hash: ( $prefix_{url,path,host,name,subvol_path,rsh} => value, ... )
sub vinfo_prefixed_keys($$)
{
@ -1484,8 +1446,8 @@ sub btrfs_send_to_file($$$$;@)
my $source_path = $source->{PATH} // die;
my $target_path = $target->{PATH} // die;
my $parent_path = $parent ? $parent->{PATH} : undef;
my $parent_uuid = $parent ? $parent->{uuid} : undef ;
my $received_uuid = $source->{uuid};
my $parent_uuid = $parent ? $parent->{node}{uuid} : undef ;
my $received_uuid = $source->{node}{uuid};
$received_uuid = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" if((not $received_uuid) && $dryrun);
die unless($received_uuid);
die if($parent && !$parent_uuid);
@ -1667,6 +1629,18 @@ sub btr_tree($$)
}
sub _is_child_of
{
my $node = shift;
my $uuid = shift;
foreach(@{$node->{SUBTREE}}) {
return 1 if($_->{uuid} eq $uuid);
return 1 if(_is_child_of($_, $uuid));
}
return 0;
}
sub _btr_tree_fill_url_cache
{
my $node = shift;
@ -1682,30 +1656,9 @@ sub _btr_tree_fill_url_cache
}
sub _vinfo_subtree_list
{
my $tree = shift;
my $vinfo_parent = shift;
my $list = shift // [];
my $path_prefix = shift // "";
foreach(@{$tree->{SUBTREE}}) {
my $path = $path_prefix . $_->{REL_PATH};
my $vinfo = vinfo_child($vinfo_parent, $path);
vinfo_set_detail($vinfo, $_);
$vinfo->{node} = $_;
push(@$list, $vinfo);
_vinfo_subtree_list($_, $vinfo_parent, $list, $path . '/');
}
return $list;
}
sub vinfo_subvol_list($;@)
sub vinfo_init_root($)
{
my $vol = shift || die;
my %opts = @_;
my $tree_root;
my @fill_cache;
@ -1721,12 +1674,11 @@ sub vinfo_subvol_list($;@)
unless($tree_root) {
# url_cache miss, read the subvolume detail
my $detail = btrfs_subvolume_show($vol);
return undef unless $detail;
vinfo_set_detail($vol, $detail);
push @fill_cache, $symlink{$vol->{URL}} if($symlink{$vol->{URL}});
my $real_url = $symlink{$vol->{URL}};
push @fill_cache, $vol->{URL};
push @fill_cache, $real_url if($real_url && (not $url_cache{$real_url}));
# check uuid_cache
if($detail->{uuid}) {
@ -1736,26 +1688,47 @@ sub vinfo_subvol_list($;@)
unless($tree_root) {
# cache miss, read the fresh tree
my $root_id = $detail->{is_root} ? 5 : $detail->{id};
$tree_root = btr_tree($vol, $root_id);
push @fill_cache, $vol->{URL};
$tree_root = btr_tree($vol, $detail->{id});
}
}
return undef unless($tree_root);
# fill cache
# fill cache if needed
foreach (@fill_cache) {
if($url_cache{$_}) {
TRACE "vinfo_subvol_list: fill_cache: btrfs_tree: cache HIT: $_";
next;
}
TRACE "vinfo_subvol_list: fill_cache: btrfs_tree: cache MISS: $_";
TRACE "vinfo_subvol_list: fill_cache: $_";
_btr_tree_fill_url_cache($tree_root, $_);
}
$vol->{node} = $tree_root;
return $tree_root;
}
sub _vinfo_subtree_list
{
my $tree = shift;
my $vinfo_parent = shift;
my $list = shift // [];
my $path_prefix = shift // "";
foreach(@{$tree->{SUBTREE}}) {
my $path = $path_prefix . $_->{REL_PATH};
my $vinfo = vinfo_child($vinfo_parent, $path);
$vinfo->{node} = $_;
push(@$list, $vinfo);
_vinfo_subtree_list($_, $vinfo_parent, $list, $path . '/');
}
return $list;
}
sub vinfo_subvol_list($)
{
my $vol = shift || die;
my $tree_root = $vol->{node} || die;
# recurse into $tree_root, returns array of vinfo
return _vinfo_subtree_list($tree_root, $vol);
}
@ -1766,38 +1739,23 @@ sub get_cached_url_by_uuid($)
{
my $uuid = shift;
my @result;
while(my ($key, $n) = each(%url_cache)) {
next if($n->{is_root});
next unless($n->{uuid} eq $uuid);
push @result, $key;
while(my ($url, $node) = each(%url_cache)) {
next if($node->{is_root});
next unless($node->{uuid} eq $uuid);
push @result, $url;
}
return @result;
}
sub vinfo_subvol($$;$)
sub vinfo_subvol($$)
{
my $vol = shift || die;
my $filter_value = shift // die;
my $filter_key = shift || 'SUBVOL_PATH';
my $subvol_list = vinfo_subvol_list($vol);
my @ret = grep { $_->{$filter_key} eq $filter_value } @$subvol_list;
return undef unless(scalar @ret);
die unless(scalar(@ret) == 1);
return $ret[0];
}
sub vinfo_subvol_by_id($$)
{
my $vol = shift;
my $id = shift;
my $subvol_list = vinfo_subvol_list($vol);
my @ret = grep { $_->{id} == $id } @$subvol_list;
return undef unless(scalar @ret);
die unless(scalar(@ret) == 1);
return $ret[0];
my $subvol_path = shift // die;
foreach (@{vinfo_subvol_list($vol)}) {
return $_ if($_->{SUBVOL_PATH} eq $subvol_path);
}
return undef;
}
@ -1859,7 +1817,7 @@ sub macro_send_receive(@)
{
unless($dryrun) {
# make sure we know the source uuid
unless($source->{uuid}) {
unless($source->{node}{uuid}) {
DEBUG "Fetching uuid of new subvolume: $source->{PRINT}";
my $detail = btrfs_subvolume_show($source);
die unless($detail->{uuid});
@ -1923,7 +1881,7 @@ sub macro_delete($$$$;@)
}
# NOTE: checking received_uuid does not make much sense, as this received_uuid is propagated to snapshots
# if($vol->{received_uuid} && ($vol->{received_uuid} eq '-')) {
# if($vol->{node}{received_uuid} && ($vol->{node}{received_uuid} eq '-')) {
# INFO "Target subvolume is not a received backup, skipping deletion of: $vol->{PRINT}";
# next;
# }
@ -1987,8 +1945,8 @@ sub get_snapshot_children($$)
my $sroot_subvols = vinfo_subvol_list($sroot);
foreach (@$sroot_subvols) {
next unless($_->{readonly});
next unless($_->{parent_uuid} eq $svol->{uuid});
next unless($_->{node}{readonly});
next unless($_->{node}{parent_uuid} eq $svol->{node}{uuid});
TRACE "get_snapshot_children: found: $_->{PRINT}";
push(@ret, $_);
}
@ -2009,7 +1967,7 @@ sub get_receive_targets($$)
# guess matches by subvolume name (node->received_uuid is not available if BTRFS_PROGS_COMPAT is set)
DEBUG "Fallback to compatibility mode (get_receive_targets)";
foreach my $target (@$droot_subvols) {
next unless($_->{readonly});
next unless($_->{node}{readonly});
if($target->{NAME} eq $src_vol->{NAME}) {
TRACE "get_receive_targets: by-name: Found receive target: $target->{SUBVOL_PATH}";
push(@ret, $target);
@ -2019,11 +1977,11 @@ sub get_receive_targets($$)
else
{
# find matches by comparing uuid / received_uuid
my $uuid = $src_vol->{uuid};
my $uuid = $src_vol->{node}{uuid};
die("subvolume info not present: $uuid") unless($uuid_cache{$uuid});
foreach (@$droot_subvols) {
next unless($_->{readonly});
next unless($_->{received_uuid} eq $uuid);
next unless($_->{node}{readonly});
next unless($_->{node}{received_uuid} eq $uuid);
TRACE "get_receive_targets: by-uuid: Found receive target: $_->{SUBVOL_PATH}";
push(@ret, $_);
}
@ -2047,10 +2005,10 @@ sub get_latest_common($$$;$)
$debug_src .= "#" . $threshold_gen if($threshold_gen);
# sort children of svol descending by generation
foreach my $child (sort { $b->{cgen} <=> $a->{cgen} } get_snapshot_children($sroot, $svol)) {
foreach my $child (sort { $b->{node}{cgen} <=> $a->{node}{cgen} } get_snapshot_children($sroot, $svol)) {
TRACE "get_latest_common: checking source snapshot: $child->{SUBVOL_PATH}";
if($threshold_gen && ($child->{cgen} >= $threshold_gen)) {
TRACE "get_latest_common: skipped gen=$child->{cgen} >= $threshold_gen: $child->{SUBVOL_PATH}";
if($threshold_gen && ($child->{node}{cgen} >= $threshold_gen)) {
TRACE "get_latest_common: skipped gen=$child->{node}{cgen} >= $threshold_gen: $child->{SUBVOL_PATH}";
next;
}
@ -2079,13 +2037,13 @@ sub get_latest_snapshot_child($$)
my $latest = undef;
my $gen = -1;
foreach (get_snapshot_children($sroot, $svol)) {
if($_->{cgen} > $gen) {
if($_->{node}{cgen} > $gen) {
$latest = $_;
$gen = $_->{cgen};
$gen = $_->{node}{cgen};
}
}
if($latest) {
DEBUG "Latest snapshot child for \"$svol->{PRINT}#$svol->{gen}\" is: $latest->{PRINT}#$latest->{cgen}";
DEBUG "Latest snapshot child for \"$svol->{PRINT}#$svol->{node}{gen}\" is: $latest->{PRINT}#$latest->{node}{cgen}";
} else {
DEBUG "No latest snapshots found for: $svol->{PRINT}";
}
@ -2665,26 +2623,24 @@ MAIN:
my $src_vol = vinfo($src_url, { CONTEXT => "cmdline" });
unless(vinfo_init_root($src_vol)) { ERROR "Failed to fetch subvolume detail for '$src_vol->{PRINT}'" . ($err ? ": $err" : ""); exit 1; }
if($src_vol->{is_root}) { ERROR "Subvolume at \"$src_url\" is btrfs root!"; exit 1; }
unless($src_vol->{cgen}) { ERROR "Subvolume at \"$src_url\" does not provide cgen"; exit 1; }
if($src_vol->{node}{is_root}) { ERROR "Subvolume is btrfs root: $src_vol->{PRINT}"; exit 1; }
my $target_vol = vinfo($target_url, { CONTEXT => "cmdline" });
unless(vinfo_init_root($target_vol)) { ERROR "Failed to fetch subvolume detail for '$target_vol->{PRINT}'" . ($err ? ": $err" : ""); exit 1; }
unless($target_vol->{cgen}) { ERROR "Subvolume at \"$target_url\" does not provide cgen"; exit 1; }
if($target_vol->{node}{is_root}) { ERROR "Subvolume is btrfs root: $target_vol->{PRINT}"; exit 1; }
unless($uuid_cache{$src_vol->{uuid}} && $uuid_cache{$target_vol->{uuid}} &&
$uuid_cache{$src_vol->{uuid}}->{TREE_ROOT} eq $uuid_cache{$target_vol->{uuid}}->{TREE_ROOT}) {
ERROR "Subvolumes are is not on the same btrfs filesystem!";
unless(_is_child_of($src_vol->{node}->{TREE_ROOT}, $target_vol->{node}{uuid})) {
ERROR "Subvolumes are not on the same btrfs filesystem!";
exit 1;
}
my $lastgen;
# check if given src and target share same parent
if($src_vol->{parent_uuid} eq $target_vol->{uuid}) {
if($src_vol->{node}{parent_uuid} eq $target_vol->{node}{uuid}) {
DEBUG "target subvolume is direct parent of source subvolume";
}
elsif($src_vol->{parent_uuid} eq $target_vol->{parent_uuid}) {
elsif($src_vol->{node}{parent_uuid} eq $target_vol->{node}{parent_uuid}) {
DEBUG "target subvolume and source subvolume share same parent";
}
else {
@ -2694,7 +2650,7 @@ MAIN:
}
# NOTE: in some cases "cgen" differs from "gen", even for read-only snapshots (observed: gen=cgen+1)
$lastgen = $src_vol->{cgen} + 1;
$lastgen = $src_vol->{node}{gen} + 1;
# dump files, sorted and unique
my $ret = btrfs_subvolume_find_new($target_vol, $lastgen);
@ -2704,12 +2660,12 @@ MAIN:
time => $start_time,
info => [
"Showing changed files for subvolume:",
" $target_vol->{PRINT} (gen=$target_vol->{gen})",
" $target_vol->{PRINT} (gen=$target_vol->{node}{gen})",
"",
"Starting at creation generation of subvolume:",
" $src_vol->{PRINT} (cgen=$src_vol->{cgen})",
" $src_vol->{PRINT} (cgen=$src_vol->{node}{cgen})",
"",
"This will show all files modified within generation range: [$lastgen..$target_vol->{gen}]",
"This will show all files modified within generation range: [$lastgen..$target_vol->{node}{gen}]",
"Newest file generation (transid marker) was: $ret->{transid_marker}",
($ret->{parse_errors} ? "Parse errors: $ret->{parse_errors}" : undef),
],
@ -3015,31 +2971,19 @@ MAIN:
WARN "Skipping volume \"$sroot->{PRINT}\": $abrt";
next;
}
foreach my $svol (vinfo_subsection($sroot, 'subvolume')) {
DEBUG "Initializing subvolume section: $svol->{PRINT}";
my $rel_path = $svol->{CONFIG}->{rel_path};
if(my $vinfo = vinfo_subvol($sroot, $rel_path)) {
DEBUG "Found \"$rel_path\" in btrfs subtree of: $sroot->{PRINT}";
vinfo_set_detail($svol, $vinfo);
unless(vinfo_init_root($svol)) {
ABORTED($svol, "Failed to fetch subvolume detail" . ($err ? ": $err" : ""));
WARN "Skipping subvolume \"$svol->{PRINT}\": $abrt";
next;
}
else {
DEBUG "Missing \"$rel_path\" in btrfs subtree of \"$sroot->{PRINT}\", resolving details";
# configured subvolume is not present in btrfs subvolume list.
# try to read subvolume detail, as configured subvolume could be a symlink.
unless(vinfo_init_root($svol)) {
ABORTED($sroot, "Failed to fetch subvolume detail" . ($err ? ": $err" : ""));
WARN "Skipping volume \"$sroot->{PRINT}\": $abrt";
next;
}
if(vinfo_subvol_by_id($sroot, $svol->{id})) {
DEBUG "Found id=$svol->{id} in btrfs subtree of: $sroot->{PRINT}";
# NOTE: detail is already set by vinfo_init_root()
} else {
ABORTED($svol, "Not a child subvolume of: $sroot->{PRINT}");
WARN "Skipping subvolume \"$svol->{PRINT}\": $abrt";
next;
}
if($svol->{node}{uuid} && _is_child_of($sroot->{node}, $svol->{node}{uuid})) {
DEBUG "Found id=$svol->{PRINT} in btrfs subtree of: $sroot->{PRINT}";
} else {
ABORTED($svol, "Not a child subvolume of: $sroot->{PRINT}");
WARN "Skipping subvolume \"$svol->{PRINT}\": $abrt";
next;
}
}
}
@ -3106,7 +3050,7 @@ MAIN:
readonly => 1, # fake subvolume readonly flag
};
vinfo_set_detail($subvol, $detail);
$uuid_cache{$subvol->{uuid}} = $subvol;
$uuid_cache{$subvol->{node}{uuid}} = $subvol;
$subvol_list{$file} = $subvol;
if($filename_info->{REMOTE_PARENT_UUID} ne '-') {
@ -3134,8 +3078,8 @@ MAIN:
# - svol.<timestamp>--<received_uuid_0>.btrfs : root (full) image
# - svol.<timestamp>--<received_uuid-n>[@<received_uuid_n-1>].btrfs : incremental image
foreach my $child (@{$child_uuid_list{$subvol->{received_uuid}}}) {
vinfo_set_detail($child, { parent_uuid => $subvol->{uuid} });
foreach my $child (@{$child_uuid_list{$subvol->{node}{received_uuid}}}) {
vinfo_set_detail($child, { parent_uuid => $subvol->{node}{uuid} });
DEBUG "Found parent/child partners, forcing preserve of: \"$subvol->{PRINT}\", \"$child->{PRINT}\"";
$subvol->{FORCE_PRESERVE} = "preserve forced: parent of another raw target";
@ -3196,13 +3140,13 @@ MAIN:
ERROR "Failed to fetch subvolume detail for: $url" . ($err ? ": $err" : "");
exit 1;
}
if($vol->{is_root}) {
if($vol->{node}{is_root}) {
ERROR "Subvolume is btrfs root: $url\n";
exit 1;
}
my $lines = [];
_origin_tree("", $vol->{uuid}, $lines);
_origin_tree("", $vol->{node}{uuid}, $lines);
print_header(title => "Origin Tree",
config => $config,
@ -3244,9 +3188,9 @@ MAIN:
foreach my $sroot (vinfo_subsection($config, 'volume')) {
foreach my $svol (vinfo_subsection($sroot, 'subvolume')) {
my $snapshot_name = config_key($svol, "snapshot_name") // die;
foreach my $snapshot (sort { $a->{cgen} <=> $b->{cgen} } get_snapshot_children($sroot, $svol)) {
foreach my $snapshot (sort { $a->{node}{cgen} <=> $b->{node}{cgen} } get_snapshot_children($sroot, $svol)) {
my $snapshot_data = { type => "snapshot",
status => ($snapshot->{cgen} == $svol->{gen}) ? "up-to-date" : undef,
status => ($snapshot->{node}{cgen} == $svol->{node}{gen}) ? "up-to-date" : undef,
vinfo_prefixed_keys("source", $svol),
vinfo_prefixed_keys("snapshot", $snapshot),
snapshot_name => $snapshot_name,
@ -3278,7 +3222,7 @@ MAIN:
my @snapshot_children = get_snapshot_children($sroot, $svol);
my $stats_snapshot_uptodate = "";
foreach my $snapshot (@snapshot_children) {
if($snapshot->{cgen} == $svol->{gen}) {
if($snapshot->{node}{cgen} == $svol->{node}{gen}) {
$stats_snapshot_uptodate = " (up-to-date)";
last;
}
@ -3301,14 +3245,14 @@ MAIN:
last;
}
} else {
if($target_vol->{received_uuid} eq '-') {
if($target_vol->{node}{received_uuid} eq '-') {
# incomplete received (garbled) subvolumes have no received_uuid (as of btrfs-progs v4.3.1).
# a subvolume in droot matching our naming is considered incomplete if received_uuid is not set!
$parent_snapshot = undef;
$incomplete_backup = 1;
last;
}
if($_->{uuid} eq $target_vol->{received_uuid}) {
if($_->{node}{uuid} eq $target_vol->{node}{received_uuid}) {
$parent_snapshot = $_;
last;
}
@ -3320,7 +3264,7 @@ MAIN:
vinfo_prefixed_keys("target", $target_vol),
vinfo_prefixed_keys("snapshot", $parent_snapshot),
vinfo_prefixed_keys("source", $svol),
status => ($parent_snapshot->{cgen} == $svol->{gen}) ? "up-to-date" : undef,
status => ($parent_snapshot->{node}{cgen} == $svol->{node}{gen}) ? "up-to-date" : undef,
};
}
else {
@ -3364,7 +3308,7 @@ MAIN:
my ($latest_common_src, $latest_common_target) = get_latest_common($sroot, $svol, $droot);
if ($latest_common_src && $latest_common_target) {
push @data, { type => "latest_common",
status => ($latest_common_src->{cgen} == $svol->{gen}) ? "up-to-date" : undef,
status => ($latest_common_src->{node}{cgen} == $svol->{node}{gen}) ? "up-to-date" : undef,
vinfo_prefixed_keys("source", $svol),
vinfo_prefixed_keys("snapshot", $latest_common_src),
vinfo_prefixed_keys("target", $latest_common_target),
@ -3375,7 +3319,7 @@ MAIN:
unless($found) {
my $latest_snapshot = get_latest_snapshot_child($sroot, $svol);
push @data, { type => "latest_snapshot",
status => ($latest_snapshot->{cgen} == $svol->{gen}) ? "up-to-date" : undef,
status => ($latest_snapshot->{node}{cgen} == $svol->{node}{gen}) ? "up-to-date" : undef,
vinfo_prefixed_keys("source", $svol),
vinfo_prefixed_keys("snapshot", $latest_snapshot), # all unset if no $latest_snapshot
};
@ -3439,7 +3383,7 @@ MAIN:
foreach my $target_vol (sort { $a->{SUBVOL_PATH} cmp $b->{SUBVOL_PATH} } @{vinfo_subvol_list($droot)}) {
# incomplete received (garbled) subvolumes have no received_uuid (as of btrfs-progs v4.3.1).
# a subvolume in droot matching our naming is considered incomplete if received_uuid is not set!
if(($target_vol->{received_uuid} eq '-') && parse_filename($target_vol->{SUBVOL_PATH}, $snapshot_name)) {
if(($target_vol->{node}{received_uuid} eq '-') && parse_filename($target_vol->{SUBVOL_PATH}, $snapshot_name)) {
DEBUG "Found incomplete target subvolume: $target_vol->{PRINT}";
push(@delete, $target_vol);
push @out, "--- $target_vol->{PRINT}";
@ -3531,12 +3475,12 @@ MAIN:
# check if latest snapshot is up-to-date with source subvolume (by generation)
my $latest = get_latest_snapshot_child($sroot, $svol);
if($latest) {
if($latest->{cgen} == $svol->{gen}) {
if($latest->{node}{cgen} == $svol->{node}{gen}) {
INFO "Snapshot creation skipped: snapshot_create=onchange, snapshot is up-to-date: $latest->{PRINT}";
$svol->{SNAPSHOT_UP_TO_DATE} = $latest;
next;
}
DEBUG "Snapshot creation enabled: snapshot_create=onchange, gen=$svol->{gen} > snapshot_cgen=$latest->{cgen}";
DEBUG "Snapshot creation enabled: snapshot_create=onchange, gen=$svol->{node}{gen} > snapshot_cgen=$latest->{node}{cgen}";
}
else {
DEBUG "Snapshot creation enabled: snapshot_create=onchange, no snapshots found";
@ -3616,7 +3560,7 @@ MAIN:
my $resume_total = 0;
my $resume_success = 0;
foreach my $child (sort { $a->{cgen} <=> $b->{cgen} } get_snapshot_children($sroot, $svol))
foreach my $child (sort { $a->{node}{cgen} <=> $b->{node}{cgen} } get_snapshot_children($sroot, $svol))
{
my $filename_info = parse_filename($child->{SUBVOL_PATH}, $snapdir . $snapshot_basename);
unless($filename_info) {
@ -3670,10 +3614,10 @@ MAIN:
my @resume = grep defined, @$preserve; # remove entries with no value from list (target subvolumes)
$resume_total = scalar @resume;
foreach my $child (sort { $a->{cgen} <=> $b->{cgen} } @resume)
foreach my $child (sort { $a->{node}{cgen} <=> $b->{node}{cgen} } @resume)
{
INFO "Resuming subvolume backup (send-receive) for: $child->{PRINT}";
my ($latest_common_src, $latest_common_target) = get_latest_common($sroot, $svol, $droot, $child->{cgen});
my ($latest_common_src, $latest_common_target) = get_latest_common($sroot, $svol, $droot, $child->{node}{cgen});
if(macro_send_receive(source => $child,
target => $droot,
parent => $latest_common_src, # this is <undef> if no common found
@ -3749,10 +3693,10 @@ MAIN:
# In incremental mode, the latest backup is most certainly our parent.
# (see note on FORCE_PRESERVE above)
$preserve_latest_backup ||= "preserve forced: possibly parent of latest backup";
# Note that we could check against $svol->{SNAPSHOT_CREATED}->{parent_uuid} to be certain,
# Note that we could check against $svol->{SNAPSHOT_CREATED}->{node}{parent_uuid} to be certain,
# but this information is not available in $dryrun:
# foreach my $vol (@{vinfo_subvol_list($droot)}) {
# $vol->{FORCE_PRESERVE} = 1 if($vol->{received_uuid} eq $svol->{SNAPSHOT_CREATED}->{parent_uuid});
# $vol->{FORCE_PRESERVE} = 1 if($vol->{node}{received_uuid} eq $svol->{SNAPSHOT_CREATED}->{node}{parent_uuid});
# }
}
}