fstests: check for unknown flag result in _require_xfs_io_command
[xfstests-dev.git] / common / rc
index 3d5c8b23214e07358544c60c9435a2a73161d399..a6967831fad51322efca9d8d9dfb1f640878e96b 100644 (file)
--- a/common/rc
+++ b/common/rc
@@ -165,6 +165,11 @@ if [ ! -z "$REPORT_LIST" ]; then
        _assert_report_list
 fi
 
+_get_filesize()
+{
+    stat -c %s "$1"
+}
+
 _mount()
 {
     $MOUNT_PROG `_mount_ops_filter $*`
@@ -184,6 +189,12 @@ _get_mount()
 
        _mount $scratch_opts $*
        if [ $? -eq 0 ]; then
+               # mount --move operation updates the mountpoint, so remove
+               # the old one and insert the new one
+               if [[ "$*" =~ --move|-M ]]; then
+                       MOUNTED_POINT_STACK=`echo $MOUNTED_POINT_STACK | \
+                                               cut -d\  -f2-`
+               fi
                MOUNTED_POINT_STACK="$mnt_point $MOUNTED_POINT_STACK"
        else
                return 1
@@ -313,7 +324,7 @@ _supports_filetype()
                local testfile=$dir/$$.ftype
                touch $testfile
                # look for DT_UNKNOWN files
-               local unknowns=$(src/t_dir_type $dir u | wc -l)
+               local unknowns=$($here/src/t_dir_type $dir u | wc -l)
                rm $testfile
                # 0 unknowns is success
                return $unknowns
@@ -386,10 +397,10 @@ _scratch_shutdown()
                if [ -z $OVL_BASE_SCRATCH_DEV ]; then
                        _fail "_scratch_shutdown: call _require_scratch_shutdown first in test"
                else
-                       src/godown $* $OVL_BASE_SCRATCH_MNT
+                       $here/src/godown $* $OVL_BASE_SCRATCH_MNT
                fi
        else
-               src/godown $* $SCRATCH_MNT
+               $here/src/godown $* $SCRATCH_MNT
        fi
 }
 
@@ -905,6 +916,17 @@ _free_memory_bytes()
     free -b | grep ^Mem | awk '{print $4}'
 }
 
+_available_memory_bytes()
+{
+       nf=`free -b | grep ^Mem | awk '{print NF}'`
+       if [[ nf -lt 7 ]]; then
+               # Doesn't have available field. Fallback.
+               _free_memory_bytes
+       else
+               free -b | grep ^Mem | awk '{print $7}'
+       fi
+}
+
 # Create fs of certain size on scratch device
 # _scratch_mkfs_sized <size in bytes> [optional blocksize]
 _scratch_mkfs_sized()
@@ -1295,7 +1317,7 @@ _is_block_dev()
     fi
 
     if [ -b "$dev" ]; then
-        src/lstat64 "$dev" | $AWK_PROG '/Device type:/ { print $9 }'
+        $here/src/lstat64 "$dev" | $AWK_PROG '/Device type:/ { print $9 }'
     fi
 }
 
@@ -1314,7 +1336,7 @@ _is_char_dev()
        fi
 
        if [ -c "$dev" ]; then
-               src/lstat64 "$dev" | $AWK_PROG '/Device type:/ { print $9 }'
+               $here/src/lstat64 "$dev" | $AWK_PROG '/Device type:/ { print $9 }'
        fi
 }
 
@@ -1852,6 +1874,17 @@ _require_dm_target()
        _require_sane_bdev_flush $SCRATCH_DEV
        _require_command "$DMSETUP_PROG" dmsetup
 
+       echo $MOUNT_OPTIONS | grep -q dax
+       if [ $? -eq 0 ]; then
+               case $target in
+               stripe|linear|log-writes)
+                       ;;
+               *)
+                       _notrun "Cannot run tests with DAX on $target devices."
+                       ;;
+               esac
+       fi
+
        modprobe dm-$target >/dev/null 2>&1
 
        $DMSETUP_PROG targets 2>&1 | grep -q ^$target
