This adds atomic write test using fio based on it's crc check verifier. fio adds a crc header for each data block, which is verified later to ensure there is no data corruption or torn write. This test essentially does a lot of parallel RWF_ATOMIC IO on a preallocated file to stress the write and end-io unwritten conversion code paths. The idea is to increase code coverage to ensure RWF_ATOMIC hasn't introduced any issues. Avoid doing overlapping parallel atomic writes because it might give unexpected results. Use offset_increment=, size= fio options to achieve this behavior. Co-developed-by: Ritesh Harjani (IBM) <ritesh.list@xxxxxxxxx> Signed-off-by: Ritesh Harjani (IBM) <ritesh.list@xxxxxxxxx> Reviewed-by: Darrick J. Wong <djwong@xxxxxxxxxx> Reviewed-by: John Garry <john.g.garry@xxxxxxxxxx> Signed-off-by: Ojaswin Mujoo <ojaswin@xxxxxxxxxxxxx> --- tests/generic/1226 | 108 +++++++++++++++++++++++++++++++++++++++++ tests/generic/1226.out | 2 + 2 files changed, 110 insertions(+) create mode 100755 tests/generic/1226 create mode 100644 tests/generic/1226.out diff --git a/tests/generic/1226 b/tests/generic/1226 new file mode 100755 index 00000000..7ad74554 --- /dev/null +++ b/tests/generic/1226 @@ -0,0 +1,108 @@ +#! /bin/bash +# SPDX-License-Identifier: GPL-2.0 +# Copyright (c) 2025 IBM Corporation. All Rights Reserved. +# +# FS QA Test 1226 +# +# Validate FS atomic write using fio crc check verifier. +# +. ./common/preamble +. ./common/atomicwrites + +_begin_fstest auto aio rw atomicwrites + +_require_scratch_write_atomic +_require_odirect +_require_aio +_require_fio_atomic_writes + +_scratch_mkfs >> $seqres.full 2>&1 +_scratch_mount +_require_xfs_io_command "falloc" + +touch "$SCRATCH_MNT/f1" +awu_min_write=$(_get_atomic_write_unit_min "$SCRATCH_MNT/f1") +awu_max_write=$(_get_atomic_write_unit_max "$SCRATCH_MNT/f1") + +blocksize=$(_max "$awu_min_write" "$((awu_max_write/2))") +threads=$(_min "$(($(nproc) * 2 * LOAD_FACTOR))" "100") +filesize=$((blocksize * threads * 100)) +depth=$threads +io_size=$((filesize / threads)) +io_inc=$io_size +testfile=$SCRATCH_MNT/test-file + +fio_config=$tmp.fio +fio_out=$tmp.fio.out + +fio_aw_config=$tmp.aw.fio +fio_verify_config=$tmp.verify.fio + +function create_fio_configs() +{ + create_fio_aw_config + create_fio_verify_config +} + +function create_fio_verify_config() +{ +cat >$fio_verify_config <<EOF + [verify-job] + direct=1 + ioengine=libaio + rw=read + bs=$blocksize + filename=$testfile + size=$filesize + iodepth=$depth + group_reporting=1 + + verify_only=1 + verify=crc32c + verify_fatal=1 + verify_state_save=0 + verify_write_sequence=0 +EOF +} + +function create_fio_aw_config() +{ +cat >$fio_aw_config <<EOF + [atomicwrite-job] + direct=1 + ioengine=libaio + rw=randwrite + bs=$blocksize + filename=$testfile + size=$io_inc + offset_increment=$io_inc + iodepth=$depth + numjobs=$threads + group_reporting=1 + atomic=1 + + verify_state_save=0 + verify=crc32c + do_verify=0 +EOF +} + +create_fio_configs +_require_fio $fio_aw_config + +cat $fio_aw_config >> $seqres.full +cat $fio_verify_config >> $seqres.full + +$XFS_IO_PROG -fc "falloc 0 $filesize" $testfile >> $seqres.full + +$FIO_PROG $fio_aw_config >> $seqres.full +ret1=$? +$FIO_PROG $fio_verify_config >> $seqres.full +ret2=$? + +[[ $ret1 -eq 0 && $ret2 -eq 0 ]] || _fail "fio with atomic write failed" + +# success, all done +echo Silence is golden +status=0 +exit diff --git a/tests/generic/1226.out b/tests/generic/1226.out new file mode 100644 index 00000000..6dce0ea5 --- /dev/null +++ b/tests/generic/1226.out @@ -0,0 +1,2 @@ +QA output created by 1226 +Silence is golden -- 2.49.0