| #! /bin/bash |
| # SPDX-License-Identifier: GPL-2.0 |
| # Copyright (c) 2025 IBM Corporation. All Rights Reserved. |
| # |
| # FS QA Test No. 775 |
| # |
| # Atomic write multi-fsblock data integrity tests with mixed mappings |
| # and O_SYNC |
| # |
| . ./common/preamble |
| . ./common/atomicwrites |
| _begin_fstest auto quick rw atomicwrites |
| |
| _require_scratch_write_atomic_multi_fsblock |
| _require_atomic_write_test_commands |
| _require_scratch_shutdown |
| _require_xfs_io_command "truncate" |
| |
| _scratch_mkfs >> $seqres.full |
| _scratch_mount >> $seqres.full |
| |
| check_data_integrity() { |
| actual=$(_hexdump $testfile) |
| if [[ "$expected" != "$actual" ]] |
| then |
| echo "Integrity check failed" |
| echo "Integrity check failed" >> $seqres.full |
| echo "# Expected file contents:" >> $seqres.full |
| echo "$expected" >> $seqres.full |
| echo "# Actual file contents:" >> $seqres.full |
| echo "$actual" >> $seqres.full |
| |
| _fail "Data integrity check failed. The atomic write was torn." |
| fi |
| } |
| |
| prep_mixed_mapping() { |
| $XFS_IO_PROG -c "truncate 0" $testfile >> $seqres.full |
| local off=0 |
| local mapping="" |
| |
| local operations=("W" "H" "U") |
| local num_blocks=$((awu_max / blksz)) |
| for ((i=0; i<num_blocks; i++)); do |
| local index=$((RANDOM % ${#operations[@]})) |
| local map="${operations[$index]}" |
| local mapping="${mapping}${map}" |
| |
| case "$map" in |
| "W") |
| $XFS_IO_PROG -dc "pwrite -S 0x61 -b $blksz $off $blksz" $testfile > /dev/null |
| ;; |
| "H") |
| # No operation needed for hole |
| ;; |
| "U") |
| $XFS_IO_PROG -c "falloc $off $blksz" $testfile >> /dev/null |
| ;; |
| esac |
| off=$((off + blksz)) |
| done |
| |
| echo "+ + Mixed mapping prep done. Full mapping pattern: $mapping" >> $seqres.full |
| |
| sync $testfile |
| } |
| |
| verify_atomic_write() { |
| test $bytes_written -eq $awu_max || _fail "atomic write len=$awu_max assertion failed" |
| check_data_integrity |
| } |
| |
| mixed_mapping_test() { |
| prep_mixed_mapping |
| |
| echo -"+ + Performing O_DSYNC atomic write from 0 to $awu_max" >> $seqres.full |
| if [[ "$1" == "shutdown" ]] |
| then |
| bytes_written=$($XFS_IO_PROG -x -dc \ |
| "pwrite -DA -V1 -b $awu_max 0 $awu_max" \ |
| -c "shutdown" $testfile | grep wrote | \ |
| awk -F'[/ ]' '{print $2}') |
| _scratch_cycle_mount >>$seqres.full 2>&1 || _fail "remount failed" |
| else |
| bytes_written=$($XFS_IO_PROG -dc \ |
| "pwrite -DA -V1 -b $awu_max 0 $awu_max" $testfile | \ |
| grep wrote | awk -F'[/ ]' '{print $2}') |
| fi |
| |
| verify_atomic_write |
| } |
| |
| testfile=$SCRATCH_MNT/testfile |
| touch $testfile |
| |
| awu_max=$(_get_atomic_write_unit_max $testfile) |
| blksz=$(_get_block_size $SCRATCH_MNT) |
| |
| # Create an expected pattern to compare with |
| $XFS_IO_PROG -tc "pwrite -b $awu_max 0 $awu_max" $testfile >> $seqres.full |
| expected=$(_hexdump $testfile) |
| echo "# Expected file contents:" >> $seqres.full |
| echo "$expected" >> $seqres.full |
| echo >> $seqres.full |
| |
| echo "# Test 1: Do O_DSYNC atomic write on random mixed mapping:" >> $seqres.full |
| echo >> $seqres.full |
| |
| iterations=10 |
| for ((i=1; i<=$iterations; i++)); do |
| echo "=== Mixed Mapping Test Iteration $i ===" >> $seqres.full |
| |
| echo "+ Testing without shutdown..." >> $seqres.full |
| mixed_mapping_test |
| echo "Passed!" >> $seqres.full |
| |
| echo "+ Testing with sudden shutdown..." >> $seqres.full |
| mixed_mapping_test "shutdown" |
| echo "Passed!" >> $seqres.full |
| |
| echo "Iteration $i completed: OK" >> $seqres.full |
| echo >> $seqres.full |
| done |
| echo "# Test 1: Do O_SYNC atomic write on random mixed mapping ($iterations iterations): OK" >> $seqres.full |
| |
| |
| echo >> $seqres.full |
| echo "# Test 2: Do extending O_SYNC atomic writes: " >> $seqres.full |
| bytes_written=$($XFS_IO_PROG -x -dstc "pwrite -A -V1 -b $awu_max 0 $awu_max" \ |
| -c "shutdown" $testfile | grep wrote | awk -F'[/ ]' '{print $2}') |
| _scratch_cycle_mount >>$seqres.full 2>&1 || _fail "remount failed" |
| verify_atomic_write |
| echo "# Test 2: Do extending O_SYNC atomic writes: OK" >> $seqres.full |
| |
| # success, all done |
| echo "Silence is golden" |
| status=0 |
| exit |