generic/{453,454}: Don't run for FSs restricting names
[xfstests-dev.git] / common / rc
index fa70453d63276b0e7a1dfa8598cd755ac1fb0dd0..d4b1f21f64c1eb0500d94cc6513bc9824ab5dfd9 100644 (file)
--- a/common/rc
+++ b/common/rc
@@ -6,16 +6,6 @@
 
 BC=$(which bc 2> /dev/null) || BC=
 
-# Some tests are not relevant or functional when testing XFS realtime
-# subvolumes along with the rtinherit=1 mkfs option.  In these cases,
-# this test will opt-out of the test.
-_require_no_rtinherit()
-{
-       [ "$FSTYP" = "xfs" ] && echo "$MKFS_OPTIONS" |
-               egrep -q "rtinherit([^=]|=1|$)" && \
-               _notrun "rtinherit mkfs option is not supported by this test."
-}
-
 _require_math()
 {
        if [ -z "$BC" ]; then
@@ -31,19 +21,13 @@ _math()
 
 dd()
 {
-   if [ "$HOSTOS" == "Linux" ]
-   then        
        command dd --help 2>&1 | grep noxfer >/dev/null
-       
        if [ "$?" -eq 0 ]
            then
                command dd status=noxfer $@
            else
                command dd $@
-       fi
-   else
-       command dd $@
-   fi
+       fi
 }
 
 # Prints the md5 checksum of a given file
@@ -144,6 +128,7 @@ case "$FSTYP" in
     9p)
         ;;
     ceph)
+        . ./common/ceph
         ;;
     glusterfs)
         ;;
@@ -170,6 +155,16 @@ _get_filesize()
     stat -c %s "$1"
 }
 
+# Get hugepagesize in bytes
+_get_hugepagesize()
+{
+       local hugepgsz=$(awk '/Hugepagesize/ {print $2}' /proc/meminfo)
+       # Call _notrun if $hugepgsz is not a number
+       echo "$hugepgsz" | egrep -q ^[0-9]+$ || \
+               _notrun "Cannot get the value of Hugepagesize"
+       echo $((hugepgsz * 1024))
+}
+
 _mount()
 {
     $MOUNT_PROG `_mount_ops_filter $*`
@@ -282,12 +277,11 @@ _mount_ops_filter()
     local params="$*"
     local last_index=$(( $# - 1 ))
 
-    #get mount point to handle dmapi mtpt option correctly
     [ $last_index -gt 0 ] && shift $last_index
     local fs_escaped=$1
 
-    echo $params | sed -e 's/dmapi/dmi/' \
-        $PERL_PROG -ne "s#mtpt=[^,|^\n|^\s]*#mtpt=$fs_escaped\1\2#; print;"
+    echo $params | \
+        $PERL_PROG -ne "s#mtpt=[^,|^\n|^\s]*#mtpt=$fs_escaped\1\2#; print;"
 
 }
 
@@ -348,6 +342,36 @@ _scratch_mount()
        _try_scratch_mount $* || _fail "mount failed"
 }
 
+_scratch_mount_idmapped()
+{
+       local type="$1"
+       local id="$2"
+
+       if [ "$type" = "u" ]; then
+               # This means root will be able to create files as uid %id in
+               # the underlying filesystem by going through the idmapped mount.
+               $here/src/idmapped-mounts/mount-idmapped --map-mount u:0:$id:1 \
+                                                        --map-mount u:$id:0:1 \
+                                                        --map-mount g:0:0:1 \
+                                                        "$SCRATCH_MNT" "$SCRATCH_MNT" || _fail "mount-idmapped failed"
+       elif [ "$type" = "g" ]; then
+               # This means root will be able to create files as gid %id in
+               # the underlying filesystem by going through the idmapped mount.
+               $here/src/idmapped-mounts/mount-idmapped --map-mount g:0:$id:1 \
+                                                        --map-mount g:$id:0:1 \
+                                                        --map-mount u:0:0:1 \
+                                                        "$SCRATCH_MNT" "$SCRATCH_MNT" || _fail "mount-idmapped failed"
+       elif [ "$type" = "b" ]; then
+               # This means root will be able to create files as uid and gid
+               # %id in the underlying filesystem by going through the idmapped mount.
+               $here/src/idmapped-mounts/mount-idmapped --map-mount b:0:$id:1 \
+                                                        --map-mount b:$id:0:1 \
+                                                        "$SCRATCH_MNT" "$SCRATCH_MNT" || _fail "mount-idmapped failed"
+       else
+               _fail "usage: either \"u\" (uid), \"g\" (gid), or \"b\" (uid and gid) must be specified "
+       fi
+}
+
 _scratch_unmount()
 {
        case "$FSTYP" in
@@ -363,6 +387,11 @@ _scratch_unmount()
        esac
 }
 
+_scratch_umount_idmapped()
+{
+       $UMOUNT_PROG $SCRATCH_MNT
+}
+
 _scratch_remount()
 {
     local opts="$1"
@@ -495,18 +524,6 @@ _scratch_do_mkfs()
        return $mkfs_status
 }
 
-_scratch_metadump()
-{
-       local dumpfile=$1
-       shift
-       local options=
-
-       [ "$USE_EXTERNAL" = yes -a ! -z "$SCRATCH_LOGDEV" ] && \
-               options="-l $SCRATCH_LOGDEV"
-
-       xfs_metadump $options "$@" $SCRATCH_DEV $dumpfile
-}
-
 _setup_large_ext4_fs()
 {
        local fs_size=$1
@@ -602,6 +619,18 @@ _scratch_mkfs_ext4()
        return $mkfs_status
 }
 
+_ext4_metadump()
+{
+       local device="$1"
+       local dumpfile="$2"
+       local compressopt="$3"
+
+       test -n "$E2IMAGE_PROG" || _fail "e2image not installed"
+       $E2IMAGE_PROG -Q "$device" "$dumpfile"
+       [ "$compressopt" = "compress" ] && [ -n "$DUMP_COMPRESSOR" ] &&
+               $DUMP_COMPRESSOR -f "$dumpfile" &>> "$seqres.full"
+}
+
 _test_mkfs()
 {
     case $FSTYP in
@@ -931,110 +960,118 @@ _available_memory_bytes()
 # _scratch_mkfs_sized <size in bytes> [optional blocksize]
 _scratch_mkfs_sized()
 {
-    local fssize=$1
-    local blocksize=$2
-    local def_blksz
-
-    case $FSTYP in
-    xfs)
-       def_blksz=`echo $MKFS_OPTIONS|sed -rn 's/.*-b ?size= ?+([0-9]+).*/\1/p'`
-       ;;
-    ext2|ext3|ext4|ext4dev|udf|btrfs|reiser4|ocfs2|reiserfs)
-       def_blksz=`echo $MKFS_OPTIONS| sed -rn 's/.*-b ?+([0-9]+).*/\1/p'`
-       ;;
-    jfs)
-       def_blksz=4096
-       ;;
-    esac
-
-    [ -n "$def_blksz" ] && blocksize=$def_blksz
-    [ -z "$blocksize" ] && blocksize=4096
+       local fssize=$1
+       local blocksize=$2
+       local def_blksz
 
