btrbk: correctly fill cache; fix vinfo_set_detail; add debug functionality (VINFO(), SUBTREE_LIST()); cleanup

pull/73/head
Axel Burri 2016-03-10 18:29:21 +01:00
parent e85b6dadf1
commit 743d7704f5
1 changed files with 55 additions and 40 deletions

95
btrbk
View File

@ -254,9 +254,17 @@ sub INFO { my $t = shift; print STDERR "$t\n" if($loglevel >= 2); }
sub WARN { my $t = shift; print STDERR "WARNING: $t\n" if($loglevel >= 1); } sub WARN { my $t = shift; print STDERR "WARNING: $t\n" if($loglevel >= 1); }
sub ERROR { my $t = shift; print STDERR "ERROR: $t\n"; } sub ERROR { my $t = shift; print STDERR "ERROR: $t\n"; }
sub VINFO { my $vinfo = shift; my $t = shift || "vinfo"; sub VINFO {
print STDERR Data::Dumper->new([$vinfo], [$t])->Maxdepth(2)->Dump(); my $vinfo = shift; my $t = shift || "vinfo";
} print STDERR Data::Dumper->new([$vinfo], [$t])->Maxdepth(2)->Dump();
}
sub TREE_CACHE {
print STDERR "btrfs_tree_cache:\n" . join("\n", (sort keys %btrfs_tree_cache)) . "\n";
}
sub SUBVOL_LIST {
my $vol = shift; my $t = shift // "SUBVOL_LIST"; my $svl = vinfo_subvol_list($vol);
print STDERR "$t:\n" . join("\n", map { "$vol->{PRINT}/./$_->{SUBVOL_PATH} $_->{id}" } @$svl) . "\n";
}
sub ABORTED($;$) sub ABORTED($;$)
{ {
@ -513,7 +521,7 @@ sub vinfo_child($$;$)
$info{$_} = $parent->{$_} if(exists $parent->{$_}); $info{$_} = $parent->{$_} if(exists $parent->{$_});
} }
TRACE "vinfo child created from \"$parent->{PRINT}\": $info{PRINT}"; # TRACE "vinfo_child: created from \"$parent->{PRINT}\": $info{PRINT}";
return \%info; return \%info;
} }
@ -536,10 +544,11 @@ sub vinfo_init_root($)
vinfo_set_detail($vol, $detail, $path_verified); vinfo_set_detail($vol, $detail, $path_verified);
# read the subvolume list, and update %btrfs_tree_cache # read the subvolume list, and update %btrfs_tree_cache
return undef unless vinfo_subvol_list($vol, fill_cache => 1); my $subvol_list = vinfo_subvol_list($vol, fill_cache => 1);
TRACE "vinfo root created: $vol->{PRINT}"; TRACE "vinfo_init_root: created vinfo root: $vol->{PRINT}";
return $vol; # VINFO($vol);
return $subvol_list;
} }
@ -548,20 +557,17 @@ sub vinfo_set_detail($$;$)
my $vol = shift || die; my $vol = shift || die;
my $detail = shift || die; my $detail = shift || die;
my $path_verified = shift; my $path_verified = shift;
my @vinfo_detail_keys = qw(id is_root gen cgen uuid parent_uuid received_uuid readonly); my @vinfo_detail_keys = qw(id is_root gen cgen uuid parent_uuid received_uuid readonly node);
TRACE "updating vinfo detail for: $vol->{PRINT}"; # TRACE "updating vinfo detail for: $vol->{PRINT}";
VINFO($detail) if($loglevel >= 4); # VINFO($detail) if($loglevel >= 4);
# add detail data to vinfo hash
# copy only from keys in @vinfo_detail_keys # copy only from keys in @vinfo_detail_keys
foreach (@vinfo_detail_keys) { foreach(@vinfo_detail_keys) {
next unless(exists($detail->{$_}));
# die if already present matches new # die if already present matches new
die if(exists($vol->{$_}) && ($vol->{$_} ne $detail->{$_})); die if(exists($vol->{$_}) && ($vol->{$_} ne $detail->{$_}));
$vol->{$_} = $detail->{$_}; $vol->{$_} = $detail->{$_};
# WARN "vinfo_set_detail: missing key \"$_\"" unless($detail->{$_});
# die unless(($_ eq "readonly") || ($_ eq "is_root") || $detail->{is_root} || $detail->{$_});
} }
# be very paranoid, this should never happen # be very paranoid, this should never happen
@ -1134,7 +1140,7 @@ sub btrfs_subvolume_detail($)
TRACE "btr_detail: found btrfs subvolume: $vol->{PRINT}"; TRACE "btr_detail: found btrfs subvolume: $vol->{PRINT}";
# NOTE: received_uuid is not required here, as btrfs-progs < 4.1 does not give us that information. # NOTE: received_uuid is not required here, as btrfs-progs < 4.1 does not give us that information.
# no worries, we get this from btrfs_subvolume_list() for all subvols. # no worries, we get this from btrfs_subvolume_list() for all subvols.
my @required_keys = qw(name uuid parent_uuid id gen cgen top_level); #!!! my @required_keys = qw(name uuid parent_uuid id gen cgen top_level);
my %trans = ( my %trans = (
"Name" => "name", "Name" => "name",
"uuid" => "uuid", "uuid" => "uuid",
@ -1628,7 +1634,7 @@ sub _btr_tree_fill_cache
#TRACE "_btr_tree_fill_cache: $abs_path"; #TRACE "_btr_tree_fill_cache: $abs_path";
$btrfs_tree_cache{$abs_path} = $node; $btrfs_tree_cache{$abs_path} = $node;
$uuid_url_map{$node->{uuid}}->{$abs_path} = $node if($node->{uuid}); $uuid_url_map{$node->{uuid}}->{$abs_path} = $node if($node->{uuid}); #!!! fix this also
foreach(values %{$node->{SUBTREE}}) { foreach(values %{$node->{SUBTREE}}) {
_btr_tree_fill_cache($_, $abs_path . '/' . $_->{REL_PATH}); _btr_tree_fill_cache($_, $abs_path . '/' . $_->{REL_PATH});
} }
@ -1649,7 +1655,7 @@ sub btr_tree($)
TRACE "btrfs_tree: cache HIT: $vol->{URL}"; TRACE "btrfs_tree: cache HIT: $vol->{URL}";
return $btrfs_tree_cache{$vol->{URL}}; return $btrfs_tree_cache{$vol->{URL}};
} }
TRACE "btrfs_tree: cache MISS: $vol->{REAL_URL} :: $vol->{URL}"; TRACE "btrfs_tree: cache MISS: $vol->{REAL_URL}, $vol->{URL}";
# NOTE: make sure to to have either $vol->{uuid} or $vol->{is_root} # NOTE: make sure to to have either $vol->{uuid} or $vol->{is_root}
# (provided by btrfs_subvolume_show()), or we cannot determine the # (provided by btrfs_subvolume_show()), or we cannot determine the
@ -1750,8 +1756,15 @@ sub vinfo_subvol_list($;@)
return undef unless($tree_root); return undef unless($tree_root);
if($opts{fill_cache}) { if($opts{fill_cache}) {
# force fill cache. _vinfo_subtree_list (below) does not do this, fix!!! TODO # force fill cache
_btr_tree_fill_cache($tree_root, $vol->{REAL_URL}); foreach ($vol->{URL}, $vol->{REAL_URL}) {
if($btrfs_tree_cache{$_}) {
TRACE "vinfo_subvol_list: fill_cache: btrfs_tree: cache HIT: $_";
next;
}
TRACE "vinfo_subvol_list: fill_cache: btrfs_tree: cache MISS: $_";
_btr_tree_fill_cache($tree_root, $_);
}
} }
# recurse into $tree_root, returns array of vinfo # recurse into $tree_root, returns array of vinfo
@ -1759,11 +1772,11 @@ sub vinfo_subvol_list($;@)
} }
sub __get_by_id($) sub __get_by_id($$)
{ {
my $subvol_list = shift; my $subvol_list = shift;
my $filter_vol = shift; my $id = shift;
my @ret = grep { $_->{id} == $filter_vol->{id} } @$subvol_list; my @ret = grep { $_->{id} == $id } @$subvol_list;
return undef unless(scalar @ret); return undef unless(scalar @ret);
die unless(scalar(@ret) == 1); die unless(scalar(@ret) == 1);
return $ret[0]; return $ret[0];
@ -1800,7 +1813,11 @@ sub vinfo_subvol($$)
{ {
my $vol = shift || die; my $vol = shift || die;
my $rel_path = shift // die; my $rel_path = shift // die;
return __get_by_key_eq(vinfo_subvol_list($vol), 'SUBVOL_PATH', $rel_path); my %opts = @_;
my $subvol_list = vinfo_subvol_list($vol);
my $vinfo = __get_by_key_eq($subvol_list, 'SUBVOL_PATH', $rel_path);
return $vinfo;
} }
@ -3019,28 +3036,26 @@ MAIN:
foreach my $svol (vinfo_subsection($sroot, 'subvolume')) { foreach my $svol (vinfo_subsection($sroot, 'subvolume')) {
DEBUG "Initializing subvolume section: $svol->{PRINT}"; DEBUG "Initializing subvolume section: $svol->{PRINT}";
if(my $svol_check = vinfo_subvol($sroot, $svol->{CONFIG}->{rel_path})) { my $rel_path = $svol->{CONFIG}->{rel_path};
DEBUG "Found \"$svol->{CONFIG}->{rel_path}\" in btrfs subtree of: $sroot->{PRINT}"; if(my $vinfo = vinfo_subvol($sroot, $rel_path)) {
vinfo_set_detail($svol, $svol_check); DEBUG "Found \"$rel_path\" in btrfs subtree of: $sroot->{PRINT}";
vinfo_set_detail($svol, $vinfo);
} }
else { else {
DEBUG "Missing \"$rel_path\" in btrfs subtree of \"$sroot->{PRINT}\", resolving details";
# configured subvolume is not present in btrfs subvolume list. # configured subvolume is not present in btrfs subvolume list.
# try to read subvolume detail, as configured subvolume could be a symlink. # try to read subvolume detail, as configured subvolume could be a symlink.
DEBUG "Missing \"$svol->{CONFIG}->{rel_path}\" in btrfs subtree of \"$sroot->{PRINT}\", checking details"; my $subvol_list = vinfo_init_root($svol);
my $detail = btrfs_subvolume_detail($svol); unless($subvol_list) {
unless($detail) { ABORTED($sroot, "Failed to fetch subvolume detail" . ($err ? ": $err" : ""));
ABORTED($svol, "Failed to fetch subvolume detail" . ($err ? ": $err" : "")); WARN "Skipping volume \"$sroot->{PRINT}\": $abrt";
WARN "Skipping subvolume \"$svol->{PRINT}\": $abrt";
next; next;
} }
if($detail->{is_root}) { $subvol_list = vinfo_subvol_list($sroot);
ABORTED($svol, "Subvolume is btrfs root"); my $vinfo = __get_by_id($subvol_list, $svol->{id});
WARN "Skipping subvolume \"$svol->{PRINT}\": $abrt"; if($vinfo) {
next; DEBUG "Found id=$svol->{id} in btrfs subtree of: $sroot->{PRINT}";
} # NOTE: detail is already set by vinfo_init_root()
# make sure $svol is in subtree of $sroot
if(grep { $_->{uuid} eq $detail->{uuid} } @{vinfo_subvol_list($sroot)}) {
vinfo_set_detail($svol, $detail);
} else { } else {
ABORTED($svol, "Not a child subvolume of: $sroot->{PRINT}"); ABORTED($svol, "Not a child subvolume of: $sroot->{PRINT}");
WARN "Skipping subvolume \"$svol->{PRINT}\": $abrt"; WARN "Skipping subvolume \"$svol->{PRINT}\": $abrt";