blob: 2a4287bbf997e5a1efaaaa118a67f8cd160d7bf8 [file] [log] [blame]
#! /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