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> --- 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