From de05b997572cee11349db6bdb98e44d67f8cd318 Mon Sep 17 00:00:00 2001 From: Axel Burri Date: Sat, 16 Apr 2016 01:09:17 +0200 Subject: [PATCH] btrbk: rename action "clone" to "archive" (should have been like this from the beginning) --- btrbk | 100 ++++++++++++++++++++++++++-------------------------- doc/FAQ.md | 47 +++++++++--------------- doc/btrbk.1 | 19 +++++----- 3 files changed, 77 insertions(+), 89 deletions(-) diff --git a/btrbk b/btrbk index 4bca40a..92b8947 100755 --- a/btrbk +++ b/btrbk @@ -245,22 +245,22 @@ sub HELP_MESSAGE print STDERR " --progress show progress bar on send-receive operation\n"; print STDERR "\n"; print STDERR "commands:\n"; - print STDERR " run perform backup operations as defined in the config file\n"; - print STDERR " dryrun don't run btrfs commands; show what would be executed\n"; - print STDERR " stats print snapshot/backup statistics\n"; - print STDERR " list available subcommands are:\n"; - print STDERR " backups all backups and corresponding snapshots\n"; - print STDERR " snapshots all snapshots and corresponding backups\n"; - print STDERR " latest most recent snapshots and backups\n"; - print STDERR " config configured source/snapshot/target relations\n"; - print STDERR " source configured source/snapshot relations\n"; - print STDERR " volume configured volume sections\n"; - print STDERR " target configured targets\n"; - print STDERR " clean delete incomplete (garbled) backups\n"; - print STDERR " clone recursively copy all subvolumes (experimental)\n"; - print STDERR " usage print filesystem usage\n"; - print STDERR " origin print origin information for subvolume\n"; - print STDERR " diff shows new files since subvolume for subvolume \n"; + print STDERR " run perform backup operations as defined in the config\n"; + print STDERR " dryrun don't run btrfs commands; show what would be executed\n"; + print STDERR " stats print snapshot/backup statistics\n"; + print STDERR " list available subcommands are:\n"; + print STDERR " backups all backups and corresponding snapshots\n"; + print STDERR " snapshots all snapshots and corresponding backups\n"; + print STDERR " latest most recent snapshots and backups\n"; + print STDERR " config configured source/snapshot/target relations\n"; + print STDERR " source configured source/snapshot relations\n"; + print STDERR " volume configured volume sections\n"; + print STDERR " target configured targets\n"; + print STDERR " clean delete incomplete (garbled) backups\n"; + print STDERR " archive recursively copy all subvolumes (experimental)\n"; + print STDERR " usage print filesystem usage\n"; + print STDERR " origin print origin information for subvolume\n"; + print STDERR " diff shows new files between related subvolumes\n"; print STDERR "\n"; print STDERR "For additional information, see $PROJECT_HOME\n"; } @@ -2634,7 +2634,7 @@ sub macro_delete($$$$$;@) } -sub macro_clone_target($$$;$) +sub macro_archive_target($$$;$) { my $sroot = shift || die; my $droot = shift || die; @@ -3181,7 +3181,7 @@ MAIN: WARN 'Found option "--progress", but "pv" is not present: (please install "pv")'; $show_progress = 0; } - my ($action_run, $action_usage, $action_resolve, $action_diff, $action_origin, $action_config_print, $action_list, $action_clean, $action_clone); + my ($action_run, $action_usage, $action_resolve, $action_diff, $action_origin, $action_config_print, $action_list, $action_clean, $action_archive); my @filter_args; my $args_allow_group = 1; my $args_expected_min = 0; @@ -3196,8 +3196,8 @@ MAIN: $action_clean = 1; @filter_args = @ARGV; } - elsif ($command eq "clone") { - $action_clone = 1; + elsif ($command eq "archive") { + $action_archive = 1; $args_expected_min = $args_expected_max = 2; $args_allow_group = 0; @filter_args = @ARGV; @@ -3412,10 +3412,10 @@ MAIN: } - if($action_clone) + if($action_archive) { # - # clone (archive) tree + # archive (clone) tree # # NOTE: This is intended to work without a config file! The only # thing used from the configuration is the SSH and transaction log @@ -3429,9 +3429,9 @@ MAIN: # FIXME: add command line options for preserve logic $config->{SUBSECTION} = []; # clear configured subsections, we build them dynamically - my $clone_src_root = vinfo($src_url, $config); - unless(vinfo_init_root($clone_src_root, resolve_subdir => 1)) { - ERROR "Failed to fetch subvolume detail for '$clone_src_root->{PRINT}'" . ($err ? ": $err" : ""); + my $src_root = vinfo($src_url, $config); + unless(vinfo_init_root($src_root, resolve_subdir => 1)) { + ERROR "Failed to fetch subvolume detail for '$src_root->{PRINT}'" . ($err ? ": $err" : ""); exit 1; } my $target_root = vinfo($target_url, $config); @@ -3441,7 +3441,7 @@ MAIN: } my %name_uniq; - my @subvol_list = @{vinfo_subvol_list($clone_src_root)}; + my @subvol_list = @{vinfo_subvol_list($src_root)}; my @sorted = sort { ($a->{subtree_depth} <=> $b->{subtree_depth}) || ($a->{SUBVOL_DIR} cmp $b->{SUBVOL_DIR}) } @subvol_list; foreach my $vol (@sorted) { next unless($vol->{node}{readonly}); @@ -3455,34 +3455,34 @@ MAIN: $name_uniq{"$subvol_dir/$snapshot_name"} = 1; my $droot_url = $target_url . ($subvol_dir eq "" ? "" : "/$subvol_dir"); my $sroot_url = $src_url . ($subvol_dir eq "" ? "" : "/$subvol_dir"); - my $config_clone_src = { CONTEXT => "clone_source", - PARENT => $config, - url => $sroot_url, # ABORTED() needs this - snapshot_name => $snapshot_name, - }; - my $config_target = { CONTEXT => "target", - PARENT => $config_clone_src, - target_type => "send-receive", # macro_send_receive checks this - url => $droot_url, # ABORTED() needs this - }; - $config_clone_src->{SUBSECTION} = [ $config_target ]; - push(@{$config->{SUBSECTION}}, $config_clone_src); + my $config_sroot = { CONTEXT => "archive_source", + PARENT => $config, + url => $sroot_url, # ABORTED() needs this + snapshot_name => $snapshot_name, + }; + my $config_droot = { CONTEXT => "target", + PARENT => $config_sroot, + target_type => "send-receive", # macro_send_receive checks this + url => $droot_url, # ABORTED() needs this + }; + $config_sroot->{SUBSECTION} = [ $config_droot ]; + push(@{$config->{SUBSECTION}}, $config_sroot); - my $sroot = vinfo($sroot_url, $config_clone_src); - vinfo_assign_config($sroot, $config_clone_src); + my $sroot = vinfo($sroot_url, $config_sroot); + vinfo_assign_config($sroot, $config_sroot); unless(vinfo_init_root($sroot, resolve_subdir => 1)) { ABORTED($sroot, "Failed to fetch subvolume detail" . ($err ? ": $err" : "")); - WARN "Skipping clone source \"$sroot->{PRINT}\": $abrt"; + WARN "Skipping archive source \"$sroot->{PRINT}\": $abrt"; next; } - my $droot = vinfo($droot_url, $config_target); - vinfo_assign_config($droot, $config_target); + my $droot = vinfo($droot_url, $config_droot); + vinfo_assign_config($droot, $config_droot); unless(vinfo_init_root($droot, resolve_subdir => 1)) { DEBUG("Failed to fetch subvolume detail" . ($err ? ": $err" : "")); unless(system_mkdir($droot)) { ABORTED($droot, "Failed to create directory: $droot->{PRINT}/"); - WARN "Skipping clone target \"$droot->{PRINT}\": $abrt"; + WARN "Skipping archive target \"$droot->{PRINT}\": $abrt"; next; } if($dryrun) { @@ -3494,7 +3494,7 @@ MAIN: # after directory is created, try to init again unless(vinfo_init_root($droot, resolve_subdir => 1)) { ABORTED($droot, "Failed to fetch subvolume detail" . ($err ? ": $err" : "")); - WARN "Skipping clone target \"$droot->{PRINT}\": $abrt"; + WARN "Skipping archive target \"$droot->{PRINT}\": $abrt"; next; } } @@ -3506,11 +3506,11 @@ MAIN: } my $schedule_results = []; - foreach my $sroot (vinfo_subsection($config, 'clone_source')) { + foreach my $sroot (vinfo_subsection($config, 'archive_source')) { foreach my $droot (vinfo_subsection($sroot, 'target')) { my $snapshot_name = config_key($droot, "snapshot_name") // die; INFO "Archiving subvolumes: $sroot->{PRINT}/${snapshot_name}.*"; - macro_clone_target($sroot, $droot, $snapshot_name, { results => $schedule_results }); + macro_archive_target($sroot, $droot, $snapshot_name, { results => $schedule_results }); if(ABORTED($droot)) { # also abort $sroot ABORTED($sroot, "At least one target aborted"); @@ -3536,7 +3536,7 @@ MAIN: # print scheduling results if($print_schedule) { my @data = map { { %$_, vinfo_prefixed_keys("", $_->{value}) }; } @$schedule_results; - print_formatted("schedule", \@data, title => "CLONE SCHEDULE"); + print_formatted("schedule", \@data, title => "ARCHIVE SCHEDULE"); print "\n"; } @@ -3546,7 +3546,7 @@ MAIN: { my @unrecoverable; my @out; - foreach my $sroot (vinfo_subsection($config, 'clone_source')) { + foreach my $sroot (vinfo_subsection($config, 'archive_source')) { foreach my $droot (vinfo_subsection($sroot, 'target', 1)) { my @subvol_out; foreach(@{$droot->{SUBVOL_RECEIVED} // []}) { @@ -3567,7 +3567,7 @@ MAIN: } } - print_header(title => "Clone Summary", + print_header(title => "Archive Summary", time => $start_time, legend => [ "--- deleted subvolume", diff --git a/doc/FAQ.md b/doc/FAQ.md index 97576c1..7a71fb6 100644 --- a/doc/FAQ.md +++ b/doc/FAQ.md @@ -199,7 +199,23 @@ data physically, either to the datacenter or to your safe in the basement. -### Answer 1: Use external storage as "stream-fifo" +### Answer 1: Use "btrbk archive" + +A robust approach is to use external disks as archives (secondary +backups), and regularly run "btrbk archive" on them. As a nice side +effect, this also detects possible read-errors on your backup targets +(Note that a "btrfs scrub" is still more effective for that purpose). + +See **btrbk archive** command in [btrbk(1)] for more details. + +**Note that kernels >=4.1 and <4.4 have a bug when re-sending +subvolumes**, make sure you run a recent/patched kernel or step 3 will +fail. Read +[this thread on gmane](http://thread.gmane.org/gmane.comp.file-systems.btrfs/48798) +(the patch provided is confirmed working on kernels 4.2.x and 4.3.x). + + +### Answer 2: Use external storage as "stream-fifo" This example uses a USB disk as "stream-fifo" for transferring (cloning) of btrfs subvolumes: @@ -217,32 +233,3 @@ This approach has the advantage that you don't need to reformat your USB disk. This works fine, but be aware that you may run into trouble if a single stream gets corrupted, making all subsequent streams unusable. - - -### Answer 2: Clone btrfs subvolumes - -A more robust approach is to use the USB disk as secondary backup. -This has the advantage that possible errors can already be detected by -btrfs on the source side: - -1. Initialize USB disk: - - `mkfs.btrfs /dev/usbX` - -2. For all source subvolumes (in order of generation): - - `btrfs send /source/subvolX -p PARENT | btrfs receive /usbdisk/` - -3. At the target location (in order of generation): - - `btrfs send /usbdisk/subvolX -p PARENT | btrfs receive /target` - -If you simply want to have a clone of the source disk, skip step 3 and -store your USB disk in a safe. You will be able to use it for -restoring backups later, or *as a replacement for your backup disks*. - -**Note that kernels >=4.1 and <4.4 have a bug when re-sending -subvolumes**, make sure you run a recent/patched kernel or step 3 will -fail. Read -[this thread on gmane](http://thread.gmane.org/gmane.comp.file-systems.btrfs/48798) -(the patch provided is confirmed working on kernels 4.2.x and 4.3.x). diff --git a/doc/btrbk.1 b/doc/btrbk.1 index 261fc35..8769369 100644 --- a/doc/btrbk.1 +++ b/doc/btrbk.1 @@ -167,26 +167,27 @@ by the \fBrun\fR command. Use in conjunction with \fI\-l debug\fR to see the btrfs commands that would be executed. .RE .PP -.B clone +.B archive .I *experimental* .RS 4 Recursively copy all subvolumes created by btrbk from to directory, optionally rescheduled using -\fIarchive_preserve_*\fR configuration options. Useful for creating -extra archive copies (clones) from your backup disks. Note that you -can continue using btrbk after swapping your backup disk with the -cloned disk. +\fIarchive_preserve_*\fR configuration options. Also creates directory +tree on (see bugs below). Useful for creating extra archive +copies (clones) from your backup disks. Note that you can continue +using btrbk after swapping your backup disk with the archive disk. .PP Note that this feature needs a \fBlinux kernel >=4.4\fR to work correctly! Kernels >=4.1 and <4.4 have a bug when re-sending -subvolumes (the cloned subvolumes will have incorrect received_uuid, +subvolumes (the archived subvolumes will have incorrect received_uuid, see ), so make sure you run a recent kernel. .PP -Known bugs: On the target filesystem, you have to create all -directories by hand, or "btrbk clone" will complain: "WARNING: -Skipping clone target <...>: Failed to fetch subvolume detail". +Known bugs: If you want to use nested subvolumes on the target +filesystem, you need to create them by hand (e.g. by running "btrfs +subvolume create /dir"). Check the output of --dry-run if +unsure. .RE .PP .B stats