btrfs: add test for zone auto reclaim
[xfstests-dev.git] / tests / btrfs / 237
1 #! /bin/bash
2 # SPDX-License-Identifier: GPL-2.0
3 # Copyright (c) 2021 Western Digital Corporation.  All Rights Reserved.
4 #
5 # FS QA Test 237
6 #
7 # Test that zone autoreclaim works as expected, that is: if the dirty
8 # threshold is exceeded the data gets relocated to new block group and the
9 # old block group gets deleted. On block group deletion, the underlying device
10 # zone also needs to be reset.
11 #
12 seq=`basename $0`
13 seqres=$RESULT_DIR/$seq
14 echo "QA output created by $seq"
15
16 here=`pwd`
17 tmp=/tmp/$$
18 status=1        # failure is the default!
19 trap "_cleanup; exit \$status" 0 1 2 3 15
20
21 _cleanup()
22 {
23         cd /
24         rm -f $tmp.*
25 }
26
27 # get standard environment, filters and checks
28 . ./common/rc
29 . ./common/filter
30
31 # remove previous $seqres.full before test
32 rm -f $seqres.full
33
34 # real QA test starts here
35
36 _supported_fs btrfs
37 _require_scratch
38 _require_btrfs_command inspect-internal dump-tree
39 _require_btrfs_command filesystem sync
40 _require_command "$BLKZONE_PROG" blkzone
41 _require_zoned_device "$SCRATCH_DEV"
42
43 get_data_bg()
44 {
45         $BTRFS_UTIL_PROG inspect-internal dump-tree -t CHUNK $SCRATCH_DEV |\
46                 grep -A 1 "CHUNK_ITEM" | grep -B 1 "type DATA" |\
47                 grep -Eo "CHUNK_ITEM [[:digit:]]+" | cut -d ' ' -f 2
48 }
49
50 zonesize=$(cat /sys/block/$(_short_dev $SCRATCH_DEV)/queue/chunk_sectors)
51 zonesize=$((zonesize << 9))
52
53 _scratch_mkfs >/dev/null 2>&1
54 _scratch_mount -o commit=1 # 1s commit time to speed up test
55
56 uuid=$(findmnt -n -o UUID "$SCRATCH_MNT")
57 reclaim_threshold=75
58 echo $reclaim_threshold > /sys/fs/btrfs/"$uuid"/bg_reclaim_threshold
59 fill_percent=$((reclaim_threshold + 2))
60 rest_percent=$((90 - fill_percent)) # make sure we're not creating a new BG
61 fill_size=$((zonesize * fill_percent / 100))
62 rest=$((zonesize * rest_percent / 100))
63
64 # step 1, fill FS over $fillsize
65 $XFS_IO_PROG -fc "pwrite 0 $fill_size" $SCRATCH_MNT/$seq.test1 >> $seqres.full
66 $XFS_IO_PROG -fc "pwrite 0 $rest" $SCRATCH_MNT/$seq.test2 >> $seqres.full
67 $BTRFS_UTIL_PROG filesystem sync $SCRATCH_MNT
68
69 zones_before=$($BLKZONE_PROG report $SCRATCH_DEV | grep -v -e em -e nw | wc -l)
70 echo "Before reclaim: $zones_before zones open" >> $seqres.full
71 old_data_zone=$(get_data_bg)
72 old_data_zone=$((old_data_zone >> 9))
73 printf "Old data zone 0x%x\n" $old_data_zone >> $seqres.full
74
75 # step 2, delete the 1st $fill_size sized file to trigger reclaim
76 rm $SCRATCH_MNT/$seq.test1
77 $BTRFS_UTIL_PROG filesystem sync $SCRATCH_MNT
78 sleep 2 # 1 transaction commit for 'rm' and 1 for balance
79
80 # check that we don't have more zones open than before
81 zones_after=$($BLKZONE_PROG report $SCRATCH_DEV | grep -v -e em -e nw | wc -l)
82 echo "After reclaim: $zones_after zones open" >> $seqres.full
83
84 # Check that old data zone was reset
85 old_wptr=$($BLKZONE_PROG report -o $old_data_zone -c 1 $SCRATCH_DEV |\
86         grep -Eo "wptr 0x[[:xdigit:]]+" | cut -d ' ' -f 2)
87 if [ "$old_wptr" != "0x000000" ]; then
88         _fail "Old wptr still at $old_wptr"
89 fi
90
91 new_data_zone=$(get_data_bg)
92 new_data_zone=$((new_data_zone >> 9))
93 printf "New data zone 0x%x\n" $new_data_zone >> $seqres.full
94
95 # Check that data was really relocated to a different zone
96 if [ $old_data_zone -eq $new_data_zone ]; then
97         echo "New zone same as old zone"
98 fi
99
100 # success, all done
101 echo "Silence is golden"
102 status=0
103 exit