From 207e8868dabe9a8f62bd1a7e24596e623b93d710 Mon Sep 17 00:00:00 2001 From: Axel Burri Date: Mon, 14 Mar 2016 16:39:13 +0100 Subject: [PATCH] btrbk: no more copy of node information in vinfo by vinfo_set_detail(); always use vinfo->{node}{key}; cleanup --- btrbk | 284 +++++++++++++++++++++++----------------------------------- 1 file changed, 114 insertions(+), 170 deletions(-) diff --git a/btrbk b/btrbk index a8fdd7e..788df53 100755 --- a/btrbk +++ b/btrbk @@ -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.--.btrfs : root (full) image # - svol.--[@].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 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}); # } } }