btrfs: add test for cases when a dio write has to fallback to a buffered write
authorFilipe Manana <fdmanana@suse.com>
Tue, 16 Mar 2021 12:22:15 +0000 (12:22 +0000)
committerEryu Guan <guaneryu@gmail.com>
Wed, 17 Mar 2021 17:40:01 +0000 (01:40 +0800)
Test cases where a direct IO write, with O_DSYNC, can not be done and has
to fallback to a buffered write.

This is motivated by the fact we don't have existing tests for these cases
and in fact we had a regression for one case in the 5.10 kernel. This was
the case when doing a direct IO write, with O_DSYNC, against a file offset
that is not aligned to the filesystem's block size, which resulted in
triggering an assertion failure when btrfs is built with assertions enabled
(CONFIG_BTRFS_ASSERT=y). One openSUSE Tumbleweed user hit this frequently
when using Docker and DB2.

The kernel commit in 5.10 that introduced the regression was commit
0eb79294dbe328 ("btrfs: dio iomap DSYNC workaround")). In kernel 5.11 the
regression fixed, by pure chance, by commit ecfdc08b8cc65d ("btrfs: remove
dio iomap DSYNC workaround"). Since the commit that fixed the bug in 5.11
was dependent on a large patchset, a special and simple fix was added to
the stable kernel 5.10.18 by commit a6703c71153438 ("btrfs: fix crash after
non-aligned direct IO write with O_DSYNC").

Signed-off-by: Filipe Manana <fdmanana@suse.com>
Reviewed-by: Eryu Guan <guaneryu@gmail.com>
Signed-off-by: Eryu Guan <guaneryu@gmail.com>
tests/btrfs/234 [new file with mode: 0755]
tests/btrfs/234.out [new file with mode: 0644]
tests/btrfs/group

diff --git a/tests/btrfs/234 b/tests/btrfs/234
new file mode 100755 (executable)
index 0000000..df64e54
--- /dev/null
@@ -0,0 +1,64 @@
+#! /bin/bash
+# SPDX-License-Identifier: GPL-2.0
+# Copyright (C) 2021 SUSE Linux Products GmbH. All Rights Reserved.
+#
+# FS QA Test No. btrfs/234
+#
+# Test cases where a direct IO write, with O_DSYNC, can not be done and has to
+# fallback to a buffered write.
+#
+seq=`basename $0`
+seqres=$RESULT_DIR/$seq
+echo "QA output created by $seq"
+
+tmp=/tmp/$$
+status=1       # failure is the default!
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+_cleanup()
+{
+       cd /
+       rm -f $tmp.*
+}
+
+# get standard environment, filters and checks
+. ./common/rc
+. ./common/filter
+. ./common/attr
+
+# real QA test starts here
+_supported_fs btrfs
+_require_scratch
+_require_odirect
+_require_chattr c
+
+rm -f $seqres.full
+
+_scratch_mkfs >>$seqres.full 2>&1
+_scratch_mount
+
+# Create a test file with compression enabled (chattr +c).
+touch $SCRATCH_MNT/foo
+$CHATTR_PROG +c $SCRATCH_MNT/foo
+
+# Now do a buffered write to create compressed extents.
+$XFS_IO_PROG -s -c "pwrite -S 0xab -b 1M 0 1M" $SCRATCH_MNT/foo | _filter_xfs_io
+
+# Now do the direct IO write with O_DSYNC into a file range that contains
+# compressed extents. It should fallback to buffered IO and succeed.
+$XFS_IO_PROG -d -s -c "pwrite -S 0xcd 512K 512K" $SCRATCH_MNT/foo | _filter_xfs_io
+
+# Now try doing a direct IO write, with O_DSYNC, for a range that starts with
+# non-aligned offset. It should also fallback to buffered IO and succeed.
+$XFS_IO_PROG -f -d -s -c "pwrite -S 0xef 1111 512K" $SCRATCH_MNT/bar | _filter_xfs_io
+
+# Unmount, mount again, and verify we have the expected data.
+_scratch_cycle_mount
+
+echo "File foo data:"
+od -A d -t x1 $SCRATCH_MNT/foo
+echo "File bar data:"
+od -A d -t x1 $SCRATCH_MNT/bar
+
+status=0
+exit
diff --git a/tests/btrfs/234.out b/tests/btrfs/234.out
new file mode 100644 (file)
index 0000000..4504a19
--- /dev/null
@@ -0,0 +1,21 @@
+QA output created by 234
+wrote 1048576/1048576 bytes at offset 0
+XXX Bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 524288/524288 bytes at offset 524288
+XXX Bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 524288/524288 bytes at offset 1111
+XXX Bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+File foo data:
+0000000 ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab
+*
+0524288 cd cd cd cd cd cd cd cd cd cd cd cd cd cd cd cd
+*
+1048576
+File bar data:
+0000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+*
+0001104 00 00 00 00 00 00 00 ef ef ef ef ef ef ef ef ef
+0001120 ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef
+*
+0525392 ef ef ef ef ef ef ef
+0525399
index 5214dbdb0db7c24a7dc2989843db23b500ed667b..6d0c70c0a1347221413121e81417af3aa10ca3ed 100644 (file)
 231 auto quick clone log replay
 232 auto quick qgroup limit
 233 auto quick subvolume
 231 auto quick clone log replay
 232 auto quick qgroup limit
 233 auto quick subvolume
+234 auto quick compress rw