+       case $FSTYP in
+       xfs)
+               def_blksz=`echo $MKFS_OPTIONS | sed -rn 's/.*-b ?size= ?+([0-9]+).*/\1/p'`
+               ;;
+       ext2|ext3|ext4|ext4dev|udf|btrfs|reiser4|ocfs2|reiserfs)
+               def_blksz=`echo $MKFS_OPTIONS | sed -rn 's/.*-b ?+([0-9]+).*/\1/p'`
+               ;;
+       jfs)
+               def_blksz=4096
+               ;;
+       esac
 
-    local re='^[0-9]+$'
-    if ! [[ $fssize =~ $re ]] ; then
-        _notrun "error: _scratch_mkfs_sized: fs size \"$fssize\" not an integer."
-    fi
-    if ! [[ $blocksize =~ $re ]] ; then
-        _notrun "error: _scratch_mkfs_sized: block size \"$blocksize\" not an integer."
-    fi
+       [ -n "$def_blksz" ] && blocksize=$def_blksz
+       [ -z "$blocksize" ] && blocksize=4096
 
-    local blocks=`expr $fssize / $blocksize`
+       local re='^[0-9]+$'
+       if ! [[ $fssize =~ $re ]] ; then
+               _notrun "error: _scratch_mkfs_sized: fs size \"$fssize\" not an integer."
+       fi
+       if ! [[ $blocksize =~ $re ]] ; then
+               _notrun "error: _scratch_mkfs_sized: block size \"$blocksize\" not an integer."
+       fi
 
-    if [ "$HOSTOS" == "Linux" -a -b "$SCRATCH_DEV" ]; then
-       local devsize=`blockdev --getsize64 $SCRATCH_DEV`
-       [ "$fssize" -gt "$devsize" ] && _notrun "Scratch device too small"
-    fi
+       local blocks=`expr $fssize / $blocksize`
 
-    case $FSTYP in
-    xfs)
-       # don't override MKFS_OPTIONS that set a block size.
-       echo $MKFS_OPTIONS |egrep -q "b?size="
-       if [ $? -eq 0 ]; then
-               _scratch_mkfs_xfs -d size=$fssize
-       else
-               _scratch_mkfs_xfs -d size=$fssize -b size=$blocksize
+       if [ -b "$SCRATCH_DEV" ]; then
+               local devsize=`blockdev --getsize64 $SCRATCH_DEV`
+               [ "$fssize" -gt "$devsize" ] && _notrun "Scratch device too small"
        fi