@@ -1919,10 +1952,10 @@ _require_aiodio()
 {
     if [ -z "$1" ]
     then
-        AIO_TEST=src/aio-dio-regress/aiodio_sparse2
+        AIO_TEST=$here/src/aio-dio-regress/aiodio_sparse2
         [ -x $AIO_TEST ] || _notrun "aio-dio utilities required"
     else
-        AIO_TEST=src/aio-dio-regress/$1
+        AIO_TEST=$here/src/aio-dio-regress/$1
         [ -x $AIO_TEST ] || _notrun "$AIO_TEST not built"
     fi
     _require_aio
@@ -1934,7 +1967,7 @@ _require_aiodio()
 #
 _require_test_program()
 {
-    local prog=src/$1
+    local prog=$here/src/$1
     [ -x $prog ] || _notrun "$prog not built"
 }
 
@@ -1959,44 +1992,61 @@ _run_aiodio()
     return $status
 }
 
-# this test requires y2038 sysfs switch and filesystem
-# timestamp ranges support.
-_require_y2038()
+_require_timestamp_range()
 {
        local device=${1:-$TEST_DEV}
-       local sysfsdir=/proc/sys/fs/fs-timestamp-check-on
-
-       if [ ! -e $sysfsdir ]; then
-               _notrun "no kernel support for y2038 sysfs switch"
-       fi
 
        local tsmin tsmax
        read tsmin tsmax <<<$(_filesystem_timestamp_range $device)
        if [ $tsmin -eq -1 -a $tsmax -eq -1 ]; then
                _notrun "filesystem $FSTYP timestamp bounds are unknown"
        fi
+
+       # expect console warning from rw scratch mount if fs limit is near
+       if [ $tsmax -le $((1<<31)) ] && \
+               ! _check_dmesg_for "filesystem being mounted at .* supports timestamps until"
+       then
+               _notrun "Kernel does not support timestamp limits"
+       fi
 }
 
 _filesystem_timestamp_range()
 {
        local device=${1:-$TEST_DEV}
-       case $FSTYP in
-       ext4)
+       local fstyp=${2:-$FSTYP}
+       u32max=$(((1<<32)-1))
+       s32min=-$((1<<31))
+       s32max=$(((1<<31)-1))
+       s64max=$(((1<<63)-1))
+       s64min=$((1<<63))
+
+       case $fstyp in
+       ext2)
+               echo "$s32min $s32max"
+               ;;
+       ext3|ext4)
                if [ $(dumpe2fs -h $device 2>/dev/null | grep "Inode size:" | cut -d: -f2) -gt 128 ]; then
-                       echo "-2147483648 15032385535"
+                       printf "%d %d\n" $s32min 0x37fffffff
                else
-                       echo "-2147483648 2147483647"
+                       echo "$s32min $s32max"
                fi
                ;;
 
+       jfs)
+               echo "0 $u32max"
+               ;;
        xfs)
-               echo "-2147483648 2147483647"
+               echo "$s32min $s32max"
                ;;
-       jfs)
-               echo "0 4294967295"
+       btrfs)
+               echo "$s64min $s64max"
                ;;
-       f2fs)
-               echo "-2147483648 2147483647"
+       overlay)
+               if [ ! -z $OVL_BASE_FSTYP -a $OVL_BASE_FSTYP != "overlay" ]; then
+                       _filesystem_timestamp_range $OVL_BASE_TEST_DEV $OVL_BASE_FSTYP
+               else
+                       echo "-1 -1"
+               fi
                ;;
        *)
                echo "-1 -1"
@@ -2184,7 +2234,7 @@ _require_xfs_io_command()
                        _notrun "xfs_io $command support is missing"
                ;;
        "utimes" )
-               testio=`$XFS_IO_PROG -f -c "utimes" 0 0 0 0 $testfile 2>&1`
+               testio=`$XFS_IO_PROG -f -c "utimes 0 0 0 0" $testfile 2>&1`
                ;;
        "syncfs")
                touch $testfile
@@ -2205,11 +2255,13 @@ _require_xfs_io_command()
                _notrun "xfs_io $command $param_checked not supported on $FSTYP"
        echo $testio | grep -q "Function not implemented" && \
                _notrun "xfs_io $command $param_checked support is missing (missing syscall?)"
+       echo $testio | grep -q "unknown flag" && \
+               _notrun "xfs_io $command $param_checked support is missing (unknown flag)"
 
        [ -n "$param" ] || return
 
        if [ -z "$param_checked" ]; then
-               $XFS_IO_PROG -c "help $command" | grep -q "^ $param --" || \
+               $XFS_IO_PROG -c "help $command" | grep -E -q "^ $param ([a-zA-Z_]+ )?--" || \
                        _notrun "xfs_io $command doesn't support $param"
        else
                # xfs_io could result in "command %c not supported" if it was
@@ -2222,10 +2274,13 @@ _require_xfs_io_command()
 # check that kernel and filesystem support direct I/O
 _require_odirect()
 {
-       if [ $FSTYP = "ext4" ] ; then
+       if [ $FSTYP = "ext4" ] || [ $FSTYP = "f2fs" ] ; then
                if echo "$MOUNT_OPTIONS" | grep -q "test_dummy_encryption"; then
-                       _notrun "ext4 encryption doesn't support O_DIRECT"
-               elif echo "$MOUNT_OPTIONS" | grep -q "data=journal"; then
+                       _notrun "$FSTYP encryption doesn't support O_DIRECT"
+               fi
+       fi
+       if [ $FSTYP = "ext4" ] ; then
+               if echo "$MOUNT_OPTIONS" | grep -q "data=journal"; then
                        _notrun "ext4 data journaling doesn't support O_DIRECT"
                fi
        fi
@@ -2304,7 +2359,7 @@ _require_fs_space()
 _require_sparse_files()
 {
     case $FSTYP in
-    hfsplus)
+    hfsplus|exfat)
         _notrun "Sparse files not supported by this filesystem type: $FSTYP"
        ;;
     *)
@@ -2322,7 +2377,7 @@ _require_fail_make_request()
 {
     [ -f "$DEBUGFS_MNT/fail_make_request/probability" ] \
        || _notrun "$DEBUGFS_MNT/fail_make_request \
- not found. Seems that CONFIG_FAIL_MAKE_REQUEST kernel config option not enabled"
+ not found. Seems that CONFIG_FAULT_INJECTION_DEBUG_FS kernel config option not enabled"
 }
 
 # Disable extent zeroing for ext4 on the given device
@@ -2860,7 +2915,7 @@ _link_out_file()
        local features
 
        if [ $# -eq 0 ]; then
-               features="$(_get_os_name)"
+               features="$(_get_os_name),$FSTYP"
                if [ -n "$MOUNT_OPTIONS" ]; then
                        features=$features,${MOUNT_OPTIONS##"-o "}
                fi
@@ -3095,7 +3150,7 @@ _require_exportfs()
 # Does shutdown work on this fs?
 _require_scratch_shutdown()
 {
-       [ -x src/godown ] || _notrun "src/godown executable not found"
+       [ -x $here/src/godown ] || _notrun "src/godown executable not found"
 
        _scratch_mkfs > /dev/null 2>&1 || _notrun "_scratch_mkfs failed on $SCRATCH_DEV"
        _scratch_mount
@@ -3108,11 +3163,11 @@ _require_scratch_shutdown()
                        # running shutdown to avoid shutting down base fs accidently.
                        _notrun "This test requires a valid $OVL_BASE_SCRATCH_DEV as ovl base fs"
                else
-                       src/godown -f $OVL_BASE_SCRATCH_MNT 2>&1 \
+                       $here/src/godown -f $OVL_BASE_SCRATCH_MNT 2>&1 \
                        || _notrun "Underlying filesystem does not support shutdown"
                fi
        else
-               src/godown -f $SCRATCH_MNT 2>&1 \
+               $here/src/godown -f $SCRATCH_MNT 2>&1 \
                        || _notrun "$FSTYP does not support shutdown"
        fi
 
@@ -3149,7 +3204,7 @@ _require_norecovery()
 # 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()
+_has_metadata_journaling()
 {
        if [ -z $1 ]; then
                local dev=$TEST_DEV
@@ -3158,43 +3213,72 @@ _require_metadata_journaling()
        fi
 
        case "$FSTYP" in
-       ext2|vfat|msdos|udf)
-               _notrun "$FSTYP does not support metadata journaling"
+       ext2|vfat|msdos|udf|exfat)
+               echo "$FSTYP does not support metadata journaling"
+               return 1
                ;;
        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"
+               $DUMPE2FS_PROG -h $dev 2>&1 | grep -q has_journal || {
+                       echo "$FSTYP on $dev not configured with metadata journaling"
+                       return 1
+               }
                # ext4 might not load a journal
-               _exclude_scratch_mount_option "noload"
+               if _normalize_mount_options | grep -qw "noload"; then
+                       echo "mount option \"noload\" not allowed in this test"
+                       return 1
+               fi
                ;;
        overlay)
                # metadata journaling check is based on base filesystem configurations
                # and  because -overlay option saves those configurations to OVL_BASE_*,
                # adding restore/override the configurations before/after the check.
                if [ ! -z $OVL_BASE_FSTYP -a $OVL_BASE_FSTYP != "overlay" ]; then
+                       local ret
+
                        _overlay_config_restore
-                       _require_metadata_journaling
+                       _has_metadata_journaling
+                       ret=$?
                        _overlay_config_override
+                       return $ret
                else
-                       _notrun "No metadata journaling support for legacy overlay setup"
+                       echo "No metadata journaling support for legacy overlay setup"
+                       return 1
                fi
                ;;
        *)
                # by default we pass; if you need to, add your fs above!
                ;;
        esac
+       return 0
+}
+
+_require_metadata_journaling()
+{
+       local msg=$(_has_metadata_journaling $@)
+       if [ -n "$msg" ]; then
+               _notrun "$msg"
+       fi
 }
 
 _count_extents()
 {
-       $XFS_IO_PROG -c "fiemap" $1 | tail -n +2 | grep -v hole | wc -l
+       $XFS_IO_PROG -r -c "fiemap" $1 | tail -n +2 | grep -v hole | wc -l
+}
+
+# Similar to _count_extents() but if any extent is shared multiples times in
+# the file (reflinked to different file offsets), it is accounted as 1 extent
+# instead of N extents.
+_count_exclusive_extents()
+{
+       $XFS_IO_PROG -r -c "fiemap" $1 | tail -n +2 | grep -v hole | \
+               cut -d ' ' -f 3 | sort | uniq | wc -l
 }
 
 _count_holes()
 {
-       $XFS_IO_PROG -c "fiemap" $1 | tail -n +2 | grep hole | wc -l
+       $XFS_IO_PROG -r -c "fiemap" $1 | tail -n +2 | grep hole | wc -l
 }
 
 _count_attr_extents()
@@ -3347,8 +3431,8 @@ _require_relatime()
 
 _require_userns()
 {
-       [ -x src/nsexec ] || _notrun "src/nsexec executable not found"
-       src/nsexec -U true 2>/dev/null || _notrun "userns not supported by this kernel"
+       [ -x $here/src/nsexec ] || _notrun "src/nsexec executable not found"
+       $here/src/nsexec -U true 2>/dev/null || _notrun "userns not supported by this kernel"
 }
 
 _create_loop_device()
@@ -3375,7 +3459,7 @@ _scale_fsstress_args()
         esac
         shift
     done
-    echo $args
+    printf '%s\n' "$args"
 }
 
 #
@@ -3399,7 +3483,7 @@ run_check()
        "$@" >> $seqres.full 2>&1 || _fail "failed: '$@'"
 }
 
-_require_test_symlinks()
+_require_symlinks()
 {
        local target=`mktemp -p $TEST_DIR`
        local link=`mktemp -p $TEST_DIR -u`
@@ -3411,6 +3495,18 @@ _require_test_symlinks()
        rm -f $target $link
 }
 
