]> git.ipfire.org Git - thirdparty/public-inbox.git/commitdiff
nodatacow: warn about CoW being disabled on btrfs
authorEric Wong <e@80x24.org>
Thu, 7 Aug 2025 00:50:05 +0000 (00:50 +0000)
committerEric Wong <e@80x24.org>
Sat, 9 Aug 2025 07:39:20 +0000 (07:39 +0000)
While Xapian and SQLite performance is untenable with CoW on
btrfs, disabling CoW is not without caveats on btrfs.  So warn
users about the possibility of data corruption.

lib/PublicInbox/Syscall.pm
t/nodatacow.t

index a7fa37363ec5e30650f2258de2f3ac1c3b012cac..b1cb4e688fee1558207cb30f94da2f92561ba761 100644 (file)
@@ -435,6 +435,7 @@ sub rename_noreplace ($$) {
        }
 }
 
+# returns "0 but true" on success, undef or
 sub nodatacow_fh ($) {
        my ($fh) = @_;
        my $buf = "\0" x 120;
@@ -453,8 +454,17 @@ sub nodatacow_fh ($) {
                warn("FS_IOC_SETFLAGS: $!\n");
 }
 
-sub nodatacow_dir {
-       if (open my $fh, '<', $_[0]) { nodatacow_fh($fh) }
+sub nodatacow_dir ($) {
+       my ($f) = @_;
+       if (open my $fh, '<', $f) {
+               my $rc = nodatacow_fh($fh); # returns "0 but true" on success
+               $rc && $rc == 0 and warn <<EOM;
+W: Disabling copy-on-write (CoW) on `$f'
+W: to avoid pathological slowdowns.  Data corruption may occur on unclean
+W: shutdowns, especially if using any form of BTRFS RAID.  Periodic defrag
+W: is recommended for *.sqlite3 and *.glass files to maintain performance.
+EOM
+       }
 }
 
 use constant \%CONST;
index 0940d908e935772183fda449be0ff7d6b152e75c..b482a0ec6c5f5aacf754403fd9cb5597666c1763 100644 (file)
@@ -34,9 +34,22 @@ SKIP: {
 
        $name = "$dn/pp.d";
        mkdir($name) or BAIL_OUT "mkdir($name) $!";
-       PublicInbox::Syscall::nodatacow_dir($name);
+
+       {
+               my @w;
+               local $SIG{__WARN__} = sub { push @w, @_ };
+               PublicInbox::Syscall::nodatacow_dir($name);
+               like "@w", qr/^W: Disabling copy-on-write/sm,
+                       'warned about disabling CoW';
+       }
        $res = xqx([$lsattr, '-d', $name]);
        like($res, qr/C.*\Q$name\E/, "`C' attribute set on dir with pure Perl");
+       {
+               my @w;
+               local $SIG{__WARN__} = sub { push @w, @_ };
+               PublicInbox::Syscall::nodatacow_dir($name);
+               is_deeply \@w, [], 'no warnings if CoW already disabled';
+       }
 };
 
 done_testing;