common/rc: add _scratch_{u}mount_idmapped() helpers
[xfstests-dev.git] / tests / shared / 298
old mode 100644 (file)
new mode 100755 (executable)
index d5c05a8..5cb30fc
@@ -1,43 +1,40 @@
 #! /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
-seqres=$RESULT_DIR/$seq
-seqres=$RESULT_DIR/$seq
 echo "QA output created by $seq"
 
 status=1       # failure is the default!
 trap "_cleanup; exit \$status" 0 1 2 3 15
 
-. common/config
-. common/rc
+. ./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_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()
 {
@@ -51,13 +48,21 @@ _cleanup()
 
 get_holes()
 {
-       $XFS_IO_PROG -c fiemap $1 | grep hole | $SED_PROG 's/.*\[\(.*\)\.\.\(.*\)\].*/\1 \2/'
+       # 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="-"};
@@ -69,13 +74,29 @@ get_free_sectors()
                     }'
        ;;
        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 -c "freesp -d" $img_file | $SED_PROG '/^.*from/,$d'| \
+       $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
 }
 
@@ -120,7 +141,7 @@ here=`pwd`
 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
@@ -133,14 +154,16 @@ merged_sectors="$tmp/merged_free_sectors"
 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.
 for i in `seq 1 10`; do
-       mkdir $loop_mnt/$i
-       cp -r $here/* $loop_mnt/$i
+       mkdir $loop_mnt/$i &> /dev/null
+       cp -r $here/* $loop_mnt/$i &> /dev/null || break
 done
 
 # Get reference fiemap, this can contain i.e. uninitialized inode table
@@ -164,7 +187,7 @@ echo "done."
 
 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
@@ -182,6 +205,16 @@ while read line; do
                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