btrfs: add test for cases when a dio write has to fallback to a buffered write

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>
This commit is contained in:
Filipe Manana
2021-03-16 12:22:15 +00:00
committed by Eryu Guan
parent 40f8dc416a
commit 4a2683ce3e
3 changed files with 86 additions and 0 deletions
+64
View File
@@ -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
+21
View File
@@ -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
+1
View File
@@ -236,3 +236,4 @@
231 auto quick clone log replay
232 auto quick qgroup limit
233 auto quick subvolume
234 auto quick compress rw