diff options
Diffstat (limited to 'lib/PublicInbox/Syscall.pm')
-rw-r--r-- | lib/PublicInbox/Syscall.pm | 46 |
1 files changed, 45 insertions, 1 deletions
diff --git a/lib/PublicInbox/Syscall.pm b/lib/PublicInbox/Syscall.pm index c00385b9..bcfae2cb 100644 --- a/lib/PublicInbox/Syscall.pm +++ b/lib/PublicInbox/Syscall.pm @@ -5,7 +5,7 @@ # This license differs from the rest of public-inbox # # This module is Copyright (c) 2005 Six Apart, Ltd. -# Copyright (C) 2019-2021 all contributors <meta@public-inbox.org> +# Copyright (C) all contributors <meta@public-inbox.org> # # All rights reserved. # @@ -68,6 +68,7 @@ our ( $SYS_renameat2, ); +my $SYS_fstatfs; # don't need fstatfs64, just statfs.f_type my $SFD_CLOEXEC = 02000000; # Perl does not expose O_CLOEXEC our $no_deprecated = 0; @@ -96,18 +97,21 @@ if ($^O eq "linux") { $SYS_epoll_wait = 256; $SYS_signalfd4 = 327; $SYS_renameat2 //= 353; + $SYS_fstatfs = 100; } elsif ($machine eq "x86_64") { $SYS_epoll_create = 213; $SYS_epoll_ctl = 233; $SYS_epoll_wait = 232; $SYS_signalfd4 = 289; $SYS_renameat2 //= 316; + $SYS_fstatfs = 138; } elsif ($machine eq 'x32') { $SYS_epoll_create = 1073742037; $SYS_epoll_ctl = 1073742057; $SYS_epoll_wait = 1073742056; $SYS_signalfd4 = 1073742113; $SYS_renameat2 //= 0x40000000 + 316; + $SYS_fstatfs = 138; } elsif ($machine eq 'sparc64') { $SYS_epoll_create = 193; $SYS_epoll_ctl = 194; @@ -116,6 +120,7 @@ if ($^O eq "linux") { $SYS_signalfd4 = 317; $SYS_renameat2 //= 345; $SFD_CLOEXEC = 020000000; + $SYS_fstatfs = 158; } elsif ($machine =~ m/^parisc/) { $SYS_epoll_create = 224; $SYS_epoll_ctl = 225; @@ -129,6 +134,7 @@ if ($^O eq "linux") { $u64_mod_8 = 1; $SYS_signalfd4 = 313; $SYS_renameat2 //= 357; + $SYS_fstatfs = 100; } elsif ($machine eq "ppc") { $SYS_epoll_create = 236; $SYS_epoll_ctl = 237; @@ -136,6 +142,7 @@ if ($^O eq "linux") { $u64_mod_8 = 1; $SYS_signalfd4 = 313; $SYS_renameat2 //= 357; + $SYS_fstatfs = 100; } elsif ($machine =~ m/^s390/) { $SYS_epoll_create = 249; $SYS_epoll_ctl = 250; @@ -143,6 +150,7 @@ if ($^O eq "linux") { $u64_mod_8 = 1; $SYS_signalfd4 = 322; $SYS_renameat2 //= 347; + $SYS_fstatfs = 100; } elsif ($machine eq "ia64") { $SYS_epoll_create = 1243; $SYS_epoll_ctl = 1244; @@ -165,6 +173,7 @@ if ($^O eq "linux") { $no_deprecated = 1; $SYS_signalfd4 = 74; $SYS_renameat2 //= 276; + $SYS_fstatfs = 44; } elsif ($machine =~ m/arm(v\d+)?.*l/) { # ARM OABI $SYS_epoll_create = 250; @@ -173,6 +182,7 @@ if ($^O eq "linux") { $u64_mod_8 = 1; $SYS_signalfd4 = 355; $SYS_renameat2 //= 382; + $SYS_fstatfs = 100; } elsif ($machine =~ m/^mips64/) { $SYS_epoll_create = 5207; $SYS_epoll_ctl = 5208; @@ -180,6 +190,7 @@ if ($^O eq "linux") { $u64_mod_8 = 1; $SYS_signalfd4 = 5283; $SYS_renameat2 //= 5311; + $SYS_fstatfs = 5135; } elsif ($machine =~ m/^mips/) { $SYS_epoll_create = 4248; $SYS_epoll_ctl = 4249; @@ -187,6 +198,7 @@ if ($^O eq "linux") { $u64_mod_8 = 1; $SYS_signalfd4 = 4324; $SYS_renameat2 //= 4351; + $SYS_fstatfs = 4100; } else { # as a last resort, try using the *.ph files which may not # exist or may be wrong @@ -323,6 +335,38 @@ sub rename_noreplace ($$) { } } +sub nodatacow_fh { + return if !defined($SYS_fstatfs); + my $buf = ''; + vec($buf, 120 * 8 - 1, 1) = 0; + my ($fh) = @_; + syscall($SYS_fstatfs, fileno($fh), $buf) == 0 or + return warn("fstatfs: $!\n"); + my $f_type = unpack('l!', $buf); # statfs.f_type is a signed word + return if $f_type != 0x9123683E; # BTRFS_SUPER_MAGIC + + state ($FS_IOC_GETFLAGS, $FS_IOC_SETFLAGS); + unless (defined $FS_IOC_GETFLAGS) { + if (substr($Config{byteorder}, 0, 4) eq '1234') { + $FS_IOC_GETFLAGS = 0x80086601; + $FS_IOC_SETFLAGS = 0x40086602; + } else { # Big endian + $FS_IOC_GETFLAGS = 0x40086601; + $FS_IOC_SETFLAGS = 0x80086602; + } + } + ioctl($fh, $FS_IOC_GETFLAGS, $buf) // + return warn("FS_IOC_GET_FLAGS: $!\n"); + my $attr = unpack('l!', $buf); + return if ($attr & 0x00800000); # FS_NOCOW_FL; + ioctl($fh, $FS_IOC_SETFLAGS, pack('l', $attr | 0x00800000)) // + warn("FS_IOC_SET_FLAGS: $!\n"); +} + +sub nodatacow_dir { + if (open my $fh, '<', $_[0]) { nodatacow_fh($fh) } +} + 1; =head1 WARRANTY |