btrfs: make sure btrfs can handle full fs trim correctly
[xfstests-dev.git] / tests / btrfs / 156
1 #! /bin/bash
2 # FS QA Test 156
3 #
4 # Check if btrfs can correctly trim free space in block groups
5 #
6 # An ancient regression prevent btrfs from trimming free space inside
7 # existing block groups, if bytenr of block group starts beyond
8 # btrfs_super_block->total_bytes.
9 # However all bytenr in btrfs is in btrfs logical address space,
10 # where any bytenr in range [0, U64_MAX] is valid.
11 #
12 # Fixed by patch named "btrfs: Ensure btrfs_trim_fs can trim the whole fs".
13 #
14 #-----------------------------------------------------------------------
15 # Copyright (c) 2017 SUSE Linux Products GmbH.  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
51 # remove previous $seqres.full before test
52 rm -f $seqres.full
53
54 # real QA test starts here
55
56 # Modify as appropriate.
57 _supported_fs btrfs
58 _supported_os Linux
59 _require_scratch
60 _require_fstrim
61
62 # 1024fs size
63 fs_size=$((1024 * 1024 * 1024))
64
65 # Use small files to fill half of the fs
66 file_size=$(( 1024 * 1024 ))
67 nr_files=$(( $fs_size / $file_size / 2))
68
69 # Force to use single data and meta profile.
70 # Since the test relies on fstrim output, which will differ for different
71 # profiles
72 _scratch_mkfs -b $fs_size -m single -d single > /dev/null
73 _scratch_mount
74
75 _require_batched_discard "$SCRATCH_MNT"
76
77 for n in $(seq -w 0 $(( $nr_files - 1))); do
78         $XFS_IO_PROG -f -c "pwrite 0 $file_size" "$SCRATCH_MNT/file_$n" \
79                 > /dev/null
80 done
81
82 # Flush all buffer data into disk, to trigger chunk allocation
83 sync
84
85 # Now we have take at least 50% of the filesystem, relocate all chunks twice
86 # so all chunks will start after 1G in logical space.
87 # (Btrfs chunk allocation will not rewind to reuse lower space)
88 _run_btrfs_util_prog balance start --full-balance "$SCRATCH_MNT"
89
90 # To avoid possible false ENOSPC alert on v4.15-rc1, seems to be a
91 # reserved space related bug (maybe related to outstanding space rework?),
92 # but that's another story.
93 sync
94
95 _run_btrfs_util_prog balance start --full-balance "$SCRATCH_MNT"
96
97 # Now remove half of the files to make some holes for later trim.
98 # While still keep the chunk space fragmented, so no chunk will be freed
99 rm $SCRATCH_MNT/file_*[13579] -f
100
101 # Make sure space is freed
102 sync
103
104 trimmed=$($FSTRIM_PROG -v "$SCRATCH_MNT" | _filter_fstrim)
105 echo "Trimmed=$trimmed total_size=$fs_size ratio=$(($trimmed * 100 / $fs_size))%" \
106         >> $seqres.full
107
108 # For correct full fs trim, both unallocated space (less than 50%)
109 # and free space in existing block groups (about 25%) should be trimmed.
110 # If less than 50% is trimmed, then only unallocated space is trimmed.
111 # BTW, without fix only 31% can be trimmed, while after fix it's 64%.
112 if [ $trimmed -lt $(( $fs_size / 2)) ]; then
113         echo "Free space in block groups not trimmed"
114         echo "Trimmed=$trimmed total_size=$fs_size ratio=$(($trimmed * 100 / $fs_size))%"
115 fi
116
117 echo "Silence is golden"
118 # success, all done
119 status=0
120 exit