All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/4] fstests: btrfs/048: extend _filter_btrfs_prop_error to handle additional errors
@ 2016-06-24 15:08 jeffm
  2016-06-24 15:08 ` [PATCH 2/4] fstests: btrfs/124: test global metadata reservation reporting jeffm
                   ` (3 more replies)
  0 siblings, 4 replies; 9+ messages in thread
From: jeffm @ 2016-06-24 15:08 UTC (permalink / raw)
  To: fstests; +Cc: linux-btrfs

From: Jeff Mahoney <jeffm@suse.com>

btrfsprogs v4.5.3 changed the formatting of some error messages.  This
patch extends the filter for btrfs prop to handle those.

Signed-off-by: Jeff Mahoney <jeffm@suse.com>
---
 common/filter.btrfs | 10 +++++++---
 tests/btrfs/048     |  6 ++++--
 tests/btrfs/048.out |  4 ++--
 3 files changed, 13 insertions(+), 7 deletions(-)

diff --git a/common/filter.btrfs b/common/filter.btrfs
index 9970f4d..54361d4 100644
--- a/common/filter.btrfs
+++ b/common/filter.btrfs
@@ -72,15 +72,19 @@ _filter_btrfs_compress_property()
 	sed -e "s/compression=\(lzo\|zlib\)/COMPRESSION=XXX/g"
 }
 
-# filter name of the property from the output, optionally verify against $1
+# filter error messages from btrfs prop, optionally verify against $1
 # recognized message(s):
 #  "object is not compatible with property: label"
+#  "invalid value for property:{, value}"
+#  "failed to {get,set} compression for $PATH[.:]: Invalid argument"
 _filter_btrfs_prop_error()
 {
 	if ! [ -z "$1" ]; then
-		sed -e "s/\(compatible with property\): $1/\1/"
+		sed -e "s#\(compatible with property\): $1#\1#" \
+		    -e "s#^\(.*failed to [sg]et compression for $1\)[:.] \(.*\)#\1: \2#"
 	else
-		sed -e "s/^\(.*compatible with property\).*/\1/"
+		sed -e "s#^\(.*compatible with property\).*#\1#" \
+		    -e "s#^\(.*invalid value for property\):.*#\1#"
 	fi
 }
 
diff --git a/tests/btrfs/048 b/tests/btrfs/048
index 4a36303..0b907b0 100755
--- a/tests/btrfs/048
+++ b/tests/btrfs/048
@@ -79,7 +79,8 @@ echo -e "\nTesting subvolume ro property"
 _run_btrfs_util_prog subvolume create $SCRATCH_MNT/sv1
 $BTRFS_UTIL_PROG property get $SCRATCH_MNT/sv1 ro
 echo "***"
-$BTRFS_UTIL_PROG property set $SCRATCH_MNT/sv1 ro foo
+$BTRFS_UTIL_PROG property set $SCRATCH_MNT/sv1 ro foo 2>&1 |
+	_filter_btrfs_prop_error
 echo "***"
 $BTRFS_UTIL_PROG property set $SCRATCH_MNT/sv1 ro true
 echo "***"
@@ -99,7 +100,8 @@ $BTRFS_UTIL_PROG property get $SCRATCH_MNT/testdir/file1 compression
 $BTRFS_UTIL_PROG property get $SCRATCH_MNT/testdir/subdir1 compression
 echo "***"
 $BTRFS_UTIL_PROG property set $SCRATCH_MNT/testdir/file1 compression \
-	foo 2>&1 | _filter_scratch
+	foo 2>&1 | _filter_scratch |
+	_filter_btrfs_prop_error SCRATCH_MNT/testdir/file1
 echo "***"
 $BTRFS_UTIL_PROG property set $SCRATCH_MNT/testdir/file1 compression lzo
 $BTRFS_UTIL_PROG property get $SCRATCH_MNT/testdir/file1 compression
diff --git a/tests/btrfs/048.out b/tests/btrfs/048.out
index 0b20d0b..3e4e3d2 100644
--- a/tests/btrfs/048.out
+++ b/tests/btrfs/048.out
@@ -15,7 +15,7 @@ ERROR: object is not compatible with property
 Testing subvolume ro property
 ro=false
 ***
-ERROR: invalid value for property.
+ERROR: invalid value for property
 ***
 ***
 ro=true
@@ -27,7 +27,7 @@ ro=false
 
 Testing compression property
 ***
-ERROR: failed to set compression for SCRATCH_MNT/testdir/file1. Invalid argument
+ERROR: failed to set compression for SCRATCH_MNT/testdir/file1: Invalid argument
 ***
 compression=lzo
 compression=lzo
-- 
1.8.5.6


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 2/4] fstests: btrfs/124: test global metadata reservation reporting
  2016-06-24 15:08 [PATCH 1/4] fstests: btrfs/048: extend _filter_btrfs_prop_error to handle additional errors jeffm
