| #! /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/rc | 
 | . ./common/filter | 
 | . ./common/dmflakey | 
 |  | 
 | # real QA test starts here | 
 |  | 
 | _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 |