+_require_hardlinks()
+{
+       local target=`mktemp -p $TEST_DIR`
+       local link=`mktemp -p $TEST_DIR -u`
+       ln $target $link
+       if [ "$?" -ne 0 ]; then
+               rm -f $target
+               _notrun "No hardlink support"
+       fi
+       rm -f $target $link
+}
+
 _require_test_fcntl_advisory_locks()
 {
        [ "$FSTYP" != "cifs" ] && return 0
@@ -3419,6 +3515,14 @@ _require_test_fcntl_advisory_locks()
                _notrun "Require fcntl advisory locks support"
 }
 
+_require_test_fcntl_setlease()
+{
+       _require_test_program "locktest"
+       touch $TEST_DIR/setlease_testfile
+       $here/src/locktest -t $TEST_DIR/setlease_testfile >/dev/null 2>&1
+       [ $? -eq 22 ] && _notrun "Require fcntl setlease support"
+}
+
 _require_ofd_locks()
 {
        # Give a test run by getlk wrlck on testfile.
@@ -3426,7 +3530,7 @@ _require_ofd_locks()
        # EINVAL will be returned.
        _require_test_program "t_ofd_locks"
        touch $TEST_DIR/ofd_testfile
-       src/t_ofd_locks -t $TEST_DIR/ofd_testfile > /dev/null 2>&1
+       $here/src/t_ofd_locks -t $TEST_DIR/ofd_testfile > /dev/null 2>&1
        [ $? -eq 22 ] && _notrun "Require OFD locks support"
 }
 
@@ -3519,7 +3623,7 @@ _get_available_space()
 # return device size in kb
 _get_device_size()
 {
-       grep `_short_dev $1` /proc/partitions | awk '{print $3}'
+       grep -w `_short_dev $1` /proc/partitions | awk '{print $3}'
 }
 
 # Make sure we actually have dmesg checking set up.
@@ -3587,7 +3691,9 @@ _check_dmesg()
                _dump_err "_check_dmesg: something found in dmesg (see $seqres.dmesg)"
                return 1
        else
-               rm -f $seqres.dmesg
+               if [ "$KEEP_DMESG" != "yes" ]; then
+                       rm -f $seqres.dmesg
+               fi
                return 0
        fi
 }
@@ -3933,7 +4039,9 @@ _get_max_lfs_filesize()
 {
        case "$(getconf LONG_BIT)" in
        "32")
-               echo $(( ($(getconf PAGE_SIZE) << ($(getconf LONG_BIT) - 1) ) - 1))
+               local ulong_max=$(getconf ULONG_MAX)
+               local page_size=$(getconf PAGE_SIZE)
+               echo $(( ulong_max * page_size ))
                ;;
        "64")
                echo 9223372036854775807
@@ -4082,6 +4190,40 @@ _check_xfs_scrub_does_unicode() {
        return 0
 }
 
+# exfat timestamps start at 1980 and cannot be prior to epoch
+_require_negative_timestamps() {
+       case "$FSTYP" in
+       ceph|exfat)
+               _notrun "$FSTYP does not support negative timestamps"
+               ;;
+       esac
+}
+
+# Require the 'accton' userspace tool and CONFIG_BSD_PROCESS_ACCT=y.
+_require_bsd_process_accounting()
+{
+       _require_command "$ACCTON_PROG" accton
+       $ACCTON_PROG on &> $tmp.test_accton
+       cat $tmp.test_accton >> $seqres.full
+       if grep 'Function not implemented' $tmp.test_accton; then
+               _notrun "BSD process accounting support unavailable"
+       fi
+       $ACCTON_PROG off >> $seqres.full
+}
+
+_require_sysctl_variable()
+{
+       local name=$1
+       sysctl $name &>/dev/null || _notrun "$name sysctl unavailable"
+}
+
+_require_mknod()
+{
+       mknod $TEST_DIR/$seq.null c 1 3 \
+               || _notrun "$FSTYP does not support mknod/mkfifo"
+       rm -f $TEST_DIR/$seq.null
+}
+
 init_rc
 
 ################################################################################