| #! /bin/bash |
| # SPDX-License-Identifier: GPL-2.0 |
| # Copyright (c) 2018 Red Hat, Inc. All Rights Reserved. |
| # |
| # FS QA Test 443 |
| # |
| # Regression test for the XFS rmapbt based extent swap algorithm. The extent |
| # swap algorithm for rmapbt=1 filesystems unmaps/remaps individual extents to |
| # rectify the rmapbt for each extent swapped between inodes. If one of the |
| # inodes happens to straddle the extent <-> btree format boundary (which can |
| # vary depending on inode size), the unmap/remap sequence can bounce the inodes |
| # back and forth between formats many times during the swap. Since extent -> |
| # btree format conversion requires a block allocation, this can consume more |
| # blocks than expected, lead to block reservation overrun and free space |
| # accounting inconsistency. |
| # |
| seq=`basename $0` |
| seqres=$RESULT_DIR/$seq |
| echo "QA output created by $seq" |
| |
| here=`pwd` |
| tmp=/tmp/$$ |
| status=1 # failure is the default! |
| trap "_cleanup; exit \$status" 0 1 2 3 15 |
| |
| _cleanup() |
| { |
| cd / |
| rm -f $tmp.* |
| } |
| |
| # get standard environment, filters and checks |
| . ./common/rc |
| . ./common/filter |
| . ./common/punch |
| |
| # remove previous $seqres.full before test |
| rm -f $seqres.full |
| |
| # real QA test starts here |
| |
| # Modify as appropriate. |
| _supported_fs generic |
| _require_scratch |
| _require_test_program "punch-alternating" |
| _require_xfs_io_command "falloc" |
| _require_xfs_io_command "fpunch" |
| _require_xfs_io_command "swapext" |
| |
| _scratch_mkfs | _filter_mkfs >> $seqres.full 2> $tmp.mkfs |
| _scratch_mount |
| |
| # get fs block size |
| . $tmp.mkfs |
| |
| file1=$SCRATCH_MNT/file1 |
| file2=$SCRATCH_MNT/file2 |
| |
| # The goal is run an extent swap where one of the associated files has the |
| # minimum number of extents to remain in btree format. First, create a couple |
| # files with large enough extent counts (200 or so should be plenty) to ensure |
| # btree format on the largest possible inode size filesystems. |
| $XFS_IO_PROG -fc "falloc 0 $((400 * dbsize))" $file1 |
| $here/src/punch-alternating $file1 |
| $XFS_IO_PROG -fc "falloc 0 $((400 * dbsize))" $file2 |
| $here/src/punch-alternating $file2 |
| |
| # Now run an extent swap at every possible extent count down to 0. Depending on |
| # inode size, one of these swaps will cover the boundary case between extent and |
| # btree format. |
| for i in $(seq 1 2 399); do |
| # punch one extent from the tmpfile and swap |
| $XFS_IO_PROG -c "fpunch $((i * dbsize)) $dbsize" $file2 |
| $XFS_IO_PROG -c "swapext $file2" $file1 |
| |
| # punch the same extent from the old fork (now in file2) to resync the |
| # extent counts and repeat |
| $XFS_IO_PROG -c "fpunch $((i * dbsize)) $dbsize" $file2 |
| done |
| |
| # sanity check that no extents are left over |
| $XFS_IO_PROG -c "fiemap" $file1 | _filter_fiemap |
| $XFS_IO_PROG -c "fiemap" $file2 | _filter_fiemap |
| |
| # failure results in fs corruption and possible assert failure |
| echo Silence is golden |
| |
| # success, all done |
| status=0 |
| exit |