@ 2016-06-24 15:08 ` jeffm
  2016-06-27  7:16   ` Eryu Guan
  2016-06-24 15:08 ` [PATCH 3/4] fstests: btrfs/125: test sysfs exports of allocation and device membership info jeffm
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 9+ messages in thread
From: jeffm @ 2016-06-24 15:08 UTC (permalink / raw)
  To: fstests; +Cc: linux-btrfs

From: Jeff Mahoney <jeffm@suse.com>

Btrfs can now 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>
---
 common/rc                |   6 ++
 src/Makefile             |   3 +-
 src/btrfs_ioctl_helper.c | 220 +++++++++++++++++++++++++++++++++++++++++++++++
 tests/btrfs/124          |  90 +++++++++++++++++++
 tests/btrfs/124.out      |   2 +
 tests/btrfs/group        |   1 +
 6 files changed, 321 insertions(+), 1 deletion(-)
 create mode 100644 src/btrfs_ioctl_helper.c
 create mode 100755 tests/btrfs/124
 create mode 100644 tests/btrfs/124.out

diff --git a/common/rc b/common/rc
index 3a9c4d1..4b05fcf 100644
--- a/common/rc
+++ b/common/rc
@@ -76,6 +76,12 @@ _btrfs_get_subvolid()
 	$BTRFS_UTIL_PROG sub list $mnt | grep $name | awk '{ print $2 }'
 }
 
+_btrfs_get_fsid()
+{
+	local dev=$1
+	$BTRFS_UTIL_PROG filesystem show $dev|awk '/uuid:/ {print $NF}'
+}
+
 # Prints the md5 checksum of a given file
 _md5_checksum()
 {
diff --git a/src/Makefile b/src/Makefile
index 1bf318b..c467475 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -20,7 +20,8 @@ LINUX_TARGETS = xfsctl bstat t_mtab getdevicesize preallo_rw_pattern_reader \
 	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 cloner \
-	renameat2 t_getcwd e4compact test-nextquota punch-alternating
+	renameat2 t_getcwd e4compact test-nextquota punch-alternating \
+	btrfs_ioctl_helper
 
 SUBDIRS =
 
diff --git a/src/btrfs_ioctl_helper.c b/src/btrfs_ioctl_helper.c
new file mode 100644
index 0000000..4344bdc
--- /dev/null
+++ b/src/btrfs_ioctl_helper.c
@@ -0,0 +1,220 @@
+#include <sys/ioctl.h>
+#include <stdio.h>
+#include <sys/fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#ifndef BTRFS_IOCTL_MAGIC
+#define BTRFS_IOCTL_MAGIC 0x94
+#endif
+
+#ifndef BTRFS_IOC_SPACE_INFO
+struct btrfs_ioctl_space_info {
+        uint64_t flags;
+        uint64_t total_bytes;
+        uint64_t used_bytes;
+};
+
+struct btrfs_ioctl_space_args {
+        uint64_t space_slots;
+        uint64_t total_spaces;
+        struct btrfs_ioctl_space_info spaces[0];
+};
+#define BTRFS_IOC_SPACE_INFO _IOWR(BTRFS_IOCTL_MAGIC, 20, \
+                                    struct btrfs_ioctl_space_args)
+#endif
+#ifndef BTRFS_SPACE_INFO_GLOBAL_RSV
+#define BTRFS_SPACE_INFO_GLOBAL_RSV    (1ULL << 49)
+#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[])
+{
+	struct btrfs_ioctl_space_args arg;
+	struct btrfs_ioctl_space_args *args;
+	int ret;
+	int i;
+	size_t size;
+
+	arg.space_slots = 0;
+
+	ret = ioctl(fd, BTRFS_IOC_SPACE_INFO, &arg);
+	if (ret)
+		return -errno;
+
+	size = sizeof(*args) + sizeof(args->spaces[0]) * arg.total_spaces;
+	args = malloc(size);
+	if (!args)
+		return -ENOMEM;
+
+	args->space_slots = arg.total_spaces;
+
+	ret = ioctl(fd, BTRFS_IOC_SPACE_INFO, args);
+	if (ret)
+		return -errno;
+
+	for (i = 0; i < args->total_spaces; i++) {
+		if (args->spaces[i].flags & BTRFS_SPACE_INFO_GLOBAL_RSV) {
+			unsigned long long reserved;
+			reserved = args->spaces[i].total_bytes;
+			printf("%llu\n", reserved);
+			return 0;
+		}
+	}
+
+	return -ENOENT;
+}
+
+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;
+}
+#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(SPACE_INFO, 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
+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/124 b/tests/btrfs/124
new file mode 100755
index 0000000..4e6e6eb
--- /dev/null
+++ b/tests/btrfs/124
@@ -0,0 +1,90 @@
+#!/bin/bash
+# FA QA Test No. 124
+#
+# Test global metadata reservation reporting
+#
+# 1) Create empty file system
+# 2) Call the BTRFS_IOC_GLOBAL_RSV ioctl and confirm it is 0 < x < 32MB
+# 3) Read the /sys/fs/btrfs/<fsid>/allocation/global_rsv_reserved file
+#    and confirm the value is 0 < x < 32 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  12110-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
+
+# Check to see if the reservation is 0 < x <= 32MB
+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 "$(( 32 * 1024 * 1024 ))" ]; then
+		echo "$method: out of range: $reserved."
+		exit 1
+	fi
+}
+
+# ioctl
+ioctl_reserved="$(src/btrfs_ioctl_helper $SCRATCH_MNT SPACE_INFO 2>&1)"
+check_reserved $? "$ioctl_reserved" "ioctl"
+
+# sysfs
+# If this directory is here, the files must be here as well
+SYSFS_PREFIX="/sys/fs/btrfs/$(_btrfs_get_fsid $SCRATCH_DEV)/allocation"
+if [ -d "$SYSFS_PREFIX" ]; then
+	reserved="$(cat $SYSFS_PREFIX/global_rsv_reserved 2>&1)"
+	check_reserved $? "$reserved" "sysfs:reserved"
+	if [ "$reserved" != "$ioctl_reserved" ]; then
+		echo "ioctl ($ioctl_reserved) != sysfs ($reserved)"
+		exit 1
+	fi
+	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/124.out b/tests/btrfs/124.out
new file mode 100644
index 0000000..aeeb0e9
--- /dev/null
+++ b/tests/btrfs/124.out
@@ -0,0 +1,2 @@
+== QA output created by 124
+Silence is golden
diff --git a/tests/btrfs/group b/tests/btrfs/group
index 5a26ed7..8b5050e 100644
--- a/tests/btrfs/group
+++ b/tests/btrfs/group
@@ -126,3 +126,4 @@
 121 auto quick snapshot qgroup
 122 auto quick snapshot qgroup
 123 auto quick qgroup
+124 auto quick metadata
-- 
1.8.5.6


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 3/4] fstests: btrfs/125: test sysfs exports of allocation and device membership info
  2016-06-24 15:08 [PATCH 1/4] fstests: btrfs/048: extend _filter_btrfs_prop_error to handle additional errors jeffm
  2016-06-24 15:08 ` [PATCH 2/4] fstests: btrfs/124: test global metadata reservation reporting jeffm
@ 2016-06-24 15:08 ` jeffm
  2016-06-27  8:26   ` Eryu Guan
  2016-06-24 15:08 ` [PATCH 4/4] fstests: btrfs/126,127,128: test feature ioctl and sysfs interfaces jeffm
  2016-06-27  4:24 ` [PATCH 1/4] fstests: btrfs/048: extend _filter_btrfs_prop_error to handle additional errors Eryu Guan
  3 siblings, 1 reply; 9+ messages in thread
From: jeffm @ 2016-06-24 15:08 UTC (permalink / raw)
  To: fstests; +Cc: linux-btrfs

From: Jeff Mahoney <jeffm@suse.com>

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.

It passes on kernels without a /sys/fs/btrfs/<fsid> directory.

Signed-off-by: Jeff Mahoney <jeffm@suse.com>
---
 common/config       |   4 +-
 common/rc           |   7 ++
 tests/btrfs/125     | 193 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 tests/btrfs/125.out |   2 +
 tests/btrfs/group   |   1 +
 5 files changed, 205 insertions(+), 2 deletions(-)
 create mode 100755 tests/btrfs/125
 create mode 100644 tests/btrfs/125.out

diff --git a/common/config b/common/config
index c25b1ec..c5e65f7 100644
--- a/common/config
+++ b/common/config
@@ -201,13 +201,13 @@ export DEBUGFS_PROG="`set_prog_path debugfs`"
 # newer systems have udevadm command but older systems like RHEL5 don't.
 # But if neither one is available, just set it to "sleep 1" to wait for lv to
 # be settled
-UDEV_SETTLE_PROG="`set_prog_path udevadm`"
+UDEVADM_PROG="`set_prog_path udevadm`"
 if [ "$UDEV_SETTLE_PROG" == "" ]; then
 	# try udevsettle command
 	UDEV_SETTLE_PROG="`set_prog_path udevsettle`"
 else
 	# udevadm is available, add 'settle' as subcommand
-	UDEV_SETTLE_PROG="$UDEV_SETTLE_PROG settle"
+	UDEV_SETTLE_PROG="$UDEVADM_PROG settle"
 fi
 # neither command is available, use sleep 1
 if [ "$UDEV_SETTLE_PROG" == "" ]; then
