#! /bin/bash # SPDX-License-Identifier: GPL-2.0 # Copyright (c) 2021 SUSE Linux Products GmbH. All Rights Reserved. # # FS QA Test 243 # # Test that if we explicitly fsync a file that was previously renamed and its # size was increased through a truncate operation, after a power failure the # file has the size set by truncate operation. In between the truncation and # the fsync, there was a rename of another file in the same directory and that # file was also fsynced before we fsynced the file that was truncated. # . ./common/preamble _begin_fstest auto quick log _cleanup() { _cleanup_flakey cd / rm -r -f $tmp.* } . ./common/filter . ./common/dmflakey _supported_fs btrfs _require_scratch _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 files. touch $SCRATCH_MNT/foo $XFS_IO_PROG -f -c "pwrite -S 0xab 0 1M" $SCRATCH_MNT/bar | _filter_xfs_io # Make them durably persisted. sync # Fsync bar, this will be a noop since the file has not yet been modified in # the current transaction. The goal here is to clear BTRFS_INODE_NEEDS_FULL_SYNC # from the inode's runtime flags. $XFS_IO_PROG -c "fsync" $SCRATCH_MNT/bar # Now rename both files, without changing their parent directory. mv $SCRATCH_MNT/bar $SCRATCH_MNT/bar2 mv $SCRATCH_MNT/foo $SCRATCH_MNT/foo2 # Increase the size of bar2 with a truncate operation. $XFS_IO_PROG -c "truncate 2M" $SCRATCH_MNT/bar2 # Now fsync foo2, this results in logging its parent inode (the root directory), # and logging the parent results in logging the inode of file bar2 (its inode # item and the new name). The inode of file bar2 is logged with an i_size of 0 # bytes since it's logged in LOG_INODE_EXISTS mode, meaning we are only logging # its names (and xattrs if it had any) and the i_size of the inode will not be # changed when the log is replayed. $XFS_IO_PROG -c "fsync" $SCRATCH_MNT/foo2 # Now explicitly fsync bar2. This resulted in doing nothing, not logging the # inode with the new i_size of 2M and the hole from file offset 1M to 2M. # Because the inode did not have the flag BTRFS_INODE_NEEDS_FULL_SYNC set, when # it was logged through the fsync of file foo2, its last_log_commit field was # updated, resulting in this explicit of file bar2 not doing anything. $XFS_IO_PROG -c "fsync" $SCRATCH_MNT/bar2 echo "File bar2 content before power failure:" od -A d -t x1 $SCRATCH_MNT/bar2 # Simulate a power failure and then mount again the filesystem to replay the log # tree. _flakey_drop_and_remount echo "File bar2 content after power failure:" od -A d -t x1 $SCRATCH_MNT/bar2 # While here, also check that the rename of foo to foo2 was durably persisted, # even if it's not the specific regression the test is checking for. [ -f $SCRATCH_MNT/foo2 ] || echo "File name foo2 does not exists" [ -f $SCRATCH_MNT/foo ] && echo "File name foo still exists" _unmount_flakey # success, all done status=0 exit