common/rc: fix unicode checker detection in xfs_scrub
[xfstests-dev.git] / common / rc
index 275b1f2421f7b60a9543dd394cad7b036a531d40..b3289de985d80f6c8d40f533c00ae76d6ce90416 100644 (file)
--- a/common/rc
+++ b/common/rc
@@ -917,15 +917,15 @@ _scratch_dev_pool_get()
                _fail "Usage: _scratch_dev_pool_get ndevs"
        fi
 
-       local test_ndevs=$1
-       local config_ndevs=`echo $SCRATCH_DEV_POOL| wc -w`
-       local -a devs="( $SCRATCH_DEV_POOL )"
-
-       typeset -p config_ndevs >/dev/null 2>&1
+       typeset -p SCRATCH_DEV_POOL >/dev/null 2>&1
        if [ $? -ne 0 ]; then
                _fail "Bug: cant find SCRATCH_DEV_POOL ndevs"
        fi
 
+       local test_ndevs=$1
+       local config_ndevs=`echo $SCRATCH_DEV_POOL| wc -w`
+       local -a devs="( $SCRATCH_DEV_POOL )"
+
        if [ $config_ndevs -lt $test_ndevs ]; then
                _notrun "Need at least test requested number of ndevs $test_ndevs"
        fi
@@ -1592,7 +1592,7 @@ _require_scratch_nocheck()
                        _notrun "this test requires a valid \$SCRATCH_MNT"
                fi
                ;;
-       nfs*|ceph)
+       nfs*)
                echo $SCRATCH_DEV | grep -q ":/" > /dev/null 2>&1
                if [ -z "$SCRATCH_DEV" -o "$?" != "0" ]; then
                        _notrun "this test requires a valid \$SCRATCH_DEV"
@@ -1601,6 +1601,15 @@ _require_scratch_nocheck()
                        _notrun "this test requires a valid \$SCRATCH_MNT"
                fi
                ;;
+       ceph)
+               echo $SCRATCH_DEV | grep -qE "=/|:/" > /dev/null 2>&1
+               if [ -z "$SCRATCH_DEV" -o "$?" != "0" ]; then
+                       _notrun "this test requires a valid \$SCRATCH_DEV"
+               fi
+               if [ ! -d "$SCRATCH_MNT" ]; then
+                       _notrun "this test requires a valid \$SCRATCH_MNT"
+               fi
+               ;;
        pvfs2)
                echo $SCRATCH_DEV | grep -q "://" > /dev/null 2>&1
                if [ -z "$SCRATCH_DEV" -o "$?" != "0" ]; then
@@ -1676,6 +1685,28 @@ _require_scratch_nocheck()
     rm -f ${RESULT_DIR}/require_scratch
 }
 
+# we need the scratch device and it needs to not be an lvm device
+_require_scratch_nolvm()
+{
+       _require_scratch_nocheck
+
+       # This works if we don't have LVM, all we want is to skip if the scratch
+       # device is an lvm device.
+       $LVM_PROG lvdisplay $SCRATCH_DEV > /dev/null 2>&1
+       [ $? -eq 0 ] && _notrun "test requires a non-lvm scratch device"
+}
+
+_require_no_compress()
+{
+       case "$FSTYP" in
+       btrfs)
+               _require_btrfs_no_compress
+               ;;
+       *)
+               ;;
+       esac
+}
+
 # we need the scratch device and it should be checked post test.
 _require_scratch()
 {
@@ -1726,6 +1757,19 @@ _require_scratch_16T_support()
        esac
 }
 
+# Require scratch fs supports delay allocation.
+_require_scratch_delalloc()
+{
+       _require_command "$FILEFRAG_PROG" filefrag
+
+       _scratch_mkfs > $seqres.full
+       _scratch_mount
+       $XFS_IO_PROG -f -c 'pwrite 0 64k' $SCRATCH_MNT/testy &> /dev/null
+       $FILEFRAG_PROG -v $SCRATCH_MNT/testy 2>&1 | grep -q delalloc || \
+               _notrun "test requires delayed allocation buffered writes"
+       _scratch_unmount
+}
+
 # this test needs a test partition - check we're ok & mount it
 #
 _require_test()
