@@ -234,6 +234,7 @@ export GZIP_PROG="$(type -P gzip)"
export BTRFS_IMAGE_PROG="$(type -P btrfs-image)"
export BTRFS_MAP_LOGICAL_PROG=$(type -P btrfs-map-logical)
export PARTED_PROG="$(type -P parted)"
+export XFS_PROPERTY_PROG="$(type -P xfs_property)"
# use 'udevadm settle' or 'udevsettle' to wait for lv to be settled.
# newer systems have udevadm command but older systems like RHEL5 don't.
@@ -1318,8 +1318,8 @@ _require_xfs_spaceman_command()
testfile=$TEST_DIR/$$.xfs_spaceman
touch $testfile
case $command in
- "health")
- testio=`$XFS_SPACEMAN_PROG -c "health $param" $TEST_DIR 2>&1`
+ "health"|"listfsprops")
+ testio=`$XFS_SPACEMAN_PROG -c "$command $param" $TEST_DIR 2>&1`
param_checked=1
;;
*)
@@ -1812,3 +1812,13 @@ _require_xfs_parent()
|| _notrun "kernel does not support parent pointers"
_scratch_unmount
}
+
+# Wipe all filesystem properties from an xfs filesystem. The sole argument
+# must be the root directory of a filesystem.
+_wipe_xfs_properties()
+{
+ getfattr --match="^trusted.xfs:" --absolute-names --dump --encoding=hex "$1" | \
+ grep '=' | sed -e 's/=.*$//g' | while read name; do
+ setfattr --remove="$name" "$1"
+ done
+}
@@ -56,6 +56,7 @@ fiexchange XFS_IOC_EXCHANGE_RANGE ioctl
freeze filesystem freeze tests
fsck general fsck tests
fsmap FS_IOC_GETFSMAP ioctl
+fsproperties Filesystem properties
fsr XFS free space reorganizer
fuzzers filesystem fuzz tests
growfs increasing the size of a filesystem
@@ -75,6 +75,10 @@ fi
_require_attrs $ATTR_MODES
+# Wipe all xfs filesystem properties (which are rootdir xattrs) before we dump
+# them all later.
+test $FSTYP = "xfs" && _wipe_xfs_properties $SCRATCH_MNT
+
for nsp in $ATTR_MODES; do
for inode in reg dir lnk dev/b dev/c dev/p; do
new file mode 100755
@@ -0,0 +1,137 @@
+#! /bin/bash
+# SPDX-License-Identifier: GPL-2.0
+# Copyright (c) 2024 Oracle. All Rights Reserved.
+#
+# FS QA Test 1886
+#
+# Functional testing for low level filesystem property manipulation by
+# xfs_{spaceman,db}.
+#
+. ./common/preamble
+_begin_fstest auto fsproperties
+
+. ./common/filter
+. ./common/attr
+
+_require_test
+_require_user fsgqa
+_require_attrs
+_require_xfs_io_command listfsprops
+_require_xfs_db_command attr_list
+
+_cleanup()
+
+{
+ cd /
+ rm -r -f $tmp.*
+ rm -f $TEST_DIR/$seq.somefile
+ rm -r -f $TEST_DIR/$seq.somedir
+ test -n "$propname" && $ATTR_PROG -R -r $propname $TEST_DEV &>/dev/null
+}
+
+filter_inum()
+{
+ sed -e 's/inode [0-9]*/inode XXX/g'
+}
+
+propname="fakeproperty" # must not be an actual property
+propval="1721943740"
+longpropname="$(perl -e 'print "x" x 300;')"
+longpropval="$(perl -e 'print "x" x 80000;')"
+
+echo "*** IO TEST ***"
+
+echo empty get property
+$XFS_IO_PROG -c "getfsprops $propname" $TEST_DIR
+
+echo pointless remove property
+$XFS_IO_PROG -c "removefsprops $propname" $TEST_DIR
+
+echo list property
+$XFS_IO_PROG -c "listfsprops" $TEST_DIR | grep $propname
+
+echo set property
+$XFS_IO_PROG -c "setfsprops $propname=$propval" $TEST_DIR
+
+echo list property
+$XFS_IO_PROG -c "listfsprops" $TEST_DIR | grep $propname
+
+echo dump xattrs
+$ATTR_PROG -R -l $TEST_DIR | grep $propname | _filter_test_dir
+
+echo get property
+$XFS_IO_PROG -c "getfsprops $propname" $TEST_DIR
+
+echo list property
+$XFS_IO_PROG -c "listfsprops" $TEST_DIR | grep $propname
+
+echo child file rejected
+touch $TEST_DIR/$seq.somefile
+$XFS_IO_PROG -c "listfsprops $propname" $TEST_DIR/$seq.somefile 2>&1 | \
+ _filter_test_dir
+
+echo child dir rejected
+mkdir -p $TEST_DIR/$seq.somedir
+$XFS_IO_PROG -c "listfsprops $propname" $TEST_DIR/$seq.somedir 2>&1 | \
+ _filter_test_dir
+
+echo remove property
+$XFS_IO_PROG -c "removefsprops $propname" $TEST_DIR
+
+echo pointless remove property
+$XFS_IO_PROG -c "removefsprops $propname" $TEST_DIR
+
+echo set too long name
+$XFS_IO_PROG -c "setfsprops $longpropname=$propval" $TEST_DIR
+
+echo set too long value
+$XFS_IO_PROG -c "setfsprops $propname=$longpropval" $TEST_DIR
+
+echo not enough permissions
+su - "$qa_user" -c "$XFS_IO_PROG -c \"setfsprops $propname=$propval\" $TEST_DIR" 2>&1 | _filter_test_dir
+
+echo "*** DB TEST ***"
+
+propval=$((propval + 1))
+_test_unmount
+
+echo empty get property
+_test_xfs_db -x -c 'path /' -c "attr_get -Z $propname" 2>&1 | filter_inum
+
+echo pointless remove property
+_test_xfs_db -x -c 'path /' -c "attr_remove -Z $propname" 2>&1 | filter_inum
+
+echo list property
+_test_xfs_db -x -c 'path /' -c "attr_list -Z" | grep $propname
+
+echo set property
+_test_xfs_db -x -c 'path /' -c "attr_set -Z $propname $propval"
+
+echo list property
+_test_xfs_db -x -c 'path /' -c "attr_list -Z" | grep $propname
+
+echo dump xattrs
+_test_mount
+$ATTR_PROG -R -l $TEST_DIR | grep $propname | _filter_test_dir
+_test_unmount
+
+echo get property
+_test_xfs_db -x -c 'path /' -c "attr_get -Z $propname"
+
+echo list property
+_test_xfs_db -x -c 'path /' -c "attr_list -Z" | grep $propname
+
+echo remove property
+_test_xfs_db -x -c 'path /' -c "attr_remove -Z $propname"
+
+echo pointless remove property
+_test_xfs_db -x -c 'path /' -c "attr_remove -Z $propname" 2>&1 | filter_inum
+
+echo set too long name
+_test_xfs_db -x -c 'path /' -c "attr_set -Z $longpropname $propval"
+
+echo set too long value
+_test_xfs_db -x -c 'path /' -c "attr_set -Z $propname $longpropval"
+
+status=0
+exit
new file mode 100644
@@ -0,0 +1,53 @@
+QA output created by 1886
+*** IO TEST ***
+empty get property
+fakeproperty: No data available
+pointless remove property
+fakeproperty: No data available
+list property
+set property
+fakeproperty=1721943740
+list property
+fakeproperty
+dump xattrs
+Attribute "xfs:fakeproperty" has a 10 byte value for TEST_DIR
+get property
+fakeproperty=1721943740
+list property
+fakeproperty
+child file rejected
+TEST_DIR/1886.somefile: Not a XFS mount point.
+child dir rejected
+TEST_DIR/1886.somedir: Not a XFS mount point.
+remove property
+pointless remove property
+fakeproperty: No data available
+set too long name
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: Invalid argument
+set too long value
+fakeproperty: Invalid argument
+not enough permissions
+TEST_DIR: Operation not permitted
+*** DB TEST ***
+empty get property
+failed to get attr xfs:fakeproperty on inode XXX: No data available
+pointless remove property
+failed to remove attr xfs:fakeproperty from inode XXX: No data available
+list property
+set property
+fakeproperty=1721943741
+list property
+fakeproperty
+dump xattrs
+Attribute "xfs:fakeproperty" has a 10 byte value for TEST_DIR
+get property
+fakeproperty=1721943741
+list property
+fakeproperty
+remove property
+pointless remove property
+failed to remove attr xfs:fakeproperty from inode XXX: No data available
+set too long name
+name too long
+set too long value
+xfs:fakeproperty: value too long
new file mode 100755
@@ -0,0 +1,122 @@
+#! /bin/bash
+# SPDX-License-Identifier: GPL-2.0
+# Copyright (c) 2024 Oracle. All Rights Reserved.
+#
+# FS QA Test 1887
+#
+# Functional testing for xfs_property the wrapper script.
+#
+. ./common/preamble
+_begin_fstest auto fsproperties
+
+. ./common/filter
+. ./common/attr
+
+_require_test
+_require_attrs
+_require_command "$XFS_PROPERTY_PROG" xfs_property
+_require_xfs_io_command listfsprops # actually detect support
+
+_cleanup()
+
+{
+ cd /
+ rm -r -f $tmp.*
+ rm -f $TEST_DIR/$seq.somefile
+ rm -r -f $TEST_DIR/$seq.somedir
+ test -n "$propname" && $ATTR_PROG -R -r $propname $TEST_DEV &>/dev/null
+}
+
+filter_inum()
+{
+ sed -e 's/inode [0-9]*/inode XXX/g'
+}
+
+propname="fakeproperty" # must not be an actual property
+propval="1721943742"
+longpropname="$(perl -e 'print "x" x 300;')"
+longpropval="$(perl -e 'print "x" x 80000;')"
+
+echo "*** OFFLINE XFS_PROPERTY TEST ***"
+
+_test_unmount
+
+echo empty get property
+$XFS_PROPERTY_PROG $TEST_DEV get "$propname" 2>&1 | filter_inum
+
+echo pointless remove property
+$XFS_PROPERTY_PROG $TEST_DEV remove "$propname" 2>&1 | filter_inum
+
+echo list property
+$XFS_PROPERTY_PROG $TEST_DEV list | grep $propname
+
+echo set property
+$XFS_PROPERTY_PROG $TEST_DEV set "$propname=$propval"
+
+echo list property
+$XFS_PROPERTY_PROG $TEST_DEV list | grep $propname
+
+echo dump xattrs
+$ATTR_PROG -R -l $TEST_DEV | grep $propname | _filter_test_dir
+
+echo get property
+$XFS_PROPERTY_PROG $TEST_DEV get "$propname"
+
+echo list property
+$XFS_PROPERTY_PROG $TEST_DEV list | grep $propname
+
+echo remove property
+$XFS_PROPERTY_PROG $TEST_DEV remove "$propname"
+
+echo pointless remove property
+$XFS_PROPERTY_PROG $TEST_DEV remove "$propname" 2>&1 | filter_inum
+
+echo set too long name
+$XFS_PROPERTY_PROG $TEST_DEV set "$longpropname=$propval"
+
+echo set too long value
+$XFS_PROPERTY_PROG $TEST_DEV set "$propname=$longpropval"
+
+echo "*** ONLINE XFS_PROPERTY TEST ***"
+
+propval=$((propval+1))
+_test_mount
+
+echo empty get property
+$XFS_PROPERTY_PROG $TEST_DIR get "$propname"
+
+echo pointless remove property
+$XFS_PROPERTY_PROG $TEST_DIR remove "$propname"
+
+echo list property
+$XFS_PROPERTY_PROG $TEST_DIR list | grep $propname
+
+echo set property
+$XFS_PROPERTY_PROG $TEST_DIR set "$propname=$propval"
+
+echo list property
+$XFS_PROPERTY_PROG $TEST_DIR list | grep $propname
+
+echo dump xattrs
+$ATTR_PROG -R -l $TEST_DIR | grep $propname | _filter_test_dir
+
+echo get property
+$XFS_PROPERTY_PROG $TEST_DIR get "$propname"
+
+echo list property
+$XFS_PROPERTY_PROG $TEST_DIR list | grep $propname
+
+echo remove property
+$XFS_PROPERTY_PROG $TEST_DIR remove "$propname"
+
+echo pointless remove property
+$XFS_PROPERTY_PROG $TEST_DIR remove "$propname"
+
+echo set too long name
+$XFS_PROPERTY_PROG $TEST_DIR set "$longpropname=$propval"
+
+echo set too long value
+$XFS_PROPERTY_PROG $TEST_DIR set "$propname=$longpropval"
+
+status=0
+exit
new file mode 100644
@@ -0,0 +1,46 @@
+QA output created by 1887
+*** OFFLINE XFS_PROPERTY TEST ***
+empty get property
+failed to get attr xfs:fakeproperty on inode XXX: No data available
+pointless remove property
+failed to remove attr xfs:fakeproperty from inode XXX: No data available
+list property
+set property
+fakeproperty=1721943742
+list property
+fakeproperty
+dump xattrs
+get property
+fakeproperty=1721943742
+list property
+fakeproperty
+remove property
+pointless remove property
+failed to remove attr xfs:fakeproperty from inode XXX: No data available
+set too long name
+name too long
+set too long value
+xfs:fakeproperty: value too long
+*** ONLINE XFS_PROPERTY TEST ***
+empty get property
+fakeproperty: No data available
+pointless remove property
+fakeproperty: No data available
+list property
+set property
+fakeproperty=1721943743
+list property
+fakeproperty
+dump xattrs
+Attribute "xfs:fakeproperty" has a 10 byte value for TEST_DIR
+get property
+fakeproperty=1721943743
+list property
+fakeproperty
+remove property
+pointless remove property
+fakeproperty: No data available
+set too long name
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: Invalid argument
+set too long value
+fakeproperty: Invalid argument
new file mode 100755
@@ -0,0 +1,66 @@
+#! /bin/bash
+# SPDX-License-Identifier: GPL-2.0
+# Copyright (c) 2024 Oracle. All Rights Reserved.
+#
+# FS QA Test 1888
+#
+# Functional testing for mkfs applying autofsck fs property.
+#
+. ./common/preamble
+_begin_fstest auto fsproperties
+
+. ./common/filter
+. ./common/attr
+
+_require_test
+_require_xfs_io_command listfsprops # needed for fs props
+_require_xfs_db_command attr_get
+
+_cleanup()
+
+{
+ cd /
+ rm -r -f $tmp.*
+ rm -f $dummyfile
+ rmdir $dummymnt &>/dev/null
+}
+
+dummyfile=$TEST_DIR/$seq.somefile
+dummymnt=$TEST_DIR/$seq.mount
+
+truncate -s 10g $dummyfile
+mkdir -p $dummymnt
+
+filter_inum()
+{
+ sed -e 's/inode [0-9]*/inode XXX/g'
+}
+
+testme() {
+ local mkfs_args=('-f')
+ local value="$1"
+ test -n "$value" && value="=$value"
+
+ if [ $# -gt 0 ]; then
+ mkfs_args+=('-m' "autofsck$value")
+ fi
+
+ echo "testing ${mkfs_args[*]}" >> $seqres.full
+
+ $MKFS_XFS_PROG "${mkfs_args[@]}" $dummyfile >> $seqres.full || \
+ _notrun "mkfs.xfs ${mkfs_args[*]} failed?"
+
+ $XFS_DB_PROG -x -c 'path /' -c "attr_get -Z autofsck" $dummyfile 2>&1 | filter_inum
+}
+
+testme ''
+testme
+testme none
+testme check
+testme optimize
+testme repair
+testme 0
+testme 1
+
+status=0
+exit
new file mode 100644
@@ -0,0 +1,9 @@
+QA output created by 1888
+autofsck=repair
+failed to get attr xfs:autofsck on inode XXX: No data available
+autofsck=none
+autofsck=check
+autofsck=optimize
+autofsck=repair
+autofsck=none
+autofsck=repair
new file mode 100755
@@ -0,0 +1,63 @@
+#! /bin/bash
+# SPDX-License-Identifier: GPL-2.0
+# Copyright (c) 2024 Oracle. All Rights Reserved.
+#
+# FS QA Test 1889
+#
+# Functional testing for mkfs applying autofsck fs property and xfs_scrub
+# changing its behavior accordingly. Or at least claiming to.
+#
+. ./common/preamble
+_begin_fstest auto fsproperties
+
+. ./common/filter
+. ./common/fuzzy
+
+_require_test
+_require_xfs_io_command listfsprops # needed for fs props
+_require_xfs_db_command attr_get
+_require_scrub
+
+_cleanup()
+
+{
+ cd /
+ rm -r -f $tmp.*
+ _umount $dummymnt &>/dev/null
+ rmdir $dummymnt &>/dev/null
+ rm -f $dummyfile
+}
+
+dummyfile=$TEST_DIR/$seq.somefile
+dummymnt=$TEST_DIR/$seq.mount
+
+truncate -s 10g $dummyfile
+mkdir -p $dummymnt
+
+testme() {
+ local mkfs_args=('-f' '-m' "$1")
+
+ echo "testing ${mkfs_args[*]}" >> $seqres.full
+
+ $MKFS_XFS_PROG "${mkfs_args[@]}" $dummyfile >> $seqres.full || \
+ echo "mkfs.xfs ${mkfs_args[*]} failed?"
+
+ _mount -o loop $dummyfile $dummymnt
+ XFS_SCRUB_PHASE=7 $XFS_SCRUB_PROG -d -o autofsck $dummymnt 2>&1 | \
+ grep autofsck | _filter_test_dir | \
+ sed -e 's/\(directive.\).*$/\1/g'
+ _umount $dummymnt
+}
+
+# We don't test the absence of an autofsck directive because xfs_scrub behaves
+# differently depending on whether or not mkfs adds rmapbt/pptrs to the fs.
+testme 'autofsck'
+testme 'autofsck=none'
+testme 'autofsck=check'
+testme 'autofsck=optimize'
+testme 'autofsck=repair'
+testme 'autofsck=0'
+testme 'autofsck=1'
+
+status=0
+exit
new file mode 100644
@@ -0,0 +1,8 @@
+QA output created by 1889
+Info: TEST_DIR/1889.mount: Checking and repairing per autofsck directive.
+Info: TEST_DIR/1889.mount: Disabling scrub per autofsck directive.
+Info: TEST_DIR/1889.mount: Checking per autofsck directive.
+Info: TEST_DIR/1889.mount: Optimizing per autofsck directive.
+Info: TEST_DIR/1889.mount: Checking and repairing per autofsck directive.
+Info: TEST_DIR/1889.mount: Disabling scrub per autofsck directive.
+Info: TEST_DIR/1889.mount: Checking and repairing per autofsck directive.