-       ;;
-    ext2|ext3|ext4|ext4dev)
-       ${MKFS_PROG}.$FSTYP -F $MKFS_OPTIONS -b $blocksize $SCRATCH_DEV $blocks
-       ;;
-    gfs2)
-       # mkfs.gfs2 doesn't automatically shrink journal files on small
-       # filesystems, so the journal files may end up being bigger than the
-       # filesystem, which will cause mkfs.gfs2 to fail.  Until that's fixed,
-       # shrink the journal size to at most one eigth of the filesystem and at
-       # least 8 MiB, the minimum size allowed.
-       local min_journal_size=8
-       local default_journal_size=128
-       if (( fssize/8 / (1024*1024) < default_journal_size )); then
-           local journal_size=$(( fssize/8 / (1024*1024) ))
-           (( journal_size >= min_journal_size )) || journal_size=$min_journal_size
-           MKFS_OPTIONS="-J $journal_size $MKFS_OPTIONS"
-       fi
-       ${MKFS_PROG}.$FSTYP $MKFS_OPTIONS -O -b $blocksize $SCRATCH_DEV $blocks
-       ;;
-    ocfs2)
-       yes | ${MKFS_PROG}.$FSTYP -F $MKFS_OPTIONS -b $blocksize $SCRATCH_DEV $blocks
-       ;;
-    udf)
-       $MKFS_UDF_PROG $MKFS_OPTIONS -b $blocksize $SCRATCH_DEV $blocks
-       ;;
-    btrfs)
-       local mixed_opt=
-       # minimum size that's needed without the mixed option.
-       # Ref: btrfs-prog: btrfs_min_dev_size()
-       # Non mixed mode is also the default option.
-       (( fssize < $((256 * 1024 *1024)) )) && mixed_opt='--mixed'
-       $MKFS_BTRFS_PROG $MKFS_OPTIONS $mixed_opt -b $fssize $SCRATCH_DEV
-       ;;
-    jfs)
-       ${MKFS_PROG}.$FSTYP $MKFS_OPTIONS $SCRATCH_DEV $blocks
-       ;;
-    reiserfs)
-       ${MKFS_PROG}.$FSTYP $MKFS_OPTIONS -b $blocksize $SCRATCH_DEV $blocks
-       ;;
-    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`
-       ;;
-    f2fs)
-       # mkfs.f2fs requires # of sectors as an input for the size
-       local sector_size=`blockdev --getss $SCRATCH_DEV`
-       $MKFS_F2FS_PROG $MKFS_OPTIONS $SCRATCH_DEV `expr $fssize / $sector_size`
-       ;;
-    tmpfs)
-       local free_mem=`_free_memory_bytes`
-       if [ "$free_mem" -lt "$fssize" ] ; then
-          _notrun "Not enough memory ($free_mem) for tmpfs with $fssize bytes"
+
+       if [ "$FSTYP" = "xfs" ] && [ -b "$SCRATCH_RTDEV" ]; then
+               local rtdevsize=`blockdev --getsize64 $SCRATCH_RTDEV`
+               [ "$fssize" -gt "$rtdevsize" ] && _notrun "Scratch rt device too small"
+               rt_ops="-r size=$fssize"
        fi
-       export MOUNT_OPTIONS="-o size=$fssize $TMPFS_MOUNT_OPTIONS"
-       ;;
-    *)
-       _notrun "Filesystem $FSTYP not supported in _scratch_mkfs_sized"
-       ;;
-    esac
+
+       case $FSTYP in
+       xfs)
+               # don't override MKFS_OPTIONS that set a block size.
+               echo $MKFS_OPTIONS |egrep -q "b?size="
+               if [ $? -eq 0 ]; then
+                       _scratch_mkfs_xfs -d size=$fssize $rt_ops
+               else
+                       _scratch_mkfs_xfs -d size=$fssize $rt_ops -b size=$blocksize
+               fi
+               ;;
+       ext2|ext3|ext4|ext4dev)
+               ${MKFS_PROG} -t $FSTYP -F $MKFS_OPTIONS -b $blocksize $SCRATCH_DEV $blocks
+               ;;
+       gfs2)
+               # mkfs.gfs2 doesn't automatically shrink journal files on small
+               # filesystems, so the journal files may end up being bigger than the
+               # filesystem, which will cause mkfs.gfs2 to fail.  Until that's fixed,
+               # shrink the journal size to at most one eigth of the filesystem and at
+               # least 8 MiB, the minimum size allowed.
+               local min_journal_size=8
+               local default_journal_size=128
+               if (( fssize/8 / (1024*1024) < default_journal_size )); then
+                       local journal_size=$(( fssize/8 / (1024*1024) ))
+                       (( journal_size >= min_journal_size )) || journal_size=$min_journal_size
+                       MKFS_OPTIONS="-J $journal_size $MKFS_OPTIONS"
+               fi
+               ${MKFS_PROG} -t $FSTYP $MKFS_OPTIONS -O -b $blocksize $SCRATCH_DEV $blocks
+               ;;
+       ocfs2)
+               yes | ${MKFS_PROG} -t $FSTYP -F $MKFS_OPTIONS -b $blocksize $SCRATCH_DEV $blocks
+               ;;
+       udf)
+               $MKFS_UDF_PROG $MKFS_OPTIONS -b $blocksize $SCRATCH_DEV $blocks
+               ;;
+       btrfs)
+               local mixed_opt=
+               # minimum size that's needed without the mixed option.
+               # Ref: btrfs-prog: btrfs_min_dev_size()
+               # Non mixed mode is also the default option.
+               (( fssize < $((256 * 1024 *1024)) )) && mixed_opt='--mixed'
+               $MKFS_BTRFS_PROG $MKFS_OPTIONS $mixed_opt -b $fssize $SCRATCH_DEV
+               ;;
+       jfs)
+               ${MKFS_PROG} -t $FSTYP $MKFS_OPTIONS $SCRATCH_DEV $blocks
+               ;;
+       reiserfs)
+               ${MKFS_PROG} -t $FSTYP $MKFS_OPTIONS -b $blocksize $SCRATCH_DEV $blocks
+               ;;
+       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`
+               ;;
+       f2fs)
+               # mkfs.f2fs requires # of sectors as an input for the size
+               local sector_size=`blockdev --getss $SCRATCH_DEV`
+               $MKFS_F2FS_PROG $MKFS_OPTIONS $SCRATCH_DEV `expr $fssize / $sector_size`
+               ;;
+       tmpfs)
+               local free_mem=`_free_memory_bytes`
+               if [ "$free_mem" -lt "$fssize" ] ; then
+                  _notrun "Not enough memory ($free_mem) for tmpfs with $fssize bytes"
+               fi
+               export MOUNT_OPTIONS="-o size=$fssize $TMPFS_MOUNT_OPTIONS"
+               ;;
+       bcachefs)
+               $MKFS_PROG -t $FSTYP -- $MKFS_OPTIONS --fs_size=$fssize --block_size=$blocksize $SCRATCH_DEV
+               ;;
+       *)
+               _notrun "Filesystem $FSTYP not supported in _scratch_mkfs_sized"
+               ;;
+       esac
 }
 
 # Emulate an N-data-disk stripe w/ various stripe units
