diff options
author | Eric Wong <e@80x24.org> | 2022-01-30 21:49:08 +0000 |
---|---|---|
committer | Eric Wong <e@80x24.org> | 2022-01-31 02:04:11 +0000 |
commit | 14fa0abdcc7b6513540e529375e53edd74ce13e8 (patch) | |
tree | 9f0de95629590def3c2dd72df28243faf129014e /lib/PublicInbox/Syscall.pm | |
parent | 6beeb75e5ccddf9f4e8eefc62cbe349972f59917 (diff) | |
download | public-inbox-14fa0abdcc7b6513540e529375e53edd74ce13e8.tar.gz |
btrfs is Linux-only at the moment (and likely to remain that way for practical purposes). So rely on Linux ABI stability and use the `syscall' and `ioctl' perlops rather than relying on Inline::C. Inline::C (and gcc||clang) are monstrous dependencies which we can't expect users to have. This makes supporting new architectures more difficult, but new architectures come along rarely and this reduces the burden for the majority of Linux users on popular architectures (while still avoiding the distribution of pre-built binaries). Link: https://public-inbox.org/meta/YbCPWGaJEkV6eWfo@codewreck.org/
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 |