btrbk: cleanup aio extentmap

pull/358/head
Axel Burri 2020-11-08 17:10:48 +01:00
parent dc1b7f1b5c
commit 0719fc415d
1 changed files with 23 additions and 24 deletions

47
btrbk
View File

@ -2358,9 +2358,10 @@ sub filefrag_extentmap($)
sub aio_extentmap($) sub aio_extentmap($)
{ {
my $vol = shift || die; my $vol = shift || die;
my $starttime = time;
INFO("Fetching extent information (IO::AIO) for: $vol->{PRINT}"); INFO("Fetching extent information (IO::AIO) for: $vol->{PRINT}");
my $starttime = time;
# NOTE: this returns exitstatus=0 if file is not found, or no files found # NOTE: this returns exitstatus=0 if file is not found, or no files found
my $ret = run_cmd( cmd => [ 'find', { unsafe => $vol->{PATH} }, '-xdev', '-type', 'f' ], my $ret = run_cmd( cmd => [ 'find', { unsafe => $vol->{PATH} }, '-xdev', '-type', 'f' ],
large_output => 1 ); large_output => 1 );
@ -2369,44 +2370,42 @@ sub aio_extentmap($)
return undef; return undef;
} }
DEBUG("Reading ioctl FIEMAP on all files"); DEBUG("Reading ioctl FIEMAP of " . scalar(@$ret) . " files");
IO::AIO::max_outstanding(512); # < 1024 (max file descriptors) IO::AIO::max_outstanding(128); # < 1024 (max file descriptors)
IO::AIO::max_poll_reqs(32);
# not sure how IO::AIO does its threading, it says we should not care about it (?).
# anyway, it works without "my @range :shared" (from threads::shared).
# Note: aio_fiemap returns byte range (not blocks) # Note: aio_fiemap returns byte range (not blocks)
my @range; my @range;
my $relax = 0;
my $count = 0; my $count = 0;
my $inline = 0;
foreach my $file (@$ret) { foreach my $file (@$ret) {
IO::AIO::aio_open($file, IO::AIO::O_RDONLY(), 0, sub { IO::AIO::aio_open($file, IO::AIO::O_RDONLY(), 0, sub {
my $fh = shift or die "failed to open $file: $!"; return unless($_[0]); # graceful abort on file open errors (check $count below)
#aioreq_pri 4; IO::AIO::aio_fiemap($_[0], 0, undef, 0, undef, sub {
# aio_fiemap $fh, $start, $length, $flags, $count, $cb->(\@extents)
IO::AIO::aio_fiemap($fh, 0, undef, 0, undef, sub {
my $aref = shift; # [$logical, $physical, $length, $flags]
# ignore inline data: for some reason, filefrag reports different size (x 4096 ?)
push @range, map { ($_->[3] & IO::AIO::FIEMAP_EXTENT_DATA_INLINE()) ? () :
[ $_->[1], $_->[1] + $_->[2] - 1 ] } @$aref;
$count++; $count++;
close $fh; foreach(@{$_[0]}) { # [$logical, $physical, $length, $flags]
if($_->[3] & IO::AIO::FIEMAP_EXTENT_DATA_INLINE() ) {
# ignore inline data: for some reason, filefrag reports different size (x 4096 ?)
$inline++;
next;
}
push @range, [ $_->[1], $_->[1] + $_->[2] - 1 ];
}
}); });
}); });
# the above eats up all our filedescriptors, relax every now and then # poll, or the above eats up all our filedescriptors
$relax++; IO::AIO::poll_cb(); # takes "max_outstanding" and "max_poll_reqs" settings
if($relax > 256) { #TRACE "aio_fiemap: processed $ret : $count files (inline=$inline), " . scalar(@range) . " regions" if($loglevel >= 4);
# poll_cb is slow, no need to call it every time
IO::AIO::poll_cb(); # max_outstanding is only unsed if poll_cb is called
TRACE "aio_fiemap: processed $count files, " . scalar(@range) . " regions" if($loglevel >= 4);
$relax = 0;
}
} }
IO::AIO::flush(); IO::AIO::flush();
DEBUG("parsed FIEMAP of $count files: " . scalar(@range) . " regions in " . (time - $starttime) . "s for: $vol->{PRINT}"); WARN "Failed to open $count / " . scalar(@$ret) . " files" if($count != scalar(@$ret));
DEBUG("Parsed " . scalar(@range) . " regions for $count files in " . (time - $starttime) . "s for: $vol->{PRINT}");
DEBUG("Ignored $inline \"inline\" extents for: $vol->{PRINT}") if($inline);
return extentmap_merge(\@range); return extentmap_merge(\@range);
} }