@@ -1051,7 +1088,19 @@ _scratch_mkfs_geom()
 
     case $FSTYP in
     xfs)
-       MKFS_OPTIONS+=" -b size=$blocksize, -d su=$sunit_bytes,sw=$swidth_mult"
+       if echo "$MKFS_OPTIONS" | egrep -q "b?size="; then
+               MKFS_OPTIONS=$(echo "$MKFS_OPTIONS" | sed -r "s/(b?size=)[0-9]+k?/\1$blocksize/")
+       else
+               MKFS_OPTIONS+=" -b size=$blocksize"
+       fi
+
+       if echo "$MKFS_OPTIONS" | egrep -q "(su|sunit|sw|swidth)="; then
+               MKFS_OPTIONS=$(echo "$MKFS_OPTIONS" | sed -r \
+                       -e "s/(su|sunit)=[0-9kmg]+/su=$sunit_bytes/" \
+                       -e "s/(sw|swidth)=[0-9kmg]+/sw=$swidth_mult/")
+       else
+               MKFS_OPTIONS+=" -d su=$sunit_bytes,sw=$swidth_mult"
+       fi
        ;;
     ext4|ext4dev)
        MKFS_OPTIONS+=" -b $blocksize -E stride=$sunit_blocks,stripe_width=$swidth_blocks"
@@ -1067,30 +1116,44 @@ _scratch_mkfs_geom()
 # _scratch_mkfs_blocksized blocksize
 _scratch_mkfs_blocksized()
 {
-    local blocksize=$1
+       local blocksize=$1
 
-    local re='^[0-9]+$'
-    if ! [[ $blocksize =~ $re ]] ; then
-        _notrun "error: _scratch_mkfs_sized: block size \"$blocksize\" not an integer."
-    fi
+       local re='^[0-9]+$'
+       if ! [[ $blocksize =~ $re ]] ; then
+               _notrun "error: _scratch_mkfs_sized: block size \"$blocksize\" not an integer."
+       fi
 
-    case $FSTYP in
-    xfs)
-       _scratch_mkfs_xfs $MKFS_OPTIONS -b size=$blocksize
-       ;;
-    ext2|ext3|ext4)
-       ${MKFS_PROG}.$FSTYP -F $MKFS_OPTIONS -b $blocksize $SCRATCH_DEV
-       ;;
-    gfs2)
-       ${MKFS_PROG}.$FSTYP $MKFS_OPTIONS -O -b $blocksize $SCRATCH_DEV
-       ;;
-    ocfs2)
-       yes | ${MKFS_PROG}.$FSTYP -F $MKFS_OPTIONS -b $blocksize -C $blocksize $SCRATCH_DEV
-       ;;
-    *)
-       _notrun "Filesystem $FSTYP not supported in _scratch_mkfs_blocksized"
-       ;;
-    esac
+       case $FSTYP in
+       btrfs)
+               test -f /sys/fs/btrfs/features/supported_sectorsizes || \
+               _notrun "Subpage sectorsize support is not found in $FSTYP"
+
+               grep -wq $blocksize /sys/fs/btrfs/features/supported_sectorsizes || \
+               _notrun "$FSTYP does not support sectorsize=$blocksize yet"
+
+               _scratch_mkfs --sectorsize=$blocksize
+               ;;
+       xfs)
+               _scratch_mkfs_xfs $MKFS_OPTIONS -b size=$blocksize
+               ;;
+       ext2|ext3|ext4)
+               ${MKFS_PROG} -t $FSTYP -F $MKFS_OPTIONS -b $blocksize $SCRATCH_DEV
+               ;;
+       gfs2)
+               ${MKFS_PROG} -t $FSTYP $MKFS_OPTIONS -O -b $blocksize $SCRATCH_DEV
+               ;;
+       ocfs2)
+               yes | ${MKFS_PROG} -t $FSTYP -F $MKFS_OPTIONS -b $blocksize \
+                                               -C $blocksize $SCRATCH_DEV
+               ;;
+       bcachefs)
+               ${MKFS_PROG} -t $FSTYP $MKFS_OPTIONS --block_size=$blocksize \
+                                                               $SCRATCH_DEV
+               ;;
+       *)
+               _notrun "Filesystem $FSTYP not supported in _scratch_mkfs_blocksized"
+               ;;
+       esac
 }
 
 _scratch_resvblks()
