On Mon, Jun 16, 2025 at 02:52:13PM -0700, Catherine Hoang wrote: > From: "Darrick J. Wong" <djwong@xxxxxxxxxx> > > Add xfs specific tests for realtime volumes and error recovery. > > The first test validates multi-block atomic writes on a realtime file. We > perform basic atomic writes operations within the advertised sizes and ensure > that atomic writes will fail outside of these bounds. The hardware used in this > test is not required to support atomic writes. > > The second test verifies that a large atomic write can complete after a crash. > The error is injected while attempting to free an extent. We ensure that this > error occurs by first creating a heavily fragmented filesystem. After recovery, > we check that the write completes successfully. > > The third test verifies that a large atomic write on a reflinked file can > complete after a crash. We start with two files that share the same data and > inject an error while attempting to perform a write on one of the files. After > recovery, we verify that these files now contain different data, indicating > that the write has succeeded. > > Signed-off-by: "Darrick J. Wong" <djwong@xxxxxxxxxx> > Signed-off-by: Catherine Hoang <catherine.hoang@xxxxxxxxxx> > Reviewed-by: John Garry <john.g.garry@xxxxxxxxxx> > --- Similar review points as patch 2/3, but as cases in this patch are xfs only, so _require_block_device might not be necessary. Thanks, Zorro > tests/xfs/1216 | 68 ++++++++++++++++++++++++++++++++++++++++++++ > tests/xfs/1216.out | 9 ++++++ > tests/xfs/1217 | 71 ++++++++++++++++++++++++++++++++++++++++++++++ > tests/xfs/1217.out | 3 ++ > tests/xfs/1218 | 60 +++++++++++++++++++++++++++++++++++++++ > tests/xfs/1218.out | 15 ++++++++++ > 6 files changed, 226 insertions(+) > create mode 100755 tests/xfs/1216 > create mode 100644 tests/xfs/1216.out > create mode 100755 tests/xfs/1217 > create mode 100644 tests/xfs/1217.out > create mode 100755 tests/xfs/1218 > create mode 100644 tests/xfs/1218.out > > diff --git a/tests/xfs/1216 b/tests/xfs/1216 > new file mode 100755 > index 00000000..694e3a98 > --- /dev/null > +++ b/tests/xfs/1216 > @@ -0,0 +1,68 @@ > +#! /bin/bash > +# SPDX-License-Identifier: GPL-2.0 > +# Copyright (c) 2025 Oracle. All Rights Reserved. > +# > +# FS QA Test 1216 > +# > +# Validate multi-fsblock realtime file atomic write support with or without hw > +# support > +# > +. ./common/preamble > +_begin_fstest auto quick rw atomicwrites > + > +. ./common/atomicwrites > + > +_require_realtime > +_require_scratch > +_require_atomic_write_test_commands > +_require_scratch_write_atomic_multi_fsblock > + > +echo "scratch device atomic write properties" >> $seqres.full > +$XFS_IO_PROG -c "statx -r -m $STATX_WRITE_ATOMIC" $SCRATCH_RTDEV >> $seqres.full > + > +_scratch_mkfs >> $seqres.full > +_scratch_mount > + > +testfile=$SCRATCH_MNT/testfile > +touch $testfile > + > +echo "filesystem atomic write properties" >> $seqres.full > +$XFS_IO_PROG -c "statx -r -m $STATX_WRITE_ATOMIC" $testfile >> $seqres.full > + > +sector_size=$(blockdev --getss $SCRATCH_RTDEV) > +min_awu=$(_get_atomic_write_unit_min $testfile) > +max_awu=$(_get_atomic_write_unit_max $testfile) > + > +$XFS_IO_PROG -f -c "falloc 0 $((max_awu * 2))" -c fsync $testfile > + > +# try outside the advertised sizes > +echo "two EINVAL for unsupported sizes" > +min_i=$((min_awu / 2)) > +_simple_atomic_write $min_i $min_i $testfile -d > +max_i=$((max_awu * 2)) > +_simple_atomic_write $max_i $max_i $testfile -d > + > +# try all of the advertised sizes > +for ((i = min_awu; i <= max_awu; i *= 2)); do > + $XFS_IO_PROG -f -c "falloc 0 $((max_awu * 2))" -c fsync $testfile > + _test_atomic_file_writes $i $testfile > + _simple_atomic_write $i $i $testfile -d > +done > + > +# does not support buffered io > +echo "one EOPNOTSUPP for buffered atomic" > +_simple_atomic_write 0 $min_awu $testfile > + > +# does not support unaligned directio > +echo "one EINVAL for unaligned directio" > +if [ $sector_size -lt $min_awu ]; then > + _simple_atomic_write $sector_size $min_awu $testfile -d > +else > + # not supported, so fake the output > + echo "pwrite: Invalid argument" > +fi > + > +# success, all done > +echo Silence is golden > +status=0 > +exit > diff --git a/tests/xfs/1216.out b/tests/xfs/1216.out > new file mode 100644 > index 00000000..51546082 > --- /dev/null > +++ b/tests/xfs/1216.out > @@ -0,0 +1,9 @@ > +QA output created by 1216 > +two EINVAL for unsupported sizes > +pwrite: Invalid argument > +pwrite: Invalid argument > +one EOPNOTSUPP for buffered atomic > +pwrite: Operation not supported > +one EINVAL for unaligned directio > +pwrite: Invalid argument > +Silence is golden > diff --git a/tests/xfs/1217 b/tests/xfs/1217 > new file mode 100755 > index 00000000..f3f59ae4 > --- /dev/null > +++ b/tests/xfs/1217 > @@ -0,0 +1,71 @@ > +#! /bin/bash > +# SPDX-License-Identifier: GPL-2.0 > +# Copyright (c) 2025 Oracle. All Rights Reserved. > +# > +# FS QA Test 1217 > +# > +# Check that software atomic writes can complete an operation after a crash. > +# > +. ./common/preamble > +_begin_fstest auto quick rw atomicwrites > + > +. ./common/atomicwrites > +. ./common/inject > +. ./common/filter > + > +_require_scratch > +_require_atomic_write_test_commands > +_require_scratch_write_atomic_multi_fsblock > +_require_xfs_io_error_injection "free_extent" > +_require_test_program "punch-alternating" > + > +echo "scratch device atomic write properties" >> $seqres.full > +$XFS_IO_PROG -c "statx -r -m $STATX_WRITE_ATOMIC" $SCRATCH_RTDEV >> $seqres.full > + > +_scratch_mkfs >> $seqres.full > +_scratch_mount > + > +testfile=$SCRATCH_MNT/testfile > +touch $testfile > + > +echo "filesystem atomic write properties" >> $seqres.full > +$XFS_IO_PROG -c "statx -r -m $STATX_WRITE_ATOMIC" $testfile >> $seqres.full > + > +bsize=$(_get_file_block_size $SCRATCH_MNT) > +max_awu=$(_get_atomic_write_unit_max $testfile) > + > +test $max_awu -gt $((bsize * 2)) || \ > + _notrun "max atomic write $max_awu less than 2 fsblocks $bsize" > + > +# Create a fragmented file to force a software fallback > +$XFS_IO_PROG -f -c "pwrite -S 0x58 0 $((max_awu * 2))" $testfile >> $seqres.full > +$XFS_IO_PROG -f -c "pwrite -S 0x58 0 $((max_awu * 2))" $testfile.check >> $seqres.full > +$here/src/punch-alternating $testfile > +$here/src/punch-alternating $testfile.check > +$XFS_IO_PROG -c "pwrite -S 0xcd 0 $max_awu" $testfile.check >> $seqres.full > +$XFS_IO_PROG -c syncfs $SCRATCH_MNT > + > +# inject an error to force crash recovery on the second block > +_scratch_inject_error "free_extent" > +_simple_atomic_write 0 $max_awu $testfile -d >> $seqres.full > + > +# make sure we're shut down > +touch $SCRATCH_MNT/barf 2>&1 | _filter_scratch > + > +# check that recovery worked > +_scratch_cycle_mount > + > +test -e $SCRATCH_MNT/barf && \ > + echo "saw $SCRATCH_MNT/barf that should not exist" > + > +if ! cmp -s $testfile $testfile.check; then > + echo "crash recovery did not work" > + md5sum $testfile > + md5sum $testfile.check > + > + od -tx1 -Ad -c $testfile >> $seqres.full > + od -tx1 -Ad -c $testfile.check >> $seqres.full > +fi > + > +status=0 > +exit > diff --git a/tests/xfs/1217.out b/tests/xfs/1217.out > new file mode 100644 > index 00000000..6e5b22be > --- /dev/null > +++ b/tests/xfs/1217.out > @@ -0,0 +1,3 @@ > +QA output created by 1217 > +pwrite: Input/output error > +touch: cannot touch 'SCRATCH_MNT/barf': Input/output error > diff --git a/tests/xfs/1218 b/tests/xfs/1218 > new file mode 100755 > index 00000000..799519b1 > --- /dev/null > +++ b/tests/xfs/1218 > @@ -0,0 +1,60 @@ > +#! /bin/bash > +# SPDX-License-Identifier: GPL-2.0 > +# Copyright (c) 2025 Oracle. All Rights Reserved. > +# > +# FS QA Test 1218 > +# > +# hardware large atomic writes error inject test > +# > +. ./common/preamble > +_begin_fstest auto rw quick atomicwrites > + > +. ./common/filter > +. ./common/inject > +. ./common/atomicwrites > + > +_require_scratch_write_atomic > +_require_scratch_write_atomic_multi_fsblock > +_require_xfs_io_command pwrite -A > +_require_xfs_io_error_injection "bmap_finish_one" > + > +_scratch_mkfs >> $seqres.full 2>&1 > +_scratch_mount > + > +echo "Create files" > +file1=$SCRATCH_MNT/file1 > +touch $file1 > + > +max_awu=$(_get_atomic_write_unit_max $file1) > +test $max_awu -ge 4096 || _notrun "cannot perform 4k atomic writes" > + > +file2=$SCRATCH_MNT/file2 > +_pwrite_byte 0x66 0 64k $SCRATCH_MNT/file1 >> $seqres.full > +cp --reflink=always $file1 $file2 > + > +echo "Check files" > +md5sum $SCRATCH_MNT/file1 | _filter_scratch > +md5sum $SCRATCH_MNT/file2 | _filter_scratch > + > +echo "Inject error" > +_scratch_inject_error "bmap_finish_one" > + > +echo "Atomic write to a reflinked file" > +$XFS_IO_PROG -dc "pwrite -A -D -V1 -S 0x67 0 4096" $file1 > + > +echo "FS should be shut down, touch will fail" > +touch $SCRATCH_MNT/badfs 2>&1 | _filter_scratch > + > +echo "Remount to replay log" > +_scratch_remount_dump_log >> $seqres.full > + > +echo "Check files" > +md5sum $SCRATCH_MNT/file1 | _filter_scratch > +md5sum $SCRATCH_MNT/file2 | _filter_scratch > + > +echo "FS should be online, touch should succeed" > +touch $SCRATCH_MNT/goodfs 2>&1 | _filter_scratch > + > +# success, all done > +status=0 > +exit > diff --git a/tests/xfs/1218.out b/tests/xfs/1218.out > new file mode 100644 > index 00000000..02800213 > --- /dev/null > +++ b/tests/xfs/1218.out > @@ -0,0 +1,15 @@ > +QA output created by 1218 > +Create files > +Check files > +77e3a730e3c75274c9ce310d7e39f938 SCRATCH_MNT/file1 > +77e3a730e3c75274c9ce310d7e39f938 SCRATCH_MNT/file2 > +Inject error > +Atomic write to a reflinked file > +pwrite: Input/output error > +FS should be shut down, touch will fail > +touch: cannot touch 'SCRATCH_MNT/badfs': Input/output error > +Remount to replay log > +Check files > +0df1f61ed02a7e9bee2b8b7665066ddc SCRATCH_MNT/file1 > +77e3a730e3c75274c9ce310d7e39f938 SCRATCH_MNT/file2 > +FS should be online, touch should succeed > -- > 2.34.1 > >