xfs: rmapbt swapext block reservation overrun test
[xfstests-dev.git] / tests / xfs / 443
1 #! /bin/bash
2 # FS QA Test 443
3 #
4 # Regression test for the XFS rmapbt based extent swap algorithm. The extent
5 # swap algorithm for rmapbt=1 filesystems unmaps/remaps individual extents to
6 # rectify the rmapbt for each extent swapped between inodes. If one of the
7 # inodes happens to straddle the extent <-> btree format boundary (which can
8 # vary depending on inode size), the unmap/remap sequence can bounce the inodes
9 # back and forth between formats many times during the swap. Since extent ->
10 # btree format conversion requires a block allocation, this can consume more
11 # blocks than expected, lead to block reservation overrun and free space
12 # accounting inconsistency.
13 #
14 #-----------------------------------------------------------------------
15 # Copyright (c) 2018 Red Hat, Inc.  All Rights Reserved.
16 #
17 # This program is free software; you can redistribute it and/or
18 # modify it under the terms of the GNU General Public License as
19 # published by the Free Software Foundation.
20 #
21 # This program is distributed in the hope that it would be useful,
22 # but WITHOUT ANY WARRANTY; without even the implied warranty of
23 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24 # GNU General Public License for more details.
25 #
26 # You should have received a copy of the GNU General Public License
27 # along with this program; if not, write the Free Software Foundation,
28 # Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
29 #-----------------------------------------------------------------------
30 #
31
32 seq=`basename $0`
33 seqres=$RESULT_DIR/$seq
34 echo "QA output created by $seq"
35
36 here=`pwd`
37 tmp=/tmp/$$
38 status=1        # failure is the default!
39 trap "_cleanup; exit \$status" 0 1 2 3 15
40
41 _cleanup()
42 {
43         cd /
44         rm -f $tmp.*
45 }
46
47 # get standard environment, filters and checks
48 . ./common/rc
49 . ./common/filter
50 . ./common/punch
51
52 # remove previous $seqres.full before test
53 rm -f $seqres.full
54
55 # real QA test starts here
56
57 # Modify as appropriate.
58 _supported_fs generic
59 _supported_os Linux
60 _require_scratch
61 _require_test_program "punch-alternating"
62 _require_xfs_io_command "falloc"
63 _require_xfs_io_command "fpunch"
64 _require_xfs_io_command "swapext"
65
66 _scratch_mkfs | _filter_mkfs >> $seqres.full 2> $tmp.mkfs
67 _scratch_mount || _fail "mount failed"
68
69 # get fs block size
70 . $tmp.mkfs
71
72 file1=$SCRATCH_MNT/file1
73 file2=$SCRATCH_MNT/file2
74
75 # The goal is run an extent swap where one of the associated files has the
76 # minimum number of extents to remain in btree format. First, create a couple
77 # files with large enough extent counts (200 or so should be plenty) to ensure
78 # btree format on the largest possible inode size filesystems.
79 $XFS_IO_PROG -fc "falloc 0 $((400 * dbsize))" $file1
80 ./src/punch-alternating $file1
81 $XFS_IO_PROG -fc "falloc 0 $((400 * dbsize))" $file2
82 ./src/punch-alternating $file2
83
84 # Now run an extent swap at every possible extent count down to 0. Depending on
85 # inode size, one of these swaps will cover the boundary case between extent and
86 # btree format.
87 for i in $(seq 1 2 399); do
88         # punch one extent from the tmpfile and swap
89         $XFS_IO_PROG -c "fpunch $((i * dbsize)) $dbsize" $file2
90         $XFS_IO_PROG -c "swapext $file2" $file1
91
92         # punch the same extent from the old fork (now in file2) to resync the
93         # extent counts and repeat
94         $XFS_IO_PROG -c "fpunch $((i * dbsize)) $dbsize" $file2
95 done
96
97 # sanity check that no extents are left over
98 $XFS_IO_PROG -c "fiemap" $file1 | _filter_fiemap
99 $XFS_IO_PROG -c "fiemap" $file2 | _filter_fiemap
100
101 # failure results in fs corruption and possible assert failure
102 echo Silence is golden
103
104 # success, all done
105 status=0
106 exit