@@ -1133,6 +1196,11 @@ _repair_scratch_fs()
        fi
        return $res
         ;;
+    bcachefs)
+       # With bcachefs, if fsck detects any errors we consider it a bug and we
+       # want the test to fail:
+       _check_scratch_fs
+       ;;
     *)
        local dev=$SCRATCH_DEV
        local fstyp=$FSTYP
@@ -1428,24 +1496,6 @@ _supported_fs()
     _notrun "not suitable for this filesystem type: $FSTYP"
 }
 
-
-# tests whether $FSTYP is one of the supported OSes for a test
-#
-_supported_os()
-{
-    local h
-
-    for h
-    do
-       if [ "$h" = "$HOSTOS" ]
-       then
-           return
-       fi
-    done
-
-    _notrun "not suitable for this OS: $HOSTOS"
-}
-
 # check if a FS on a device is mounted
 # if so, verify that it is mounted on mount point
 # if fstype is given as argument, verify that it is also
@@ -1544,7 +1594,7 @@ _require_scratch_nocheck()
        tmpfs)
                if [ -z "$SCRATCH_DEV" -o ! -d "$SCRATCH_MNT" ];
                then
-                   _notrun "this test requires a valid \$SCRATCH_MNT and unique $SCRATCH_DEV"
+                   _notrun "this test requires a valid \$SCRATCH_MNT and unique \$SCRATCH_DEV"
                fi
                ;;
        ubifs)
@@ -1604,6 +1654,38 @@ _require_scratch_size()
        [ $devsize -lt $1 ] && _notrun "scratch dev too small"
 }
 
+# require a scratch dev of a minimum size (in kb) and should not be checked
+# post test
+_require_scratch_size_nocheck()
+{
+       [ $# -eq 1 ] || _fail "_require_scratch_size: expected size param"
+
+       _require_scratch_nocheck
+       local devsize=`_get_device_size $SCRATCH_DEV`
+       [ $devsize -lt $1 ] && _notrun "scratch dev too small"
+}
+
+# Require scratch fs which supports >16T of filesystem size.
+# _require_scratch must be called before this function is called.
+_require_scratch_16T_support()
+{
+       case $FSTYP in
+       ext2|ext3|f2fs)
+               _notrun "$FSTYP doesn't support >16T filesystem"
+               ;;
+       ext4)
+               _scratch_mkfs >> $seqres.full 2>&1
+               _scratch_mount
+               local blocksize=$(_get_block_size $SCRATCH_MNT)
+               if [ $blocksize -lt 4096 ]; then
+                       _notrun "This test requires >16T fs support"
+               fi
+               _scratch_unmount
+               ;;
+       *)
+               ;;
+       esac
+}
 
 # this test needs a test partition - check we're ok & mount it
 #
@@ -1733,11 +1815,6 @@ _require_logdev()
 #
 _require_loop()
 {
-    if [ "$HOSTOS" != "Linux" ]
-    then
-       _notrun "This test requires linux for loopback device support"
-    fi
-
     modprobe loop >/dev/null 2>&1
     if grep loop /proc/devices >/dev/null 2>&1
     then
@@ -1747,31 +1824,13 @@ _require_loop()
     fi
 }
 
-# this test requires ext2 filesystem support
-#
-_require_ext2()
-{
-    if [ "$HOSTOS" != "Linux" ]
-    then
-       _notrun "This test requires linux for ext2 filesystem support"
-    fi
-
-    modprobe ext2 >/dev/null 2>&1
-    if grep ext2 /proc/filesystems >/dev/null 2>&1
-    then
-       :
-    else
-       _notrun "This test requires ext2 filesystem support"
-    fi
-}
-
-# this test requires tmpfs filesystem support
+# this test requires kernel support for a secondary filesystem
 #
-_require_tmpfs()
+_require_extra_fs()
 {
-       modprobe tmpfs >/dev/null 2>&1
-       grep -q tmpfs /proc/filesystems ||
-               _notrun "this test requires tmpfs support"
+       modprobe "$1" >/dev/null 2>&1
+       grep -q -w "$1" /proc/filesystems ||
+               _notrun "this test requires $1 support"
 }
 
 # this test requires that (large) loopback device files are not in use
@@ -1874,7 +1933,8 @@ _require_dm_target()
        _require_sane_bdev_flush $SCRATCH_DEV
        _require_command "$DMSETUP_PROG" dmsetup
 
-       echo $MOUNT_OPTIONS | grep -q dax
+       _normalize_mount_options | egrep -q "dax(=always| |$)" || \
+                       test -e "/sys/block/$(_short_dev $SCRATCH_DEV)/dax"
        if [ $? -eq 0 ]; then
                case $target in
                stripe|linear|log-writes)
@@ -1893,6 +1953,50 @@ _require_dm_target()
        fi
 }
 