diff --git a/common/rc b/common/rc
index 4b05fcf..f4c4312 100644
--- a/common/rc
+++ b/common/rc
@@ -76,6 +76,13 @@ _btrfs_get_subvolid()
 	$BTRFS_UTIL_PROG sub list $mnt | grep $name | awk '{ print $2 }'
 }
 
+_btrfs_get_feature_flags()
+{
+	local dev=$1
+	local class=$2
+	$BTRFS_SHOW_SUPER_PROG $dev | grep ^${class}_flags | awk '{print $NF}'
+}
+
 _btrfs_get_fsid()
 {
 	local dev=$1
diff --git a/tests/btrfs/125 b/tests/btrfs/125
new file mode 100755
index 0000000..83f1921
--- /dev/null
+++ b/tests/btrfs/125
@@ -0,0 +1,193 @@
+#! /bin/bash
+# FS QA Test No. 125
+#
+# Test of the btrfs sysfs publishing
+#
+#-----------------------------------------------------------------------
+# Copyright (C) 2013-2016 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
+_supported_fs btrfs
+_require_scratch
+_require_scratch_dev_pool
+_require_command "$UDEVADM_PROG"
+
+rm -f $seqres.full
+rm -f $tmp.tmp
+
+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 disk_used 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
+	local used_devs=""
+
+	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
+
+	if [ "$num_devs4raid" -gt 1 ]; then
+		used_devs=$(echo $SCRATCH_DEV_POOL|tr '\t' ' '| \
+			    cut -d ' ' -f 2-$num_devs4raid)
+	fi
+
+	_scratch_mkfs $mkfs_options $used_devs >> $seqres.full 2>&1 || \
+	_fail "mkfs failed"
+
+	_scratch_mount
+
+	# Check allocation
+	sysfs_base="/sys/fs/btrfs/$(_btrfs_get_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/125.out b/tests/btrfs/125.out
new file mode 100644
index 0000000..91f76e8
--- /dev/null
+++ b/tests/btrfs/125.out
@@ -0,0 +1,2 @@
+== QA output created by 125
+Silence is golden
diff --git a/tests/btrfs/group b/tests/btrfs/group
index 8b5050e..3535f02 100644
--- a/tests/btrfs/group
+++ b/tests/btrfs/group
@@ -127,3 +127,4 @@
 122 auto quick snapshot qgroup
 123 auto quick qgroup
 124 auto quick metadata
+125 auto quick metadata
-- 
1.8.5.6


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 4/4] fstests: btrfs/126,127,128: test feature ioctl and sysfs interfaces
  2016-06-24 15:08 [PATCH 1/4] fstests: btrfs/048: extend _filter_btrfs_prop_error to handle additional errors jeffm
  2016-06-24 15:08 ` [PATCH 2/4] fstests: btrfs/124: test global metadata reservation reporting jeffm
  2016-06-24 15:08 ` [PATCH 3/4] fstests: btrfs/125: test sysfs exports of allocation and device membership info jeffm
@ 2016-06-24 15:08 ` jeffm
  2016-06-27  9:11   ` Eryu Guan
  2016-06-27  4:24 ` [PATCH 1/4] fstests: btrfs/048: extend _filter_btrfs_prop_error to handle additional errors Eryu Guan
  3 siblings, 1 reply; 9+ messages in thread
From: jeffm @ 2016-06-24 15:08 UTC (permalink / raw)
  To: fstests; +Cc: linux-btrfs

From: Jeff Mahoney <jeffm@suse.com>

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>
---
 tests/btrfs/126     | 269 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 tests/btrfs/126.out |   2 +
 tests/btrfs/127     | 185 ++++++++++++++++++++++++++++++++++++
 tests/btrfs/127.out |   2 +
 tests/btrfs/128     | 178 ++++++++++++++++++++++++++++++++++
 tests/btrfs/128.out |   2 +
 tests/btrfs/group   |   3 +
 7 files changed, 641 insertions(+)
 create mode 100755 tests/btrfs/126
 create mode 100644 tests/btrfs/126.out
 create mode 100755 tests/btrfs/127
 create mode 100644 tests/btrfs/127.out
 create mode 100755 tests/btrfs/128
 create mode 100644 tests/btrfs/128.out

diff --git a/tests/btrfs/126 b/tests/btrfs/126
new file mode 100755
index 0000000..3d660c5
--- /dev/null
+++ b/tests/btrfs/126
@@ -0,0 +1,269 @@
+#!/bin/bash
+# FA QA Test No. 126
+#
+# 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
+
+_scratch_mkfs > /dev/null 2>&1
+_scratch_mount
+
+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 test. Not implemented." >> $seqres.full
+                return
+        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"
+
+test_ioctl=true
+[ "${features[*]}" = "Not implemented." ] && test_ioctl=false
+
+read -a supp_features < <(src/btrfs_ioctl_helper $SCRATCH_MNT GET_SUPPORTED_FEATURES 2>&1)
+check_features $? "$supp_features" "GET_SUPPORTED_FEATURES"
+[ "${supp_features[*]}" = "Not implemented." ] && test_ioctl=false
+
+# Sysfs checks
+fsid=$(_btrfs_get_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
+}
+
+test_sysfs=false
+if [ -d "$sysfs_base/features" -a -d "$sysfs_base/$fsid/features" ]; then
+	test_sysfs=true
+fi
+
+# Check enabled features in sysfs vs what the superblock claims
+sysfs_features=(0 0 0)
+for file in $sysfs_base/$fsid/features/*; do
+	$test_sysfs || break
+	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
+	$test_sysfs || break
+	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
+
+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
+	class=${fields[$index]}
+	disk_flags[$index]=$(_btrfs_get_feature_flags $SCRATCH_DEV $class)
+	$test_ioctl && check_ioctl_flags "$index"
+	$test_sysfs && check_sysfs_flags "$index"
+done
+
+$error && exit 1
+
+#
+echo "Silence is golden"
+status=0
+exit
diff --git a/tests/btrfs/126.out b/tests/btrfs/126.out
new file mode 100644
index 0000000..fd12fb0
--- /dev/null
+++ b/tests/btrfs/126.out
@@ -0,0 +1,2 @@
+== QA output created by 126
+Silence is golden
diff --git a/tests/btrfs/127 b/tests/btrfs/127
new file mode 100755
index 0000000..0a7eb91
--- /dev/null
+++ b/tests/btrfs/127
@@ -0,0 +1,185 @@
+#!/bin/bash
+# FA QA Test No. 127
+#
+# 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
+
+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
+}
+
+check_flags() {
+	local index=$1
+	local expected=$(( $2 ))
+	local class=${fields[$index]}
+	disk_flags="$(( $(_btrfs_get_feature_flags $SCRATCH_DEV $class) ))"
+	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)"
+	[ -z "$fset" ] && break
+	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)"
+	[ -z "$fclear" ] && break
+	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/127.out b/tests/btrfs/127.out
new file mode 100644
index 0000000..2ff4733
--- /dev/null
+++ b/tests/btrfs/127.out
@@ -0,0 +1,2 @@
+== QA output created by 127
+Silence is golden
diff --git a/tests/btrfs/128 b/tests/btrfs/128
new file mode 100755
index 0000000..7de780a
--- /dev/null
+++ b/tests/btrfs/128
@@ -0,0 +1,178 @@
+#!/bin/bash
+# FA QA Test No. 128
+#
+# 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
+
+IOCTL=src/btrfs_ioctl_helper
+
+check_flags() {
+	local class=$1
+	local expected=$2
+	disk_flags="$(_btrfs_get_feature_flags $SCRATCH_DEV $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 "Silence is golden"
+	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/$(_btrfs_get_fsid $SCRATCH_DEV)"
+
+if [ ! -d "$sysfs_fs_base/features" ]; then
+	echo "Silence is golden"
+	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=$(_btrfs_get_feature_flags $SCRATCH_DEV $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=$(_btrfs_get_feature_flags $SCRATCH_DEV $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/128.out b/tests/btrfs/128.out
new file mode 100644
index 0000000..1b86f92
--- /dev/null
+++ b/tests/btrfs/128.out
@@ -0,0 +1,2 @@
+== QA output created by 128
+Silence is golden
diff --git a/tests/btrfs/group b/tests/btrfs/group
index 3535f02..e76265d 100644
--- a/tests/btrfs/group
+++ b/tests/btrfs/group
@@ -128,3 +128,6 @@
 123 auto quick qgroup
 124 auto quick metadata
 125 auto quick metadata
+126 auto quick metadata
+127 auto quick metadata
+128 auto quick metadata
-- 
1.8.5.6


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH 1/4] fstests: btrfs/048: extend _filter_btrfs_prop_error to handle additional errors
  2016-06-24 15:08 [PATCH 1/4] fstests: btrfs/048: extend _filter_btrfs_prop_error to handle additional errors jeffm
                   ` (2 preceding siblings ...)
  2016-06-24 15:08 ` [PATCH 4/4] fstests: btrfs/126,127,128: test feature ioctl and sysfs interfaces jeffm
@ 2016-06-27  4:24 ` Eryu Guan
  3 siblings, 0 replies; 9+ messages in thread
