common/rc: Add extra check for xfs_io -c "chattr" on XFS
authorXiao Yang <yangx.jy@cn.fujitsu.com>
Mon, 14 Sep 2020 05:14:00 +0000 (13:14 +0800)
committerEryu Guan <guaneryu@gmail.com>
Sun, 20 Sep 2020 15:56:21 +0000 (23:56 +0800)
On XFS, ioctl(FSSETXATTR)(called by xfs_io -c "chattr") maskes off unsupported
or invalid flags silently.  For example,
1) With kernel v4.4 which doesn't support dax flag, try to set dax flag on a
file by the lastest xfs_io -c "chattr" command:
--------------------------------------------
0
----------------X testfile
--------------------------------------------
2) Realtime inheritance flag is only valid for a directory and try to set
realtime inheritance flag on a file:
--------------------------------------------
0
----------------X testfile
--------------------------------------------

In this case, we need to check these flags by extra ioctl(FSGETXATTR)(called
by xfs_io -c "lsattr").

Signed-off-by: Xiao Yang <yangx.jy@cn.fujitsu.com>
Reviewed-by: Eryu Guan <guaneryu@gmail.com>
Signed-off-by: Eryu Guan <guaneryu@gmail.com>
common/rc

index 6487b9f2d010cfb4208893181e6a22cc53cbf45c..807a1f6ca225c5b5fbbde1af7a62f4e1f55ff929 100644 (file)
--- a/common/rc
+++ b/common/rc
@@ -2158,6 +2158,7 @@ _require_xfs_io_command()
        local param="$*"
        local param_checked=""
        local opts=""
        local param="$*"
        local param_checked=""
        local opts=""
+       local attr_info=""
 
        local testfile=$TEST_DIR/$$.xfs_io
        local testio
 
        local testfile=$TEST_DIR/$$.xfs_io
        local testio
@@ -2173,9 +2174,11 @@ _require_xfs_io_command()
                # '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`
                # '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`
                        $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"
                        $XFS_IO_PROG -F -r -c "chattr -$param" $testfile 2>&1
                fi
                param_checked="+$param"
@@ -2300,6 +2303,19 @@ _require_xfs_io_command()
                echo $testio | grep -q "\(invalid option\|not supported\)" && \
                        _notrun "xfs_io $command doesn't support $param"
        fi
                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
 }
 
 # check that kernel and filesystem support direct I/O