| #! /bin/bash |
| # SPDX-License-Identifier: GPL-2.0 |
| # Copyright (c) 2020 Red Hat, Inc. All Rights Reserved. |
| # |
| # FS QA Test 612 |
| # |
| # Regression test for reflink corruption present as of: |
| # 78f0cc9d55cb "xfs: don't use delalloc extents for COW on files with extsize hints" |
| # and (inadvertently) fixed as of: |
| # 36adcbace24e "xfs: fill out the srcmap in iomap_begin" |
| # upstream, and in the 5.4 stable tree with: |
| # aee38af574a1 "xfs: trim IO to found COW extent limit" |
| # |
| . ./common/preamble |
| _begin_fstest auto quick clone |
| |
| # Import common functions. |
| . ./common/filter |
| . ./common/reflink |
| |
| # real QA test starts here |
| |
| # Modify as appropriate. |
| _supported_fs generic |
| _require_test |
| _require_test_reflink |
| |
| DIR=$TEST_DIR/dir.$seq |
| mkdir -p $DIR |
| rm -f $DIR/a $DIR/b |
| |
| # This test essentially creates an existing COW extent which |
| # covers the first 1M, and then does another IO that overlaps it, |
| # but extends beyond it. The bug was that we did not trim the |
| # new IO to the end of the existing COW extent, and so the IO |
| # extended past the COW blocks and corrupted the reflinked files(s). |
| |
| # Make all files w/ 1m hints; create original 2m file |
| $XFS_IO_PROG -c "extsize 1048576" $DIR >/dev/null 2>&1 |
| $XFS_IO_PROG -c "cowextsize 1048576" $DIR >/dev/null 2>&1 |
| |
| echo "Create file b" |
| $XFS_IO_PROG -f -c "pwrite -S 0x0 0 2m" -c fsync $DIR/b | _filter_xfs_io |
| |
| # Make a reflinked copy |
| echo "Reflink copy from b to a" |
| cp --reflink=always $DIR/b $DIR/a |
| |
| echo "Contents of b" |
| _hexdump $DIR/b |
| |
| # Cycle mount to get stuff out of cache |
| _test_cycle_mount |
| |
| # Create a 1m-hinted IO at offset 0, then |
| # do another IO that overlaps but extends past the 1m hint |
| echo "Write to a" |
| $XFS_IO_PROG -c "pwrite -S 0xa 0k -b 4k 4k" \ |
| -c "pwrite -S 0xa 4k -b 1m 1m" \ |
| $DIR/a | _filter_xfs_io |
| |
| $XFS_IO_PROG -c fsync $DIR/a |
| |
| echo "Contents of b now:" |
| _hexdump $DIR/b |
| |
| # success, all done |
| status=0 |
| exit |