btrbk: add options "{snapshot,target,archive}_qgroup_destroy": destroy qgroups whenever a subvolume is deleted

Btrfs does not destroy qgroups when subvolumes are deleted (see
https://bugzilla.kernel.org/show_bug.cgi?id=91751). As a workaround
for this, btrbk can be configured to always destroy the corresponding
default qgroup "0/<subvol-id>" whenever a subvolume (snapshot, backup
or archive) is deleted.

Added configuration options:
 - snapshot_qgroup_destroy
 - target_qgroup_destroy
 - archive_qgroup_destroy
pull/204/head
Axel Burri 2017-10-02 14:00:09 +02:00
parent 6cb98700d8
commit e9a517f161
3 changed files with 59 additions and 0 deletions

View File

@ -12,6 +12,8 @@ btrbk-current
* Change raw backup format (sidecar file instead of uuid in file).
* Honor target_preserve for raw targets (delete raw targets).
* Add symmetric encryption for raw targets (close #157).
* Add "{snapshot,target,archive}_qgroup_destroy" configuration
options (close #49, #189).
* 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.

44
btrbk
View File

@ -124,6 +124,10 @@ my %config_options = (
backend_local => { default => undef, accept => [ "no", "btrfs-progs", "btrfs-progs-btrbk", "btrfs-progs-sudo" ] },
backend_remote => { default => undef, accept => [ "no", "btrfs-progs", "btrfs-progs-btrbk", "btrfs-progs-sudo" ] },
snapshot_qgroup_destroy => { default => undef, accept => [ "yes", "no" ], context => [ "root", "volume", "subvolume" ] },
target_qgroup_destroy => { default => undef, accept => [ "yes", "no" ] },
archive_qgroup_destroy => { default => undef, accept => [ "yes", "no" ], context => [ "root" ] },
# deprecated options
btrfs_progs_compat => { default => undef, accept => [ "yes", "no" ],
deprecated => { DEFAULT => { ABORT => 1, warn => 'This feature has been dropped in btrbk-v0.23.0. Please update to newest btrfs-progs, AT LEAST >= $BTRFS_PROGS_MIN' } } },
@ -214,6 +218,7 @@ my %backend_cmd_map = (
"btrfs subvolume delete" => [ "btrfs-subvolume-delete" ],
"btrfs send" => [ "btrfs-send" ],
"btrfs receive" => [ "btrfs-receive" ],
"btrfs qgroup destroy" => [ "btrfs-qgroup-destroy" ],
},
"btrfs-progs-sudo" => { "btrfs subvolume list" => [ "sudo", "-n", "btrfs", "subvolume", "list" ],
"btrfs subvolume show" => [ "sudo", "-n", "btrfs", "subvolume", "show" ],
@ -221,6 +226,7 @@ my %backend_cmd_map = (
"btrfs subvolume delete" => [ "sudo", "-n", "btrfs", "subvolume", "delete" ],
"btrfs send" => [ "sudo", "-n", "btrfs", "send" ],
"btrfs receive" => [ "sudo", "-n", "btrfs", "receive" ],
"btrfs qgroup destroy" => [ "sudo", "-n", "btrfs", "qgroup", "destroy" ],
},
);
@ -1280,6 +1286,33 @@ sub btrfs_subvolume_delete($@)
}
sub btrfs_qgroup_destroy($@)
{
my $vol = shift // die;
my %opts = @_;
my $vol_id = $vol->{node}{id};
unless($vol_id) {
ERROR "Unknown subvolume_id for: $vol->{PRINT}";
return undef;
}
my $path = $vol->{PATH} // die;
my $qgroup_id = "0/$vol_id";
INFO "[qgroup-destroy] qgroup_id: $qgroup_id";
INFO "[qgroup-destroy] subvolume: $vol->{PRINT}";
start_transaction($opts{type} // "qgroup_destroy",
vinfo_prefixed_keys("target", $vol));
my $ret = run_cmd(cmd => vinfo_cmd($vol, "btrfs qgroup destroy", $qgroup_id, { unsafe => $path }),
rsh => vinfo_rsh($vol),
);
end_transaction($opts{type} // "qgroup_destroy", defined($ret));
unless(defined($ret)) {
ERROR "Failed to destroy qgroup \"$qgroup_id\" for subvolume: $vol->{PRINT}";
return undef;
}
return $vol;
}
sub btrfs_send_receive($$$$)
{
my $snapshot = shift || die;
@ -3512,6 +3545,11 @@ sub macro_delete($$$$$;@)
preserve_date_in_future => 1,
);
if($delete_options{qgroup}->{destroy}) {
# NOTE: we do not abort on qgroup destroy errors
btrfs_qgroup_destroy($_, %{$delete_options{qgroup}}) foreach(@$delete);
}
my @delete_success = btrfs_subvolume_delete($delete, %delete_options);
$subvol_dir .= '/' if($subvol_dir ne "");
INFO "Deleted " . scalar(@delete_success) . " subvolumes in: $root_subvol->{PRINT}/$subvol_dir$subvol_basename.*";
@ -4605,6 +4643,8 @@ MAIN:
},
commit => config_key($droot, "btrfs_commit_delete"),
type => "delete_archive",
qgroup => { destroy => config_key($droot, "archive_qgroup_destroy"),
type => "qgroup_destroy_archive" },
);
}
}
@ -5751,6 +5791,8 @@ MAIN:
},
commit => config_key($droot, "btrfs_commit_delete"),
type => "delete_target",
qgroup => { destroy => config_key($droot, "target_qgroup_destroy"),
type => "qgroup_destroy_target" },
))
{
$target_aborted = 1;
@ -5780,6 +5822,8 @@ MAIN:
},
commit => config_key($svol, "btrfs_commit_delete"),
type => "delete_snapshot",
qgroup => { destroy => config_key($svol, "snapshot_qgroup_destroy"),
type => "qgroup_destroy_snapshot" },
);
}
}

View File

@ -320,6 +320,19 @@ For convenience, it is also possible to set \fIbackend_local\fR or
local or remote sources/targets (e.g. "backend_remote
btrfs-progs-btrbk").
.RE
.PP
\fBsnapshot_qgroup_destroy\fR yes|no \fI*experimental*\fR
.PD 0
.PP
\fBtarget_qgroup_destroy\fR yes|no \fI*experimental*\fR
.PP
\fBarchive_qgroup_destroy\fR yes|no \fI*experimental*\fR
.PD
.RS 4
Whenever a subvolume is deleted, also destroy corresponding default
qgroup "0/<subvol-id>". Only useful if you have enabled btrfs quota
support. See also: <https://bugzilla.kernel.org/show_bug.cgi?id=91751>
.RE
.SH RETENTION POLICY
btrbk uses separate retention policies for snapshots and backups,
which are defined by the \fIsnapshot_preserve_min\fR,