Jeff Mahoney
2013-Oct-25 20:52 UTC
[patch 0/3] xfstests: tests for btrfs publishing/export patchset
These are the tests that Josef requested accompany the submission of the btrfs publishing/export patchset[1]. 100: Test new global metadata reservation ioctl 101: Test new sysfs exporting of allocation and device membership 102: Test new sysfs exporting of feature bits 103: Test setting/clearing feature bits via ioctl 104: Test setting/clearing feature bits via sysfs As part of the ioctl testing, I added a helper that can be extended easily to export simple information via ioctl. This means that the tests can be independent of btrfsprogs version or its output formatting. -Jeff [1] http://thread.gmane.org/gmane.comp.file-systems.btrfs/29307 -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Jeff Mahoney
2013-Oct-25 20:52 UTC
[patch 1/3] [PATCH 1/3] xfstests: add test for global metadata reservation publishing
My publishing patchset added the ability for the kernel to report the size of the global metadata reservation via ioctl and sysfs. This test confirms that we get sane results on an empty file system. ENOTTY and missing /sys/fs/btrfs/<fsid>/allocation are not considered failures. Signed-off-by: Jeff Mahoney <jeffm@suse.com> --- src/Makefile | 3 +- src/btrfs_ioctl_helper.c | 90 ++++++++++++++++++++++++++++++++++++++++++++++ tests/btrfs/100 | 92 ++++++++++++++++++++++++++++++++++++++++++++++++ tests/btrfs/100.out | 2 ++ 4 files changed, 186 insertions(+), 1 deletion(-) create mode 100644 src/btrfs_ioctl_helper.c create mode 100755 tests/btrfs/100 create mode 100644 tests/btrfs/100.out diff --git a/src/Makefile b/src/Makefile index 84c8297..299f675 100644 --- a/src/Makefile +++ b/src/Makefile @@ -18,7 +18,8 @@ LINUX_TARGETS = xfsctl bstat t_mtab getdevicesize preallo_rw_pattern_reader \ locktest unwritten_mmap bulkstat_unlink_test t_stripealign \ bulkstat_unlink_test_modified t_dir_offset t_futimens t_immutable \ stale_handle pwrite_mmap_blocked t_dir_offset2 seek_sanity_test \ - seek_copy_test t_readdir_1 t_readdir_2 fsync-tester nsexec + seek_copy_test t_readdir_1 t_readdir_2 fsync-tester nsexec \ + btrfs_ioctl_helper SUBDIRS diff --git a/src/btrfs_ioctl_helper.c b/src/btrfs_ioctl_helper.c new file mode 100644 index 0000000..a88b7b5 --- /dev/null +++ b/src/btrfs_ioctl_helper.c @@ -0,0 +1,90 @@ +#include <sys/ioctl.h> +#include <stdio.h> +#include <sys/fcntl.h> +#include <errno.h> +#include <string.h> +#include <stdint.h> +#include <unistd.h> + +#ifndef BTRFS_IOCTL_MAGIC +#define BTRFS_IOCTL_MAGIC 0x94 +#endif + +#ifndef BTRFS_IOC_GLOBAL_RSV +#define BTRFS_IOC_GLOBAL_RSV _IOR(BTRFS_IOCTL_MAGIC, 20, uint64_t) +#endif + +static int global_rsv_ioctl(int fd, int argc, char *argv[]) +{ + uint64_t reserved; + int ret = ioctl(fd, BTRFS_IOC_GLOBAL_RSV, &reserved); + if (ret) + return -errno; + + printf("%llu\n", (unsigned long long)reserved); + return 0; +} + +#define IOCTL_TABLE_ENTRY(_ioctl_name, _handler) \ + { .name = #_ioctl_name, .ioctl_cmd = BTRFS_IOC_##_ioctl_name, \ + .handler = _handler, } + +struct ioctl_table_entry { + const char *name; + unsigned ioctl_cmd; + int (*handler)(int fd, int argc, char *argv[]); +}; + +static struct ioctl_table_entry ioctls[] = { + IOCTL_TABLE_ENTRY(GLOBAL_RSV, global_rsv_ioctl), +}; + +int +main(int argc, char *argv[]) +{ + int fd; + int ret; + struct ioctl_table_entry *entry = NULL; + int i; + + if (argc < 3) { + fprintf(stderr, + "usage: %s <fs mount point> <ioctl name> [args..]\n", + argv[0]); + return 1; + } + + fd = open(argv[1], O_RDONLY|O_DIRECTORY); + if (fd < 0) { + perror(argv[1]); + return 1; + } + + for (i = 0; i < (sizeof(ioctls)/sizeof(ioctls[0])); i++) { + if (strcmp(argv[2], ioctls[i].name) == 0) { + entry = &ioctls[i]; + break; + } + } + + if (!entry) { + fprintf(stderr, "ERROR: unknown ioctl %s\n", argv[2]); + close(fd); + return 1; + } + + ret = entry->handler(fd, argc - 3, argv + 3); + if (ret == -ENOTTY) { + printf("Not implemented.\n"); + close(fd); + return 0; + } else if (ret) { + fprintf(stderr, "ERROR: %s failed: %s\n", + entry->name, strerror(-ret)); + close(fd); + return 1; + } + + close(fd); + return 0; +} diff --git a/tests/btrfs/100 b/tests/btrfs/100 new file mode 100755 index 0000000..d2a40b4 --- /dev/null +++ b/tests/btrfs/100 @@ -0,0 +1,92 @@ +#!/bin/bash +# FA QA Test No. 100 +# +# Test global metadata reservation reporting +# +# 1) Create empty file system +# 2) Call the BTRFS_IOC_GLOBAL_RSV ioctl and confirm it is 0 < x < 10MB +# 3) Read the /sys/fs/btrfs/<fsid>/allocation/global_rsv_reserved file +# and confirm the value is 0 < x < 10 MB +# +#----------------------------------------------------------------------- +# Copyright (c) 2013 SUSE, All Rights Reserved. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it would be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +#----------------------------------------------------------------------- + +seq=$(basename $0) +seqres=$RESULT_DIR/$seq +echo "== QA output created by $seq" + +here=$(pwd) +tmp=/tmp/$$ +status=1 + +# get standard environment, filters and checks +. ./common/rc +. ./common/filter.btrfs + +_supported_fs btrfs +_supported_os Linux +_require_scratch + +_scratch_mkfs > /dev/null 2>&1 +_scratch_mount + +fsid() { + $BTRFS_UTIL_PROG filesystem show $1|awk ''/uuid:/ {print $NF}'' +} + +# Check to see if the reservation is 0 < x <= 10MB +# At the time of this writing, it should always be exactly 4 MB +# but that is an implementation detail subject to change. +check_reserved() { + reserved="$2" + method="$3" + if [ "$1" != 0 ]; then + echo "$method: failed: $reserved" + exit 1 + fi + if [ "$reserved" = "Not implemented." ]; then + echo "Skipping ioctl test. Not implemented." >> $seqres.full + return + fi + if [ -n "$(echo $reserved | tr -d 0-9)" ]; then + echo "ERROR: numerical value expected (got $reserved)" + exit 1 + fi + if [ "$reserved" -le 0 -o \ + "$reserved" -gt "$(( 10 * 1024 * 1024 ))" ]; then + echo "$method: out of range: $reserved." + exit + fi +} + +# ioctl +reserved="$(src/btrfs_ioctl_helper $SCRATCH_MNT GLOBAL_RSV 2>&1)" +check_reserved $? "$reserved" "ioctl" + +# sysfs +# If this directory is here, the files must be here as well +SYSFS_PREFIX="/sys/fs/btrfs/$(fsid $SCRATCH_DEV)/allocation" +if [ -d "$SYSFS_PREFIX" ]; then + reserved="$(cat $SYSFS_PREFIX/global_rsv_reserved 2>&1)" + check_reserved $? "$reserved" "sysfs:reserved" + size="$(cat $SYSFS_PREFIX/global_rsv_size 2>&1)" + check_reserved $? "$size" "sysfs:size" +fi + +echo "Silence is golden" +status=0 +exit diff --git a/tests/btrfs/100.out b/tests/btrfs/100.out new file mode 100644 index 0000000..798c013 --- /dev/null +++ b/tests/btrfs/100.out @@ -0,0 +1,2 @@ +QA output created by 100 +Silence is golden -- 1.8.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Jeff Mahoney
2013-Oct-25 20:52 UTC
[patch 2/3] [PATCH 2/3] xfstests: add test for sysfs publication of btrfs info
This tests the sysfs publishing for btrfs allocation and device membership info under a number of different layouts, similar to the btrfs replace test. We test the allocation files only for existence and that they contain numerical values. We test the device membership by mapping the devices used to create the file system to sysfs paths and matching them against the paths used for the device membership symlinks. Since this is a new feature, it passes on kernels without a /sys/fs/btrfs/<fsid> directory. Signed-off-by: Jeff Mahoney <jeffm@suse.com> --- common/config | 1 + tests/btrfs/101 | 188 ++++++++++++++++++++++++++++++++++++++++++++++++++++ tests/btrfs/101.out | 2 + 3 files changed, 191 insertions(+) create mode 100755 tests/btrfs/101 create mode 100644 tests/btrfs/101.out diff --git a/common/config b/common/config index 20c5b09..5f9e2e8 100644 --- a/common/config +++ b/common/config @@ -208,6 +208,7 @@ case "$HOSTOS" in export MKFS_UDF_PROG="`set_prog_path mkudffs`" export MKFS_BTRFS_PROG="`set_btrfs_mkfs_prog_path_with_opts`" export BTRFS_UTIL_PROG="`set_prog_path btrfs`" + export UDEVADM_PROG="`set_prog_path udevadm`" export BTRFS_SHOW_SUPER_PROG="`set_prog_path btrfs-show-super`" export XFS_FSR_PROG="`set_prog_path xfs_fsr`" export MKFS_NFS_PROG="false" diff --git a/tests/btrfs/101 b/tests/btrfs/101 new file mode 100755 index 0000000..9a2834b --- /dev/null +++ b/tests/btrfs/101 @@ -0,0 +1,188 @@ +#! /bin/bash +# FS QA Test No. btrfs/101 +# +# Test of the btrfs sysfs publishing +# +#----------------------------------------------------------------------- +# Copyright (C) 2013 SUSE. All rights reserved. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it would be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +#----------------------------------------------------------------------- +# + +seq=`basename $0` +seqres=$RESULT_DIR/$seq +echo "QA output created by $seq" + +here=`pwd` +tmp=/tmp/$$ +status=1 + +# get standard environment, filters and checks +. ./common/rc +. ./common/filter + +# real QA test starts here +_need_to_be_root +_supported_fs btrfs +_require_scratch +_require_scratch_dev_pool +_require_command $UDEVADM_PROG udevadm + +rm -f $seqres.full +rm -f $tmp.tmp + +fsid() { + $BTRFS_UTIL_PROG filesystem show $1|awk ''/uuid:/ {print $NF}'' +} + +check_file() { + local file=$1 + base="$(echo "$file" | sed -e ''s#/sys/fs/btrfs/[0-9a-f-][0-9a-f-]*/##'')" + if [ ! -f "$file" ]; then + echo "$base missing." + return 0 + else + value="$(cat $file)" + if [ -n "$(echo $value | tr -d 0-9)" ]; then + echo "ERROR: $base: numerical value expected (got $value)" + return 0 + fi + fi + return 1 +} + +check_chunk() { + path=$1 + mkfs_options=$2 + error=false + + chunktype=$(basename $path) + if [ ! -d "$path" ]; then + echo "No $chunktype directory." + exit 1 + fi + + for file in bytes_may_use bytes_pinned bytes_reserved bytes_used \ + disk_total flags total_bytes total_bytes_pinned; do + if check_file "$path/$file"; then + error=true + fi + done + + if [ "$chunktype" = "data" -o "$chunktype" = "mixed" ]; then + opt="-d" + elif [ "$chunktype" = "metadata" -o "$chunktype" = "system" ]; then + opt="-m" + fi + + profile=$(echo $mkfs_options | sed -e "s/.*$opt \([[:alnum:]]*\).*/\1/") + if [ ! -d "$path/$profile" ]; then + echo "No $profile dir for $chunktype" + exit 1 + fi + + for file in total_bytes used_bytes; do + if check_file $path/$profile/$file; then + error=true + fi + done + + $error && exit 1 +} + +check_dev_link() { + local dev=$1 + DEV="/sys/$($UDEVADM_PROG info --query=path $dev)" + DEV="$(readlink -f $DEV)" + found=false + for link in $sysfs_base/devices/*; do + LINK="$(readlink -f $link)" + if [ "$LINK" = "$DEV" ]; then + found=true + break + fi + done + if ! $found; then + echo "Symlink for $dev missing in $sysfs_base/devices" + return 1 + fi + return 0 +} + +workout() +{ + local mkfs_options="$1" + local num_devs4raid="$2" + local fssize + + if [ "`echo $SCRATCH_DEV_POOL | wc -w`" -lt $num_devs4raid ]; then + echo "Skip workout $1 $2 $3 $4" + echo "Too few devices in SCRATCH_DEV_POOL $SCRATCH_DEV_POOL, required: $num_devs4raid" + echo "Skip workout $1 $2 $3 $4" >> $seqres.full + echo "Too few devices in SCRATCH_DEV_POOL $SCRATCH_DEV_POOL, required: $num_devs4raid" >> $seqres.full + return 0 + fi + + used_devs=$(echo $SCRATCH_DEV_POOL|tr ''\t'' '' ''| cut -d '' '' -f 1-$num_devs4raid) + + _scratch_mkfs $mkfs_options $used_devs >> $seqres.full 2>&1 || _fail "mkfs failed" + + _scratch_mount + + # Check allocation + sysfs_base="/sys/fs/btrfs/$(fsid $SCRATCH_DEV)" + + # Feature isn''t present for testing + if [ ! -d "$sysfs_base" ]; then + echo "Skipping sysfs test: $sysfs_base not found." >> $seqres.full + return + fi + + mixed=false + case "$mkfs_options" in + *-M*) + mixed=true; + ;; + esac + + check_chunk "$sysfs_base/allocation/system" "$mkfs_options" + if $mixed; then + check_chunk "$sysfs_base/allocation/mixed" "$mkfs_options" + else + check_chunk "$sysfs_base/allocation/data" "$mkfs_options" + check_chunk "$sysfs_base/allocation/metadata" "$mkfs_options" + fi + + for dev in $used_devs; do + check_dev_link $dev || exit 1 + done + + umount $SCRATCH_MNT > /dev/null 2>&1 +} + +workout "-m single -d single" 1 +workout "-m single -d single -M" 1 +workout "-m dup -d single" 1 +workout "-m dup -d dup -M" 1 +workout "-m raid0 -d raid0" 2 +workout "-m raid1 -d raid1" 2 +workout "-m raid5 -d raid5" 2 +workout "-m raid6 -d raid6" 3 +workout "-m raid10 -d raid10" 4 + +echo "Silence is golden." +status=0 +exit diff --git a/tests/btrfs/101.out b/tests/btrfs/101.out new file mode 100644 index 0000000..e651a91 --- /dev/null +++ b/tests/btrfs/101.out @@ -0,0 +1,2 @@ +QA output created by 101 +Silence is golden -- 1.8.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Jeff Mahoney
2013-Oct-25 20:52 UTC
[patch 3/3] [PATCH 3/3] xfstests: add tests for new feature ioctl and sysfs interfaces
This tests the exporting of feature information from the kernel via sysfs and ioctl. The first test works whether the sysfs permissions are correct, if the information exported via sysfs matches what the ioctls are reporting, and if they both match the on-disk superblock''s version of the feature sets. The second and third tests test online setting and clearing of feature bits via the sysfs and ioctl interfaces, checking whether they match the on-disk super on each cycle. In every case, if the features are not present, it is not considered a failure and a message indicating that will be dumped to the $num.full file. Signed-off-by: Jeff Mahoney <jeffm@suse.com> --- src/btrfs_ioctl_helper.c | 93 +++++++++++++++++ tests/btrfs/102 | 263 +++++++++++++++++++++++++++++++++++++++++++++++ tests/btrfs/102.out | 2 + tests/btrfs/103 | 188 +++++++++++++++++++++++++++++++++ tests/btrfs/103.out | 2 + tests/btrfs/104 | 186 +++++++++++++++++++++++++++++++++ tests/btrfs/104.out | 2 + 7 files changed, 736 insertions(+) create mode 100755 tests/btrfs/102 create mode 100644 tests/btrfs/102.out create mode 100755 tests/btrfs/103 create mode 100644 tests/btrfs/103.out create mode 100755 tests/btrfs/104 create mode 100644 tests/btrfs/104.out diff --git a/src/btrfs_ioctl_helper.c b/src/btrfs_ioctl_helper.c index a88b7b5..73cfa60 100644 --- a/src/btrfs_ioctl_helper.c +++ b/src/btrfs_ioctl_helper.c @@ -5,6 +5,7 @@ #include <string.h> #include <stdint.h> #include <unistd.h> +#include <stdlib.h> #ifndef BTRFS_IOCTL_MAGIC #define BTRFS_IOCTL_MAGIC 0x94 @@ -14,6 +15,21 @@ #define BTRFS_IOC_GLOBAL_RSV _IOR(BTRFS_IOCTL_MAGIC, 20, uint64_t) #endif +#ifndef BTRFS_IOC_GET_FEATURES +struct btrfs_ioctl_feature_flags { + uint64_t compat_flags; + uint64_t compat_ro_flags; + uint64_t incompat_flags; +}; + +#define BTRFS_IOC_GET_FEATURES _IOR(BTRFS_IOCTL_MAGIC, 57, \ + struct btrfs_ioctl_feature_flags) +#define BTRFS_IOC_SET_FEATURES _IOW(BTRFS_IOCTL_MAGIC, 57, \ + struct btrfs_ioctl_feature_flags[2]) +#define BTRFS_IOC_GET_SUPPORTED_FEATURES _IOR(BTRFS_IOCTL_MAGIC, 57, \ + struct btrfs_ioctl_feature_flags[3]) +#endif + static int global_rsv_ioctl(int fd, int argc, char *argv[]) { uint64_t reserved; @@ -25,6 +41,80 @@ static int global_rsv_ioctl(int fd, int argc, char *argv[]) return 0; } +static int get_features_ioctl(int fd, int argc, char *argv[]) +{ + struct btrfs_ioctl_feature_flags flags; + int ret = ioctl(fd, BTRFS_IOC_GET_FEATURES, &flags); + if (ret) + return -errno; + + printf("0x%llx 0x%llx 0x%llx\n", + (unsigned long long)flags.compat_flags, + (unsigned long long)flags.compat_ro_flags, + (unsigned long long)flags.incompat_flags); + return 0; +} + +static int set_features_ioctl(int fd, int argc, char *argv[]) +{ + struct btrfs_ioctl_feature_flags flags[2]; + uint64_t bit, *bits, *mask; + if (argc != 3) + goto usage; + + memset(flags, 0, sizeof(flags)); + + errno = 0; + bit = strtoull(argv[2], NULL, 10); + if (errno) + goto usage; + + if (strcmp(argv[1], "compat") == 0) { + mask = &flags[0].compat_flags; + bits = &flags[1].compat_flags; + } else if (strcmp(argv[1], "compat_ro") == 0) { + mask = &flags[0].compat_ro_flags; + bits = &flags[1].compat_ro_flags; + } else if (strcmp(argv[1], "incompat") == 0) { + mask = &flags[0].incompat_flags; + bits = &flags[1].incompat_flags; + } else + goto usage; + + *mask |= bit; + + if (strcmp(argv[0], "set") == 0) + *bits |= bit; + + return ioctl(fd, BTRFS_IOC_SET_FEATURES, &flags); +usage: + fprintf(stderr, "usage: SET_FEATURES <set|clear> <compat|compat_ro|incompat> <base-10 bitmask>\n"); + return -EINVAL; +} + +static int get_supported_features_ioctl(int fd, int argc, char *argv[]) +{ + struct btrfs_ioctl_feature_flags flags[3]; + int ret; + int i; + + ret = ioctl(fd, BTRFS_IOC_GET_SUPPORTED_FEATURES, &flags); + if (ret) + return -errno; + + for (i = 0; i < 3; i++) + printf("0x%llx 0x%llx 0x%llx ", + (unsigned long long)flags[i].compat_flags, + (unsigned long long)flags[i].compat_ro_flags, + (unsigned long long)flags[i].incompat_flags); + + printf("\n"); + return 0; +usage: + fprintf(stderr, + "usage: GET_SUPPORTED_FEATURES <supported|settable|clearable>\n"); + return -EINVAL; +} #define IOCTL_TABLE_ENTRY(_ioctl_name, _handler) \ { .name = #_ioctl_name, .ioctl_cmd = BTRFS_IOC_##_ioctl_name, \ .handler = _handler, } @@ -37,6 +127,9 @@ struct ioctl_table_entry { static struct ioctl_table_entry ioctls[] = { IOCTL_TABLE_ENTRY(GLOBAL_RSV, global_rsv_ioctl), + IOCTL_TABLE_ENTRY(GET_FEATURES, get_features_ioctl), + IOCTL_TABLE_ENTRY(SET_FEATURES, set_features_ioctl), + IOCTL_TABLE_ENTRY(GET_SUPPORTED_FEATURES, get_supported_features_ioctl), }; int diff --git a/tests/btrfs/102 b/tests/btrfs/102 new file mode 100755 index 0000000..77f2162 --- /dev/null +++ b/tests/btrfs/102 @@ -0,0 +1,263 @@ +#!/bin/bash +# FA QA Test No. 102 +# +# Test online feature publishing +# This test doesn''t test the changing of features. It does test that +# the proper publishing bits and permissions match up with +# the expected values. +# +#----------------------------------------------------------------------- +# Copyright (c) 2013 SUSE, All Rights Reserved. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it would be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +#----------------------------------------------------------------------- + +seq=$(basename $0) +seqres=$RESULT_DIR/$seq +echo "== QA output created by $seq" + +here=$(pwd) +tmp=/tmp/$$ +status=1 + +# get standard environment, filters and checks +. ./common/rc +. ./common/filter.btrfs + +_supported_fs btrfs +_supported_os Linux +_require_scratch +_require_command $BTRFS_SHOW_SUPER_PROG btrfs-show-super + +_scratch_mkfs > /dev/null 2>&1 +_scratch_mount + +fsid() { + $BTRFS_UTIL_PROG filesystem show $1|awk ''/uuid:/ {print $NF}'' +} + +check_features() { + reserved="$2" + method="$3" + if [ "$1" != 0 ]; then + echo "$method: failed: $reserved" + exit 1 + fi +} + +error=false + +# test -w will always return true if root is making the call. +# This would be true in most cases, but for sysfs files, the permissions +# are enforced even for root. +is_writeable() { + local file=$1 + mode=$(stat -c "0%a" "$file") + mode=$(( $mode & 0200 )) + + [ "$mode" -eq 0 ] && return 1 + return 0 +} + +# ioctl +read -a features < <(src/btrfs_ioctl_helper $SCRATCH_MNT GET_FEATURES 2>&1) +check_features $? "$features" "GET_FEATURES" + +read -a supp_features < <(src/btrfs_ioctl_helper $SCRATCH_MNT GET_SUPPORTED_FEATURES 2>&1) +check_features $? "$features" "GET_SUPPORTED_FEATURES" + +# Sysfs checks +fsid=$(fsid $SCRATCH_DEV) +sysfs_base="/sys/fs/btrfs" + +# TODO Add tool to enable and test unknown feature bits +get_feature_mask() { + class="" + case "$attr" in + mixed_backref) class=incompat; bit=0x1 ;; + default_subvol) class=incompat; bit=0x2 ;; + mixed_groups) class=incompat; bit=0x4 ;; + compress_lzo) class=incompat; bit=0x8 ;; + compress_lsov2) class=incompat; bit=0x10 ;; + big_metadata) class=incompat; bit=0x20 ;; + extended_iref) class=incompat; bit=0x40 ;; + raid56) class=incompat; bit=0x80 ;; + skinny_metadata)class=incompat; bit=0x100 ;; + compat:*) class=compat; bit=${attr##compat:} ;; + compat_ro:*) class=compat_ro; bit=${attr##compat_ro:} ;; + incompat:*) class=incompat; bit=${attr##incompat:} ;; + esac + if [ -z "$class" ]; then + echo "Unknown feature name $attr. xfstests needs updating." \ + " Skipping the test of sysfs values to superblock values" \ + >> $seqres.full + return + fi + + echo "$class $bit" +} + +get_changeable_mask() { + local class=$1 + local index=0 + if [ "$class" = "compat" ]; then + index=0 + elif [ "$class" = "compat_ro" ]; then + index=1 + elif [ "$class" = "incompat" ]; then + index=2 + fi + local set_index=$(( $index + 3 )) + local clear_index=$(( $index + 6 )) + + local mask=$(( ${supp_features[$set_index]} | \ + ${supp_features[$clear_index]} )) + + echo $mask +} + +# Check enabled features in sysfs vs what the superblock claims +sysfs_features=(0 0 0) +for file in $sysfs_base/$fsid/features/*; do + attr=$(basename $file) + val=$(cat $file) + read class bit < <(get_feature_mask $attr) + + # A file that exists but has a 0 value means that it''s changeable + if [ "$val" -eq 0 ]; then + if [ ! -e "$sysfs_base/features/$attr" ]; then + echo "$fsid/$attr exists with a 0 value but" \ + "features/$attr doesn''t exist." + error=true + continue + elif ! is_writeable "$file"; then + echo "$attr is not writable but exists and has a" \ + "0 value." + error=true + fi + + mask=$(get_changeable_mask $class) + if [ "$(( $bit & ~$mask ))" -ne 0 ]; then + echo "$attr is writable but GET_SUPPORTED_FEATURES" \ + "ioctl claims it shouldn''t be." + error=true + fi + + continue + fi + if [ "$class" = "compat" ]; then + sysfs_features[0]=$(( ${sysfs_features[0]} | $bit )) + elif [ "$class" = "compat_ro" ]; then + sysfs_features[1]=$(( ${sysfs_features[1]} | $bit )) + elif [ "$class" = "incompat" ]; then + sysfs_features[2]=$(( ${sysfs_features[2]} | $bit )) + else + # We will end up with a bit set in the superblock that + # doesn''t have a matching bit here. The feature-bit to name + # mapping must be kept up-to-date for this test to succeed. + echo "Unknown feature name $attr. xfstests needs updating." \ + "Skipping the test of sysfs values to superblock values" \ + >> $seqres.full + skip_sysfs_super_check=true + fi +done + +for file in $sysfs_base/features/*; do + attr=$(basename $file) + val=$(cat $file) + if [ "$val" -gt 0 ]; then + if [ ! -e "$sysfs_base/$fsid/features/$attr" ]; then + echo "features/$attr has a nonzero value ($val)" \ + "but $fsid/features/$attr doesn''t exist" + error=true + continue + fi + if ! is_writeable "$sysfs_base/$fsid/features/$attr"; then + echo "features/$attr has a nonzero value ($val)" \ + "but $fsid/features/$attr is not writable" + error=true + continue + fi + continue + fi + + [ ! -e "$sysfs_base/$fsid/features/$attr" ] && continue + + if is_writeable "$sysfs_base/$fsid/features/$attr"; then + echo "features/$attr has a zero value but" \ + "$fsid/features/$attr is writable." + error=true + continue + fi + + read class bit < <(get_feature_mask $attr) + mask=$(get_changeable_mask $class) + if [ "$(( $bit & $mask ))" -ne 0 ]; then + echo "$attr isn''t writable but GET_SUPPORTED_FEATURES" \ + "ioctl claims it should be." + error=true + continue + fi +done + +umount $SCRATCH_MNT > /dev/null 2>&1 + +fields=("compat" "compat_ro" "incompat") +declare -a disk_flags +get_disk_flags() { + local index=$1 + + # Grab the flags from the superblock directly to compare + disk_flags[$index]=$($BTRFS_SHOW_SUPER_PROG $SCRATCH_DEV | \ + grep "^${fields[$index]}_flags"|awk ''{print $NF}'') +} + +check_ioctl_flags() { + local index=$1 + local flags=${features[$index]} + + if [ "$flags" != "${disk_flags[$index]}" ]; then + echo "ioctl returned different ${fields[$index]} flags" \ + "($flags) than those contained in superblock" \ + "(${disk_flags[$index]})" + error=true + fi +} + +check_sysfs_flags() { + local index=$1 + $skip_sysfs_super_check || return + + flags=$(printf "0x%llx" ${sysfs_features[$index]}) + if [ "$flags" != "${disk_flags[$index]}" ]; then + echo "sysfs returned different ${fields[$index]}" \ + "flags ($flags) than those contained in" \ + "superblock (${disk_flags[$index]})" + error=true + fi +} + + +for index in $(seq 0 2); do + get_disk_flags "$index" + check_ioctl_flags "$index" + check_sysfs_flags "$index" +done + +$error && exit 1 + +# +echo "Silence is golden" +status=0 +exit diff --git a/tests/btrfs/102.out b/tests/btrfs/102.out new file mode 100644 index 0000000..28b7182 --- /dev/null +++ b/tests/btrfs/102.out @@ -0,0 +1,2 @@ +== QA output created by 102 +Silence is golden diff --git a/tests/btrfs/103 b/tests/btrfs/103 new file mode 100755 index 0000000..ff083c7 --- /dev/null +++ b/tests/btrfs/103 @@ -0,0 +1,188 @@ +#!/bin/bash +# FA QA Test No. 103 +# +# Test online feature changing via ioctl +# +#----------------------------------------------------------------------- +# Copyright (c) 2013 SUSE, All Rights Reserved. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it would be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +#----------------------------------------------------------------------- + +seq=$(basename $0) +seqres=$RESULT_DIR/$seq +echo "== QA output created by $seq" + +here=$(pwd) +tmp=/tmp/$$ +status=1 + +# get standard environment, filters and checks +. ./common/rc +. ./common/filter.btrfs + +_supported_fs btrfs +_supported_os Linux +_require_scratch +_require_command $BTRFS_SHOW_SUPER_PROG btrfs-show-super + +IOCTL=src/btrfs_ioctl_helper + +check_features() { + reserved="$2" + method="$3" + if [ "$1" != 0 ]; then + echo "$method: failed: $reserved" + exit 1 + fi + if [ "$reserved" = "Not implemented." ]; then + echo "Skipping ioctl $method test. Not implemented." \ + >> $seqres.full + echo "Silence is golden." + exit 0 + fi +} + +# 3 values, one for each each of the fields +update_features() { + read -a features < <($IOCTL $SCRATCH_MNT GET_FEATURES 2>&1) + check_features $? "${features[@]}" "GET_FEATURES" +} + +set_feature() { + local field=$1 + local bits=$2 + local class=${fields[$field]} + local old=${features[$field]} + msg=$($IOCTL $SCRATCH_MNT SET_FEATURES set $class $bits) + check_features $? "$msg" "SET_FEATURES" + update_features + local new=${features[$field]} + + if [ "$old" = "$new" ]; then + echo "Feature setting failed" + exit 1 + fi + expected=$(( $old | $bits )) + new=$(( $new )) + if [ "$expected" -ne "$new" ]; then + echo "Feature setting failed; Got $new, expected $expected" + exit 1 + fi + echo $new +} + +clear_feature() { + local field=$1 + local bits=$2 + local class=${fields[$field]} + local old=${features[$field]} + msg=$($IOCTL $SCRATCH_MNT SET_FEATURES clear $class $bits) + check_features $? "$msg" "SET_FEATURES" + update_features + local new="${features[$field]}" + + if [ "$old" = "$new" ]; then + echo "Feature clearing failed" + exit 1 + fi + expected=$(( $old & ~$bits )) + new=$(( $new )) + if [ "$expected" -ne "$new" ]; then + echo "Feature clearing failed; Got $new, expected $expected" + exit 1 + fi +} + +get_disk_flags () { + local index=$1 + $BTRFS_SHOW_SUPER_PROG $SCRATCH_DEV | grep ^${fields[$index]}_flags | \ + awk ''{print $NF}'' +} + +check_flags() { + local index=$1 + local expected=$(( $2 )) + disk_flags="$(( $(get_disk_flags $index) ))" + if [ "$disk_flags" -ne "$expected" ]; then + echo "mismatch: $disk_flags-$expected" + error=true + fi +} + +error=false +fields=("compat" "compat_ro" "incompat") + +_scratch_mkfs > /dev/null 2>&1 +_scratch_mount + +update_features + +# 9 values; 3 each for supported, settable, and clearable +read -a supp_features < <($IOCTL $SCRATCH_MNT GET_SUPPORTED_FEATURES 2>&1) +check_features $? "$supp_features" "GET_SUPPORTED_FEATURES" + +# Cycle through settable features. +# Set the feature +# Reload ioctl version and test against expected new value +# Unmount and test against expected new value +# Reount +settable() { + echo "${supp_features[$(( $1 + 3 ))]}" +} +did_set=false +for field in $(seq 0 2); do + fset="$(settable $field)" + for n in $(seq 0 63); do + old="${features[$field]}" + v="$(( $fset & (1 << $n) ))" + [ "$v" -eq 0 ] && continue + new="$(set_feature $field $v)" + umount $SCRATCH_MNT > /dev/null 2>&1 + expected="$(( $old | $v ))" + check_flags "$field" "$expected" + _scratch_mount + did_set=true + done +done +$did_set || echo "No online-settable features to test." >> $seqres.full + +# Repeat with clearing features +clearable() { + echo "${supp_features[$(( $1 + 6 ))]}" +} +did_clear=false +for field in $(seq 0 2); do + fclear="$(clearable $field)" + for n in $(seq 0 63); do + v="$(( $fclear & (1 << $n) ))" + [ "$v" -eq 0 ] && continue + + new="$(clear_feature $field $v)" + umount $SCRATCH_MNT > /dev/null 2>&1 + expected=$(( $old &~ $v )) + check_flags $field $expected + _scratch_mount + did_clear=true + done +done +$did_clear || echo "No online-clearable features to test." >> $seqres.full + +umount $SCRATCH_MNT > /dev/null 2>&1 + +$error && exit 1 + +echo "Silence is golden" +status=0 +exit diff --git a/tests/btrfs/103.out b/tests/btrfs/103.out new file mode 100644 index 0000000..aa66c3b --- /dev/null +++ b/tests/btrfs/103.out @@ -0,0 +1,2 @@ +== QA output created by 103 +Silence is golden diff --git a/tests/btrfs/104 b/tests/btrfs/104 new file mode 100755 index 0000000..3ac4040 --- /dev/null +++ b/tests/btrfs/104 @@ -0,0 +1,186 @@ +#!/bin/bash +# FA QA Test No. 104 +# +# Test online feature changing via sysfs +# +#----------------------------------------------------------------------- +# Copyright (c) 2013 SUSE, All Rights Reserved. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it would be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +#----------------------------------------------------------------------- + +seq=$(basename $0) +seqres=$RESULT_DIR/$seq +echo "== QA output created by $seq" + +here=$(pwd) +tmp=/tmp/$$ +status=1 + +# get standard environment, filters and checks +. ./common/rc +. ./common/filter.btrfs + +_supported_fs btrfs +_supported_os Linux +_require_scratch +_require_command $BTRFS_SHOW_SUPER_PROG btrfs-show-super + +IOCTL=src/btrfs_ioctl_helper + +fsid() { + $BTRFS_UTIL_PROG filesystem show $1|awk ''/uuid:/ {print $NF}'' +} + +get_disk_flags () { + local class=$1 + $BTRFS_SHOW_SUPER_PROG $SCRATCH_DEV | grep ^${class}_flags | \ + awk ''{print $NF}'' +} + +check_flags() { + local class=$1 + local expected=$2 + disk_flags="$(get_disk_flags $class)" + disk_flags=$(printf 0x%llx $disk_flags) + expected=$(printf 0x%llx $expected) + if [ "$disk_flags" != "$expected" ]; then + echo "mismatch: $disk_flags-$expected" + error=true + fi +} + +get_feature_mask() { + local attr=$1 + local class="" + local bit+ case "$attr" in + mixed_backref) class=incompat bit=0x1 ;; + default_subvol) class=incompat bit=0x2 ;; + mixed_groups) class=incompat bit=0x4 ;; + compress_lzo) class=incompat bit=0x8 ;; + compress_lsov2) class=incompat bit=0x10 ;; + big_metadata) class=incompat bit=0x20 ;; + extended_iref) class=incompat bit=0x40 ;; + raid56) class=incompat bit=0x80 ;; + skinny_metadata)class=incompat bit=0x100 ;; + compat:*) class=compat; bit=${attr##compat:} ;; + compat_ro:*) class=compat_ro; bit=${attr##compat_ro:} ;; + incompat:*) class=incompat; bit=${attr##incompat:} ;; + esac + if [ -z "$class" ]; then + echo "Unknown feature name $attr. xfstests needs updating." \ + " Skipping the test of sysfs values to superblock values" \ + >> $seqres.full + return + fi + echo "$class $bit" +} + + +_scratch_mkfs > /dev/null 2>&1 +error=false +fields=("compat" "compat_ro" "incompat") +sysfs_base="/sys/fs/btrfs" +settable="" +clearable="" + +if [ ! -d "$sysfs_base/features" ]; then + echo "This kernel does not export $sysfs_base/features." \ + "Nothing to test." >> $seqres.full + exit 0 +fi + +# Gather up the features the kernel knows about +_scratch_mount +for feature in $sysfs_base/features/*; do + val=$(cat $feature) + fname=$(basename $feature) + if [ "$(( $val & 0x1 ))" -eq 1 ]; then + settable="$settable $fname" + fi + if [ "$(( $val & 0x2 ))" -eq 2 ]; then + clearable="$clearable $fname" + fi +done +umount $SCRATCH_MNT > /dev/null 2>&1 + +# Set/clear tests do their own mount cycling +sysfs_fs_base="$sysfs_base/$(fsid $SCRATCH_DEV)" + +if [ ! -d "$sysfs_fs_base/features" ]; then + echo "This kernel does not export $sysfs_fs_base/features." \ + "Nothing to test." >> $seqres.full + exit 0 +fi + +did_set=false +for feature in $settable; do + read class bit < <(get_feature_mask $feature) + [ -z "$class" ] && continue + flags=$(get_disk_flags $class) + _scratch_mount + val=$(cat $sysfs_fs_base/features/$feature) + [ "$val" -ne 0 ] && continue + echo 1 > $sysfs_fs_base/features/$feature + if [ $? -ne 0 ] ; then + echo "Error while setting $feature - $st" + error=true + umount $SCRATCH_MNT > /dev/null 2>&1 + continue + fi + newval=$(cat $sysfs_fs_base/features/$feature) + if [ "$newval" -ne 1 ]; then + echo "Setting feature $feature was ignored." + error=true + fi + umount $SCRATCH_MNT > /dev/null 2>&1 + check_flags $class $(( $flags | $bit )) + did_set=true +done +$did_set || echo "No online-settable features to test." >> $seqres.full + +did_clear=false +for feature in $clearable; do + read class bit < <(get_feature_mask $feature) + [ -z "$class" ] && continue + flags=$(get_disk_flags $class) + _scratch_mount + val=$(cat $sysfs_fs_base/features/$feature) + [ "$val" -ne 1 ] && continue + echo 0 > $sysfs_fs_base/features/$feature + if [ $? -ne 0 ] ; then + echo "Error while clearing $feature - $st" + error=true + umount $SCRATCH_MNT > /dev/null 2>&1 + continue + fi + newval=$(cat $sysfs_fs_base/features/$feature) + if [ "$newval" -ne 0 ]; then + echo "Clearing feature $feature was ignored." + error=true + fi + umount $SCRATCH_MNT > /dev/null 2>&1 + check_flags $class $(( $flags & ~$bit )) + did_clear=true +done +$did_clear || echo "No online-clearable features to test." >> $seqres.full + +# Still umounted from set/clear tests + +$error && exit 1 + +echo "Silence is golden" +status=0 +exit diff --git a/tests/btrfs/104.out b/tests/btrfs/104.out new file mode 100644 index 0000000..ce6cb03 --- /dev/null +++ b/tests/btrfs/104.out @@ -0,0 +1,2 @@ +== QA output created by 104 +Silence is golden -- 1.8.1.4 _______________________________________________ xfs mailing list xfs@oss.sgi.com http://oss.sgi.com/mailman/listinfo/xfs
Jeff Mahoney
2013-Oct-25 21:21 UTC
Re: [patch 0/3] xfstests: tests for btrfs publishing/export patchset
On 10/25/13, 4:52 PM, Jeff Mahoney wrote:> These are the tests that Josef requested accompany the submission of > the btrfs publishing/export patchset[1]. > > 100: Test new global metadata reservation ioctl > 101: Test new sysfs exporting of allocation and device membership > 102: Test new sysfs exporting of feature bits > 103: Test setting/clearing feature bits via ioctl > 104: Test setting/clearing feature bits via sysfs > > As part of the ioctl testing, I added a helper that can be extended > easily to export simple information via ioctl. This means that the > tests can be independent of btrfsprogs version or its output formatting. > > -Jeff > > [1] http://thread.gmane.org/gmane.comp.file-systems.btrfs/29307Apologies for the formatting of the subjects and lack of direct btrfs mention in the commits. I''ll fix and resend. -Jeff -- Jeff Mahoney SUSE Labs _______________________________________________ xfs mailing list xfs@oss.sgi.com http://oss.sgi.com/mailman/listinfo/xfs
Josef Bacik
2013-Oct-28 15:53 UTC
Re: [patch 2/3] [PATCH 2/3] xfstests: add test for sysfs publication of btrfs info
On Fri, Oct 25, 2013 at 04:52:48PM -0400, Jeff Mahoney wrote:> This tests the sysfs publishing for btrfs allocation and device > membership info under a number of different layouts, similar to the > btrfs replace test. We test the allocation files only for existence and > that they contain numerical values. We test the device membership > by mapping the devices used to create the file system to sysfs paths > and matching them against the paths used for the device membership > symlinks. > > Since this is a new feature, it passes on kernels without > a /sys/fs/btrfs/<fsid> directory. > > Signed-off-by: Jeff Mahoney <jeffm@suse.com> > --- > common/config | 1 + > tests/btrfs/101 | 188 ++++++++++++++++++++++++++++++++++++++++++++++++++++ > tests/btrfs/101.out | 2 + > 3 files changed, 191 insertions(+) > create mode 100755 tests/btrfs/101 > create mode 100644 tests/btrfs/101.out > > diff --git a/common/config b/common/config > index 20c5b09..5f9e2e8 100644 > --- a/common/config > +++ b/common/config > @@ -208,6 +208,7 @@ case "$HOSTOS" in > export MKFS_UDF_PROG="`set_prog_path mkudffs`" > export MKFS_BTRFS_PROG="`set_btrfs_mkfs_prog_path_with_opts`" > export BTRFS_UTIL_PROG="`set_prog_path btrfs`" > + export UDEVADM_PROG="`set_prog_path udevadm`" > export BTRFS_SHOW_SUPER_PROG="`set_prog_path btrfs-show-super`" > export XFS_FSR_PROG="`set_prog_path xfs_fsr`" > export MKFS_NFS_PROG="false" > diff --git a/tests/btrfs/101 b/tests/btrfs/101 > new file mode 100755 > index 0000000..9a2834b > --- /dev/null > +++ b/tests/btrfs/101 > @@ -0,0 +1,188 @@ > +#! /bin/bash > +# FS QA Test No. btrfs/101 > +# > +# Test of the btrfs sysfs publishing > +# > +#----------------------------------------------------------------------- > +# Copyright (C) 2013 SUSE. All rights reserved. > +# > +# This program is free software; you can redistribute it and/or > +# modify it under the terms of the GNU General Public License as > +# published by the Free Software Foundation. > +# > +# This program is distributed in the hope that it would be useful, > +# but WITHOUT ANY WARRANTY; without even the implied warranty of > +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > +# GNU General Public License for more details. > +# > +# You should have received a copy of the GNU General Public License > +# along with this program; if not, write the Free Software Foundation, > +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA > +# > +#----------------------------------------------------------------------- > +# > + > +seq=`basename $0` > +seqres=$RESULT_DIR/$seq > +echo "QA output created by $seq" > + > +here=`pwd` > +tmp=/tmp/$$ > +status=1 > + > +# get standard environment, filters and checks > +. ./common/rc > +. ./common/filter > + > +# real QA test starts here > +_need_to_be_root > +_supported_fs btrfs > +_require_scratch > +_require_scratch_dev_pool > +_require_command $UDEVADM_PROG udevadmI don''t think you need the extra udevadm here. Thanks, Josef -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Josef Bacik
2013-Oct-28 15:59 UTC
Re: [patch 1/3] [PATCH 1/3] xfstests: add test for global metadata reservation publishing
On Fri, Oct 25, 2013 at 04:52:47PM -0400, Jeff Mahoney wrote:> My publishing patchset added the ability for the kernel to report > the size of the global metadata reservation via ioctl and sysfs. > > This test confirms that we get sane results on an empty file system. > > ENOTTY and missing /sys/fs/btrfs/<fsid>/allocation are not considered > failures. > > Signed-off-by: Jeff Mahoney <jeffm@suse.com> > --- > src/Makefile | 3 +- > src/btrfs_ioctl_helper.c | 90 ++++++++++++++++++++++++++++++++++++++++++++++ > tests/btrfs/100 | 92 ++++++++++++++++++++++++++++++++++++++++++++++++ > tests/btrfs/100.out | 2 ++ > 4 files changed, 186 insertions(+), 1 deletion(-) > create mode 100644 src/btrfs_ioctl_helper.c > create mode 100755 tests/btrfs/100 > create mode 100644 tests/btrfs/100.out > > diff --git a/src/Makefile b/src/Makefile > index 84c8297..299f675 100644 > --- a/src/Makefile > +++ b/src/Makefile > @@ -18,7 +18,8 @@ LINUX_TARGETS = xfsctl bstat t_mtab getdevicesize preallo_rw_pattern_reader \ > locktest unwritten_mmap bulkstat_unlink_test t_stripealign \ > bulkstat_unlink_test_modified t_dir_offset t_futimens t_immutable \ > stale_handle pwrite_mmap_blocked t_dir_offset2 seek_sanity_test \ > - seek_copy_test t_readdir_1 t_readdir_2 fsync-tester nsexec > + seek_copy_test t_readdir_1 t_readdir_2 fsync-tester nsexec \ > + btrfs_ioctl_helper > > SUBDIRS > > diff --git a/src/btrfs_ioctl_helper.c b/src/btrfs_ioctl_helper.c > new file mode 100644 > index 0000000..a88b7b5 > --- /dev/null > +++ b/src/btrfs_ioctl_helper.c > @@ -0,0 +1,90 @@ > +#include <sys/ioctl.h> > +#include <stdio.h> > +#include <sys/fcntl.h> > +#include <errno.h> > +#include <string.h> > +#include <stdint.h> > +#include <unistd.h> > + > +#ifndef BTRFS_IOCTL_MAGIC > +#define BTRFS_IOCTL_MAGIC 0x94 > +#endif > + > +#ifndef BTRFS_IOC_GLOBAL_RSV > +#define BTRFS_IOC_GLOBAL_RSV _IOR(BTRFS_IOCTL_MAGIC, 20, uint64_t) > +#endif > + > +static int global_rsv_ioctl(int fd, int argc, char *argv[]) > +{ > + uint64_t reserved; > + int ret = ioctl(fd, BTRFS_IOC_GLOBAL_RSV, &reserved); > + if (ret) > + return -errno; > + > + printf("%llu\n", (unsigned long long)reserved); > + return 0; > +} > + > +#define IOCTL_TABLE_ENTRY(_ioctl_name, _handler) \ > + { .name = #_ioctl_name, .ioctl_cmd = BTRFS_IOC_##_ioctl_name, \ > + .handler = _handler, } > + > +struct ioctl_table_entry { > + const char *name; > + unsigned ioctl_cmd; > + int (*handler)(int fd, int argc, char *argv[]); > +}; > + > +static struct ioctl_table_entry ioctls[] = { > + IOCTL_TABLE_ENTRY(GLOBAL_RSV, global_rsv_ioctl), > +}; > + > +int > +main(int argc, char *argv[]) > +{ > + int fd; > + int ret; > + struct ioctl_table_entry *entry = NULL; > + int i; > + > + if (argc < 3) { > + fprintf(stderr, > + "usage: %s <fs mount point> <ioctl name> [args..]\n", > + argv[0]); > + return 1; > + } > + > + fd = open(argv[1], O_RDONLY|O_DIRECTORY); > + if (fd < 0) { > + perror(argv[1]); > + return 1; > + } > + > + for (i = 0; i < (sizeof(ioctls)/sizeof(ioctls[0])); i++) { > + if (strcmp(argv[2], ioctls[i].name) == 0) { > + entry = &ioctls[i]; > + break; > + } > + } > + > + if (!entry) { > + fprintf(stderr, "ERROR: unknown ioctl %s\n", argv[2]); > + close(fd); > + return 1; > + } > + > + ret = entry->handler(fd, argc - 3, argv + 3); > + if (ret == -ENOTTY) { > + printf("Not implemented.\n"); > + close(fd); > + return 0; > + } else if (ret) { > + fprintf(stderr, "ERROR: %s failed: %s\n", > + entry->name, strerror(-ret)); > + close(fd); > + return 1; > + } > + > + close(fd); > + return 0; > +} > diff --git a/tests/btrfs/100 b/tests/btrfs/100 > new file mode 100755 > index 0000000..d2a40b4 > --- /dev/null > +++ b/tests/btrfs/100 > @@ -0,0 +1,92 @@ > +#!/bin/bash > +# FA QA Test No. 100 > +# > +# Test global metadata reservation reporting > +# > +# 1) Create empty file system > +# 2) Call the BTRFS_IOC_GLOBAL_RSV ioctl and confirm it is 0 < x < 10MB > +# 3) Read the /sys/fs/btrfs/<fsid>/allocation/global_rsv_reserved file > +# and confirm the value is 0 < x < 10 MB > +# > +#----------------------------------------------------------------------- > +# Copyright (c) 2013 SUSE, All Rights Reserved. > +# > +# This program is free software; you can redistribute it and/or > +# modify it under the terms of the GNU General Public License as > +# published by the Free Software Foundation. > +# > +# This program is distributed in the hope that it would be useful, > +# but WITHOUT ANY WARRANTY; without even the implied warranty of > +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > +# GNU General Public License for more details. > +# > +# You should have received a copy of the GNU General Public License > +# along with this program; if not, write the Free Software Foundation, > +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA > +#----------------------------------------------------------------------- > + > +seq=$(basename $0) > +seqres=$RESULT_DIR/$seq > +echo "== QA output created by $seq" > + > +here=$(pwd) > +tmp=/tmp/$$ > +status=1 > + > +# get standard environment, filters and checks > +. ./common/rc > +. ./common/filter.btrfs > + > +_supported_fs btrfs > +_supported_os Linux > +_require_scratch > + > +_scratch_mkfs > /dev/null 2>&1 > +_scratch_mount > + > +fsid() { > + $BTRFS_UTIL_PROG filesystem show $1|awk ''/uuid:/ {print $NF}'' > +}This is the second place you use this, should go into common/rc or some other common place. Thanks, Josef -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Josef Bacik
2013-Oct-28 16:02 UTC
Re: [patch 3/3] [PATCH 3/3] xfstests: add tests for new feature ioctl and sysfs interfaces
On Fri, Oct 25, 2013 at 04:52:49PM -0400, Jeff Mahoney wrote:> This tests the exporting of feature information from the kernel via > sysfs and ioctl. The first test works whether the sysfs permissions > are correct, if the information exported via sysfs matches > what the ioctls are reporting, and if they both match the on-disk > superblock''s version of the feature sets. The second and third tests > test online setting and clearing of feature bits via the sysfs and > ioctl interfaces, checking whether they match the on-disk super on > each cycle. > > In every case, if the features are not present, it is not considered > a failure and a message indicating that will be dumped to the $num.full > file. > > Signed-off-by: Jeff Mahoney <jeffm@suse.com> > --- > src/btrfs_ioctl_helper.c | 93 +++++++++++++++++ > tests/btrfs/102 | 263 +++++++++++++++++++++++++++++++++++++++++++++++ > tests/btrfs/102.out | 2 + > tests/btrfs/103 | 188 +++++++++++++++++++++++++++++++++ > tests/btrfs/103.out | 2 + > tests/btrfs/104 | 186 +++++++++++++++++++++++++++++++++ > tests/btrfs/104.out | 2 + > 7 files changed, 736 insertions(+) > create mode 100755 tests/btrfs/102 > create mode 100644 tests/btrfs/102.out > create mode 100755 tests/btrfs/103 > create mode 100644 tests/btrfs/103.out > create mode 100755 tests/btrfs/104 > create mode 100644 tests/btrfs/104.out > > diff --git a/src/btrfs_ioctl_helper.c b/src/btrfs_ioctl_helper.c > index a88b7b5..73cfa60 100644 > --- a/src/btrfs_ioctl_helper.c > +++ b/src/btrfs_ioctl_helper.c > @@ -5,6 +5,7 @@ > #include <string.h> > #include <stdint.h> > #include <unistd.h> > +#include <stdlib.h> > > #ifndef BTRFS_IOCTL_MAGIC > #define BTRFS_IOCTL_MAGIC 0x94 > @@ -14,6 +15,21 @@ > #define BTRFS_IOC_GLOBAL_RSV _IOR(BTRFS_IOCTL_MAGIC, 20, uint64_t) > #endif > > +#ifndef BTRFS_IOC_GET_FEATURES > +struct btrfs_ioctl_feature_flags { > + uint64_t compat_flags; > + uint64_t compat_ro_flags; > + uint64_t incompat_flags; > +}; > + > +#define BTRFS_IOC_GET_FEATURES _IOR(BTRFS_IOCTL_MAGIC, 57, \ > + struct btrfs_ioctl_feature_flags) > +#define BTRFS_IOC_SET_FEATURES _IOW(BTRFS_IOCTL_MAGIC, 57, \ > + struct btrfs_ioctl_feature_flags[2]) > +#define BTRFS_IOC_GET_SUPPORTED_FEATURES _IOR(BTRFS_IOCTL_MAGIC, 57, \ > + struct btrfs_ioctl_feature_flags[3]) > +#endif > + > static int global_rsv_ioctl(int fd, int argc, char *argv[]) > { > uint64_t reserved; > @@ -25,6 +41,80 @@ static int global_rsv_ioctl(int fd, int argc, char *argv[]) > return 0; > } > > +static int get_features_ioctl(int fd, int argc, char *argv[]) > +{ > + struct btrfs_ioctl_feature_flags flags; > + int ret = ioctl(fd, BTRFS_IOC_GET_FEATURES, &flags); > + if (ret) > + return -errno; > + > + printf("0x%llx 0x%llx 0x%llx\n", > + (unsigned long long)flags.compat_flags, > + (unsigned long long)flags.compat_ro_flags, > + (unsigned long long)flags.incompat_flags); > + return 0; > +} > + > +static int set_features_ioctl(int fd, int argc, char *argv[]) > +{ > + struct btrfs_ioctl_feature_flags flags[2]; > + uint64_t bit, *bits, *mask; > + if (argc != 3) > + goto usage; > + > + memset(flags, 0, sizeof(flags)); > + > + errno = 0; > + bit = strtoull(argv[2], NULL, 10); > + if (errno) > + goto usage; > + > + if (strcmp(argv[1], "compat") == 0) { > + mask = &flags[0].compat_flags; > + bits = &flags[1].compat_flags; > + } else if (strcmp(argv[1], "compat_ro") == 0) { > + mask = &flags[0].compat_ro_flags; > + bits = &flags[1].compat_ro_flags; > + } else if (strcmp(argv[1], "incompat") == 0) { > + mask = &flags[0].incompat_flags; > + bits = &flags[1].incompat_flags; > + } else > + goto usage; > + > + *mask |= bit; > + > + if (strcmp(argv[0], "set") == 0) > + *bits |= bit; > + > + return ioctl(fd, BTRFS_IOC_SET_FEATURES, &flags); > +usage: > + fprintf(stderr, "usage: SET_FEATURES <set|clear> <compat|compat_ro|incompat> <base-10 bitmask>\n"); > + return -EINVAL; > +} > + > +static int get_supported_features_ioctl(int fd, int argc, char *argv[]) > +{ > + struct btrfs_ioctl_feature_flags flags[3]; > + int ret; > + int i; > + > + ret = ioctl(fd, BTRFS_IOC_GET_SUPPORTED_FEATURES, &flags); > + if (ret) > + return -errno; > + > + for (i = 0; i < 3; i++) > + printf("0x%llx 0x%llx 0x%llx ", > + (unsigned long long)flags[i].compat_flags, > + (unsigned long long)flags[i].compat_ro_flags, > + (unsigned long long)flags[i].incompat_flags); > + > + printf("\n"); > + return 0; > +usage: > + fprintf(stderr, > + "usage: GET_SUPPORTED_FEATURES <supported|settable|clearable>\n"); > + return -EINVAL; > +} > #define IOCTL_TABLE_ENTRY(_ioctl_name, _handler) \ > { .name = #_ioctl_name, .ioctl_cmd = BTRFS_IOC_##_ioctl_name, \ > .handler = _handler, } > @@ -37,6 +127,9 @@ struct ioctl_table_entry { > > static struct ioctl_table_entry ioctls[] = { > IOCTL_TABLE_ENTRY(GLOBAL_RSV, global_rsv_ioctl), > + IOCTL_TABLE_ENTRY(GET_FEATURES, get_features_ioctl), > + IOCTL_TABLE_ENTRY(SET_FEATURES, set_features_ioctl), > + IOCTL_TABLE_ENTRY(GET_SUPPORTED_FEATURES, get_supported_features_ioctl), > }; > > int > diff --git a/tests/btrfs/102 b/tests/btrfs/102 > new file mode 100755 > index 0000000..77f2162 > --- /dev/null > +++ b/tests/btrfs/102 > @@ -0,0 +1,263 @@ > +#!/bin/bash > +# FA QA Test No. 102 > +# > +# Test online feature publishing > +# This test doesn''t test the changing of features. It does test that > +# the proper publishing bits and permissions match up with > +# the expected values. > +# > +#----------------------------------------------------------------------- > +# Copyright (c) 2013 SUSE, All Rights Reserved. > +# > +# This program is free software; you can redistribute it and/or > +# modify it under the terms of the GNU General Public License as > +# published by the Free Software Foundation. > +# > +# This program is distributed in the hope that it would be useful, > +# but WITHOUT ANY WARRANTY; without even the implied warranty of > +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > +# GNU General Public License for more details. > +# > +# You should have received a copy of the GNU General Public License > +# along with this program; if not, write the Free Software Foundation, > +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA > +#----------------------------------------------------------------------- > + > +seq=$(basename $0) > +seqres=$RESULT_DIR/$seq > +echo "== QA output created by $seq" > + > +here=$(pwd) > +tmp=/tmp/$$ > +status=1 > + > +# get standard environment, filters and checks > +. ./common/rc > +. ./common/filter.btrfs > + > +_supported_fs btrfs > +_supported_os Linux > +_require_scratch > +_require_command $BTRFS_SHOW_SUPER_PROG btrfs-show-superYou don''t need the extra btrfs-show-super here, the var should be good enough.> + > +_scratch_mkfs > /dev/null 2>&1 > +_scratch_mount > + > +fsid() { > + $BTRFS_UTIL_PROG filesystem show $1|awk ''/uuid:/ {print $NF}'' > +} > + > +check_features() { > + reserved="$2" > + method="$3" > + if [ "$1" != 0 ]; then > + echo "$method: failed: $reserved" > + exit 1 > + fi > +} > + > +error=false > + > +# test -w will always return true if root is making the call. > +# This would be true in most cases, but for sysfs files, the permissions > +# are enforced even for root. > +is_writeable() { > + local file=$1 > + mode=$(stat -c "0%a" "$file") > + mode=$(( $mode & 0200 )) > + > + [ "$mode" -eq 0 ] && return 1 > + return 0 > +} > + > +# ioctl > +read -a features < <(src/btrfs_ioctl_helper $SCRATCH_MNT GET_FEATURES 2>&1) > +check_features $? "$features" "GET_FEATURES" > + > +read -a supp_features < <(src/btrfs_ioctl_helper $SCRATCH_MNT GET_SUPPORTED_FEATURES 2>&1) > +check_features $? "$features" "GET_SUPPORTED_FEATURES" > + > +# Sysfs checks > +fsid=$(fsid $SCRATCH_DEV) > +sysfs_base="/sys/fs/btrfs" > + > +# TODO Add tool to enable and test unknown feature bits > +get_feature_mask() { > + class="" > + case "$attr" in > + mixed_backref) class=incompat; bit=0x1 ;; > + default_subvol) class=incompat; bit=0x2 ;; > + mixed_groups) class=incompat; bit=0x4 ;; > + compress_lzo) class=incompat; bit=0x8 ;; > + compress_lsov2) class=incompat; bit=0x10 ;; > + big_metadata) class=incompat; bit=0x20 ;; > + extended_iref) class=incompat; bit=0x40 ;; > + raid56) class=incompat; bit=0x80 ;; > + skinny_metadata)class=incompat; bit=0x100 ;; > + compat:*) class=compat; bit=${attr##compat:} ;; > + compat_ro:*) class=compat_ro; bit=${attr##compat_ro:} ;; > + incompat:*) class=incompat; bit=${attr##incompat:} ;; > + esac > + if [ -z "$class" ]; then > + echo "Unknown feature name $attr. xfstests needs updating." \ > + " Skipping the test of sysfs values to superblock values" \ > + >> $seqres.full > + return > + fi > + > + echo "$class $bit" > +} > + > +get_changeable_mask() { > + local class=$1 > + local index=0 > + if [ "$class" = "compat" ]; then > + index=0 > + elif [ "$class" = "compat_ro" ]; then > + index=1 > + elif [ "$class" = "incompat" ]; then > + index=2 > + fi > + local set_index=$(( $index + 3 )) > + local clear_index=$(( $index + 6 )) > + > + local mask=$(( ${supp_features[$set_index]} | \ > + ${supp_features[$clear_index]} )) > + > + echo $mask > +} > + > +# Check enabled features in sysfs vs what the superblock claims > +sysfs_features=(0 0 0) > +for file in $sysfs_base/$fsid/features/*; do > + attr=$(basename $file) > + val=$(cat $file) > + read class bit < <(get_feature_mask $attr) > + > + # A file that exists but has a 0 value means that it''s changeable > + if [ "$val" -eq 0 ]; then > + if [ ! -e "$sysfs_base/features/$attr" ]; then > + echo "$fsid/$attr exists with a 0 value but" \ > + "features/$attr doesn''t exist." > + error=true > + continue > + elif ! is_writeable "$file"; then > + echo "$attr is not writable but exists and has a" \ > + "0 value." > + error=true > + fi > + > + mask=$(get_changeable_mask $class) > + if [ "$(( $bit & ~$mask ))" -ne 0 ]; then > + echo "$attr is writable but GET_SUPPORTED_FEATURES" \ > + "ioctl claims it shouldn''t be." > + error=true > + fi > + > + continue > + fi > + if [ "$class" = "compat" ]; then > + sysfs_features[0]=$(( ${sysfs_features[0]} | $bit )) > + elif [ "$class" = "compat_ro" ]; then > + sysfs_features[1]=$(( ${sysfs_features[1]} | $bit )) > + elif [ "$class" = "incompat" ]; then > + sysfs_features[2]=$(( ${sysfs_features[2]} | $bit )) > + else > + # We will end up with a bit set in the superblock that > + # doesn''t have a matching bit here. The feature-bit to name > + # mapping must be kept up-to-date for this test to succeed. > + echo "Unknown feature name $attr. xfstests needs updating." \ > + "Skipping the test of sysfs values to superblock values" \ > + >> $seqres.full > + skip_sysfs_super_check=true > + fi > +done > + > +for file in $sysfs_base/features/*; do > + attr=$(basename $file) > + val=$(cat $file) > + if [ "$val" -gt 0 ]; then > + if [ ! -e "$sysfs_base/$fsid/features/$attr" ]; then > + echo "features/$attr has a nonzero value ($val)" \ > + "but $fsid/features/$attr doesn''t exist" > + error=true > + continue > + fi > + if ! is_writeable "$sysfs_base/$fsid/features/$attr"; then > + echo "features/$attr has a nonzero value ($val)" \ > + "but $fsid/features/$attr is not writable" > + error=true > + continue > + fi > + continue > + fi > + > + [ ! -e "$sysfs_base/$fsid/features/$attr" ] && continue > + > + if is_writeable "$sysfs_base/$fsid/features/$attr"; then > + echo "features/$attr has a zero value but" \ > + "$fsid/features/$attr is writable." > + error=true > + continue > + fi > + > + read class bit < <(get_feature_mask $attr) > + mask=$(get_changeable_mask $class) > + if [ "$(( $bit & $mask ))" -ne 0 ]; then > + echo "$attr isn''t writable but GET_SUPPORTED_FEATURES" \ > + "ioctl claims it should be." > + error=true > + continue > + fi > +done > + > +umount $SCRATCH_MNT > /dev/null 2>&1 > + > +fields=("compat" "compat_ro" "incompat") > +declare -a disk_flags > +get_disk_flags() { > + local index=$1 > + > + # Grab the flags from the superblock directly to compare > + disk_flags[$index]=$($BTRFS_SHOW_SUPER_PROG $SCRATCH_DEV | \ > + grep "^${fields[$index]}_flags"|awk ''{print $NF}'') > +} > + > +check_ioctl_flags() { > + local index=$1 > + local flags=${features[$index]} > + > + if [ "$flags" != "${disk_flags[$index]}" ]; then > + echo "ioctl returned different ${fields[$index]} flags" \ > + "($flags) than those contained in superblock" \ > + "(${disk_flags[$index]})" > + error=true > + fi > +} > + > +check_sysfs_flags() { > + local index=$1 > + $skip_sysfs_super_check || return > + > + flags=$(printf "0x%llx" ${sysfs_features[$index]}) > + if [ "$flags" != "${disk_flags[$index]}" ]; then > + echo "sysfs returned different ${fields[$index]}" \ > + "flags ($flags) than those contained in" \ > + "superblock (${disk_flags[$index]})" > + error=true > + fi > +} > + > + > +for index in $(seq 0 2); do > + get_disk_flags "$index" > + check_ioctl_flags "$index" > + check_sysfs_flags "$index" > +done > + > +$error && exit 1 > + > +# > +echo "Silence is golden" > +status=0 > +exit > diff --git a/tests/btrfs/102.out b/tests/btrfs/102.out > new file mode 100644 > index 0000000..28b7182 > --- /dev/null > +++ b/tests/btrfs/102.out > @@ -0,0 +1,2 @@ > +== QA output created by 102 > +Silence is golden > diff --git a/tests/btrfs/103 b/tests/btrfs/103 > new file mode 100755 > index 0000000..ff083c7 > --- /dev/null > +++ b/tests/btrfs/103 > @@ -0,0 +1,188 @@ > +#!/bin/bash > +# FA QA Test No. 103 > +# > +# Test online feature changing via ioctl > +# > +#----------------------------------------------------------------------- > +# Copyright (c) 2013 SUSE, All Rights Reserved. > +# > +# This program is free software; you can redistribute it and/or > +# modify it under the terms of the GNU General Public License as > +# published by the Free Software Foundation. > +# > +# This program is distributed in the hope that it would be useful, > +# but WITHOUT ANY WARRANTY; without even the implied warranty of > +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > +# GNU General Public License for more details. > +# > +# You should have received a copy of the GNU General Public License > +# along with this program; if not, write the Free Software Foundation, > +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA > +#----------------------------------------------------------------------- > + > +seq=$(basename $0) > +seqres=$RESULT_DIR/$seq > +echo "== QA output created by $seq" > + > +here=$(pwd) > +tmp=/tmp/$$ > +status=1 > + > +# get standard environment, filters and checks > +. ./common/rc > +. ./common/filter.btrfs > + > +_supported_fs btrfs > +_supported_os Linux > +_require_scratch > +_require_command $BTRFS_SHOW_SUPER_PROG btrfs-show-super > +Same here.> +IOCTL=src/btrfs_ioctl_helper > + > +check_features() { > + reserved="$2" > + method="$3" > + if [ "$1" != 0 ]; then > + echo "$method: failed: $reserved" > + exit 1 > + fi > + if [ "$reserved" = "Not implemented." ]; then > + echo "Skipping ioctl $method test. Not implemented." \ > + >> $seqres.full > + echo "Silence is golden." > + exit 0 > + fi > +} > + > +# 3 values, one for each each of the fields > +update_features() { > + read -a features < <($IOCTL $SCRATCH_MNT GET_FEATURES 2>&1) > + check_features $? "${features[@]}" "GET_FEATURES" > +} > + > +set_feature() { > + local field=$1 > + local bits=$2 > + local class=${fields[$field]} > + local old=${features[$field]} > + msg=$($IOCTL $SCRATCH_MNT SET_FEATURES set $class $bits) > + check_features $? "$msg" "SET_FEATURES" > + update_features > + local new=${features[$field]} > + > + if [ "$old" = "$new" ]; then > + echo "Feature setting failed" > + exit 1 > + fi > + expected=$(( $old | $bits )) > + new=$(( $new )) > + if [ "$expected" -ne "$new" ]; then > + echo "Feature setting failed; Got $new, expected $expected" > + exit 1 > + fi > + echo $new > +} > + > +clear_feature() { > + local field=$1 > + local bits=$2 > + local class=${fields[$field]} > + local old=${features[$field]} > + msg=$($IOCTL $SCRATCH_MNT SET_FEATURES clear $class $bits) > + check_features $? "$msg" "SET_FEATURES" > + update_features > + local new="${features[$field]}" > + > + if [ "$old" = "$new" ]; then > + echo "Feature clearing failed" > + exit 1 > + fi > + expected=$(( $old & ~$bits )) > + new=$(( $new )) > + if [ "$expected" -ne "$new" ]; then > + echo "Feature clearing failed; Got $new, expected $expected" > + exit 1 > + fi > +} > + > +get_disk_flags () { > + local index=$1 > + $BTRFS_SHOW_SUPER_PROG $SCRATCH_DEV | grep ^${fields[$index]}_flags | \ > + awk ''{print $NF}'' > +} > + > +check_flags() { > + local index=$1 > + local expected=$(( $2 )) > + disk_flags="$(( $(get_disk_flags $index) ))" > + if [ "$disk_flags" -ne "$expected" ]; then > + echo "mismatch: $disk_flags-$expected" > + error=true > + fi > +} > + > +error=false > +fields=("compat" "compat_ro" "incompat") > + > +_scratch_mkfs > /dev/null 2>&1 > +_scratch_mount > + > +update_features > + > +# 9 values; 3 each for supported, settable, and clearable > +read -a supp_features < <($IOCTL $SCRATCH_MNT GET_SUPPORTED_FEATURES 2>&1) > +check_features $? "$supp_features" "GET_SUPPORTED_FEATURES" > + > +# Cycle through settable features. > +# Set the feature > +# Reload ioctl version and test against expected new value > +# Unmount and test against expected new value > +# Reount > +settable() { > + echo "${supp_features[$(( $1 + 3 ))]}" > +} > +did_set=false > +for field in $(seq 0 2); do > + fset="$(settable $field)" > + for n in $(seq 0 63); do > + old="${features[$field]}" > + v="$(( $fset & (1 << $n) ))" > + [ "$v" -eq 0 ] && continue > + new="$(set_feature $field $v)" > + umount $SCRATCH_MNT > /dev/null 2>&1 > + expected="$(( $old | $v ))" > + check_flags "$field" "$expected" > + _scratch_mount > + did_set=true > + done > +done > +$did_set || echo "No online-settable features to test." >> $seqres.full > + > +# Repeat with clearing features > +clearable() { > + echo "${supp_features[$(( $1 + 6 ))]}" > +} > +did_clear=false > +for field in $(seq 0 2); do > + fclear="$(clearable $field)" > + for n in $(seq 0 63); do > + v="$(( $fclear & (1 << $n) ))" > + [ "$v" -eq 0 ] && continue > + > + new="$(clear_feature $field $v)" > + umount $SCRATCH_MNT > /dev/null 2>&1 > + expected=$(( $old &~ $v )) > + check_flags $field $expected > + _scratch_mount > + did_clear=true > + done > +done > +$did_clear || echo "No online-clearable features to test." >> $seqres.full > + > +umount $SCRATCH_MNT > /dev/null 2>&1 > + > +$error && exit 1 > + > +echo "Silence is golden" > +status=0 > +exit > diff --git a/tests/btrfs/103.out b/tests/btrfs/103.out > new file mode 100644 > index 0000000..aa66c3b > --- /dev/null > +++ b/tests/btrfs/103.out > @@ -0,0 +1,2 @@ > +== QA output created by 103 > +Silence is golden > diff --git a/tests/btrfs/104 b/tests/btrfs/104 > new file mode 100755 > index 0000000..3ac4040 > --- /dev/null > +++ b/tests/btrfs/104 > @@ -0,0 +1,186 @@ > +#!/bin/bash > +# FA QA Test No. 104 > +# > +# Test online feature changing via sysfs > +# > +#----------------------------------------------------------------------- > +# Copyright (c) 2013 SUSE, All Rights Reserved. > +# > +# This program is free software; you can redistribute it and/or > +# modify it under the terms of the GNU General Public License as > +# published by the Free Software Foundation. > +# > +# This program is distributed in the hope that it would be useful, > +# but WITHOUT ANY WARRANTY; without even the implied warranty of > +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > +# GNU General Public License for more details. > +# > +# You should have received a copy of the GNU General Public License > +# along with this program; if not, write the Free Software Foundation, > +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA > +#----------------------------------------------------------------------- > + > +seq=$(basename $0) > +seqres=$RESULT_DIR/$seq > +echo "== QA output created by $seq" > + > +here=$(pwd) > +tmp=/tmp/$$ > +status=1 > + > +# get standard environment, filters and checks > +. ./common/rc > +. ./common/filter.btrfs > + > +_supported_fs btrfs > +_supported_os Linux > +_require_scratch > +_require_command $BTRFS_SHOW_SUPER_PROG btrfs-show-super > +And here. Thanks, Josef -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Jeff Mahoney
2013-Oct-28 19:55 UTC
Re: [patch 1/3] [PATCH 1/3] xfstests: add test for global metadata reservation publishing
On 10/28/13, 11:59 AM, Josef Bacik wrote:> On Fri, Oct 25, 2013 at 04:52:47PM -0400, Jeff Mahoney wrote: >> My publishing patchset added the ability for the kernel to report >> the size of the global metadata reservation via ioctl and sysfs. >> >> This test confirms that we get sane results on an empty file system. >> >> ENOTTY and missing /sys/fs/btrfs/<fsid>/allocation are not considered >> failures. >> >> Signed-off-by: Jeff Mahoney <jeffm@suse.com> >> --- >> src/Makefile | 3 +- >> src/btrfs_ioctl_helper.c | 90 ++++++++++++++++++++++++++++++++++++++++++++++ >> tests/btrfs/100 | 92 ++++++++++++++++++++++++++++++++++++++++++++++++ >> tests/btrfs/100.out | 2 ++ >> 4 files changed, 186 insertions(+), 1 deletion(-) >> create mode 100644 src/btrfs_ioctl_helper.c >> create mode 100755 tests/btrfs/100 >> create mode 100644 tests/btrfs/100.out >> >> diff --git a/src/Makefile b/src/Makefile >> index 84c8297..299f675 100644 >> --- a/src/Makefile >> +++ b/src/Makefile >> @@ -18,7 +18,8 @@ LINUX_TARGETS = xfsctl bstat t_mtab getdevicesize preallo_rw_pattern_reader \ >> locktest unwritten_mmap bulkstat_unlink_test t_stripealign \ >> bulkstat_unlink_test_modified t_dir_offset t_futimens t_immutable \ >> stale_handle pwrite_mmap_blocked t_dir_offset2 seek_sanity_test \ >> - seek_copy_test t_readdir_1 t_readdir_2 fsync-tester nsexec >> + seek_copy_test t_readdir_1 t_readdir_2 fsync-tester nsexec \ >> + btrfs_ioctl_helper >> >> SUBDIRS >> >> diff --git a/src/btrfs_ioctl_helper.c b/src/btrfs_ioctl_helper.c >> new file mode 100644 >> index 0000000..a88b7b5 >> --- /dev/null >> +++ b/src/btrfs_ioctl_helper.c >> @@ -0,0 +1,90 @@ >> +#include <sys/ioctl.h> >> +#include <stdio.h> >> +#include <sys/fcntl.h> >> +#include <errno.h> >> +#include <string.h> >> +#include <stdint.h> >> +#include <unistd.h> >> + >> +#ifndef BTRFS_IOCTL_MAGIC >> +#define BTRFS_IOCTL_MAGIC 0x94 >> +#endif >> + >> +#ifndef BTRFS_IOC_GLOBAL_RSV >> +#define BTRFS_IOC_GLOBAL_RSV _IOR(BTRFS_IOCTL_MAGIC, 20, uint64_t) >> +#endif >> + >> +static int global_rsv_ioctl(int fd, int argc, char *argv[]) >> +{ >> + uint64_t reserved; >> + int ret = ioctl(fd, BTRFS_IOC_GLOBAL_RSV, &reserved); >> + if (ret) >> + return -errno; >> + >> + printf("%llu\n", (unsigned long long)reserved); >> + return 0; >> +} >> + >> +#define IOCTL_TABLE_ENTRY(_ioctl_name, _handler) \ >> + { .name = #_ioctl_name, .ioctl_cmd = BTRFS_IOC_##_ioctl_name, \ >> + .handler = _handler, } >> + >> +struct ioctl_table_entry { >> + const char *name; >> + unsigned ioctl_cmd; >> + int (*handler)(int fd, int argc, char *argv[]); >> +}; >> + >> +static struct ioctl_table_entry ioctls[] = { >> + IOCTL_TABLE_ENTRY(GLOBAL_RSV, global_rsv_ioctl), >> +}; >> + >> +int >> +main(int argc, char *argv[]) >> +{ >> + int fd; >> + int ret; >> + struct ioctl_table_entry *entry = NULL; >> + int i; >> + >> + if (argc < 3) { >> + fprintf(stderr, >> + "usage: %s <fs mount point> <ioctl name> [args..]\n", >> + argv[0]); >> + return 1; >> + } >> + >> + fd = open(argv[1], O_RDONLY|O_DIRECTORY); >> + if (fd < 0) { >> + perror(argv[1]); >> + return 1; >> + } >> + >> + for (i = 0; i < (sizeof(ioctls)/sizeof(ioctls[0])); i++) { >> + if (strcmp(argv[2], ioctls[i].name) == 0) { >> + entry = &ioctls[i]; >> + break; >> + } >> + } >> + >> + if (!entry) { >> + fprintf(stderr, "ERROR: unknown ioctl %s\n", argv[2]); >> + close(fd); >> + return 1; >> + } >> + >> + ret = entry->handler(fd, argc - 3, argv + 3); >> + if (ret == -ENOTTY) { >> + printf("Not implemented.\n"); >> + close(fd); >> + return 0; >> + } else if (ret) { >> + fprintf(stderr, "ERROR: %s failed: %s\n", >> + entry->name, strerror(-ret)); >> + close(fd); >> + return 1; >> + } >> + >> + close(fd); >> + return 0; >> +} >> diff --git a/tests/btrfs/100 b/tests/btrfs/100 >> new file mode 100755 >> index 0000000..d2a40b4 >> --- /dev/null >> +++ b/tests/btrfs/100 >> @@ -0,0 +1,92 @@ >> +#!/bin/bash >> +# FA QA Test No. 100 >> +# >> +# Test global metadata reservation reporting >> +# >> +# 1) Create empty file system >> +# 2) Call the BTRFS_IOC_GLOBAL_RSV ioctl and confirm it is 0 < x < 10MB >> +# 3) Read the /sys/fs/btrfs/<fsid>/allocation/global_rsv_reserved file >> +# and confirm the value is 0 < x < 10 MB >> +# >> +#----------------------------------------------------------------------- >> +# Copyright (c) 2013 SUSE, All Rights Reserved. >> +# >> +# This program is free software; you can redistribute it and/or >> +# modify it under the terms of the GNU General Public License as >> +# published by the Free Software Foundation. >> +# >> +# This program is distributed in the hope that it would be useful, >> +# but WITHOUT ANY WARRANTY; without even the implied warranty of >> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >> +# GNU General Public License for more details. >> +# >> +# You should have received a copy of the GNU General Public License >> +# along with this program; if not, write the Free Software Foundation, >> +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA >> +#----------------------------------------------------------------------- >> + >> +seq=$(basename $0) >> +seqres=$RESULT_DIR/$seq >> +echo "== QA output created by $seq" >> + >> +here=$(pwd) >> +tmp=/tmp/$$ >> +status=1 >> + >> +# get standard environment, filters and checks >> +. ./common/rc >> +. ./common/filter.btrfs >> + >> +_supported_fs btrfs >> +_supported_os Linux >> +_require_scratch >> + >> +_scratch_mkfs > /dev/null 2>&1 >> +_scratch_mount >> + >> +fsid() { >> + $BTRFS_UTIL_PROG filesystem show $1|awk ''/uuid:/ {print $NF}'' >> +} > > This is the second place you use this, should go into common/rc or some other > common place. Thanks,Thanks for the review. I''ve posted an updated patchset that fixes these and other issues. -Jeff -- Jeff Mahoney SUSE Labs _______________________________________________ xfs mailing list xfs@oss.sgi.com http://oss.sgi.com/mailman/listinfo/xfs