common/rc: Add extra check for xfs_io -c "chattr" on XFS
[xfstests-dev.git] / common / rc
index 062eb6ba5cd17e0a03939012465bcef059259cd5..807a1f6ca225c5b5fbbde1af7a62f4e1f55ff929 100644 (file)
--- a/common/rc
+++ b/common/rc
@@ -1896,7 +1896,7 @@ _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| |$)"
        if [ $? -eq 0 ]; then
                case $target in
                stripe|linear|log-writes)
@@ -2158,19 +2158,31 @@ _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
        "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`
@@ -2291,6 +2303,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
@@ -3483,12 +3508,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