@@ -1748,7 +1792,7 @@ _require_test()
                        _notrun "this test requires a valid \$TEST_DIR"
                fi
                ;;
-       nfs*|ceph)
+       nfs*)
                echo $TEST_DEV | grep -q ":/" > /dev/null 2>&1
                if [ -z "$TEST_DEV" -o "$?" != "0" ]; then
                        _notrun "this test requires a valid \$TEST_DEV"
@@ -1757,6 +1801,15 @@ _require_test()
                        _notrun "this test requires a valid \$TEST_DIR"
                fi
                ;;
+       ceph)
+               echo $TEST_DEV | grep -qE "=/|:/" > /dev/null 2>&1
+               if [ -z "$TEST_DEV" -o "$?" != "0" ]; then
+                       _notrun "this test requires a valid \$TEST_DEV"
+               fi
+               if [ ! -d "$TEST_DIR" ]; then
+                       _notrun "this test requires a valid \$TEST_DIR"
+               fi
+               ;;
        cifs)
                echo $TEST_DEV | grep -q "//" > /dev/null 2>&1
                if [ -z "$TEST_DEV" -o "$?" != "0" ]; then
@@ -1965,12 +2018,19 @@ _require_sane_bdev_flush()
 }
 
 # Decide if the scratch filesystem is likely to be mounted in fsdax mode.
-# If there's a dax clause in the mount options we assume the test runner
-# wants us to test DAX; or if the scratch device itself advertises dax mode
-# in sysfs.
-__detect_scratch_fsdax()
+# It goes 3 ways based on mount options::
+#      1. "dax" or "dax=always" means always test using DAX
+#      2. "dax=never" means we'll never use DAX
+#      3. "dax=inode" or nothing means "use scratch dev capability" to
+#          determine whether DAX is going to be used.
+#
+# Returns 0 if DAX will be used, 1 if DAX is not going to be used.
+__scratch_uses_fsdax()
 {
-       _normalize_mount_options | egrep -q "dax(=always| |$)" && return 0
+       local ops=$(_normalize_mount_options "$MOUNT_OPTIONS")
+
+       echo $ops | egrep -qw "dax(=always| |$)" && return 0
+       echo $ops | grep -qw "dax=never" && return 1
 
        local sysfs="/sys/block/$(_short_dev $SCRATCH_DEV)"
        test -e "${sysfs}/dax" && return 0
@@ -1982,6 +2042,8 @@ __detect_scratch_fsdax()
 _require_dm_target()
 {
        local target=$1
+       local fsdax
+       local bdevdax
 
        # require SCRATCH_DEV to be a valid block device with sane BLKFLSBUF
        # behaviour
@@ -1989,7 +2051,7 @@ _require_dm_target()
        _require_sane_bdev_flush $SCRATCH_DEV
        _require_command "$DMSETUP_PROG" dmsetup
 
-       if __detect_scratch_fsdax; then
+       if __scratch_uses_fsdax; then
                case $target in
                stripe|linear|log-writes)
                        ;;
@@ -2301,18 +2363,27 @@ _cat_group()
        cat /etc/group
 }
 
-# check for a user on the machine, fsgqa as default
+# check if a user exists in the system
+#
+_require_user_exists()
+{
+       local user=$1
+       _cat_passwd | grep -q "^$user:"
+       [ "$?" == "0" ] || _notrun "$user user not defined."
+}
+
+# check if a user exists and is able to execute commands.
+# Uses 'fsgqa' user as default.
 #
 _require_user()
 {
-    qa_user=fsgqa
-    if [ -n "$1" ];then
-        qa_user=$1
-    fi
-    _cat_passwd | grep -q $qa_user
-    [ "$?" == "0" ] || _notrun "$qa_user user not defined."
-    echo /bin/true | su $qa_user
-    [ "$?" == "0" ] || _notrun "$qa_user cannot execute commands."
+       qa_user=fsgqa
+       if [ -n "$1" ];then
+               qa_user=$1
+       fi
+       _require_user_exists $qa_user
+       echo /bin/true | su $qa_user
+       [ "$?" == "0" ] || _notrun "$qa_user cannot execute commands."
 }
 
 # check for a chown support
