generic: xattr enospc cleanup test
[xfstests-dev.git] / common / rc
index 9f17564e37733c743f623e50b3bdeaee7df97933..5e83c809160f8ac60fa9d2c403ecbc7b9f480654 100644 (file)
--- a/common/rc
+++ b/common/rc
 
 BC=$(which bc 2> /dev/null) || BC=
 
+# Valid test names start with 3 digits "NNN":
+#  "[0-9]\{3\}"
+# followed by an optional "-":
+#  "-\?"
+# followed by an optional combination of alphanumeric and "-" chars:
+#  "[[:alnum:]-]*"
+# e.g. 999-the-mark-of-fstests
+#
+VALID_TEST_NAME="[0-9]\{3\}-\?[[:alnum:]-]*"
+
 _require_math()
 {
        if [ -z "$BC" ]; then
@@ -108,10 +118,16 @@ case "$FSTYP" in
     ext4)
         [ "$MKFS_EXT4_PROG" = "" ] && _fatal "mkfs.ext4 not found"
         ;;
+    f2fs)
+        [ "$MKFS_F2FS_PROG" = "" ] && _fatal "mkfs.f2fs not found"
+        ;;
     nfs)
         ;;
     cifs)
         ;;
+    reiser4)
+        [ "$MKFS_REISER4_PROG" = "" ] && _fatal "mkfs.reiser4 not found"
+        ;;
 esac
 
 # make sure we have a standard umask
@@ -292,6 +308,11 @@ _scratch_mkfs_xfs_opts()
 {
        mkfs_opts=$*
 
+       # remove crc related mkfs options if mkfs.xfs doesn't support v5 xfs
+       if [ -n "$XFS_MKFS_HAS_NO_META_SUPPORT" ]; then
+               mkfs_opts=`echo $mkfs_opts | sed "s/-m\s\+crc=.//"`
+       fi
+
        _scratch_options mkfs
 
        $MKFS_XFS_PROG $SCRATCH_OPTIONS $mkfs_opts $SCRATCH_DEV
@@ -349,9 +370,12 @@ _scratch_mkfs_xfs()
                mkfs_status=$?
        fi
 
-       # output stored mkfs output
-       cat $tmp_dir.mkfserr >&2
+       # output stored mkfs output, filtering unnecessary warnings from stderr
        cat $tmp_dir.mkfsstd
+       cat $tmp_dir.mkfserr | sed \
+               -e '/less than device physical sector/d' \
+               -e '/switching to logical sector/d' \
+               >&2
        rm -f $tmp_dir.mkfserr $tmp_dir.mkfsstd
 
        return $mkfs_status
@@ -517,6 +541,9 @@ _test_mkfs()
     btrfs)
         $MKFS_BTRFS_PROG $MKFS_OPTIONS $* $TEST_DEV > /dev/null
        ;;
+    ext2|ext3|ext4)
+       $MKFS_PROG -t $FSTYP -- -F $MKFS_OPTIONS $* $TEST_DEV
+       ;;
     *)
        yes | $MKFS_PROG -t $FSTYP -- $MKFS_OPTIONS $* $TEST_DEV
        ;;
@@ -535,6 +562,11 @@ _mkfs_dev()
     btrfs)
         $MKFS_BTRFS_PROG $MKFS_OPTIONS $* 2>$tmp_dir.mkfserr 1>$tmp_dir.mkfsstd
        ;;
+    ext2|ext3|ext4)
+       $MKFS_PROG -t $FSTYP -- -F $MKFS_OPTIONS $* \
+               2>$tmp_dir.mkfserr 1>$tmp_dir.mkfsstd
+       ;;
+
     *)
        yes | $MKFS_PROG -t $FSTYP -- $MKFS_OPTIONS $* \
                2>$tmp_dir.mkfserr 1>$tmp_dir.mkfsstd
@@ -551,6 +583,14 @@ _mkfs_dev()
     rm -f $tmp_dir.mkfserr $tmp_dir.mkfsstd
 }
 