From: Eryu Guan @ 2016-06-27  4:24 UTC (permalink / raw)
  To: jeffm; +Cc: fstests, linux-btrfs

On Fri, Jun 24, 2016 at 11:08:31AM -0400, jeffm@suse.com wrote:
> From: Jeff Mahoney <jeffm@suse.com>
> 
> btrfsprogs v4.5.3 changed the formatting of some error messages.  This
> patch extends the filter for btrfs prop to handle those.
> 
> Signed-off-by: Jeff Mahoney <jeffm@suse.com>
> ---
>  common/filter.btrfs | 10 +++++++---
>  tests/btrfs/048     |  6 ++++--
>  tests/btrfs/048.out |  4 ++--
>  3 files changed, 13 insertions(+), 7 deletions(-)
> 
> diff --git a/common/filter.btrfs b/common/filter.btrfs
> index 9970f4d..54361d4 100644
> --- a/common/filter.btrfs
> +++ b/common/filter.btrfs
> @@ -72,15 +72,19 @@ _filter_btrfs_compress_property()
>  	sed -e "s/compression=\(lzo\|zlib\)/COMPRESSION=XXX/g"
>  }
>  
> -# filter name of the property from the output, optionally verify against $1
> +# filter error messages from btrfs prop, optionally verify against $1
>  # recognized message(s):
>  #  "object is not compatible with property: label"
> +#  "invalid value for property:{, value}"
> +#  "failed to {get,set} compression for $PATH[.:]: Invalid argument"
>  _filter_btrfs_prop_error()
>  {
>  	if ! [ -z "$1" ]; then
> -		sed -e "s/\(compatible with property\): $1/\1/"
> +		sed -e "s#\(compatible with property\): $1#\1#" \
> +		    -e "s#^\(.*failed to [sg]et compression for $1\)[:.] \(.*\)#\1: \2#"
>  	else
> -		sed -e "s/^\(.*compatible with property\).*/\1/"
> +		sed -e "s#^\(.*compatible with property\).*#\1#" \
> +		    -e "s#^\(.*invalid value for property\):.*#\1#"

I think the last regex should be
-		    -e "s#^\(.*invalid value for property\):.*#\1#"
+		    -e "s#^\(.*invalid value for property\)[:.].*#\1#"

because...

>  	fi
>  }
>  
> diff --git a/tests/btrfs/048 b/tests/btrfs/048
> index 4a36303..0b907b0 100755
> --- a/tests/btrfs/048
> +++ b/tests/btrfs/048
> @@ -79,7 +79,8 @@ echo -e "\nTesting subvolume ro property"
>  _run_btrfs_util_prog subvolume create $SCRATCH_MNT/sv1
>  $BTRFS_UTIL_PROG property get $SCRATCH_MNT/sv1 ro
>  echo "***"
> -$BTRFS_UTIL_PROG property set $SCRATCH_MNT/sv1 ro foo
> +$BTRFS_UTIL_PROG property set $SCRATCH_MNT/sv1 ro foo 2>&1 |
> +	_filter_btrfs_prop_error
>  echo "***"
>  $BTRFS_UTIL_PROG property set $SCRATCH_MNT/sv1 ro true
>  echo "***"
> @@ -99,7 +100,8 @@ $BTRFS_UTIL_PROG property get $SCRATCH_MNT/testdir/file1 compression
>  $BTRFS_UTIL_PROG property get $SCRATCH_MNT/testdir/subdir1 compression
>  echo "***"
>  $BTRFS_UTIL_PROG property set $SCRATCH_MNT/testdir/file1 compression \
> -	foo 2>&1 | _filter_scratch
> +	foo 2>&1 | _filter_scratch |
> +	_filter_btrfs_prop_error SCRATCH_MNT/testdir/file1
>  echo "***"
>  $BTRFS_UTIL_PROG property set $SCRATCH_MNT/testdir/file1 compression lzo
>  $BTRFS_UTIL_PROG property get $SCRATCH_MNT/testdir/file1 compression
> diff --git a/tests/btrfs/048.out b/tests/btrfs/048.out
> index 0b20d0b..3e4e3d2 100644
> --- a/tests/btrfs/048.out
> +++ b/tests/btrfs/048.out
> @@ -15,7 +15,7 @@ ERROR: object is not compatible with property
>  Testing subvolume ro property
>  ro=false
>  ***
> -ERROR: invalid value for property.
> +ERROR: invalid value for property

this change breaks test with older btrfs-progs, the filter didn't remove
the ending "." correctly.

With above fix btrfs/048 works for me with both v3.19 and v4.6
btrfs-progs.

Thanks,
Eryu