@@ -2575,9 +2646,11 @@ _require_odirect()
        rm -f $testfile 2>&1 > /dev/null
 }
 
+# Format a swapfile and return its size in bytes
 _format_swapfile() {
        local fname="$1"
        local sz="$2"
+       local swap_log=""
 
        rm -f "$fname"
        touch "$fname"
@@ -2586,8 +2659,10 @@ _format_swapfile() {
        $CHATTR_PROG +C "$fname" > /dev/null 2>&1
        _pwrite_byte 0x61 0 "$sz" "$fname" >> $seqres.full
        # Ignore permission complaints on filesystems that don't support perms
-       $MKSWAP_PROG "$fname" 2>&1 >> $seqres.full | \
-               grep -v "insecure permission"
+       swap_log=$($MKSWAP_PROG "$fname" 2>&1 | grep -v "insecure permission")
+       echo $swap_log >> $seqres.full
+
+       echo $swap_log | grep -oP '\w+(?= bytes)'
 }
 
 _swapon_file() {
@@ -2619,7 +2694,7 @@ _require_scratch_swapfile()
        _scratch_mount
 
        # Minimum size for mkswap is 10 pages
-       _format_swapfile "$SCRATCH_MNT/swap" $(($(get_page_size) * 10))
+       _format_swapfile "$SCRATCH_MNT/swap" $(($(get_page_size) * 10)) > /dev/null
 
        # ext* has supported all variants of swap files since their
        # introduction, so swapon should not fail.
@@ -3631,7 +3706,7 @@ _has_metadata_journaling()
                        return 1
                }
                # ext4 might not load a journal
-               if _normalize_mount_options | grep -qw "noload"; then
+               if _normalize_mount_options "$MOUNT_OPTIONS" | grep -qw "noload"; then
                        echo "mount option \"noload\" not allowed in this test"
                        return 1
                fi
@@ -3795,20 +3870,20 @@ _require_cloner()
                _notrun "cloner binary not present at $CLONER_PROG"
 }
 
-# Normalize mount options from global $MOUNT_OPTIONS
-# Convert options like "-o opt1,opt2 -oopt3" to
-# "opt1 opt2 opt3"
+# Normalize mount options from the option string in $1
+# Convert options like "-o opt1,opt2 -oopt3" to "opt1 opt2 opt3"
 _normalize_mount_options()
 {
-       echo $MOUNT_OPTIONS | sed -n 's/-o\s*\(\S*\)/\1/gp'| sed 's/,/ /g'
+       echo "$1" | sed -n 's/-o\s*\(\S*\)/\1/gp'| sed 's/,/ /g'
 }
 
-# skip test if MOUNT_OPTIONS contains the given strings
+# skip test if $1 contains the given strings in trailing arguments
 # Both dax and dax=always are excluded if dax or dax=always is passed
-_exclude_scratch_mount_option()
+_exclude_mount_option()
 {
-       local mnt_opts=$(_normalize_mount_options)
+       local mnt_opts=$(_normalize_mount_options "$1")
 
+       shift
        while [ $# -gt 0 ]; do
                local pattern=$1
                echo "$pattern" | egrep -q "dax(=always|$)" && \
@@ -3820,6 +3895,16 @@ _exclude_scratch_mount_option()
        done
 }
 
+_exclude_scratch_mount_option()
+{
+       _exclude_mount_option "$MOUNT_OPTIONS" $@
+}
+
+_exclude_test_mount_option()
+{
+       _exclude_mount_option "$TEST_FS_MOUNT_OPTS" $@
+}
+
 _require_atime()
 {
        _exclude_scratch_mount_option "noatime"
@@ -3849,6 +3934,14 @@ _create_loop_device()
 {
        local file=$1 dev
        dev=`losetup -f --show $file` || _fail "Cannot assign $file to a loop device"
+
+       # Try to enable asynchronous directio mode on the loopback device so
+       # that writeback started by a filesystem mounted on the loop device
+       # won't be throttled by buffered writes to the lower filesystem.  This
+       # is a performance optimization for tests that want to write a lot of
+       # data, so it isn't required to work.
+       test -b "$dev" && losetup --direct-io=on $dev 2> /dev/null
+
        echo $dev
 }
 
@@ -3930,7 +4023,10 @@ _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"
+       local ret=$?
+       [ $ret -eq 22 ] && _notrun "Require fcntl setlease support"
+       [ "$FSTYP" == "nfs" -a $ret -eq 11 ] && \
+               _notrun "NFS requires delegation before setlease"
 }
 
 _require_ofd_locks()
@@ -4360,7 +4456,14 @@ run_fsx()
 _require_fs_sysfs()
 {
        local attr=$1
-       local dname=$(_short_dev $TEST_DEV)
+       local dname
+
+       case "$FSTYP" in
+       btrfs)
+               dname=$(findmnt -n -o UUID $TEST_DEV) ;;
+       *)
+               dname=$(_short_dev $TEST_DEV) ;;
+       esac
 
        if [ -z "$attr" -o -z "$dname" ];then
                _fail "Usage: _require_fs_sysfs <sysfs_attr_path>"
@@ -4398,7 +4501,14 @@ _set_fs_sysfs_attr()
                _fail "Usage: _set_fs_sysfs_attr <mounted_device> <attr> <content>"
        fi
 
-       local dname=$(_short_dev $dev)
+       local dname
+       case "$FSTYP" in
+       btrfs)
+               dname=$(findmnt -n -o UUID ${dev}) ;;
+       *)
+               dname=$(_short_dev $dev) ;;
+       esac
+
        echo "$content" > /sys/fs/${FSTYP}/${dname}/${attr}
 }
 
@@ -4419,7 +4529,14 @@ _get_fs_sysfs_attr()
                _fail "Usage: _get_fs_sysfs_attr <mounted_device> <attr>"
        fi
 
-       local dname=$(_short_dev $dev)
+       local dname
+       case "$FSTYP" in
+       btrfs)
+               dname=$(findmnt -n -o UUID ${dev}) ;;
+       *)
+               dname=$(_short_dev $dev) ;;
+       esac
+
        cat /sys/fs/${FSTYP}/${dname}/${attr}
 }
 
@@ -4609,13 +4726,22 @@ _check_xfs_scrub_does_unicode() {
 
        _supports_xfs_scrub "${mount}" "${dev}" || return 1
 
-       # We only care if xfs_scrub has unicode string support...
-       if ! type ldd > /dev/null 2>&1 || \
-          ! ldd "${XFS_SCRUB_PROG}" | grep -q libicui18n; then
-               return 1
+       # If the xfs_scrub binary contains the string "Unicode name.*%s", then
+       # we know that it has the ability to complain about improper Unicode
+       # names.
+       if strings "${XFS_SCRUB_PROG}" | grep -q 'Unicode name.*%s'; then
+               return 0
        fi
 
-       return 0
+       # If the xfs_scrub binary is linked against the libicui18n Unicode
+       # library, then we surmise that it contains the Unicode name checker.
+       if type ldd > /dev/null 2>&1 && \
+          ldd "${XFS_SCRUB_PROG}" 2> /dev/null | grep -q libicui18n; then
+               return 0
+       fi
+
+       # We could not establish that xfs_scrub supports unicode names.
+       return 1
 }
 
 # exfat timestamps start at 1980 and cannot be prior to epoch
@@ -4677,6 +4803,35 @@ _require_names_are_bytes() {
         esac
 }
 
+_has_kernel_config()
+{
+       local option=$1
+       local uname=$(uname -r)
+       local config_list="$KCONFIG_PATH
+                    /proc/config.gz
+                    /lib/modules/$uname/build/.config
+                    /boot/config-$uname
+                    /lib/kernel/config-$uname"
+
+       for config in $config_list; do
+               [ ! -f $config ] && continue
+               [ $config = "/proc/config.gz" ] && break
+               grep -qE "^${option}=[my]" $config
+               return
+       done
+
+       [ ! -f $config ] && _notrun "Could not locate kernel config file"
+
+       # We can only get here with /proc/config.gz
+       _require_command "$GZIP_PROG" gzip
+       $GZIP_PROG -cd $config | grep -qE "^${option}=[my]"
+}
+
+_require_kernel_config()
+{
+       _has_kernel_config $1 || _notrun "Installed kernel not built with $1"
+}
+
 init_rc
 
 ################################################################################