+# remove all files in $SCRATCH_MNT, useful when testing on NFS/CIFS
+_scratch_cleanup_files()
+{
+       _scratch_mount
+       rm -rf $SCRATCH_MNT/*
+       _scratch_unmount
+}
+
 _scratch_mkfs()
 {
     case $FSTYP in
@@ -558,10 +598,14 @@ _scratch_mkfs()
         _scratch_mkfs_xfs $*
        ;;
     nfs*)
-       # do nothing for nfs
+       # unable to re-create NFS, just remove all files in $SCRATCH_MNT to
+       # avoid EEXIST caused by the leftover files created in previous runs
+        _scratch_cleanup_files
        ;;
     cifs)
-       # do nothing for cifs
+       # unable to re-create CIFS, just remove all files in $SCRATCH_MNT to
+       # avoid EEXIST caused by the leftover files created in previous runs
+        _scratch_cleanup_files
        ;;
     udf)
         $MKFS_UDF_PROG $MKFS_OPTIONS $* $SCRATCH_DEV > /dev/null
@@ -569,12 +613,18 @@ _scratch_mkfs()
     btrfs)
         $MKFS_BTRFS_PROG $MKFS_OPTIONS $* $SCRATCH_DEV > /dev/null
        ;;
+    ext2|ext3)
+       $MKFS_PROG -t $FSTYP -- -F $MKFS_OPTIONS $* $SCRATCH_DEV
+       ;;
     ext4)
        _scratch_mkfs_ext4 $*
        ;;
     tmpfs)
        # do nothing for tmpfs
        ;;
+    f2fs)
+        $MKFS_F2FS_PROG $MKFS_OPTIONS $* $SCRATCH_DEV > /dev/null
+       ;;
     *)
        yes | $MKFS_PROG -t $FSTYP -- $MKFS_OPTIONS $* $SCRATCH_DEV
        ;;
@@ -610,7 +660,7 @@ _scratch_mkfs_sized()
     xfs)
        def_blksz=`echo $MKFS_OPTIONS|sed -rn 's/.*-b ?size= ?+([0-9]+).*/\1/p'`
        ;;
-    ext2|ext3|ext4|ext4dev|udf|btrfs)
+    ext2|ext3|ext4|ext4dev|udf|btrfs|reiser4)
        def_blksz=`echo $MKFS_OPTIONS| sed -rn 's/.*-b ?+([0-9]+).*/\1/p'`
        ;;
     esac
@@ -645,7 +695,7 @@ _scratch_mkfs_sized()
        fi
        ;;
     ext2|ext3|ext4|ext4dev)
-       yes | ${MKFS_PROG}.$FSTYP $MKFS_OPTIONS -b $blocksize $SCRATCH_DEV $blocks
+       ${MKFS_PROG}.$FSTYP -F $MKFS_OPTIONS -b $blocksize $SCRATCH_DEV $blocks
        ;;
     udf)
        $MKFS_UDF_PROG $MKFS_OPTIONS -b $blocksize $SCRATCH_DEV $blocks
@@ -653,6 +703,11 @@ _scratch_mkfs_sized()
     btrfs)
        $MKFS_BTRFS_PROG $MKFS_OPTIONS -b $fssize $SCRATCH_DEV
        ;;
+    reiser4)
+       # mkfs.resier4 requires size in KB as input for creating filesystem
+       $MKFS_REISER4_PROG $MKFS_OPTIONS -y -b $blocksize $SCRATCH_DEV \
+                          `expr $fssize / 1024`
+       ;;
     *)
        _notrun "Filesystem $FSTYP not supported in _scratch_mkfs_sized"
        ;;
@@ -920,11 +975,11 @@ _is_block_dev()
 
     _dev=$1
     if [ -L "${_dev}" ]; then
-        _dev=`readlink -f ${_dev}`
+        _dev=`readlink -f "${_dev}"`
     fi
 
     if [ -b "${_dev}" ]; then
-        src/lstat64 ${_dev} | $AWK_PROG '/Device type:/ { print $9 }'
+        src/lstat64 "${_dev}" | $AWK_PROG '/Device type:/ { print $9 }'
     fi
 }
 
@@ -1034,10 +1089,22 @@ _require_scratch_nocheck()
 {
     case "$FSTYP" in
        nfs*)
