mirror of https://github.com/digint/btrbk
btrbk: add extentmap_cache (new cache_dir option)
parent
c6375967b8
commit
7facb44833
75
btrbk
75
btrbk
|
@ -144,6 +144,8 @@ my %config_options = (
|
||||||
archive_exclude => { default => undef, accept_file => { wildcards => 1 }, allow_multiple => 1, context => [ "global" ] },
|
archive_exclude => { default => undef, accept_file => { wildcards => 1 }, allow_multiple => 1, context => [ "global" ] },
|
||||||
archive_exclude_older => { default => undef, accept => [ "yes", "no" ] },
|
archive_exclude_older => { default => undef, accept => [ "yes", "no" ] },
|
||||||
|
|
||||||
|
cache_dir => { default => undef, accept_file => { absolute => 1 }, allow_multiple => 1, context => [ "global" ] },
|
||||||
|
|
||||||
# deprecated options
|
# deprecated options
|
||||||
ssh_port => { default => "default", accept => [ "default" ], accept_numeric => 1,
|
ssh_port => { default => "default", accept => [ "default" ], accept_numeric => 1,
|
||||||
deprecated => { DEFAULT => { warn => 'Please use "ssh://hostname[:port]" notation in the "volume" and "target" configuration lines.' } } },
|
deprecated => { DEFAULT => { warn => 'Please use "ssh://hostname[:port]" notation in the "volume" and "target" configuration lines.' } } },
|
||||||
|
@ -2257,6 +2259,68 @@ sub system_urandom($;$) {
|
||||||
die "unsupported format";
|
die "unsupported format";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub read_extentmap_cache($)
|
||||||
|
{
|
||||||
|
my $vol = shift;
|
||||||
|
my $cache_dir = config_key($vol, 'cache_dir');
|
||||||
|
return undef unless($cache_dir);
|
||||||
|
my $uuid = $vol->{node}{uuid} // die;
|
||||||
|
foreach (@$cache_dir) {
|
||||||
|
my $file = "$_/${uuid}.extentmap.bin";
|
||||||
|
next unless (-f $file);
|
||||||
|
|
||||||
|
DEBUG "Reading extentmap cache: $file";
|
||||||
|
if(open(my $fh, '<:raw', $file)) {
|
||||||
|
my @range;
|
||||||
|
my $buf;
|
||||||
|
read($fh, $buf, 24 + 8 * 3); # read header
|
||||||
|
my ($v, $gen, $time, $blocksize) = unpack('a24Q<Q<Q<', $buf);
|
||||||
|
unless(($v =~ /^btrbk_extentmap_v1/) && $gen && $time && $blocksize) {
|
||||||
|
ERROR "Ambigous cache file: $file";
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
if($gen != $vol->{node}{gen}) {
|
||||||
|
INFO "Subvolume generation has changed (cache=$gen, subvol=$vol->{node}{gen}), ignoring cache: $file";
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
while(read $fh, $buf, 8 * 2) { # read / unpack two words
|
||||||
|
push @range, [ unpack('Q<Q<', $buf) ];
|
||||||
|
#TRACE "read_extentmap_cache: range " . join("..", @{$range[-1]});
|
||||||
|
};
|
||||||
|
DEBUG "Read " . scalar(@range) . " block regions (blocksize=$blocksize, timestamp='" . localtime($time) . "') from: $file";
|
||||||
|
return { blocksize => $blocksize, rmap => \@range, CACHED => $file };
|
||||||
|
} else {
|
||||||
|
ERROR "Failed to open '$file': $!";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return undef;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub write_extentmap_cache($)
|
||||||
|
{
|
||||||
|
my $vol = shift;
|
||||||
|
my $extmap = $vol->{EXTENTMAP};
|
||||||
|
my $cache_dir = config_key($vol, 'cache_dir');
|
||||||
|
return undef unless($extmap && $cache_dir);
|
||||||
|
my $uuid = $vol->{node}{uuid} // die;
|
||||||
|
foreach (@$cache_dir) {
|
||||||
|
unless(-d $_) {
|
||||||
|
WARN_ONCE "Ignoring cache_dir (not a directory): $_";
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
my $file = "$_/${uuid}.extentmap.bin";
|
||||||
|
|
||||||
|
INFO "Writing extentmap cache: $file";
|
||||||
|
if(open(my $fh, '>:raw', $file)) {
|
||||||
|
# pack Q: unsigned quad (64bit, Documentation/filesystems/fiemap.txt)
|
||||||
|
print $fh pack('a24Q<Q<Q<', "btrbk_extentmap_v1", $vol->{node}{gen}, time, $extmap->{blocksize});
|
||||||
|
print $fh pack('Q<*', map(@{$_}, @{$extmap->{rmap}}));
|
||||||
|
close($fh);
|
||||||
|
} else {
|
||||||
|
ERROR "Failed to create '$file': $!";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
# returns extents range (sorted array of [start,end], inclusive) from FIEMAP ioctl
|
# returns extents range (sorted array of [start,end], inclusive) from FIEMAP ioctl
|
||||||
sub filefrag_extentmap($)
|
sub filefrag_extentmap($)
|
||||||
|
@ -5619,7 +5683,16 @@ MAIN:
|
||||||
($a->{node}{readonly} ? $a->{node}{cgen} : $a->{node}{gen}) }
|
($a->{node}{readonly} ? $a->{node}{cgen} : $a->{node}{gen}) }
|
||||||
@resolved_vol) {
|
@resolved_vol) {
|
||||||
next if($prev_vol && ($prev_vol->{node}{id} == $_->{node}{id})); # skip duplicates
|
next if($prev_vol && ($prev_vol->{node}{id} == $_->{node}{id})); # skip duplicates
|
||||||
$_->{EXTENTMAP} = filefrag_extentmap($_);
|
|
||||||
|
# read extents map
|
||||||
|
if($_->{EXTENTMAP} = read_extentmap_cache($_)) {
|
||||||
|
INFO "Using cached extents map for: $_->{PRINT}";
|
||||||
|
} else {
|
||||||
|
$_->{EXTENTMAP} = filefrag_extentmap($_);
|
||||||
|
write_extentmap_cache($_);
|
||||||
|
}
|
||||||
|
next unless($_->{EXTENTMAP});
|
||||||
|
|
||||||
if($prev_vol) {
|
if($prev_vol) {
|
||||||
my $diff_map = extentmap_diff($prev_vol->{EXTENTMAP}, $_->{EXTENTMAP});
|
my $diff_map = extentmap_diff($prev_vol->{EXTENTMAP}, $_->{EXTENTMAP});
|
||||||
|
|
||||||
|
|
|
@ -410,6 +410,8 @@ If you want to set this option for regular (non-root) user only, set
|
||||||
can set *compat_local* or *compat_remote*
|
can set *compat_local* or *compat_remote*
|
||||||
(e.g. "compat_remote busybox").
|
(e.g. "compat_remote busybox").
|
||||||
|
|
||||||
|
*cache_dir* <file>|no _*experimental*_::
|
||||||
|
If set, cache extent maps for the 'extents-diff' command.
|
||||||
|
|
||||||
=== Btrfs Specific Options
|
=== Btrfs Specific Options
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue