blob: a99147e2f0773ac18a4eb73f8ab0a03e81116b97 [file] [log] [blame]
#! /bin/bash
# SPDX-License-Identifier: GPL-2.0
# Copyright (C) 2019 SUSE Linux Products GmbH. All Rights Reserved.
#
# FSQA Test No. 552
#
# Check that if we write some data to a file, its inode gets evicted (while its
# parent directory's inode is not evicted due to being in use), then we rename
# the file and fsync it, after a power failure the file data is not lost.
#
seq=`basename $0`
seqres=$RESULT_DIR/$seq
echo "QA output created by $seq"
tmp=/tmp/$$
status=1 # failure is the default!
trap "_cleanup; exit \$status" 0 1 2 3 15
_cleanup()
{
_cleanup_flakey
cd /
rm -f $tmp.*
}
# get standard environment, filters and checks
. ./common/rc
. ./common/filter
. ./common/dmflakey
# real QA test starts here
_supported_fs generic
_require_scratch
_require_odirect
_require_dm_target flakey
rm -f $seqres.full
_scratch_mkfs >>$seqres.full 2>&1
_require_metadata_journaling $SCRATCH_DEV
_init_flakey
_mount_flakey
# Create our test directory with two files in it.
mkdir $SCRATCH_MNT/dir
touch $SCRATCH_MNT/dir/foo
touch $SCRATCH_MNT/dir/bar
# Do a direct IO write into file bar.
# To trigger the bug found in btrfs, doing a buffered write would also work as
# long as writeback completes before the file's inode is evicted (the inode can
# not be evicted while delalloc exists). But since that is hard to trigger from
# a user space test, without resulting in a transaction commit as well, just do
# a direct IO write since it is much simpler.
$XFS_IO_PROG -d -c "pwrite -S 0xd3 0 4K" $SCRATCH_MNT/dir/bar | _filter_xfs_io
# Keep the directory in use while we evict all inodes. This is to prevent
# eviction of the directory's inode (a necessary condition to trigger the bug
# found in btrfs, as evicting the directory inode would result in commiting the
# current transaction when the fsync of file foo happens below).
(
cd $SCRATCH_MNT/dir
while true; do
:
done
) &
pid=$!
# Wait a bit to give time to the background process to chdir to the directory.
sleep 0.1
# Evict all inodes from memory, except the directory's inode because a background
# process is using it.
echo 2 > /proc/sys/vm/drop_caches
# Now fsync our file foo, which ends up persisting information about its parent
# directory inode because it is a new inode.
$XFS_IO_PROG -c "fsync" $SCRATCH_MNT/dir/foo
# Rename our file bar to baz right before we fsync it.
mv $SCRATCH_MNT/dir/bar $SCRATCH_MNT/dir/baz
# Fsync our file baz, after a power failure we expect to see the data we
# previously wrote to it.
$XFS_IO_PROG -c "fsync" $SCRATCH_MNT/dir/baz
# Kill the background process using our test directory.
kill $pid
wait $pid
# Simulate a power failure and then check no data loss happened.
_flakey_drop_and_remount
echo "File data after power failure:"
od -t x1 -A d $SCRATCH_MNT/dir/baz
_unmount_flakey
status=0
exit