common/rc: add _scratch_{u}mount_idmapped() helpers
[xfstests-dev.git] / tests / shared / 298
index e7b7b233de45f2370e13634e79921ee730fe0dc8..5cb30fc983f7a8de3ba37fd5f4892766c41227cd 100755 (executable)
@@ -15,14 +15,26 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
 
 . ./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_command "fiemap"
-_require_fs_space $TEST_DIR 307200
+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()
 {
@@ -36,13 +48,21 @@ _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="-"};
@@ -61,6 +81,22 @@ get_free_sectors()
                 $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
 }
 
@@ -105,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
@@ -118,6 +154,7 @@ 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_dev $loop_dev
 _mount $loop_dev $loop_mnt
@@ -168,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