Re: [PATCH v5 3/3] xfs: more multi-block atomic writes tests

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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





[Index of Archives]     [XFS Filesystem Development (older mail)]     [Linux Filesystem Development]     [Linux Audio Users]     [Yosemite Trails]     [Linux Kernel]     [Linux RAID]     [Linux SCSI]


  Powered by Linux