>  ***
>  ***
>  ro=true
> @@ -27,7 +27,7 @@ ro=false
>  
>  Testing compression property
>  ***
> -ERROR: failed to set compression for SCRATCH_MNT/testdir/file1. Invalid argument
> +ERROR: failed to set compression for SCRATCH_MNT/testdir/file1: Invalid argument
>  ***
>  compression=lzo
>  compression=lzo
> -- 
> 1.8.5.6
> 
> --
> To unsubscribe from this list: send the line "unsubscribe fstests" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 2/4] fstests: btrfs/124: test global metadata reservation reporting
  2016-06-24 15:08 ` [PATCH 2/4] fstests: btrfs/124: test global metadata reservation reporting jeffm
@ 2016-06-27  7:16   ` Eryu Guan
  2016-06-27  7:24     ` Eryu Guan
  0 siblings, 1 reply; 9+ messages in thread
From: Eryu Guan @ 2016-06-27  7:16 UTC (permalink / raw)
  To: jeffm; +Cc: fstests, linux-btrfs

On Fri, Jun 24, 2016 at 11:08:32AM -0400, jeffm@suse.com wrote:
> From: Jeff Mahoney <jeffm@suse.com>
> 
> Btrfs can now 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>

I'm reviewing mainly from the fstests perspective, need help from other
btrfs developers to review the test itself to see if it's a valid &
useful test.

> ---
>  common/rc                |   6 ++
>  src/Makefile             |   3 +-
>  src/btrfs_ioctl_helper.c | 220 +++++++++++++++++++++++++++++++++++++++++++++++
>  tests/btrfs/124          |  90 +++++++++++++++++++
>  tests/btrfs/124.out      |   2 +
>  tests/btrfs/group        |   1 +
>  6 files changed, 321 insertions(+), 1 deletion(-)
>  create mode 100644 src/btrfs_ioctl_helper.c
>  create mode 100755 tests/btrfs/124
>  create mode 100644 tests/btrfs/124.out
> 
> diff --git a/common/rc b/common/rc
> index 3a9c4d1..4b05fcf 100644
> --- a/common/rc
> +++ b/common/rc
> @@ -76,6 +76,12 @@ _btrfs_get_subvolid()
>  	$BTRFS_UTIL_PROG sub list $mnt | grep $name | awk '{ print $2 }'
>  }
>  
> +_btrfs_get_fsid()
> +{
> +	local dev=$1
> +	$BTRFS_UTIL_PROG filesystem show $dev|awk '/uuid:/ {print $NF}'
> +}
> +
>  # Prints the md5 checksum of a given file
>  _md5_checksum()
>  {
> diff --git a/src/Makefile b/src/Makefile
> index 1bf318b..c467475 100644
> --- a/src/Makefile
> +++ b/src/Makefile
> @@ -20,7 +20,8 @@ LINUX_TARGETS = xfsctl bstat t_mtab getdevicesize preallo_rw_pattern_reader \
>  	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 cloner \
> -	renameat2 t_getcwd e4compact test-nextquota punch-alternating
> +	renameat2 t_getcwd e4compact test-nextquota punch-alternating \
> +	btrfs_ioctl_helper

.gitignore needs an entry for new binary.

But I'm wondering that is this something that can be added to
btrfs-progs, either as part of the btrfs command or a seperate command?

>  
>  SUBDIRS =
>  
> diff --git a/src/btrfs_ioctl_helper.c b/src/btrfs_ioctl_helper.c
> new file mode 100644
> index 0000000..4344bdc
> --- /dev/null
> +++ b/src/btrfs_ioctl_helper.c
> @@ -0,0 +1,220 @@
> +#include <sys/ioctl.h>
> +#include <stdio.h>
> +#include <sys/fcntl.h>
> +#include <errno.h>
> +#include <string.h>
> +#include <stdint.h>
> +#include <unistd.h>
> +#include <stdlib.h>
> +
> +#ifndef BTRFS_IOCTL_MAGIC
> +#define BTRFS_IOCTL_MAGIC 0x94
> +#endif
> +
> +#ifndef BTRFS_IOC_SPACE_INFO
> +struct btrfs_ioctl_space_info {
> +        uint64_t flags;
> +        uint64_t total_bytes;
> +        uint64_t used_bytes;
> +};
> +
> +struct btrfs_ioctl_space_args {
> +        uint64_t space_slots;
> +        uint64_t total_spaces;
> +        struct btrfs_ioctl_space_info spaces[0];
> +};
> +#define BTRFS_IOC_SPACE_INFO _IOWR(BTRFS_IOCTL_MAGIC, 20, \
> +                                    struct btrfs_ioctl_space_args)
> +#endif
> +#ifndef BTRFS_SPACE_INFO_GLOBAL_RSV
> +#define BTRFS_SPACE_INFO_GLOBAL_RSV    (1ULL << 49)
> +#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[])
> +{
> +	struct btrfs_ioctl_space_args arg;
> +	struct btrfs_ioctl_space_args *args;
> +	int ret;
> +	int i;
> +	size_t size;
> +
> +	arg.space_slots = 0;
> +
> +	ret = ioctl(fd, BTRFS_IOC_SPACE_INFO, &arg);
> +	if (ret)
> +		return -errno;
> +
> +	size = sizeof(*args) + sizeof(args->spaces[0]) * arg.total_spaces;
> +	args = malloc(size);
> +	if (!args)
> +		return -ENOMEM;
> +
> +	args->space_slots = arg.total_spaces;
> +
> +	ret = ioctl(fd, BTRFS_IOC_SPACE_INFO, args);
> +	if (ret)
> +		return -errno;
> +
> +	for (i = 0; i < args->total_spaces; i++) {
> +		if (args->spaces[i].flags & BTRFS_SPACE_INFO_GLOBAL_RSV) {
> +			unsigned long long reserved;
> +			reserved = args->spaces[i].total_bytes;
> +			printf("%llu\n", reserved);
> +			return 0;
> +		}
> +	}
> +
> +	return -ENOENT;
> +}
> +
> +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;
> +}
> +#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(SPACE_INFO, 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
> +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/124 b/tests/btrfs/124
> new file mode 100755
> index 0000000..4e6e6eb
> --- /dev/null
> +++ b/tests/btrfs/124
> @@ -0,0 +1,90 @@
> +#!/bin/bash
> +# FA QA Test No. 124
> +#
> +# Test global metadata reservation reporting
> +#
> +# 1) Create empty file system
> +# 2) Call the BTRFS_IOC_GLOBAL_RSV ioctl and confirm it is 0 < x < 32MB
> +# 3) Read the /sys/fs/btrfs/<fsid>/allocation/global_rsv_reserved file
> +#    and confirm the value is 0 < x < 32 MB
> +#
> +#-----------------------------------------------------------------------
> +# Copyright (c) 2013 SUSE, All Rights Reserved.
                   ^^^^ 2016
> +#
> +# 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  12110-1301  USA
> +#-----------------------------------------------------------------------
> +
> +seq=$(basename $0)
> +seqres=$RESULT_DIR/$seq
> +echo "== QA output created by $seq"

No need to change the default, so it's consistent with other tests

"QA output created by $seq"

> +
> +here=$(pwd)
> +tmp=/tmp/$$
> +status=1

You're missing a _cleanup function and its trap

trap "_cleanup; exit $status" 0 1 2 3 15

Please use "./new btrfs" and follow the template to create new test for
btrfs.

> +
> +# 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

There should be some kind of "_require_xxx" or something like that to
_notrun if current running kernel doesn't have global metadata
reservation report implemented.

> +
> +# Check to see if the reservation is 0 < x <= 32MB
> +check_reserved() {
> +	reserved="$2"
> +	method="$3"
> +	if [ "$1" != 0 ]; then
> +		echo "$method: failed: $reserved"
> +		exit 1

No need to check the return value, if ioctl fails, $reserved contains
some kind of error message, which should fail one of the following
checks. The whole point of "golden image matching" is what we don't have
to check commands return value :)

> +	fi
> +	if [ "$reserved" = "Not implemented." ]; then
> +		echo "Skipping ioctl test. Not implemented." >> $seqres.full
> +		return

This doesn't belong here, it should call '_notrun' if the ioctl is not
implemented.

> +	fi
> +	if [ -n "$(echo $reserved | tr -d 0-9)" ]; then
> +		echo "ERROR: numerical value expected (got $reserved)"
> +		exit 1

No need to exit the whole test, just return should be fine.

> +	fi
> +	if [ "$reserved" -le 0 -o \
> +	       "$reserved" -gt "$(( 32 * 1024 * 1024 ))" ]; then

Need some comments about the range, why is it 0-32M?

> +		echo "$method: out of range: $reserved."
> +		exit 1

Don't exit.

> +	fi
> +}
> +
> +# ioctl
> +ioctl_reserved="$(src/btrfs_ioctl_helper $SCRATCH_MNT SPACE_INFO 2>&1)"
> +check_reserved $? "$ioctl_reserved" "ioctl"
> +
> +# sysfs
> +# If this directory is here, the files must be here as well
> +SYSFS_PREFIX="/sys/fs/btrfs/$(_btrfs_get_fsid $SCRATCH_DEV)/allocation"
> +if [ -d "$SYSFS_PREFIX" ]; then

_notrun if the sysfs entry doesn't exist.

> +	reserved="$(cat $SYSFS_PREFIX/global_rsv_reserved 2>&1)"
> +	check_reserved $? "$reserved" "sysfs:reserved"
> +	if [ "$reserved" != "$ioctl_reserved" ]; then
> +		echo "ioctl ($ioctl_reserved) != sysfs ($reserved)"
> +		exit 1

Don't exit.

Thanks,
Eryu
> +	fi
> +	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/124.out b/tests/btrfs/124.out
> new file mode 100644
> index 0000000..aeeb0e9
> --- /dev/null
> +++ b/tests/btrfs/124.out
> @@ -0,0 +1,2 @@
> +== QA output created by 124
> +Silence is golden
> diff --git a/tests/btrfs/group b/tests/btrfs/group
> index 5a26ed7..8b5050e 100644
> --- a/tests/btrfs/group
> +++ b/tests/btrfs/group
> @@ -126,3 +126,4 @@
>  121 auto quick snapshot qgroup
>  122 auto quick snapshot qgroup
>  123 auto quick qgroup
> +124 auto quick metadata
> -- 
> 1.8.5.6
> 
> --
> To unsubscribe from this list: send the line "unsubscribe fstests" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 2/4] fstests: btrfs/124: test global metadata reservation reporting
  2016-06-27  7:16   ` Eryu Guan
@ 2016-06-27  7:24     ` Eryu Guan
  0 siblings, 0 replies; 9+ messages in thread
From: Eryu Guan @ 2016-06-27  7:24 UTC (permalink / raw)
  To: jeffm; +Cc: fstests, linux-btrfs

On Mon, Jun 27, 2016 at 03:16:47PM +0800, Eryu Guan wrote:
> On Fri, Jun 24, 2016 at 11:08:32AM -0400, jeffm@suse.com wrote:
> > From: Jeff Mahoney <jeffm@suse.com>
> > 
[snip]
> > +
> > +# 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
> 
> There should be some kind of "_require_xxx" or something like that to
> _notrun if current running kernel doesn't have global metadata
> reservation report implemented.

Also need a _require_test_program call to make sure btrfs_ioctl_helper
is built and in src/ dir.

_require_test_program "btrfs_ioctl_helper"

Sorry, I missed it in first revlew.

Thanks,
Eryu

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 3/4] fstests: btrfs/125: test sysfs exports of allocation and device membership info
  2016-06-24 15:08 ` [PATCH 3/4] fstests: btrfs/125: test sysfs exports of allocation and device membership info jeffm
@ 2016-06-27  8:26   ` Eryu Guan
  0 siblings, 0 replies; 9+ messages in thread
From: Eryu Guan @ 2016-06-27  8:26 UTC (permalink / raw)
  To: jeffm; +Cc: fstests, linux-btrfs

On Fri, Jun 24, 2016 at 11:08:33AM -0400, jeffm@suse.com wrote:
> From: Jeff Mahoney <jeffm@suse.com>
> 
> 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.
> 
> It passes on kernels without a /sys/fs/btrfs/<fsid> directory.
> 
> Signed-off-by: Jeff Mahoney <jeffm@suse.com>
> ---
>  common/config       |   4 +-
>  common/rc           |   7 ++
>  tests/btrfs/125     | 193 ++++++++++++++++++++++++++++++++++++++++++++++++++++
>  tests/btrfs/125.out |   2 +
>  tests/btrfs/group   |   1 +
>  5 files changed, 205 insertions(+), 2 deletions(-)
>  create mode 100755 tests/btrfs/125
>  create mode 100644 tests/btrfs/125.out
> 
> diff --git a/common/config b/common/config
> index c25b1ec..c5e65f7 100644
> --- a/common/config
> +++ b/common/config
> @@ -201,13 +201,13 @@ export DEBUGFS_PROG="`set_prog_path debugfs`"
>  # newer systems have udevadm command but older systems like RHEL5 don't.
>  # But if neither one is available, just set it to "sleep 1" to wait for lv to
>  # be settled
> -UDEV_SETTLE_PROG="`set_prog_path udevadm`"
> +UDEVADM_PROG="`set_prog_path udevadm`"
>  if [ "$UDEV_SETTLE_PROG" == "" ]; then

$UDEVADM_PROG should be checked here, not $UDEV_SETTLE_PROG anymore.

>  	# try udevsettle command
>  	UDEV_SETTLE_PROG="`set_prog_path udevsettle`"
>  else
>  	# udevadm is available, add 'settle' as subcommand
> -	UDEV_SETTLE_PROG="$UDEV_SETTLE_PROG settle"
> +	UDEV_SETTLE_PROG="$UDEVADM_PROG settle"
>  fi
>  # neither command is available, use sleep 1
>  if [ "$UDEV_SETTLE_PROG" == "" ]; then
> diff --git a/common/rc b/common/rc
> index 4b05fcf..f4c4312 100644
> --- a/common/rc
> +++ b/common/rc
> @@ -76,6 +76,13 @@ _btrfs_get_subvolid()
>  	$BTRFS_UTIL_PROG sub list $mnt | grep $name | awk '{ print $2 }'
>  }
>  
> +_btrfs_get_feature_flags()
> +{
> +	local dev=$1
> +	local class=$2
> +	$BTRFS_SHOW_SUPER_PROG $dev | grep ^${class}_flags | awk '{print $NF}'
> +}
> +
>  _btrfs_get_fsid()
>  {
>  	local dev=$1
> diff --git a/tests/btrfs/125 b/tests/btrfs/125
> new file mode 100755
> index 0000000..83f1921
> --- /dev/null
> +++ b/tests/btrfs/125
> @@ -0,0 +1,193 @@
> +#! /bin/bash
> +# FS QA Test No. 125
> +#
> +# Test of the btrfs sysfs publishing
> +#
> +#-----------------------------------------------------------------------
> +# Copyright (C) 2013-2016 SUSE.  All rights reserved.

Copyright year is 2016.

> +#
> +# 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

Missing _cleanup and trap, use "./new btrfs" to generate new btrfs test.

> +
> +# get standard environment, filters and checks
> +. ./common/rc
> +. ./common/filter
> +
> +# real QA test starts here
> +_supported_fs btrfs

Missing "_supported_os" call. Following the template create by the
'./new' script makes it easier :)

> +_require_scratch
> +_require_scratch_dev_pool
> +_require_command "$UDEVADM_PROG"

We usually provide a program name as a second param

_require_command "$UDEVADM_PROG" udevadm

> +
> +rm -f $seqres.full
> +rm -f $tmp.tmp

This should be "rm -f $tmp.*" and belongs to _cleanup()

> +
> +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

No need to return 0/1 based on failure/pass, because check_chunk()
doesn't need to exit on failure.

> +	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

Don't exit, 'return' just works.

> +	fi
> +
> +	for file in bytes_may_use bytes_pinned bytes_reserved bytes_used \
> +		    disk_total disk_used flags total_bytes \
> +		    total_bytes_pinned; do
> +		if check_file "$path/$file"; then
> +			error=true
> +		fi

No need to check errors

> +	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

Don't exit, 'return' is OK.

> +	fi
> +
> +	for file in total_bytes used_bytes; do
> +		if check_file $path/$profile/$file; then
> +			error=true
> +		fi

No need to check errors

> +	done
> +
> +	$error && exit 1

Because no need to exit.

> +}
> +
> +check_dev_link() {

"{" in a seperate line.

> +	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
> +}

check_dev_link() is basiclly checking every device used by this btrfs
filesystem is listed in $sysfs_base/devices/ dir and points to a valid
device entry in sysfs, so I think we can do something like this:

check_dev_link()
{
	local dev=$1
	local dname=`_short_dev $dev`

	if [ ! -e $sysfs_base/devices/$dname ]; then
		echo "Symlink for $dev is missing in $sysfs_base/devices"
	fi
}

And we don't require $UDEVADM_PROG in this test. Hope I didn't miss
anything.

> +
> +workout()
> +{
> +	local mkfs_options="$1"
> +	local num_devs4raid="$2"
> +	local fssize
> +	local used_devs=""
> +
> +	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"

These echos breaks golden image and fails the test if there aren't
enough devices in $SCRATCH_DEV_POOL

You should call _require_scratch_dev_pool with a number as parameter to
specify the minium number of devices needed in this test.

_require_scratch_dev_pool 4

> +		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
> +
> +	if [ "$num_devs4raid" -gt 1 ]; then
> +		used_devs=$(echo $SCRATCH_DEV_POOL|tr '\t' ' '| \
> +			    cut -d ' ' -f 2-$num_devs4raid)
> +	fi
> +
> +	_scratch_mkfs $mkfs_options $used_devs >> $seqres.full 2>&1 || \

You should update $SCRATCH_DEV_POOL to contain $num_devs4raid devices
and call _scratch_pool_mkfs here, and reset $SCRATCH_DEV_POOL to
original dev list for next test. _scratch_mkfs only creates filesystem
on SCRATCH_DEV.

> +	_fail "mkfs failed"

Don't _fail, just print out error message and return, so next profile
config can be tested.

> +
> +	_scratch_mount
> +
> +	# Check allocation
> +	sysfs_base="/sys/fs/btrfs/$(_btrfs_get_fsid $SCRATCH_DEV)"

Hmm, I think _btrfs_get_fsid should work on $SCRATCH_MNT, $SCRATCH_DEV
might not be in current $SCRATCH_DEV_POOL (though not likely).

> +
> +	# Feature isn't present for testing
> +	if [ ! -d "$sysfs_base" ]; then
> +		echo "Skipping sysfs test: $sysfs_base not found." \
> +		     >> $seqres.full
> +		return
> +	fi

Test should _notrun if feature is not present. And we do the check
before any actual tests.

> +
> +	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

Don't exit.

> +	done
> +
> +	umount $SCRATCH_MNT > /dev/null 2>&1

_scratch_unmount

Thanks,
Eryu

> +}
> +
> +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/125.out b/tests/btrfs/125.out
> new file mode 100644
> index 0000000..91f76e8
> --- /dev/null
> +++ b/tests/btrfs/125.out
> @@ -0,0 +1,2 @@
> +== QA output created by 125
> +Silence is golden
> diff --git a/tests/btrfs/group b/tests/btrfs/group
> index 8b5050e..3535f02 100644
> --- a/tests/btrfs/group
> +++ b/tests/btrfs/group
> @@ -127,3 +127,4 @@
>  122 auto quick snapshot qgroup
>  123 auto quick qgroup
>  124 auto quick metadata
> +125 auto quick metadata
> -- 
> 1.8.5.6
> 
> --
> To unsubscribe from this list: send the line "unsubscribe fstests" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 4/4] fstests: btrfs/126,127,128: test feature ioctl and sysfs interfaces
  2016-06-24 15:08 ` [PATCH 4/4] fstests: btrfs/126,127,128: test feature ioctl and sysfs interfaces jeffm