-                 _notrun "requires a scratch device"
-                ;;
+               echo $SCRATCH_DEV | grep -q ":/" > /dev/null 2>&1
+               if [ -z "$SCRATCH_DEV" -o "$?" != "0" ]; then
+                       _notrun "this test requires a valid \$SCRATCH_DEV"
+               fi
+               if [ ! -d "$SCRATCH_MNT" ]; then
+                       _notrun "this test requires a valid \$SCRATCH_MNT"
+               fi
+               ;;
        cifs)
-               _notrun "requires a scratch device"
+               echo $SCRATCH_DEV | grep -q "//" > /dev/null 2>&1
+               if [ -z "$SCRATCH_DEV" -o "$?" != "0" ]; then
+                       _notrun "this test requires a valid \$SCRATCH_DEV"
+               fi
+               if [ ! -d "$SCRATCH_MNT" ]; then
+                    _notrun "this test requires a valid \$SCRATCH_MNT"
+               fi
                ;;
        tmpfs)
                if [ -z "$SCRATCH_DEV" -o ! -d "$SCRATCH_MNT" ];
@@ -1046,11 +1113,11 @@ _require_scratch_nocheck()
                fi
                ;;
        *)
-                if [ -z "$SCRATCH_DEV" -o "`_is_block_dev $SCRATCH_DEV`" = "" ]
+                if [ -z "$SCRATCH_DEV" -o "`_is_block_dev "$SCRATCH_DEV"`" = "" ]
                 then
                     _notrun "this test requires a valid \$SCRATCH_DEV"
                 fi
-                if [ "`_is_block_dev $SCRATCH_DEV`" = "`_is_block_dev $TEST_DEV`" ]
+                if [ "`_is_block_dev "$SCRATCH_DEV"`" = "`_is_block_dev "$TEST_DEV"`" ]
                 then
                     _notrun "this test requires a valid \$SCRATCH_DEV"
                 fi
@@ -1062,10 +1129,12 @@ _require_scratch_nocheck()
     esac
 
     # mounted?
-    if _mount | grep -q $SCRATCH_DEV
+    # Note that we use -F here so grep doesn't try to interpret an NFS over
+    # IPv6 server as a regular expression.
+    if _mount | grep -F -q $SCRATCH_DEV
     then
         # if it's mounted, make sure its on $SCRATCH_MNT
-        if ! _mount | grep $SCRATCH_DEV | grep -q $SCRATCH_MNT
+        if ! _mount | grep -F $SCRATCH_DEV | grep -q $SCRATCH_MNT
         then
             echo "\$SCRATCH_DEV is mounted but not on \$SCRATCH_MNT - aborting"
             exit 1
@@ -1088,7 +1157,7 @@ _require_scratch()
 }
 
 
-# this test needs a test partition - check we're ok & unmount it
+# this test needs a test partition - check we're ok & mount it
 #
 _require_test()
 {
@@ -1118,11 +1187,11 @@ _require_test()
                fi
                ;;
        *)
-                if [ -z "$TEST_DEV" -o "`_is_block_dev $TEST_DEV`" = "" ]
+                if [ -z "$TEST_DEV" ] || [ "`_is_block_dev "$TEST_DEV"`" = "" ]
                 then
                     _notrun "this test requires a valid \$TEST_DEV"
                 fi
-                if [ "`_is_block_dev $SCRATCH_DEV`" = "`_is_block_dev $TEST_DEV`" ]
+                if [ "`_is_block_dev "$SCRATCH_DEV"`" = "`_is_block_dev "$TEST_DEV"`" ]
                 then
                     _notrun "this test requires a valid \$TEST_DEV"
                 fi
@@ -1225,26 +1294,75 @@ _require_realtime()
 # this test requires that a specified command (executable) exists
 # $1 - command, $2 - name for error message
 #
+# Note: the command string might have parameters, so strip them before checking
+# whether it is executable.
 _require_command()
 {
-    [ -n "$1" ] && _cmd="$1" || _cmd="$2"
-    [ -n "$1" -a -x "$1" ] || _notrun "$_cmd utility required, skipped this test"
+       if [ $# -eq 2 ]; then
+               _name="$2"
+       elif [ $# -eq 1 ]; then
+               _name="$1"
+       else
+               _fail "usage: _require_command <command> [<name>]"
+       fi
+
+       _command=`echo "$1" | awk '{ print $1 }'`
+       if [ ! -x "$_command" ]; then
+               _notrun "$_name utility required, skipped this test"
+       fi
+}
+
+# this test requires the device to be valid block device
+# $1 - device
+_require_block_device()
+{
+       if [ -z "$1" ]; then
+               echo "Usage: _require_block_device <dev>" 1>&2
+               exit 1
+       fi
+       if [ "`_is_block_dev "$1"`" == "" ]; then
+               _notrun "require $1 to be valid block disk"
+       fi
+}
+
+# brd based ram disks erase the device when they receive a flush command when no
+# active references are present. This causes problems for DM devices sitting on
+# top of brd devices as DM doesn't hold active references to the brd device.
+_require_sane_bdev_flush()
+{
+       echo $1 | grep -q "^/dev/ram[0-9]\+$"
+       if [ $? -eq 0 ]; then
+               _notrun "This test requires a sane block device flush"
+       fi
 }
 
 # this test requires the device mapper flakey target
 #
 _require_dm_flakey()
 {
-    _require_command $DMSETUP_PROG
+       # require SCRATCH_DEV to be a valid block device with sane BLKFLSBUF
+       # behaviour
+       _require_block_device $SCRATCH_DEV
+       _require_sane_bdev_flush $SCRATCH_DEV
+       _require_command "$DMSETUP_PROG" dmsetup
 
-    modprobe dm-flakey >/dev/null 2>&1
-    $DMSETUP_PROG targets | grep flakey >/dev/null 2>&1
-    if [ $? -eq 0 ]
-    then
-       :
-    else
-       _notrun "This test requires dm flakey support"
-    fi
+       modprobe dm-flakey >/dev/null 2>&1
+       $DMSETUP_PROG targets | grep flakey >/dev/null 2>&1
+       if [ $? -ne 0 ]; then
+               _notrun "This test requires dm flakey support"
+       fi
+}
+
+_require_dm_snapshot()
+{
+       _require_block_device $SCRATCH_DEV
+       _require_sane_bdev_flush $SCRATCH_DEV
+       _require_command "$DMSETUP_PROG" dmsetup
+       modprobe dm-snapshot >/dev/null 2>&1
+       $DMSETUP_PROG targets | grep -q snapshot
+       if [ $? -ne 0 ]; then
+               _notrun "This test requires dm snapshot support"
+       fi
 }
 
 # this test requires the projid32bit feature to be available in mkfs.xfs.
@@ -1283,7 +1401,7 @@ _require_xfs_crc()
 #
 _require_ext4_mkfs_bigalloc()
 {
-       $MKFS_EXT4_PROG -F -O bigalloc -n $SCRATCH_DEV 200k >/dev/null 2>&1 \
+       $MKFS_EXT4_PROG -F -O bigalloc -n $SCRATCH_DEV 512m >/dev/null 2>&1 \
           || _notrun "mkfs.ext4 doesn't have bigalloc feature"
 }
 
@@ -1291,7 +1409,7 @@ _require_ext4_mkfs_bigalloc()
 #
 _require_ext4_bigalloc()
 {
-       $MKFS_EXT4_PROG -F -O bigalloc $SCRATCH_DEV 200k >/dev/null 2>&1
+       $MKFS_EXT4_PROG -F -O bigalloc $SCRATCH_DEV 512m >/dev/null 2>&1
        _scratch_mount >/dev/null 2>&1 \
           || _notrun "Ext4 kernel doesn't support bigalloc feature"
        umount $SCRATCH_MNT
@@ -1331,6 +1449,18 @@ _require_xfs_sysfs()
        fi
 }
 
+# this test requires the xfs sparse inode feature
+#
+_require_xfs_sparse_inodes()
+{
+       _scratch_mkfs_xfs_supported -m crc=1 -i sparse > /dev/null 2>&1 \
+               || _notrun "mkfs.xfs does not support sparse inodes"
+       _scratch_mkfs_xfs -m crc=1 -i sparse > /dev/null 2>&1
+       _scratch_mount >/dev/null 2>&1 \
+               || _notrun "kernel does not support sparse inodes"
+       umount $SCRATCH_MNT
+}
+
 # this test requires that external log/realtime devices are not in use
 #
 _require_nonexternal()
@@ -1352,6 +1482,7 @@ _require_aiodio()
         AIO_TEST=src/aio-dio-regress/$1
         [ -x $AIO_TEST ] || _notrun "$AIO_TEST not built"
     fi
+    _require_odirect
 }
 
 # run an aio-dio program
@@ -1455,7 +1586,7 @@ _require_xfs_io_command()
        "falloc" )
                testio=`$XFS_IO_PROG -F -f -c "falloc 0 1m" $testfile 2>&1`
                ;;
