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
+234 auto quick compress rw