#! /bin/bash
-# FS QA Test No. 298
-#
-# Test that filesystem sends discard requests only on free blocks
-#
-#-----------------------------------------------------------------------
+# SPDX-License-Identifier: GPL-2.0
# Copyright (c) 2013 Red Hat, Inc., Tomas Racek <tracek@redhat.com>
#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License as
-# published by the Free Software Foundation.
-#
-# This program is distributed in the hope that it would be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
+# FS QA Test No. 298
#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-#-----------------------------------------------------------------------
+# Test that filesystem sends discard requests only on free blocks
#
-
seq=`basename $0`
seqres=$RESULT_DIR/$seq
echo "QA output created by $seq"
. ./common/rc
-_supported_fs ext4 xfs
-_supported_os Linux
+# remove previous $seqres.full before test
+rm -f $seqres.full
+
+_supported_fs ext4 xfs btrfs
+_require_test
+_require_loop
_require_fstrim
-_require_xfs_io_fiemap
-_require_fs_space $TEST_DIR 307200
+_require_xfs_io_command "fiemap"
+if [ "$FSTYP" = "btrfs" ]; then
+ # 3g for btrfs to have distinct bgs
+ _require_fs_space $TEST_DIR 3145728
+ fssize=3000
+else
+ _require_fs_space $TEST_DIR 307200
+ fssize=300
+fi
+
[ "$FSTYP" = "ext4" ] && _require_dumpe2fs
+[ "$FSTYP" = "btrfs" ] && _require_btrfs_command inspect-internal dump-super
+[ "$FSTYP" = "btrfs" ] && _require_btrfs_command inspect-internal dump-tree
_cleanup()
{
get_holes()
{
+ # It's not a good idea to be running tools against the image file
+ # backing a live filesystem because the filesystem could be maintaining
+ # in-core state that will perturb the free space map on umount. Stick
+ # to established convention which requires the filesystem to be
+ # unmounted while we probe the underlying file.
+ $UMOUNT_PROG $loop_mnt
$XFS_IO_PROG -F -c fiemap $1 | grep hole | $SED_PROG 's/.*\[\(.*\)\.\.\(.*\)\].*/\1 \2/'
+ _mount $loop_dev $loop_mnt
}
get_free_sectors()
{
case $FSTYP in
ext4)
+ $UMOUNT_PROG $loop_mnt
$DUMPE2FS_PROG $img_file 2>&1 | grep " Free blocks" | cut -d ":" -f2- | \
tr ',' '\n' | $SED_PROG 's/^ //' | \
$AWK_PROG -v spb=$sectors_per_block 'BEGIN{FS="-"};
}'
;;
xfs)
- agsize=`xfs_info $loop_mnt | $SED_PROG -n 's/.*agsize=\(.*\) blks.*/\1/p'`
+ agsize=`$XFS_INFO_PROG $loop_mnt | $SED_PROG -n 's/.*agsize=\(.*\) blks.*/\1/p'`
# Convert free space (agno, block, length) to (start sector, end sector)
$UMOUNT_PROG $loop_mnt
$XFS_DB_PROG -r -c "freesp -d" $img_file | $SED_PROG '/^.*from/,$d'| \
$AWK_PROG -v spb=$sectors_per_block -v agsize=$agsize \
'{ print spb * ($1 * agsize + $2), spb * ($1 * agsize + $2 + $3) - 1 }'
;;
+ btrfs)
+ local device_size=$($BTRFS_UTIL_PROG filesystem show --raw $loop_mnt 2>&1 \
+ | sed -n "s/^.*size \([0-9]*\).*$/\1/p")
+
+ local nodesize=$($BTRFS_UTIL_PROG inspect-internal dump-super $img_file \
+ | sed -n 's/nodesize\s*\(.*\)/\1/p')
+
+ # Get holes within block groups
+ $BTRFS_UTIL_PROG inspect-internal dump-tree -t extent $img_file \
+ | $AWK_PROG -v sectorsize=512 -v nodesize=$nodesize -f $here/src/parse-extent-tree.awk
+
+ # Get holes within unallocated space on disk
+ $BTRFS_UTIL_PROG inspect-internal dump-tree -t dev $img_file \
+ | $AWK_PROG -v sectorsize=512 -v devsize=$device_size -f $here/src/parse-dev-tree.awk
+
+ ;;
esac
}
tmp=`mktemp -d`
img_file=$TEST_DIR/$$.fs
-dd if=/dev/zero of=$img_file bs=1M count=300 &> /dev/null
+dd if=/dev/zero of=$img_file bs=1M count=$fssize &> /dev/null
loop_dev=$(_create_loop_device $img_file)
loop_mnt=$tmp/loop_mnt
mkdir $loop_mnt
[ "$FSTYP" = "xfs" ] && MKFS_OPTIONS="-f $MKFS_OPTIONS"
+[ "$FSTYP" = "btrfs" ] && MKFS_OPTIONS="$MKFS_OPTIONS -f -dsingle -msingle"
-$MKFS_PROG -t $FSTYP $MKFS_OPTIONS $loop_dev &> /dev/null
-$MOUNT_PROG $loop_dev $loop_mnt
+_mkfs_dev $loop_dev
+_mount $loop_dev $loop_mnt
echo -n "Generating garbage on loop..."
# Goal is to fill it up, ignore any errors.
echo -n "Comparing holes to the reported space from FS..."
# Get block size
-block_size=$(stat -f -c "%S" $loop_mnt/)
+block_size=$(_get_block_size $loop_mnt/)
sectors_per_block=`expr $block_size / 512`
# Obtain free space from filesystem
END { if(found) exit 0; else exit 1}' $merged_sectors
then
echo "Sectors $from-$to are not marked as free!"
+
+ # Dump the state to make it easier to debug this...
+ echo free_sectors >> $seqres.full
+ sort -g < $free_sectors >> $seqres.full
+ echo fiemap_ref >> $seqres.full
+ sort -g < $fiemap_ref >> $seqres.full
+ echo merged_sectors >> $seqres.full
+ sort -g < $merged_sectors >> $seqres.full
+ echo fiemap_after >> $seqres.full
+ sort -g < $fiemap_after >> $seqres.full
exit
fi
done < $fiemap_after