-       "fpunch" | "fcollapse" | "zero" | "fzero" )
+       "fpunch" | "fcollapse" | "zero" | "fzero" | "finsert" )
                testio=`$XFS_IO_PROG -F -f -c "pwrite 0 20k" -c "fsync" \
                        -c "$command 4k 8k" $testfile 2>&1`
                ;;
@@ -1480,6 +1611,17 @@ _require_xfs_io_command()
                _notrun "xfs_io $command failed (old kernel/wrong fs?)"
 }
 
+# check that kernel and filesystem support direct I/O
+_require_odirect()
+{
+       testfile=$TEST_DIR/$$.direct
+       $XFS_IO_PROG -F -f -d -c "pwrite 0 20k" $testfile > /dev/null 2>&1
+       if [ $? -ne 0 ]; then
+               _notrun "O_DIRECT is not supported"
+       fi
+       rm -f $testfile 2>&1 > /dev/null
+}
+
 # Check that a fs has enough free space (in 1024b blocks)
 #
 _require_fs_space()
@@ -1678,7 +1820,10 @@ _check_generic_filesystem()
 
     if [ $ok -eq 0 ]; then
        status=1
-       exit 1
+       if [ "$iam" != "check" ]; then
+               exit 1
+       fi
+       return 1
     fi
 
     return 0
@@ -1780,6 +1925,7 @@ _check_xfs_filesystem()
        if [ "$iam" != "check" ]; then
                exit 1
        fi
+       return 1
     fi
 
     return 0
@@ -1824,7 +1970,8 @@ _check_udf_filesystem()
     $here/src/udf_test $OPT_ARG $device | tee $seqres.checkfs | egrep "Error|Warning" | \
        _udf_test_known_error_filter | \
        egrep -iv "Error count:.*[0-9]+.*total occurrences:.*[0-9]+|Warning count:.*[0-9]+.*total occurrences:.*[0-9]+" && \
-        echo "Warning UDF Verifier reported errors see $seqres.checkfs."
+        echo "Warning UDF Verifier reported errors see $seqres.checkfs." && return 1
+    return 0
 }
 
 _check_xfs_test_fs()
@@ -1889,7 +2036,10 @@ _check_btrfs_filesystem()
 
     if [ $ok -eq 0 ]; then
        status=1
-       exit 1
+       if [ "$iam" != "check" ]; then
+               exit 1
+       fi
+       return 1
     fi
 
     return 0
@@ -2152,10 +2302,10 @@ _require_scratch_dev_pool()
        esac
 
        for i in $SCRATCH_DEV_POOL; do
-               if [ "`_is_block_dev $i`" = "" ]; then
+               if [ "`_is_block_dev "$i"`" = "" ]; then
                        _notrun "this test requires valid block disk $i"
                fi
-               if [ "`_is_block_dev $i`" = "`_is_block_dev $TEST_DEV`" ]; then
+               if [ "`_is_block_dev "$i"`" = "`_is_block_dev "$TEST_DEV"`" ]; then
                        _notrun "$i is part of TEST_DEV, this test requires unique disks"
                fi
                if _mount | grep -q $i; then
