#! /bin/bash # SPDX-License-Identifier: GPL-2.0 # Copyright (c) 2021 Western Digital Corporation. All Rights Reserved. # # FS QA Test 237 # # Test that zone autoreclaim works as expected, that is: if the dirty # threshold is exceeded the data gets relocated to new block group and the # old block group gets deleted. On block group deletion, the underlying device # zone also needs to be reset. # . ./common/preamble _begin_fstest auto quick zone balance . ./common/zoned _supported_fs btrfs _require_scratch _require_btrfs_command inspect-internal dump-tree _require_btrfs_command filesystem sync _require_command "$BLKZONE_PROG" blkzone _require_zoned_device "$SCRATCH_DEV" # This test requires specific data space usage, skip if we have compression # enabled. _require_no_compress get_data_bg() { $BTRFS_UTIL_PROG inspect-internal dump-tree -t CHUNK $SCRATCH_DEV |\ grep -A 1 "CHUNK_ITEM" | grep -B 1 "type DATA" |\ grep -Eo "CHUNK_ITEM [[:digit:]]+" | cut -d ' ' -f 2 } get_data_bg_physical() { # Assumes SINGLE data profile $BTRFS_UTIL_PROG inspect-internal dump-tree -t CHUNK $SCRATCH_DEV |\ grep -A 4 CHUNK_ITEM | grep -A 3 'type DATA\|SINGLE' |\ grep -Eo 'offset [[:digit:]]+'| cut -d ' ' -f 2 } sdev="$(_short_dev $SCRATCH_DEV)" zone_size=$(($(cat /sys/block/${sdev}/queue/chunk_sectors) << 9)) fssize=$((zone_size * 16)) devsize=$(($(_get_device_size $SCRATCH_DEV) * 1024)) # Create a minimal FS to kick the reclaim process if [[ $devsize -gt $fssize ]]; then _scratch_mkfs_sized $fssize >> $seqres.full 2>&1 else _scratch_mkfs >> $seqres.full 2>&1 fi _scratch_mount -o commit=1 # 1s commit time to speed up test uuid=$($BTRFS_UTIL_PROG filesystem show $SCRATCH_DEV |grep uuid: |\ $AWK_PROG '{print $NF}') if [[ "$uuid" == "" ]]; then echo "UUID for $SCRATCH_DEV is empty, this is not expected" exit 1 fi start_data_bg_phy=$(get_data_bg_physical) start_data_bg_phy=$((start_data_bg_phy >> 9)) size=$(_zone_capacity $start_data_bg_phy) reclaim_threshold=75 if [[ -f /sys/fs/btrfs/"$uuid"/allocation/data/bg_reclaim_threshold ]]; then fs_fill=1 echo $fs_fill > /sys/fs/btrfs/"$uuid"/bg_reclaim_threshold || _notrun "Need CONFIG_BTRFS_DEBUG to lower the reclaim threshold" echo $reclaim_threshold > /sys/fs/btrfs/"$uuid"/allocation/data/bg_reclaim_threshold else echo $reclaim_threshold > /sys/fs/btrfs/"$uuid"/bg_reclaim_threshold fi fill_percent=$((reclaim_threshold + 2)) rest_percent=$((90 - fill_percent)) # make sure we're not creating a new BG fill_size=$((size * fill_percent / 100)) rest=$((size * rest_percent / 100)) # step 1, fill FS over $fillsize $XFS_IO_PROG -fc "pwrite 0 $fill_size" $SCRATCH_MNT/$seq.test1 >> $seqres.full $XFS_IO_PROG -fc "pwrite 0 $rest" $SCRATCH_MNT/$seq.test2 >> $seqres.full $BTRFS_UTIL_PROG filesystem sync $SCRATCH_MNT zones_before=$($BLKZONE_PROG report $SCRATCH_DEV | grep -v -e em -e nw | wc -l) echo "Before reclaim: $zones_before zones open" >> $seqres.full old_data_zone=$(get_data_bg) old_data_zone=$((old_data_zone >> 9)) printf "Old data zone 0x%x\n" $old_data_zone >> $seqres.full # step 2, delete the 1st $fill_size sized file to trigger reclaim rm $SCRATCH_MNT/$seq.test1 $BTRFS_UTIL_PROG filesystem sync $SCRATCH_MNT sleep 2 # 1 transaction commit for 'rm' and 1 for balance # check that we don't have more zones open than before zones_after=$($BLKZONE_PROG report $SCRATCH_DEV | grep -v -e em -e nw | wc -l) echo "After reclaim: $zones_after zones open" >> $seqres.full # Check that old data zone was reset old_wptr=$($BLKZONE_PROG report -o $old_data_zone -c 1 $SCRATCH_DEV |\ grep -Eo "wptr 0x[[:xdigit:]]+" | cut -d ' ' -f 2) if [ "$old_wptr" != "0x000000" ]; then _fail "Old wptr still at $old_wptr" fi new_data_zone=$(get_data_bg) new_data_zone=$((new_data_zone >> 9)) printf "New data zone 0x%x\n" $new_data_zone >> $seqres.full # Check that data was really relocated to a different zone if [ $old_data_zone -eq $new_data_zone ]; then echo "New zone same as old zone" fi # success, all done echo "Silence is golden" status=0 exit