+_zone_type()
+{
+       local target=$1
+       if [ -z $target ]; then
+               echo "Usage: _zone_type <device>"
+               exit 1
+       fi
+       local sdev=`_short_dev $target`
+
+       if [ -e /sys/block/${sdev}/queue/zoned ]; then
+               cat /sys/block/${sdev}/queue/zoned
+       else
+               echo none
+       fi
+}
+
+_require_zoned_device()
+{
+       local target=$1
+       if [ -z $target ]; then
+               echo "Usage: _require_zoned_device <device>"
+               exit 1
+       fi
+
+       local type=`_zone_type ${target}`
+       if [ "${type}" = "none" ]; then
+               _notrun "this test require zoned block device"
+       fi
+}
+
+_require_non_zoned_device()
+{
+       local target=$1
+       if [ -z $target ]; then
+               echo "Usage: _require_non_zoned_device <device>"
+               exit 1
+       fi
+
+       local type=`_zone_type ${target}`
+       if [ "${type}" != "none" ]; then
+               _notrun "this test require non-zoned block device"
+       fi
+}
+
 # this test requires the ext4 kernel support crc feature on scratch device
 #
 _require_scratch_ext4_crc()
@@ -1962,6 +2066,56 @@ _require_aiodio()
     _require_odirect
 }
 
+# this test requires that the kernel supports IO_URING
+_require_io_uring()
+{
+       $here/src/feature -R
+       case $? in
+       0)
+               ;;
+       1)
+               _notrun "kernel does not support IO_URING"
+               ;;
+       *)
+               _fail "unexpected error testing for IO_URING support"
+               ;;
+       esac
+}
+
+# test whether the mount_setattr syscall is available
+_require_mount_setattr()
+{
+       $here/src/feature -r
+       case $? in
+       0)
+               ;;
+       1)
+               _notrun "kernel does not support mount_setattr syscall"
+               ;;
+       *)
+               _fail "unexpected error testing for mount_setattr support"
+               ;;
+       esac
+}
+
+# test whether idmapped mounts are supported
+_require_idmapped_mounts()
+{
+        IDMAPPED_MOUNTS_TEST=$here/src/idmapped-mounts/idmapped-mounts
+        [ -x $IDMAPPED_MOUNTS_TEST ] || _notrun "idmapped-mounts utilities required"
+
+       _require_mount_setattr
+
+       $here/src/idmapped-mounts/idmapped-mounts --supported \
+               --device "$TEST_DEV" \
+               --mount "$TEST_DIR" \
+               --fstype "$FSTYP"
+
+       if [ $? -ne 0 ]; then
+               _notrun "idmapped-mounts not support by $FSTYP"
+       fi
+}
+
 # this test requires that a test program exists under src/
 # $1 - command (require)
 #
@@ -2036,7 +2190,7 @@ _filesystem_timestamp_range()
                echo "0 $u32max"
                ;;
        xfs)
-               echo "$s32min $s32max"
+               _xfs_timestamp_range "$device"
                ;;
        btrfs)
                echo "$s64min $s64max"
@@ -2097,6 +2251,40 @@ _require_user()
     [ "$?" == "0" ] || _notrun "$qa_user cannot execute commands."
 }
 
+# check for a chown support
+#
+_require_chown()
+{
+       local rnd_uid=4242
+       local file="$TEST_DIR/chown_testfile"
+
+       rm -f $file
+       touch $file
+       chown ${rnd_uid}:${rnd_uid} $file >/dev/null 2>&1 \
+               || _notrun "chown is not supported ${FSTYP}"
+}
+
+
+# check for a chmod support
+# Since chmod sometimes fails silently actual functionality test is done
+#
+_require_chmod()
+{
+       local file="$TEST_DIR/chmod_testfile"
+
+       rm -f $file
+       touch $file
+
+       # get original file mode
+       local mode=`stat --format="0%a" $file`
+       # flip the user's read bit
+       let mode^=0400
+       chmod `printf '%o' "$mode"` $file
+       # check that the chmod actually flipped the bit
+       [ `stat --format="0%a" $file` == `printf '0%o' "$mode"` ] \
+               || _notrun "chmod is not supported ${FSTYP}"
+}
+
 # check for a group on the machine, fsgqa as default
 #
 _require_group()
@@ -2136,19 +2324,37 @@ _require_xfs_io_command()
        local param="$*"
        local param_checked=""
        local opts=""
+       local attr_info=""
 
        local testfile=$TEST_DIR/$$.xfs_io
        local testio
        case $command in
+       "lsattr")
+               # Test xfs_io lsattr support and filesystem FS_IOC_FSSETXATTR
+               # support.
+               testio=`$XFS_IO_PROG -F -f -c "lsattr $param" $testfile 2>&1`
+               param_checked="$param"
+               ;;
        "chattr")
+               local testdir=$TEST_DIR/$$.attr_dir
+               mkdir $TEST_DIR/$$.attr_dir
                if [ -z "$param" ]; then
                        param=s
                fi
                # Test xfs_io chattr support AND
                # filesystem FS_IOC_FSSETXATTR support
-               testio=`$XFS_IO_PROG -F -f -c "chattr +$param" $testfile 2>&1`
-               $XFS_IO_PROG -F -f -r -c "chattr -$param" $testfile 2>&1
+               # 'tPnE' flags are only valid for a directory so check them on a directory.
+               if echo "$param" | egrep -q 't|P|n|E'; then
+                       testio=`$XFS_IO_PROG -F -c "chattr +$param" $testdir 2>&1`
+                       attr_info=`$XFS_IO_PROG -F -r -c "lsattr" $testdir | awk '{print $1}'`
+                       $XFS_IO_PROG -F -r -c "chattr -$param" $testdir 2>&1
+               else
+                       testio=`$XFS_IO_PROG -F -f -c "chattr +$param" $testfile 2>&1`
+                       attr_info=`$XFS_IO_PROG -F -r -c "lsattr" $testfile | awk '{print $1}'`
+                       $XFS_IO_PROG -F -r -c "chattr -$param" $testfile 2>&1
+               fi
                param_checked="+$param"
