From 683e5fbbfef867ff04b376b3d5230976004a6c7a Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Sat, 8 Aug 2020 04:59:48 +0000 Subject: support setting No_COW on Perl <5.22 fileno(DIRHANDLE) only works on Perl 5.22+, so we need to use dirfd(3) ourselves from Inline::C (or rely on chattr(1) being installed). While we're at it, rename `set_nodatacow' to `nodatacow_fd' for consistency with `nodatacow_dir'. --- lib/PublicInbox/Msgmap.pm | 2 +- lib/PublicInbox/NDC_PP.pm | 13 +++++++++---- lib/PublicInbox/Over.pm | 4 ++-- lib/PublicInbox/SearchIdx.pm | 10 ++-------- lib/PublicInbox/Spawn.pm | 21 ++++++++++++++++++--- lib/PublicInbox/Xapcmd.pm | 4 ++-- 6 files changed, 34 insertions(+), 20 deletions(-) (limited to 'lib/PublicInbox') diff --git a/lib/PublicInbox/Msgmap.pm b/lib/PublicInbox/Msgmap.pm index eee8d6ca..e7f7e2c9 100644 --- a/lib/PublicInbox/Msgmap.pm +++ b/lib/PublicInbox/Msgmap.pm @@ -51,7 +51,7 @@ sub new_file { sub tmp_clone { my ($self, $dir) = @_; my ($fh, $fn) = tempfile('msgmap-XXXXXXXX', EXLOCK => 0, DIR => $dir); - PublicInbox::Spawn::set_nodatacow(fileno($fh)); + PublicInbox::Spawn::nodatacow_fd(fileno($fh)); my $tmp; if ($self->{dbh}->can('sqlite_backup_to_dbh')) { $tmp = ref($self)->new_file($fn, 2); diff --git a/lib/PublicInbox/NDC_PP.pm b/lib/PublicInbox/NDC_PP.pm index 0d20030d..10a7ee2a 100644 --- a/lib/PublicInbox/NDC_PP.pm +++ b/lib/PublicInbox/NDC_PP.pm @@ -6,10 +6,8 @@ package PublicInbox::NDC_PP; use strict; use v5.10.1; -sub set_nodatacow ($) { - my ($fd) = @_; - return if $^O ne 'linux'; - defined(my $path = readlink("/proc/self/fd/$fd")) or return; +sub nodatacow_dir ($) { + my ($path) = @_; open my $mh, '<', '/proc/self/mounts' or return; for (grep(/ btrfs /, <$mh>)) { my (undef, $mnt_path, $type) = split(/ /); @@ -26,4 +24,11 @@ sub set_nodatacow ($) { } } +sub nodatacow_fd ($) { + my ($fd) = @_; + return if $^O ne 'linux'; + defined(my $path = readlink("/proc/self/fd/$fd")) or return; + nodatacow_dir($path); +} + 1; diff --git a/lib/PublicInbox/Over.pm b/lib/PublicInbox/Over.pm index 0146414c..2b314882 100644 --- a/lib/PublicInbox/Over.pm +++ b/lib/PublicInbox/Over.pm @@ -20,10 +20,10 @@ sub dbh_new { if ($rw) { require PublicInbox::Spawn; open my $fh, '+>>', $f or die "failed to open $f: $!"; - PublicInbox::Spawn::set_nodatacow(fileno($fh)); + PublicInbox::Spawn::nodatacow_fd(fileno($fh)); my $j = "$f-journal"; open $fh, '+>>', $j or die "failed to open $j: $!"; - PublicInbox::Spawn::set_nodatacow(fileno($fh)); + PublicInbox::Spawn::nodatacow_fd(fileno($fh)); } else { $self->{filename} = $f; # die on stat() below: } diff --git a/lib/PublicInbox/SearchIdx.pm b/lib/PublicInbox/SearchIdx.pm index 01b9f52d..1cf3e66c 100644 --- a/lib/PublicInbox/SearchIdx.pm +++ b/lib/PublicInbox/SearchIdx.pm @@ -18,10 +18,10 @@ use PublicInbox::IdxStack; use Carp qw(croak); use POSIX qw(strftime); use PublicInbox::OverIdx; -use PublicInbox::Spawn qw(spawn); +use PublicInbox::Spawn qw(spawn nodatacow_dir); use PublicInbox::Git qw(git_unquote); use PublicInbox::MsgTime qw(msg_timestamp msg_datestamp); -our @EXPORT_OK = qw(crlf_adjust log2stack is_ancestor check_size nodatacow_dir); +our @EXPORT_OK = qw(crlf_adjust log2stack is_ancestor check_size); my $X = \%PublicInbox::Search::X; my ($DB_CREATE_OR_OPEN, $DB_OPEN); our $DB_NO_SYNC = 0; @@ -109,12 +109,6 @@ sub load_xapian_writable () { 1; } -sub nodatacow_dir ($) { - my ($dir) = @_; - opendir my $dh, $dir or die "opendir($dir): $!\n"; - PublicInbox::Spawn::set_nodatacow(fileno($dh)); -} - sub idx_acquire { my ($self) = @_; my $flag; diff --git a/lib/PublicInbox/Spawn.pm b/lib/PublicInbox/Spawn.pm index 508d43fd..cb16fcf6 100644 --- a/lib/PublicInbox/Spawn.pm +++ b/lib/PublicInbox/Spawn.pm @@ -19,7 +19,7 @@ use strict; use parent qw(Exporter); use Symbol qw(gensym); use PublicInbox::ProcessPipe; -our @EXPORT_OK = qw/which spawn popen_rd/; +our @EXPORT_OK = qw/which spawn popen_rd nodatacow_dir/; our @RLIMITS = qw(RLIMIT_CPU RLIMIT_CORE RLIMIT_DATA); my $vfork_spawn = <<'VFORK_SPAWN'; @@ -159,11 +159,12 @@ my $set_nodatacow = $^O eq 'linux' ? <<'SET_NODATACOW' : ''; #include #include #include +#include #include #include #include -void set_nodatacow(int fd) +void nodatacow_fd(int fd) { struct statfs buf; int val = 0; @@ -185,6 +186,19 @@ void set_nodatacow(int fd) if (ioctl(fd, FS_IOC_SETFLAGS, &val) < 0) fprintf(stderr, "FS_IOC_SET_FLAGS: %s\\n", strerror(errno)); } + +void nodatacow_dir(const char *dir) +{ + DIR *dh = opendir(dir); + int fd; + + if (!dh) croak("opendir(%s): %s", dir, strerror(errno)); + fd = dirfd(dh); + if (fd >= 0) + nodatacow_fd(fd); + /* ENOTSUP probably won't happen under Linux... */ + closedir(dh); +} SET_NODATACOW my $inline_dir = $ENV{PERL_INLINE_DIRECTORY} //= ( @@ -226,7 +240,8 @@ unless (defined $vfork_spawn) { unless ($set_nodatacow) { require PublicInbox::NDC_PP; no warnings 'once'; - *set_nodatacow = \&PublicInbox::NDC_PP::set_nodatacow; + *nodatacow_fd = \&PublicInbox::NDC_PP::nodatacow_fd; + *nodatacow_dir = \&PublicInbox::NDC_PP::nodatacow_dir; } undef $set_nodatacow; undef $vfork_spawn; diff --git a/lib/PublicInbox/Xapcmd.pm b/lib/PublicInbox/Xapcmd.pm index 8423194f..714f6859 100644 --- a/lib/PublicInbox/Xapcmd.pm +++ b/lib/PublicInbox/Xapcmd.pm @@ -3,9 +3,9 @@ package PublicInbox::Xapcmd; use strict; use warnings; -use PublicInbox::Spawn qw(which popen_rd); +use PublicInbox::Spawn qw(which popen_rd nodatacow_dir); use PublicInbox::Over; -use PublicInbox::SearchIdx qw(nodatacow_dir); +use PublicInbox::SearchIdx; use File::Temp 0.19 (); # ->newdir use File::Path qw(remove_tree); use File::Basename qw(dirname); -- cgit v1.2.3-24-ge0c7