#! /bin/bash
# SPDX-License-Identifier: GPL-2.0
# Copyright (c) 2025 Chao Yu.  All Rights Reserved.
#
# FS QA Test No. f2fs/013
#
# This is a regression testcase to check whether we will handle database
# inode dirty status correctly:
# 1. mount f2fs image w/ timeout fault injection option
# 2. create a regular file, and write data into the file
# 3. start transaction on the file (via F2FS_IOC_START_ATOMIC_WRITE)
# 4. write transaction data to the file
# 5. commit and end the transaction (via F2FS_IOC_COMMIT_ATOMIC_WRITE)
# 6. meanwhile loop call fsync in parallel
# Before f098aeba04c9 ("f2fs: fix to avoid atomicity corruption of atomic
# file"), database file may become corrupted after atomic write while
# there is concurrent dirty inode flush in background.
#
. ./common/preamble
_begin_fstest auto quick
_require_kernel_config CONFIG_F2FS_FAULT_INJECTION
_require_command "$F2FS_IO_PROG" f2fs_io

_cleanup()
{
	[ -n "$atomic_write_pid" ] && kill -9 $atomic_write_pid
	wait
	cd /
	rm -r -f $tmp.*
}

_fixed_by_kernel_commit f098aeba04c9 \
	"f2fs: fix to avoid atomicity corruption of atomic file"

_require_scratch

_scratch_mkfs >> $seqres.full
# note that it relies on FAULT_TIMEOUT fault injection support in f2fs
_scratch_mount "-o fault_injection=1,fault_type=4194304" >> $seqres.full

dbfile=$SCRATCH_MNT/file.db

# initialize database file
$XFS_IO_PROG -c "pwrite 0 4k" -c "fsync" -f $dbfile >> $seqres.full

# sync filesystem to clear dirty inode
sync

# start atomic_write on src.db database file and commit transaction
$F2FS_IO_PROG write 1 0 2 zero atomic_commit $dbfile >> $seqres.full &
atomic_write_pid=$!

# call fsync to flush dirty inode of database file in parallel
for ((j=0;j<1000;j++)) do
	$F2FS_IO_PROG fsync $dbfile >> $seqres.full
done

wait $atomic_write_pid
unset atomic_write_pid

# flush dirty data and drop cache
sync
echo 3 > /proc/sys/vm/drop_caches

stat $dbfile -c %s

rm $dbfile
sync

status=0
exit
