#! /bin/bash
# SPDX-License-Identifier: GPL-2.0
# Copyright (c) 2025 Oracle.  All Rights Reserved.
#
# FS QA Test No. 839
#
# 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_xfs_io_command "statx" "-r"
_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