@@ -2205,7 +2355,7 @@ _require_deletable_scratch_dev_pool()
 _require_btrfs()
 {
        cmd=$1
-       _require_command $BTRFS_UTIL_PROG btrfs
+       _require_command "$BTRFS_UTIL_PROG" btrfs
        if [ -z "$1" ]; then
                return 1;
        fi
@@ -2218,7 +2368,7 @@ _require_fio()
 {
        job=$1
 
-       _require_command $FIO_PROG
+       _require_command "$FIO_PROG" fio
        if [ -z "$1" ]; then
                return 1;
        fi
@@ -2236,6 +2386,76 @@ _require_freeze()
        [ $result -eq 0 ] || _notrun "$FSTYP does not support freezing"
 }
 
+# Does shutdown work on this fs?
+_require_scratch_shutdown()
+{
+       [ -x src/godown ] || _notrun "src/godown executable not found"
+
+       _scratch_mkfs > /dev/null 2>&1
+       _scratch_mount
+       src/godown -f $SCRATCH_MNT 2>&1 \
+               || _notrun "$FSTYP does not support shutdown"
+       _scratch_unmount
+}
+
+# Does norecovery support by this fs?
+_require_norecovery()
+{
+       _scratch_mount -o ro,norecovery || \
+               _notrun "$FSTYP does not support norecovery"
+       _scratch_unmount
+}
+
+# Does this filesystem support metadata journaling?
+# We exclude ones here that don't; otherwise we assume that it does, so the
+# test will run, fail, and motivate someone to update this test for a new
+# filesystem.
+#
+# It's possible that TEST_DEV and SCRATCH_DEV have different features (it'd be
+# odd, but possible) so check $TEST_DEV by default, but we can optionall pass
+# any dev we want.
+_require_metadata_journaling()
+{
+       if [ -z $1 ]; then
+               DEV=$TEST_DEV
+       else
+               DEV=$1
+       fi
+
+       case "$FSTYP" in
+       ext2|vfat|msdos)
+               _notrun "$FSTYP does not support metadata journaling"
+               ;;
+       ext4)
+               # ext4 could be mkfs'd without a journal...
+               _require_dumpe2fs
+               $DUMPE2FS_PROG -h $DEV 2>&1 | grep -q has_journal || \
+                       _notrun "$FSTYP on $DEV not configured with metadata journaling"
+               ;;
+       *)
+               # by default we pass; if you need to, add your fs above!
+               ;;
+       esac
+}
+
+# Does fiemap support?
+_require_fiemap()
+{
+       _require_xfs_io_command "fiemap"
+}
+
+_count_extents()
+{
+       res=`$XFS_IO_PROG -c "fiemap" $1 | tail -n +2`
+       echo $res | grep -v hole | wc -l | $AWK_PROG '{print $1}'
+}
+
+_count_holes()
+{
+       res=`$XFS_IO_PROG -c "fiemap" $1 | tail -n +2`
+       echo $res | grep hole | wc -l | $AWK_PROG '{print $1}'
+}
+
 # arg 1 is dev to remove and is output of the below eg.
 # ls -l /sys/class/block/sdd | rev | cut -d "/" -f 3 | rev
 _devmgt_remove()
@@ -2297,14 +2517,14 @@ _require_fstrim()
        fi
 }
 
-_test_batched_discard()
+_require_batched_discard()
 {
        if [ $# -ne 1 ]; then
-               echo "Usage: _test_batched_discard mnt_point" 1>&2
+               echo "Usage: _require_batched_discard mnt_point" 1>&2
                exit 1
        fi
        _require_fstrim
-       $FSTRIM_PROG ${1} &>/dev/null
+       $FSTRIM_PROG $1 > /dev/null 2>&1 || _notrun "FITRIM not supported on $1"
 }
 
 _require_dumpe2fs()
@@ -2336,7 +2556,7 @@ _require_fssum()
        [ -x $FSSUM_PROG ] || _notrun "fssum not built"
 }
 
-_require_btrfs_cloner()
+_require_cloner()
 {
        CLONER_PROG=$here/src/cloner
        [ -x $CLONER_PROG ] || \
@@ -2358,10 +2578,17 @@ _verify_reflink()
                || echo "$1 and $2 are not reflinks: different extents"
 }
 
+_require_atime()
+{
+       if [ "$FSTYP" == "nfs" ]; then
+               _notrun "atime related mount options have no effect on NFS"
+       fi
+}
+
 _require_relatime()
 {
         _scratch_mkfs > /dev/null 2>&1
-        _mount -t $FSTYP -o relatime $SCRATCH_DEV $SCRATCH_MNT || \
+        _scratch_mount -o relatime || \
                 _notrun "relatime not supported by the current kernel"
        _scratch_unmount
 }
@@ -2509,6 +2736,18 @@ _get_used_inode()
        echo $nr_inode
 }
 
