From e804930b5ef4436d5ef0bfc952282bf5b8c7e198 Mon Sep 17 00:00:00 2001 From: Axel Burri Date: Fri, 30 Jun 2017 18:49:17 +0200 Subject: [PATCH] btrbk: allow deletion of non-incremental raw targets implemented directly in btrfs_subvolume_delete() --- ChangeLog | 1 + btrbk | 59 ++++++++++++++++++++++++------------------------ doc/btrbk.conf.5 | 5 ++-- 3 files changed, 33 insertions(+), 32 deletions(-) diff --git a/ChangeLog b/ChangeLog index 0770bae..f969f74 100644 --- a/ChangeLog +++ b/ChangeLog @@ -8,6 +8,7 @@ btrbk-current * Add "snapshot" command (close #150). * Add "--preserve-snapshots" and "--preserve-backups" options. * Change raw backup format (sidecar file instead of uuid in file). + * Honor target_preserve for raw targets (delete raw targets). * Do not run in "perl taint mode" by default: remove "perl -T" in hashbang; hardcode $PATH only if taint mode is enabled. * Remove "duration" column from transaction_log/transaction_syslog. diff --git a/btrbk b/btrbk index c24a1d1..f113267 100755 --- a/btrbk +++ b/btrbk @@ -1139,24 +1139,44 @@ sub btrfs_subvolume_delete($@) $targets = [ $targets ] unless(ref($targets) eq "ARRAY"); return 0 unless(scalar(@$targets)); - # assert all targets share same HOST # NOTE: rsh and backend command is taken from first target my $rsh_host_check = $targets->[0]->{HOST} || ""; + my $target_type = $targets->[0]->{node}{TARGET_TYPE} || ""; foreach (@$targets) { + # assert all targets share same HOST die if($rsh_host_check ne ($_->{HOST} || "")); + # assert all targets share same target type + die if($target_type && ($_->{node}{TARGET_TYPE} ne $target_type)); } - INFO "[delete] options: commit-$commit" if($commit); + INFO "[delete] options: commit-$commit" if($commit && (not $target_type)); INFO "[delete] target: $_->{PRINT}" foreach(@$targets); - my @options; - @options = ("--commit-$commit") if($commit); start_transaction($opts{type} // "delete", map( { { vinfo_prefixed_keys("target", $_) }; } @$targets) ); - my @cmd_target_paths = map { { unsafe => $_->{PATH} } } @$targets; - my $ret = run_cmd(cmd => vinfo_cmd($targets->[0], "btrfs subvolume delete", @options, @cmd_target_paths ), - rsh => vinfo_rsh($targets->[0]), - ); + my $ret; + if($target_type eq "raw") { + my @cmd_target_paths; + foreach(@$targets) { + if($_->{node}{BTRBK_RAW}{split}) { + push @cmd_target_paths, "$_->{PATH}.split_??"; # unsafe is checked with path.info below + } else { + push @cmd_target_paths, { unsafe => $_->{PATH} }; + } + push @cmd_target_paths, { unsafe => "$_->{PATH}.info" }; + } + $ret = run_cmd(cmd => ['rm', @cmd_target_paths ], + rsh => vinfo_rsh($targets->[0]), + ); + } + else { + my @cmd_target_paths = map { { unsafe => $_->{PATH} } } @$targets; + my @options; + @options = ("--commit-$commit") if($commit); + $ret = run_cmd(cmd => vinfo_cmd($targets->[0], "btrfs subvolume delete", @options, @cmd_target_paths ), + rsh => vinfo_rsh($targets->[0]), + ); + } end_transaction($opts{type} // "delete", ($dryrun ? "DRYRUN" : (defined($ret) ? "success" : "ERROR"))); ERROR "Failed to delete btrfs subvolumes: " . join(' ', map( { $_->{PRINT} } @$targets)) unless(defined($ret)); return defined($ret) ? scalar(@$targets) : undef; @@ -4830,10 +4850,6 @@ MAIN: $subvol->{node}{FORCE_PRESERVE} = "preserve forced: parent of another raw target"; $child->{node}{FORCE_PRESERVE} ||= "preserve forced: child of another raw target"; } - - # For now, always preserve all raw files. - # TODO: remove this line as soon as incremental rotation is implemented. - $subvol->{node}{FORCE_PRESERVE} = "preserve forced: raw target"; } # TRACE(Data::Dumper->Dump([\@subvol_list], ["vinfo_raw_subvol_list{$droot}"])); } @@ -5116,8 +5132,6 @@ MAIN: foreach my $svol (vinfo_subsection($sroot, 'subvolume')) { my $snapshot_name = config_key($svol, "snapshot_name") // die; foreach my $droot (vinfo_subsection($svol, 'target')) { - my $target_type = $droot->{CONFIG}->{target_type} || die; - INFO "Cleaning incomplete backups in: $droot->{PRINT}/$snapshot_name.*"; push @out, "$droot->{PRINT}/$snapshot_name.*"; my @delete; @@ -5130,22 +5144,7 @@ MAIN: push(@delete, $target_vol); } } - my $ret; - if($target_type eq "raw") { - if(scalar(@delete)) { - DEBUG "[raw] delete:"; - DEBUG "[raw] file: $_->{PRINT}" foreach(@delete); - $ret = run_cmd({ - cmd => ['rm', (map { { unsafe => $_->{PATH} } } @delete) ], - rsh => vinfo_rsh($droot), - }); - } else { - $ret = 0; - } - } - else { - $ret = btrfs_subvolume_delete(\@delete, commit => config_key($droot, "btrfs_commit_delete"), type => "delete_garbled"); - } + my $ret = btrfs_subvolume_delete(\@delete, commit => config_key($droot, "btrfs_commit_delete"), type => "delete_garbled"); if(defined($ret)) { INFO "Deleted $ret incomplete backups in: $droot->{PRINT}/$snapshot_name.*"; $droot->{SUBVOL_DELETED} //= []; diff --git a/doc/btrbk.conf.5 b/doc/btrbk.conf.5 index 4697e55..f8179a1 100644 --- a/doc/btrbk.conf.5 +++ b/doc/btrbk.conf.5 @@ -414,8 +414,9 @@ a directory within a subvolume. See btrfs\-send(8), btrfs\-receive(8). Backup to a raw (filesystem independent) file from the output of btrfs\-send(8), with optional compression and encryption. .PP -Note that the target preserve mechanism is currently disabled for raw -backups (btrbk does not delete any raw files)! +Note that the target preserve mechanism is currently disabled for +incremental raw backups (btrbk does not delete any incremental raw +files)! .PP Additional options for raw targets: .PP