#! /bin/bash
# SPDX-License-Identifier: GPL-2.0
# Copyright (c) 2025 Oracle.  All Rights Reserved.
#
# FS QA Test No. 768
#
# Validate multi-fsblock atomic write support with or without hw support
#
. ./common/preamble
_begin_fstest auto quick rw atomicwrites

. ./common/atomicwrites

_require_scratch
_require_block_device $SCRATCH_DEV
_require_xfs_io_command "statx" "-r"
_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_DEV >> $seqres.full

_scratch_mkfs >> $seqres.full
_scratch_mount
test "$FSTYP" = "xfs" && _xfs_force_bdev data $SCRATCH_MNT

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