mirror of https://github.com/digint/btrbk
btrbk: improved error handling
parent
8930c0a87f
commit
299edde0d7
103
btrbk
103
btrbk
|
@ -109,7 +109,10 @@ sub run_cmd($;$)
|
||||||
$ret = `$cmd`;
|
$ret = `$cmd`;
|
||||||
chomp($ret);
|
chomp($ret);
|
||||||
TRACE "command output:\n$ret";
|
TRACE "command output:\n$ret";
|
||||||
die("command execution failed: \"$cmd\"") if($?);
|
if($?) {
|
||||||
|
WARN "command execution failed (exitcode=$?): \"$cmd\"";
|
||||||
|
return undef;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return $ret;
|
return $ret;
|
||||||
}
|
}
|
||||||
|
@ -147,36 +150,39 @@ sub btr_subvolume_detail($)
|
||||||
{
|
{
|
||||||
my $vol = shift;
|
my $vol = shift;
|
||||||
my $ret = run_cmd("/sbin/btrfs subvolume show $vol 2>/dev/null", 1);
|
my $ret = run_cmd("/sbin/btrfs subvolume show $vol 2>/dev/null", 1);
|
||||||
if($ret eq "$vol is btrfs root") {
|
if($ret)
|
||||||
TRACE "btr_detail: found btrfs root: $vol";
|
{
|
||||||
return { id => 5, is_root => 1 };
|
if($ret eq "$vol is btrfs root") {
|
||||||
}
|
TRACE "btr_detail: found btrfs root: $vol";
|
||||||
elsif($ret =~ /^$vol/) {
|
return { id => 5, is_root => 1 };
|
||||||
TRACE "btr_detail: found btrfs subvolume: $vol";
|
}
|
||||||
my %trans = (
|
elsif($ret =~ /^$vol/) {
|
||||||
name => "Name",
|
TRACE "btr_detail: found btrfs subvolume: $vol";
|
||||||
uuid => "uuid",
|
my %trans = (
|
||||||
parent_uuid => "Parent uuid",
|
name => "Name",
|
||||||
creation_time => "Creation time",
|
uuid => "uuid",
|
||||||
id => "Object ID",
|
parent_uuid => "Parent uuid",
|
||||||
gen => "Generation \\(Gen\\)",
|
creation_time => "Creation time",
|
||||||
cgen => "Gen at creation",
|
id => "Object ID",
|
||||||
parent_id => "Parent",
|
gen => "Generation \\(Gen\\)",
|
||||||
top_level => "Top Level",
|
cgen => "Gen at creation",
|
||||||
flags => "Flags",
|
parent_id => "Parent",
|
||||||
);
|
top_level => "Top Level",
|
||||||
my %detail;
|
flags => "Flags",
|
||||||
foreach (keys %trans) {
|
);
|
||||||
if($ret =~ /^\s+$trans{$_}:\s+(.*)$/m) {
|
my %detail;
|
||||||
$detail{$_} = $1;
|
foreach (keys %trans) {
|
||||||
} else {
|
if($ret =~ /^\s+$trans{$_}:\s+(.*)$/m) {
|
||||||
WARN "Failed to parse subvolume detail \"$trans{$_}\": $ret";
|
$detail{$_} = $1;
|
||||||
}
|
} else {
|
||||||
|
WARN "Failed to parse subvolume detail \"$trans{$_}\": $ret";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TRACE "btr_detail for $vol: " . Dumper \%detail;
|
||||||
|
return \%detail;
|
||||||
}
|
}
|
||||||
TRACE "btr_detail for $vol: " . Dumper \%detail;
|
|
||||||
return \%detail;
|
|
||||||
}
|
}
|
||||||
ERROR "Failed to fetch subvolume detail for: $vol";
|
WARN "Failed to fetch subvolume detail for: $vol";
|
||||||
return undef;
|
return undef;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -254,6 +260,10 @@ sub btr_subvolume_list($;@)
|
||||||
my $filter_option = "-a";
|
my $filter_option = "-a";
|
||||||
$filter_option = "-o" if($opts{subvol_only});
|
$filter_option = "-o" if($opts{subvol_only});
|
||||||
my $ret = run_cmd("/sbin/btrfs subvolume list $filter_option -c -u -q -R $vol", 1);
|
my $ret = run_cmd("/sbin/btrfs subvolume list $filter_option -c -u -q -R $vol", 1);
|
||||||
|
unless($ret) {
|
||||||
|
WARN "Failed to fetch btrfs subvolume list for: $vol";
|
||||||
|
return undef;
|
||||||
|
}
|
||||||
my @nodes;
|
my @nodes;
|
||||||
foreach (split(/\n/, $ret))
|
foreach (split(/\n/, $ret))
|
||||||
{
|
{
|
||||||
|
@ -275,7 +285,7 @@ sub btr_subvolume_list($;@)
|
||||||
};
|
};
|
||||||
# $node{parent_uuid} = undef if($node{parent_uuid} eq '-');
|
# $node{parent_uuid} = undef if($node{parent_uuid} eq '-');
|
||||||
}
|
}
|
||||||
return @nodes;
|
return \@nodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub btr_subvolume_find_new($$)
|
sub btr_subvolume_find_new($$)
|
||||||
|
@ -283,6 +293,8 @@ sub btr_subvolume_find_new($$)
|
||||||
my $vol = shift;
|
my $vol = shift;
|
||||||
my $lastgen = shift;
|
my $lastgen = shift;
|
||||||
my $ret = run_cmd("/sbin/btrfs subvolume find-new $vol $lastgen");
|
my $ret = run_cmd("/sbin/btrfs subvolume find-new $vol $lastgen");
|
||||||
|
ERROR "Failed to fetch modified files for: $vol" unless(defined($ret));
|
||||||
|
return $ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -291,7 +303,9 @@ sub btr_tree($)
|
||||||
my $vol = shift;
|
my $vol = shift;
|
||||||
my %tree;
|
my %tree;
|
||||||
my %id;
|
my %id;
|
||||||
foreach my $node (btr_subvolume_list($vol, subvol_only => 0))
|
my $subvol_list = btr_subvolume_list($vol, subvol_only => 0);
|
||||||
|
return undef unless(ref($subvol_list) eq "ARRAY");
|
||||||
|
foreach my $node (@$subvol_list)
|
||||||
{
|
{
|
||||||
TRACE "btr_tree: processing subvolid=$node->{id}";
|
TRACE "btr_tree: processing subvolid=$node->{id}";
|
||||||
|
|
||||||
|
@ -327,9 +341,16 @@ sub btr_subtree($)
|
||||||
{
|
{
|
||||||
my $vol = shift;
|
my $vol = shift;
|
||||||
my $detail = btr_subvolume_detail($vol);
|
my $detail = btr_subvolume_detail($vol);
|
||||||
|
unless($detail) {
|
||||||
|
WARN "Failed to build btrfs subtree for volume: $vol";
|
||||||
|
return undef;
|
||||||
|
}
|
||||||
|
|
||||||
my $volname = $detail->{name} || "";
|
my $volname = $detail->{name} || "";
|
||||||
my %tree;
|
my %tree;
|
||||||
foreach my $node (btr_subvolume_list($vol, subvol_only => 1))
|
my $subvol_list = btr_subvolume_list($vol, subvol_only => 1);
|
||||||
|
return undef unless(ref($subvol_list) eq "ARRAY");
|
||||||
|
foreach my $node (@$subvol_list)
|
||||||
{
|
{
|
||||||
TRACE "btr_subtree: processing subvolid=$node->{id}";
|
TRACE "btr_subtree: processing subvolid=$node->{id}";
|
||||||
|
|
||||||
|
@ -359,6 +380,7 @@ sub btr_subtree($)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# returns $dst, or undef on error
|
||||||
sub btrfs_snapshot($$)
|
sub btrfs_snapshot($$)
|
||||||
{
|
{
|
||||||
my $src = shift;
|
my $src = shift;
|
||||||
|
@ -367,7 +389,9 @@ sub btrfs_snapshot($$)
|
||||||
DEBUG "[btrfs] source: $src";
|
DEBUG "[btrfs] source: $src";
|
||||||
DEBUG "[btrfs] dest : $dst";
|
DEBUG "[btrfs] dest : $dst";
|
||||||
INFO ">>> $dst";
|
INFO ">>> $dst";
|
||||||
run_cmd("/sbin/btrfs subvolume snapshot -r $src $dst");
|
my $ret = run_cmd("/sbin/btrfs subvolume snapshot -r $src $dst");
|
||||||
|
ERROR "Failed to create btrfs subvolume snapshot: $src -> $dst" unless(defined($ret));
|
||||||
|
return defined($ret) ? $dst : undef;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -397,6 +421,10 @@ sub btrfs_send_receive($$;$$)
|
||||||
$receive_option = "-v -v" if($parent && $changelog);
|
$receive_option = "-v -v" if($parent && $changelog);
|
||||||
my $cmd = "/sbin/btrfs send $parent_option $src | /sbin/btrfs receive $receive_option $dst/ 2>&1";
|
my $cmd = "/sbin/btrfs send $parent_option $src | /sbin/btrfs receive $receive_option $dst/ 2>&1";
|
||||||
my $ret = run_cmd($cmd);
|
my $ret = run_cmd($cmd);
|
||||||
|
unless(defined($ret)) {
|
||||||
|
ERROR "Failed to send/receive btrfs subvolume: $src " . ($parent ? "[$parent]" : "") . " -> $dst";
|
||||||
|
return undef;
|
||||||
|
}
|
||||||
if($changelog && (not $dryrun))
|
if($changelog && (not $dryrun))
|
||||||
{
|
{
|
||||||
INFO "Writing btrfs-diff changelog: $changelog";
|
INFO "Writing btrfs-diff changelog: $changelog";
|
||||||
|
@ -412,6 +440,7 @@ sub btrfs_send_receive($$;$$)
|
||||||
WARN "Failed to open changelog file: $!";
|
WARN "Failed to open changelog file: $!";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -558,6 +587,8 @@ MAIN:
|
||||||
|
|
||||||
if($target_diff) {
|
if($target_diff) {
|
||||||
my $target_detail = btr_subvolume_detail($target_diff);
|
my $target_detail = btr_subvolume_detail($target_diff);
|
||||||
|
exit 1 unless($target_detail);
|
||||||
|
|
||||||
$target = $uuid_info{$target_detail->{uuid}};
|
$target = $uuid_info{$target_detail->{uuid}};
|
||||||
# check if given parent is really a parent
|
# check if given parent is really a parent
|
||||||
my $cur = $node;
|
my $cur = $node;
|
||||||
|
@ -575,6 +606,7 @@ MAIN:
|
||||||
|
|
||||||
# dump files, sorted and unique
|
# dump files, sorted and unique
|
||||||
my $ret = btr_subvolume_find_new($vol, $lastgen);
|
my $ret = btr_subvolume_find_new($vol, $lastgen);
|
||||||
|
exit 1 unless(defined($ret));
|
||||||
my %files;
|
my %files;
|
||||||
foreach (split(/\n/, $ret)) {
|
foreach (split(/\n/, $ret)) {
|
||||||
/\S+ \S+ \S+ \S+ \S+ \S+ \S+ \S+ \S+ \S+ \S+ \S+ \S+ \S+ \S+ \S+ (\S+)/;
|
/\S+ \S+ \S+ \S+ \S+ \S+ \S+ \S+ \S+ \S+ \S+ \S+ \S+ \S+ \S+ \S+ (\S+)/;
|
||||||
|
@ -717,7 +749,10 @@ MAIN:
|
||||||
DEBUG "***";
|
DEBUG "***";
|
||||||
INFO "Creating subvolume snapshot for: $sroot/$svol";
|
INFO "Creating subvolume snapshot for: $sroot/$svol";
|
||||||
|
|
||||||
btrfs_snapshot("$sroot/$svol", $snapshot);
|
unless(btrfs_snapshot("$sroot/$svol", $snapshot)) {
|
||||||
|
WARN "Failed to create snapshot, aborting job: $sroot/$svol";
|
||||||
|
$job->{ABORTED} = 1;
|
||||||
|
}
|
||||||
$snapshot_cache{"$sroot/$svol"} = { name => $snapshot_name,
|
$snapshot_cache{"$sroot/$svol"} = { name => $snapshot_name,
|
||||||
file => $snapshot };
|
file => $snapshot };
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue