common/rc: Check 'tPnE' flags on a directory instead of a regilar file
[xfstests-dev.git] / common / rc
index b988e91237709fe27e660f4fe06b88fe3cd0b8f1..6487b9f2d010cfb4208893181e6a22cc53cbf45c 100644 (file)
--- a/common/rc
+++ b/common/rc
@@ -170,6 +170,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 $*`
@@ -189,6 +199,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
@@ -565,7 +581,7 @@ _setup_large_ext4_fs()
 _scratch_mkfs_ext4()
 {
        local mkfs_cmd="$MKFS_EXT4_PROG -F"
-       local mkfs_filter="grep -v -e ^Warning: -e \"^mke2fs \""
+       local mkfs_filter="grep -v -e ^Warning: -e \"^mke2fs \" | grep -v \"^$\""
        local tmp=`mktemp -u`
        local mkfs_status
 
@@ -910,6 +926,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()
@@ -1034,7 +1061,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]+/\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"
@@ -1857,6 +1896,17 @@ _require_dm_target()
        _require_sane_bdev_flush $SCRATCH_DEV
        _require_command "$DMSETUP_PROG" dmsetup
 
+       _normalize_mount_options | egrep -q "dax(=always| |$)"
+       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
@@ -1973,18 +2023,26 @@ _require_timestamp_range()
        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}
+       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
+       case $fstyp in
        ext2)
                echo "$s32min $s32max"
                ;;
@@ -2005,6 +2063,13 @@ _filesystem_timestamp_range()
        btrfs)
                echo "$s64min $s64max"
                ;;
+       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"
                ;;
@@ -2098,14 +2163,23 @@ _require_xfs_io_command()
        local testio
        case $command in
        "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`
+                       $XFS_IO_PROG -F -r -c "chattr -$param" $testdir 2>&1
+               else
+                       testio=`$XFS_IO_PROG -F -f -c "chattr +$param" $testfile 2>&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`
@@ -2212,11 +2286,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
@@ -2266,7 +2342,7 @@ _require_scratch_swapfile()
        _require_scratch
        _require_command "$MKSWAP_PROG" "mkswap"
 
-       _scratch_mkfs >/dev/null
+       _scratch_mkfs >/dev/null 2>&1
 
        # With mounting SELinux context(e.g. system_u:object_r:root_t:s0),
        # standard mkswap tried to reset the type of default context to
@@ -2314,7 +2390,7 @@ _require_fs_space()
 _require_sparse_files()
 {
     case $FSTYP in
-    hfsplus)
+    hfsplus|exfat)
         _notrun "Sparse files not supported by this filesystem type: $FSTYP"
        ;;
     *)
@@ -2332,7 +2408,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
@@ -3129,18 +3205,81 @@ _require_scratch_shutdown()
        _scratch_unmount
 }
 
-# Does dax mount option work on this dev/fs?
-_require_scratch_dax()
+_check_s_dax()
+{
+       local target=$1
+       local exp_s_dax=$2
+
+       local attributes=$($XFS_IO_PROG -c 'statx -r' $target | awk '/stat.attributes / { print $3 }')
+       if [ $exp_s_dax -eq 0 ]; then
+               (( attributes & 0x2000 )) && echo "$target has unexpected S_DAX flag"
+       else
+               (( attributes & 0x2000 )) || echo "$target doen't have expected S_DAX flag"
+       fi
+}
+
+_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 doen't have expected FS_XFLAG_DAX flag"
+       fi
+}
+
+# Check if dax mount options are supported
+#
+# $1 can be either 'dax=always' or 'dax'
+#
+# dax=always
+#      Check for the new dax options (dax=inode, dax=always or dax=never)
+#      by passing "dax=always".
+# dax
+#      Check for the old dax or new dax=always by passing "dax".
+#
+# This only accepts 'dax=always' because dax=always, dax=inode and
+# dax=never are always supported together.  So if the other options are
+# required checking for 'dax=always' indicates support for the other 2.
+#
+# Return 0 if filesystem/device supports the specified dax option.
+# Return 1 if mount fails with the specified dax option.
+# Return 2 if /proc/mounts shows wrong dax option.
+_check_scratch_dax_mountopt()
 {
+       local option=$1
+
        _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
+
+       _try_scratch_mount "-o $option" > /dev/null 2>&1 || return 1
+
+       if _fs_options $SCRATCH_DEV | egrep -q "dax(=always|,|$)"; then
+               _scratch_unmount
+               return 0
+       else
+               _scratch_unmount
+               return 2
+       fi
+}
+
+# Throw notrun if _check_scratch_dax_mountopt() returns a non-zero value.
+_require_scratch_dax_mountopt()
+{
+       local mountopt=$1
+
+       _check_scratch_dax_mountopt "$mountopt"
+       local res=$?
+
+       [ $res -eq 1 ] && _notrun "mount $SCRATCH_DEV with $mountopt failed"
+       [ $res -eq 2 ] && _notrun "$SCRATCH_DEV $FSTYP does not support -o $mountopt"
+}
+
+_require_dax_iflag()
+{
+       _require_xfs_io_command "chattr" "x"
 }
 
 # Does norecovery support by this fs?
@@ -3168,7 +3307,7 @@ _has_metadata_journaling()
        fi
 
        case "$FSTYP" in
-       ext2|vfat|msdos|udf)
+       ext2|vfat|msdos|udf|exfat)
                echo "$FSTYP does not support metadata journaling"
                return 1
                ;;
@@ -3353,12 +3492,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
@@ -3414,7 +3557,7 @@ _scale_fsstress_args()
         esac
         shift
     done
-    echo $args
+    printf '%s\n' "$args"
 }
 
 #
@@ -3438,7 +3581,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`
@@ -3450,6 +3593,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
@@ -3458,6 +3613,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.
@@ -3558,7 +3721,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.
@@ -3626,7 +3789,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
 }
@@ -3972,7 +4137,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
@@ -4121,6 +4288,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
 
 ################################################################################