@ 2016-06-27  9:11   ` Eryu Guan
  0 siblings, 0 replies; 9+ messages in thread
From: Eryu Guan @ 2016-06-27  9:11 UTC (permalink / raw)
  To: jeffm; +Cc: fstests, linux-btrfs

On Fri, Jun 24, 2016 at 11:08:34AM -0400, jeffm@suse.com wrote:
> From: Jeff Mahoney <jeffm@suse.com>
> 
> 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>
> ---
>  tests/btrfs/126     | 269 ++++++++++++++++++++++++++++++++++++++++++++++++++++
>  tests/btrfs/126.out |   2 +
>  tests/btrfs/127     | 185 ++++++++++++++++++++++++++++++++++++
>  tests/btrfs/127.out |   2 +
>  tests/btrfs/128     | 178 ++++++++++++++++++++++++++++++++++
>  tests/btrfs/128.out |   2 +
>  tests/btrfs/group   |   3 +
>  7 files changed, 641 insertions(+)
>  create mode 100755 tests/btrfs/126
>  create mode 100644 tests/btrfs/126.out
>  create mode 100755 tests/btrfs/127
>  create mode 100644 tests/btrfs/127.out
>  create mode 100755 tests/btrfs/128
>  create mode 100644 tests/btrfs/128.out
> 
> diff --git a/tests/btrfs/126 b/tests/btrfs/126
> new file mode 100755
> index 0000000..3d660c5
> --- /dev/null
> +++ b/tests/btrfs/126
> @@ -0,0 +1,269 @@
> +#!/bin/bash
> +# FA QA Test No. 126
> +#
> +# 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.

Copyright year 2016.

> +#
> +# 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

Missing _cleanup() and trap, use './new btrfs' to create new btrfs
tests.

> +
> +# 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

_require_command "$BTRFS_SHOW_SUPER_PROG" btrfs-show-super

> +
> +_scratch_mkfs > /dev/null 2>&1
> +_scratch_mount
> +
> +check_features() {

"{" on a seperate line

> +	reserved="$2"
> +	method="$3"
> +	if [ "$1" != 0 ]; then
> +		echo "$method: failed: $reserved"
> +		exit 1
> +	fi

No need to check return value.

> +        if [ "$reserved" = "Not implemented." ]; then
> +                echo "Skipping ioctl test. Not implemented." >> $seqres.full
> +                return
> +        fi

Call _notrun if ioctl not implemented. Do the check before actual test
starts.

And you're mixing spaces and tabs for indention in this function.

> +}
> +
> +error=false

All the checks around error can be omitted.

> +
> +# 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() {

"{" on a seperate line

> +	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"
> +
> +test_ioctl=true
> +[ "${features[*]}" = "Not implemented." ] && test_ioctl=false
> +
> +read -a supp_features < <(src/btrfs_ioctl_helper $SCRATCH_MNT GET_SUPPORTED_FEATURES 2>&1)
> +check_features $? "$supp_features" "GET_SUPPORTED_FEATURES"
> +[ "${supp_features[*]}" = "Not implemented." ] && test_ioctl=false

These checks are not needed if the test was checked and _notrun properly
before test.

> +
> +# Sysfs checks
> +fsid=$(_btrfs_get_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

Just echo this message to stdout and fail the test, so we know test
needs update.

> +		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
> +}

This function needs comments to document it, and all the magic numbers
(0 1 2 3 6).

> +
> +test_sysfs=false
> +if [ -d "$sysfs_base/features" -a -d "$sysfs_base/$fsid/features" ]; then
> +	test_sysfs=true
> +fi

Call _notrun if there's no sysfs support.

> +
> +# Check enabled features in sysfs vs what the superblock claims
> +sysfs_features=(0 0 0)
> +for file in $sysfs_base/$fsid/features/*; do
> +	$test_sysfs || break
> +	attr=$(basename $file)
> +	val=$(cat $file)
> +	read class bit < <(get_feature_mask $attr)

Avoid using "read" if possible, it's hiding error messages from
get_feature_mask

> +
> +	# 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

Again, echo this message to stdout.

> +		skip_sysfs_super_check=true

Let it fail, don't skip

> +	fi
> +done
> +
> +for file in $sysfs_base/features/*; do
> +	$test_sysfs || break
> +	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

_scratch_unmount

And btrfs/127,128 have almost the same set of issues, and I find them
hard to review...

Thanks,
Eryu

> +
> +fields=("compat" "compat_ro" "incompat")
> +declare -a disk_flags
> +
> +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
> +	class=${fields[$index]}
> +	disk_flags[$index]=$(_btrfs_get_feature_flags $SCRATCH_DEV $class)
> +	$test_ioctl && check_ioctl_flags "$index"
> +	$test_sysfs && check_sysfs_flags "$index"
> +done
> +
> +$error && exit 1
> +
> +#
> +echo "Silence is golden"
> +status=0
> +exit
> diff --git a/tests/btrfs/126.out b/tests/btrfs/126.out
> new file mode 100644
> index 0000000..fd12fb0
> --- /dev/null
> +++ b/tests/btrfs/126.out
> @@ -0,0 +1,2 @@
> +== QA output created by 126
> +Silence is golden
> diff --git a/tests/btrfs/127 b/tests/btrfs/127
> new file mode 100755
> index 0000000..0a7eb91
> --- /dev/null
> +++ b/tests/btrfs/127
> @@ -0,0 +1,185 @@
> +#!/bin/bash
> +# FA QA Test No. 127
> +#
> +# 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
> +
> +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
> +}
> +
> +check_flags() {
> +	local index=$1
> +	local expected=$(( $2 ))
> +	local class=${fields[$index]}
> +	disk_flags="$(( $(_btrfs_get_feature_flags $SCRATCH_DEV $class) ))"
> +	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)"
> +	[ -z "$fset" ] && break
> +	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)"
> +	[ -z "$fclear" ] && break
> +	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/127.out b/tests/btrfs/127.out
> new file mode 100644
> index 0000000..2ff4733
> --- /dev/null
> +++ b/tests/btrfs/127.out
> @@ -0,0 +1,2 @@
> +== QA output created by 127
> +Silence is golden
> diff --git a/tests/btrfs/128 b/tests/btrfs/128
> new file mode 100755
> index 0000000..7de780a
> --- /dev/null
> +++ b/tests/btrfs/128
> @@ -0,0 +1,178 @@
> +#!/bin/bash
> +# FA QA Test No. 128
> +#
> +# 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
> +
> +IOCTL=src/btrfs_ioctl_helper
> +
> +check_flags() {
> +	local class=$1
> +	local expected=$2
> +	disk_flags="$(_btrfs_get_feature_flags $SCRATCH_DEV $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 "Silence is golden"
> +	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/$(_btrfs_get_fsid $SCRATCH_DEV)"
> +
> +if [ ! -d "$sysfs_fs_base/features" ]; then
> +	echo "Silence is golden"
> +	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=$(_btrfs_get_feature_flags $SCRATCH_DEV $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=$(_btrfs_get_feature_flags $SCRATCH_DEV $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/128.out b/tests/btrfs/128.out
> new file mode 100644
> index 0000000..1b86f92
> --- /dev/null
> +++ b/tests/btrfs/128.out
> @@ -0,0 +1,2 @@
> +== QA output created by 128
> +Silence is golden
> diff --git a/tests/btrfs/group b/tests/btrfs/group
> index 3535f02..e76265d 100644
> --- a/tests/btrfs/group
> +++ b/tests/btrfs/group
> @@ -128,3 +128,6 @@
>  123 auto quick qgroup
>  124 auto quick metadata
>  125 auto quick metadata
> +126 auto quick metadata
> +127 auto quick metadata
> +128 auto quick metadata
> -- 
> 1.8.5.6
> 
> --
> To unsubscribe from this list: send the line "unsubscribe fstests" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2016-06-27  9:11 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-06-24 15:08 [PATCH 1/4] fstests: btrfs/048: extend _filter_btrfs_prop_error to handle additional errors jeffm
2016-06-24 15:08 ` [PATCH 2/4] fstests: btrfs/124: test global metadata reservation reporting jeffm
2016-06-27  7:16   ` Eryu Guan
2016-06-27  7:24     ` Eryu Guan
2016-06-24 15:08 ` [PATCH 3/4] fstests: btrfs/125: test sysfs exports of allocation and device membership info jeffm
2016-06-27  8:26   ` Eryu Guan
2016-06-24 15:08 ` [PATCH 4/4] fstests: btrfs/126,127,128: test feature ioctl and sysfs interfaces jeffm
2016-06-27  9:11   ` Eryu Guan
2016-06-27  4:24 ` [PATCH 1/4] fstests: btrfs/048: extend _filter_btrfs_prop_error to handle additional errors Eryu Guan

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.