|  | #! /bin/bash | 
|  | # SPDX-License-Identifier: GPL-2.0 | 
|  | # Copyright (C) 2015 SUSE Linux Products GmbH. All Rights Reserved. | 
|  | # | 
|  | # FSQA Test No. 098 | 
|  | # | 
|  | # Test that after truncating a file into the middle of a hole causes the new | 
|  | # size of the file to be persisted after a clean unmount of the filesystem (or | 
|  | # after the inode is evicted). This is for the case where all the data following | 
|  | # the hole is not yet durably persisted, that is, that data is only present in | 
|  | # the page cache. | 
|  | # | 
|  | # This test is motivated by an issue found in btrfs. | 
|  | # | 
|  | . ./common/preamble | 
|  | _begin_fstest auto quick metadata | 
|  |  | 
|  | # Import common functions. | 
|  | . ./common/filter | 
|  |  | 
|  | _require_scratch | 
|  |  | 
|  | # This test was motivated by an issue found in btrfs when the btrfs no-holes | 
|  | # feature is enabled (introduced in kernel 3.14). So enable the feature if the | 
|  | # fs being tested is btrfs. | 
|  | if [ $FSTYP == "btrfs" ]; then | 
|  | _require_btrfs_fs_feature "no_holes" | 
|  | _require_btrfs_mkfs_feature "no-holes" | 
|  | MKFS_OPTIONS="$MKFS_OPTIONS -O no-holes" | 
|  | fi | 
|  |  | 
|  | _scratch_mkfs >>$seqres.full 2>&1 | 
|  | _scratch_mount | 
|  |  | 
|  | workout() | 
|  | { | 
|  | local need_sync=$1 | 
|  |  | 
|  | # Create our test file with some data and durably persist it. | 
|  | $XFS_IO_PROG -t -f -c "pwrite -S 0xaa 0 128K" $SCRATCH_MNT/foo | _filter_xfs_io | 
|  | sync | 
|  |  | 
|  | # Append some data to the file, increasing its size, and leave a hole between | 
|  | # the old size and the start offset if the following write. So our file gets | 
|  | # a hole in the range [128Kb, 256Kb[. | 
|  | $XFS_IO_PROG -c "pwrite -S 0xbb 256K 32K" $SCRATCH_MNT/foo | _filter_xfs_io | 
|  |  | 
|  | # This 'sync' is to flush file extent on disk and update on-disk inode size. | 
|  | # This is required to trigger a bug in btrfs truncate where it updates on-disk | 
|  | # inode size incorrectly. | 
|  | if [ $need_sync -eq 1 ]; then | 
|  | sync | 
|  | fi | 
|  |  | 
|  | # Now truncate our file to a smaller size that is in the middle of the hole we | 
|  | # previously created. | 
|  | # If we don't flush dirty page cache above, on most truncate | 
|  | # implementations the data we appended before gets discarded from | 
|  | # memory (with truncate_setsize()) and never ends up being written to | 
|  | # disk. | 
|  | $XFS_IO_PROG -c "truncate 160K" $SCRATCH_MNT/foo | 
|  |  | 
|  | _scratch_cycle_mount | 
|  |  | 
|  | # We expect to see a file with a size of 160Kb, with the first 128Kb of data all | 
|  | # having the value 0xaa and the remaining 32Kb of data all having the value 0x00 | 
|  | echo "File content after remount:" | 
|  | od -t x1 $SCRATCH_MNT/foo | 
|  | } | 
|  |  | 
|  | workout 0 | 
|  | # flush after each write | 
|  | workout 1 | 
|  |  | 
|  | status=0 | 
|  | exit |