btrbk: get_related_subvolumes: add direct children from parent chain

pull/274/head
Axel Burri 2018-10-17 17:04:03 +02:00
parent ad91b6f618
commit cb23c65eed
1 changed files with 25 additions and 45 deletions

70
btrbk
View File

@ -3020,66 +3020,36 @@ sub get_related_subvolumes($$;@)
my $snaproot = shift || die; my $snaproot = shift || die;
my $svol = shift // die; my $svol = shift // die;
my %opts = @_; my %opts = @_;
my $snapshot_dir = shift; # if not set, skip search for btrbk basename (set to empty string to enable at current dir)
my $snaproot_subvol_list = vinfo_subvol_list_all_accessible($snaproot); my $snaproot_subvol_list = vinfo_subvol_list_all_accessible($snaproot);
TRACE "get_related: resolving related subvolumes of: $svol->{PATH} (snaproot=$snaproot->{PRINT})"; TRACE "get_related: resolving related subvolumes of: $svol->{PATH} (snaproot=$snaproot->{PRINT})";
my @candidate; my @candidate;
if($svol->{node}{readonly}) {
if($svol->{node}{parent_uuid} ne '-') {
# add readonly parent
@candidate = grep { $_->{node}{readonly} && ($_->{node}{uuid} eq $svol->{node}{parent_uuid}) } @$snaproot_subvol_list;
die "multiple parents for $svol->{node}{parent_uuid}" if(scalar(@candidate) > 1);
TRACE "get_related: subvolume has a read-only parent, add parent candidate" if(scalar(@candidate) > 0);
# add snapshots with same parent_uuid (siblings) # iterate parent chain (recursive!)
my @siblings = grep { $_->{node}{readonly} && ($_->{node}{parent_uuid} eq $svol->{node}{parent_uuid}) } @$snaproot_subvol_list;
my @siblings_older = grep { $_->{node}{cgen} <= $svol->{node}{cgen} } @siblings;
my @siblings_newer = grep { $_->{node}{cgen} > $svol->{node}{cgen} } @siblings;
push @candidate, sort { $b->{node}{cgen} <=> $a->{node}{cgen} } @siblings_older; # older first, descending by cgen
push @candidate, sort { $a->{node}{cgen} <=> $b->{node}{cgen} } @siblings_newer; # then newer, ascending by cgen
TRACE "get_related: subvolume has siblings (same parent_uuid), add " . scalar(@siblings_older) . " older and " . scalar(@siblings_newer) . " newer (by cgen) candidates";
}
if($opts{fallback_btrbk_basename} && exists($svol->{node}{BTRBK_BASENAME})) {
# add subvolumes in same directory matching btrbk file name scheme
my $snaproot_btrbk_direct_leaf = vinfo_subvol_list($snaproot, readonly => 1, btrbk_direct_leaf => $svol->{node}{BTRBK_BASENAME});
my @naming_match_older = grep { cmp_date($_->{node}{BTRBK_DATE}, $svol->{node}{BTRBK_DATE}) < 0 } @$snaproot_btrbk_direct_leaf;
my @naming_match_newer = grep { cmp_date($_->{node}{BTRBK_DATE}, $svol->{node}{BTRBK_DATE}) > 0 } @$snaproot_btrbk_direct_leaf;
push @candidate, sort { cmp_date($b->{node}{BTRBK_DATE}, $a->{node}{BTRBK_DATE}) } @naming_match_older;
push @candidate, sort { cmp_date($a->{node}{BTRBK_DATE}, $b->{node}{BTRBK_DATE}) } @naming_match_newer;
TRACE "get_related: subvolume has btrbk naming scheme, add " . scalar(@naming_match_older) . " older and " . scalar(@naming_match_newer) . " newer (by file suffix) candidates with scheme: $snaproot->{PRINT}/$svol->{node}{BTRBK_BASENAME}.*";
}
}
else
{
# TODO: this is dead code, consider removing (or move to separate function)
@candidate = sort { $b->{node}{cgen} <=> $a->{node}{cgen} } get_snapshot_children($snaproot, $svol);
TRACE "get_related: subvolume is read-write, add " . scalar(@candidate) . " snapshot children, sorted by cgen: $svol->{PATH}";
if($opts{fallback_btrbk_basename}) {
# add subvolumes in same directory matching btrbk file name scheme (using $svol->{NAME} as basename)
my @naming_match = grep { $_->{node}{readonly} && exists($_->{node}{BTRBK_BASENAME}) && ($_->{SUBVOL_DIR} eq "") && ($_->{node}{BTRBK_BASENAME} eq $svol->{NAME}) } @$snaproot_subvol_list;
push @candidate, sort { cmp_date($b->{node}{BTRBK_DATE}, $a->{node}{BTRBK_DATE}) } @naming_match;
TRACE "get_related: subvolume has btrbk naming scheme, add " . scalar(@naming_match) . " candidates with scheme: $snaproot->{PRINT}/$svol->{NAME}.*";
}
}
# add read-only ancestors from parent chain (recursive!)
my $rnode = $svol->{node}; my $rnode = $svol->{node};
my $search_depth = 0; my $search_depth = 0;
while($rnode && ($search_depth < 256)) { while($rnode && ($search_depth < 256)) {
last if($rnode->{parent_uuid} eq '-'); last if($rnode->{parent_uuid} eq '-');
TRACE "get_related: searching parent chain (depth=$search_depth): $rnode->{uuid}"; TRACE "get_related: searching parent chain (depth=$search_depth) for: $rnode->{uuid}";
my @parents = grep { $_->{node}{uuid} eq $rnode->{parent_uuid} } @$snaproot_subvol_list; my @parents = grep { $_->{node}{uuid} eq $rnode->{parent_uuid} } @$snaproot_subvol_list;
if(scalar(@parents) == 1) { if(scalar(@parents) == 1) {
my $parent = $parents[0]; my $parent = $parents[0];
TRACE "get_related: found parent (depth=$search_depth): $parent->{PRINT}";
if($parent->{node}{readonly}) { if($parent->{node}{readonly}) {
TRACE "get_related: found read-only parent (depth=$search_depth), add as candidate: $parent->{PRINT}"; TRACE "get_related: parent is read-only, add as candidate: $parent->{PRINT}";
push @candidate, $parent; push @candidate, $parent;
} else {
TRACE "get_related: found read-write parent (depth=$search_depth), ignoring: $parent->{PRINT}";
} }
# add direct children (snapshots with same parent_uuid)
my @children = grep { $_->{node}{readonly} && ($_->{node}{parent_uuid} eq $rnode->{parent_uuid}) } @$snaproot_subvol_list;
my @children_older = grep { $_->{node}{cgen} <= $svol->{node}{cgen} } @children;
my @children_newer = grep { $_->{node}{cgen} > $svol->{node}{cgen} } @children;
push @candidate, sort { $b->{node}{cgen} <=> $a->{node}{cgen} } @children_older; # older first, descending by cgen
push @candidate, sort { $a->{node}{cgen} <=> $b->{node}{cgen} } @children_newer; # then newer, ascending by cgen
TRACE "get_related: add direct children as candidates: " . scalar(@children_older) . " older and " . scalar(@children_newer) . " newer (by cgen)";
$rnode = $parent->{node}; $rnode = $parent->{node};
} }
elsif(scalar(@parents) > 1) { elsif(scalar(@parents) > 1) {
@ -3091,6 +3061,16 @@ sub get_related_subvolumes($$;@)
$search_depth++; $search_depth++;
} }
if($opts{fallback_btrbk_basename} && exists($svol->{node}{BTRBK_BASENAME})) {
# add subvolumes in same directory matching btrbk file name scheme
my $snaproot_btrbk_direct_leaf = vinfo_subvol_list($snaproot, readonly => 1, btrbk_direct_leaf => $svol->{node}{BTRBK_BASENAME});
my @naming_match_older = grep { cmp_date($_->{node}{BTRBK_DATE}, $svol->{node}{BTRBK_DATE}) < 0 } @$snaproot_btrbk_direct_leaf;
my @naming_match_newer = grep { cmp_date($_->{node}{BTRBK_DATE}, $svol->{node}{BTRBK_DATE}) > 0 } @$snaproot_btrbk_direct_leaf;
push @candidate, sort { cmp_date($b->{node}{BTRBK_DATE}, $a->{node}{BTRBK_DATE}) } @naming_match_older;
push @candidate, sort { cmp_date($a->{node}{BTRBK_DATE}, $b->{node}{BTRBK_DATE}) } @naming_match_newer;
TRACE "get_related: subvolume has btrbk naming scheme, add " . scalar(@naming_match_older) . " older and " . scalar(@naming_match_newer) . " newer (by file suffix) candidates with scheme: $snaproot->{PRINT}/$svol->{node}{BTRBK_BASENAME}.*";
}
return \@candidate; return \@candidate;
} }