+               rm -rf $testdir 2>&1 > /dev/null
                ;;
        "chproj")
                testio=`$XFS_IO_PROG -F -f -c "chproj 0" $testfile 2>&1`
@@ -2269,6 +2475,19 @@ _require_xfs_io_command()
                echo $testio | grep -q "\(invalid option\|not supported\)" && \
                        _notrun "xfs_io $command doesn't support $param"
        fi
+
+       # On XFS, ioctl(FSSETXATTR)(called by xfs_io -c "chattr") maskes off unsupported
+       # or invalid flags silently so need to check these flags by extra ioctl(FSGETXATTR)
+       # (called by xfs_io -c "lsattr").
+       # The following URL explains why we don't change the behavior of XFS.
+       # https://www.spinics.net/lists/linux-xfs/msg44725.html
+       if [ -n "$attr_info" -a "$FSTYP" = "xfs" ]; then
+               local num=${#param}
+               for i in $(seq 0 $((num-1))); do
+                       echo $attr_info | grep -q "${param:$i:1}" || \
+                               _notrun "xfs_io $command +${param:$i:1} support is missing (unknown flag in kernel)"
+               done
+       fi
 }
 
 # check that kernel and filesystem support direct I/O
@@ -2302,7 +2521,15 @@ _format_swapfile() {
        # Swap files must be nocow on Btrfs.
        $CHATTR_PROG +C "$fname" > /dev/null 2>&1
        _pwrite_byte 0x61 0 "$sz" "$fname" >> $seqres.full
-       $MKSWAP_PROG "$fname" >> $seqres.full
+       # Ignore permission complaints on filesystems that don't support perms
+       $MKSWAP_PROG "$fname" 2> >(grep -v 'insecure permission' >&2) >> $seqres.full
+}
+
+_swapon_file() {
+       local fname="$1"
+
+       # Ignore permission complaints on filesystems that don't support perms
+       swapon "$fname" 2> >(grep -v "insecure permissions" >&2)
 }
 
 # Check that the filesystem supports swapfiles
@@ -2329,10 +2556,27 @@ _require_scratch_swapfile()
        # Minimum size for mkswap is 10 pages
        _format_swapfile "$SCRATCH_MNT/swap" $(($(get_page_size) * 10))
 
-       if ! swapon "$SCRATCH_MNT/swap" >/dev/null 2>&1; then
-               _scratch_unmount
-               _notrun "swapfiles are not supported"
-       fi
+       # ext* has supported all variants of swap files since their
+       # introduction, so swapon should not fail.
+       case "$FSTYP" in
+       ext2|ext3|ext4)
+               if ! swapon "$SCRATCH_MNT/swap" >/dev/null 2>&1; then
+                       if _check_s_dax "$SCRATCH_MNT/swap" 1 >/dev/null; then
+                               _scratch_unmount
+                               _notrun "swapfiles are not supported"
+                       else
+                               _scratch_unmount
+                               _fail "swapon failed for $FSTYP"
+                       fi
+               fi
+               ;;
+       *)
+               if ! swapon "$SCRATCH_MNT/swap" >/dev/null 2>&1; then
+                       _scratch_unmount
+                       _notrun "swapfiles are not supported"
+               fi
+               ;;
+       esac
 
        swapoff "$SCRATCH_MNT/swap" >/dev/null 2>&1
        _scratch_unmount
@@ -2667,6 +2911,15 @@ _check_generic_filesystem()
     fi
     rm -f $tmp.fsck
 
+    if [ $ok -eq 0 ] && [ -n "$DUMP_CORRUPT_FS" ]; then
+        case "$FSTYP" in
+        ext*)
+            local flatdev="$(basename "$device")"
+            _ext4_metadump "$seqres.$flatdev.check.qcow2" "$device" compress
+            ;;
+        esac
+    fi
+
     if [ $ok -eq 0 ]
     then
         echo "*** mount output ***"            >>$seqres.full
@@ -3174,18 +3427,54 @@ _require_scratch_shutdown()
        _scratch_unmount
 }
 