+_get_used_inode_percent()
+{
+       if [ -z "$1" ]; then
+               echo "Usage: _get_used_inode_percent <mnt>"
+               exit 1
+       fi
+       local pct_inode;
+       pct_inode=`$DF_PROG -i $1 | tail -1 | awk '{ print $6 }' | \
+                  sed -e 's/%//'`
+       echo $pct_inode
+}
+
 _get_free_inode()
 {
        if [ -z "$1" ]; then
@@ -2520,6 +2759,19 @@ _get_free_inode()
        echo $nr_inode
 }
 
+# get the available space in bytes
+#
+_get_available_space()
+{
+       if [ -z "$1" ]; then
+               echo "Usage: _get_available_space <mnt>"
+               exit 1
+       fi
+       local avail_kb;
+       avail_kb=`$DF_PROG $1 | tail -n1 | awk '{ print $5 }'`
+       echo $((avail_kb * 1024))
+}
+
 # get btrfs profile configs being tested
 #
 # A set of pre-set profile configs are exported via _btrfs_profile_configs
@@ -2708,12 +2960,58 @@ _btrfs_stress_replace()
        done
 }
 
+# find the right option to force output in bytes, older versions of btrfs-progs
+# print that by default, newer print human readable numbers with unit suffix
+_btrfs_qgroup_units()
+{
+       $BTRFS_UTIL_PROG qgroup show --help 2>&1 | grep -q -- --raw && echo "--raw"
+}
+
 # return device size in kb
 _get_device_size()
 {
        grep `_short_dev $1` /proc/partitions | awk '{print $3}'
 }
 
+# check dmesg log for WARNING/Oops/etc.
+_check_dmesg()
+{
+       if [ ! -f ${RESULT_DIR}/check_dmesg ]; then
+               return 0
+       fi
+       rm -f ${RESULT_DIR}/check_dmesg
+
+       # default filter is a simple cat command, caller could provide a
+       # customized filter and pass the name through the first argument, to
+       # filter out intentional WARNINGs or Oopses
+       filter=${1:-cat}
+
+       # search the dmesg log of last run of $seqnum for possible failures
+       # use sed \cregexpc address type, since $seqnum contains "/"
+       dmesg | tac | sed -ne "0,\#run fstests $seqnum at $date_time#p" | \
+               tac | $filter >$seqres.dmesg
+       grep -q -e "kernel BUG at" \
+            -e "WARNING:" \
+            -e "BUG:" \
+            -e "Oops:" \
+            -e "possible recursive locking detected" \
+            -e "Internal error" \
+            $seqres.dmesg
+       if [ $? -eq 0 ]; then
+               echo "_check_dmesg: something found in dmesg (see $seqres.dmesg)"
+               return 1
+       else
+               rm -f $seqres.dmesg
+               return 0
+       fi
+}
+
+# don't check dmesg log after test
+_disable_dmesg_check()
+{
+       rm -f ${RESULT_DIR}/check_dmesg
+}
+
 init_rc()
 {
        if [ "$iam" == new ]
@@ -2752,6 +3050,11 @@ init_rc()
        # Figure out if we need to add -F ("foreign", deprecated) option to xfs_io
        xfs_io -c stat $TEST_DIR 2>&1 | grep -q "is not on an XFS filesystem" && \
        export XFS_IO_PROG="$XFS_IO_PROG -F"
+
+       # xfs_copy doesn't work on v5 xfs yet without -d option
+       if [ "$FSTYP" == "xfs" ] && [[ $MKFS_OPTIONS =~ crc=1 ]]; then
+               export XFS_COPY_PROG="$XFS_COPY_PROG -d"
+       fi
 }
 
 # get real device path name by following link
@@ -2770,6 +3073,16 @@ _short_dev()
        echo `basename $(_real_dev $1)`
 }
 
+_sysfs_dev()
+{
+       local _dev=$1
+       local _maj=$(stat -c%t $_dev | tr [:lower:] [:upper:])
+       local _min=$(stat -c%T $_dev | tr [:lower:] [:upper:])
+       _maj=$(echo "ibase=16; $_maj" | bc)
+       _min=$(echo "ibase=16; $_min" | bc)
+       echo /sys/dev/block/$_maj:$_min
+}
+
 get_block_size()
 {
        if [ -z $1 ] || [ ! -d $1 ]; then