#! /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