-# Does dax mount option work on this dev/fs?
-_require_scratch_dax()
+_check_s_dax()
 {
-       _require_scratch
-       _scratch_mkfs > /dev/null 2>&1
-       _try_scratch_mount -o dax || \
-               _notrun "mount $SCRATCH_DEV with dax failed"
-       # Check options to be sure. XFS ignores dax option
-       # and goes on if dev underneath does not support dax.
-       _fs_options $SCRATCH_DEV | grep -qw "dax" || \
-               _notrun "$SCRATCH_DEV $FSTYP does not support -o dax"
-       _scratch_unmount
+       local target=$1
+       local exp_s_dax=$2
+       local ret=0
+
+       local attributes=$($XFS_IO_PROG -c 'statx -r' $target | awk '/stat.attributes / { print $3 }')
+
+       # The original attribute bit value, STATX_ATTR_DAX (0x2000), conflicted
+       # with STATX_ATTR_MOUNT_ROOT.  Therefore, STATX_ATTR_DAX was changed to
+       # 0x00200000.
+       #
+       # Because DAX tests do not run on root mounts, STATX_ATTR_MOUNT_ROOT
+       # should always be 0.  Check for the old flag and fail the test if that
+       # occurs.
+
+       if [ $(( attributes & 0x2000 )) -ne 0 ]; then
+               echo "$target has an unexpected STATX_ATTR_MOUNT_ROOT flag set"
+               echo "which used to be STATX_ATTR_DAX"
+               echo "     This test should not be running on the root inode..."
+               echo "     Does the kernel have the following patch?"
+               echo "     72d1249e2ffd uapi: fix statx attribute value overlap for DAX & MOUNT_ROOT"
+       fi
+
+       if [ $exp_s_dax -eq 0 ]; then
+               if (( attributes & 0x00200000 )); then
+                       echo "$target has unexpected S_DAX flag"
+                       ret=1
+               fi
+       else
+               if ! (( attributes & 0x00200000 )); then
+                       echo "$target doesn't have expected S_DAX flag"
+                       ret=2
+               fi
+       fi
+       return $ret
+}
+
+_check_xflag()
+{
+       local target=$1
+       local exp_xflag=$2
+
+       if [ $exp_xflag -eq 0 ]; then
+               _test_inode_flag dax $target && echo "$target has unexpected FS_XFLAG_DAX flag"
+       else
+               _test_inode_flag dax $target || echo "$target doesn't have expected FS_XFLAG_DAX flag"
+       fi
 }
 
 # Check if dax mount options are supported
@@ -3265,7 +3554,7 @@ _has_metadata_journaling()
        fi
 
        case "$FSTYP" in
-       ext2|vfat|msdos|udf|exfat)
+       ext2|vfat|msdos|udf|exfat|tmpfs)
                echo "$FSTYP does not support metadata journaling"
                return 1
                ;;
@@ -3450,12 +3739,16 @@ _normalize_mount_options()
 }
 
 # skip test if MOUNT_OPTIONS contains the given strings
+# Both dax and dax=always are excluded if dax or dax=always is passed
 _exclude_scratch_mount_option()
 {
        local mnt_opts=$(_normalize_mount_options)
 
        while [ $# -gt 0 ]; do
-               if echo $mnt_opts | grep -qw "$1"; then
+               local pattern=$1
+               echo "$pattern" | egrep -q "dax(=always|$)" && \
+                       pattern="dax(=always| |$)"
+               if echo $mnt_opts | egrep -q "$pattern"; then
                        _notrun "mount option \"$1\" not allowed in this test"
                fi
                shift
@@ -3466,7 +3759,7 @@ _require_atime()
 {
        _exclude_scratch_mount_option "noatime"
        case $FSTYP in
-       nfs|cifs)
+       nfs|cifs|virtiofs)
                _notrun "atime related mount options have no effect on $FSTYP"
                ;;
        esac
@@ -3675,7 +3968,7 @@ _get_available_space()
 # return device size in kb
 _get_device_size()
 {
-       grep -w `_short_dev $1` /proc/partitions | awk '{print $3}'
+       echo $(($(blockdev --getsz $1) >> 1))
 }
 
 # Make sure we actually have dmesg checking set up.
@@ -3935,11 +4228,18 @@ _get_file_block_size()
                echo "Missing mount point argument for _get_file_block_size"
                exit 1
        fi
-       if [ "$FSTYP" = "ocfs2" ]; then
+
+       case "$FSTYP" in
+       "ocfs2")
                stat -c '%o' $1
-       else
+               ;;
+       "xfs")
+               _xfs_get_file_block_size $1
+               ;;
+       *)
                _get_block_size $1
-       fi
+               ;;
+       esac
 }
 
 # Get the minimum block size of an fs.
@@ -3952,6 +4252,17 @@ _get_block_size()
        stat -f -c %S $1
 }
 
+# Require that the fundamental allocation unit of a file is the same as the
+# filesystem block size.  The sole parameter must be the root dir of a
+# filesystem.
+_require_file_block_size_equals_fs_block_size()
+{
+       local file_alloc_unit="$(_get_file_block_size $1)"
+       local fs_block_size="$(_get_block_size $1)"
+       test "$file_alloc_unit" != "$fs_block_size" && \
+               _notrun "File allocation unit is larger than a filesystem block"
+}
+
 get_page_size()
 {
        echo $(getconf PAGE_SIZE)
@@ -4276,6 +4587,31 @@ _require_mknod()
        rm -f $TEST_DIR/$seq.null
 }
 
+_getcap()
+{
+       $GETCAP_PROG "$@" | _filter_getcap
+       return ${PIPESTATUS[0]}
+}
+
+_require_od_endian_flag()
+{
+       od --endian=little < /dev/null > /dev/null 2>&1 || \
+               _notrun "od does not support endian flag"
+}
+
+# Skip this test unless the filesystem treats names (directory entries,
+# fs labels, and extended attribute names) as raw byte sequences.
+_require_names_are_bytes() {
+        case "$FSTYP" in
+        ext2|ext3|ext4|f2fs|xfs|btrfs)
+               # do nothing
+               ;;
+       *)
+                _notrun "$FSTYP does not allow unrestricted byte streams for names"
+               ;;
+        esac
+}
+
 init_rc
 
 ################################################################################