All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/9] xfstests: online scrub/repair support
@ 2016-11-05  0:17 Darrick J. Wong
  2016-11-05  0:17 ` [PATCH 1/9] populate: create all types of XFS metadata Darrick J. Wong
                   ` (8 more replies)
  0 siblings, 9 replies; 25+ messages in thread
From: Darrick J. Wong @ 2016-11-05  0:17 UTC (permalink / raw)
  To: david, eguan, darrick.wong; +Cc: linux-xfs, fstests

Hi all,

This is the second revision of a patchset that adds to XFS userland
tools support for online metadata scrubbing and repair.

The new patches in this series do three things: first, they expand the
filesystem populate commands inside xfstests to be able to create all
types of XFS metadata.  Second, they create a bunch of xfs_db wrapper
functions to iterate all fields present in a given metadata object and
fuzz them in various ways.  Finally, for each metadata object type there
is a separate test that iteratively fuzzes all fields of that object
and runs it through the mount/scrub/repair loop to see what happens.

If you're going to start using this mess, you probably ought to just
pull from my github trees for kernel[1], xfsprogs[2], and xfstests[3].
The kernel patches in the git trees should apply to 4.9-rc3; xfsprogs
patches to for-next; and xfstest to master.

The patches have survived all auto group xfstests both with scrub-only
mode and also a special debugging mode to xfs_scrub that forces it to
rebuild the metadata structures even if they're not damaged.  Note that
I haven't thoroughly run the new tests in [3] that try to fuzz every
field in every data structure on disk.

This is an extraordinary way to eat your data.  Enjoy! 
Comments and questions are, as always, welcome.

--D

[1] https://github.com/djwong/linux/tree/djwong-devel
[2] https://github.com/djwong/xfsprogs/tree/djwong-devel
[3] https://github.com/djwong/xfstests/tree/djwong-devel

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

* [PATCH 1/9] populate: create all types of XFS metadata
  2016-11-05  0:17 [PATCH v2 0/9] xfstests: online scrub/repair support Darrick J. Wong
@ 2016-11-05  0:17 ` Darrick J. Wong
  2016-11-07 15:34   ` Eryu Guan
  2016-11-05  0:17 ` [PATCH 2/9] populate: add _require_populate_commands to check for tools Darrick J. Wong
                   ` (7 subsequent siblings)
  8 siblings, 1 reply; 25+ messages in thread
From: Darrick J. Wong @ 2016-11-05  0:17 UTC (permalink / raw)
  To: david, eguan, darrick.wong; +Cc: linux-xfs, fstests

We have three new metadata types -- rmapbt, rtrmapbt, and refcountbt.
Ensure that we populate the scratch fs with all three.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 common/populate |   87 ++++++++++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 79 insertions(+), 8 deletions(-)


diff --git a/common/populate b/common/populate
index d0003c5..6ada902 100644
--- a/common/populate
+++ b/common/populate
@@ -24,6 +24,7 @@
 
 _require_xfs_io_command "falloc"
 _require_xfs_io_command "fpunch"
+_require_test_program "punch-alternating"
 
 _require_xfs_db_blocktrash_z_command() {
 	test "${FSTYP}" = "xfs" || _notrun "cannot run xfs_db on ${FSTYP}"
@@ -106,9 +107,7 @@ _scratch_xfs_populate() {
 	echo "+ btree extents file"
 	nr="$((blksz * 2 / 16))"
 	$XFS_IO_PROG -f -c "pwrite -S 0x62 0 $((blksz * nr))" "${SCRATCH_MNT}/S_IFREG.FMT_BTREE"
-	for i in $(seq 1 2 ${nr}); do
-		$XFS_IO_PROG -f -c "fpunch $((i * blksz)) ${blksz}" "${SCRATCH_MNT}/S_IFREG.FMT_BTREE"
-	done
+	./src/punch-alternating "${SCRATCH_MNT}/S_IFREG.FMT_BTREE"
 
 	# Directories
 	# - INLINE
@@ -128,6 +127,7 @@ _scratch_xfs_populate() {
 	__populate_create_dir "${SCRATCH_MNT}/S_IFDIR.FMT_NODE" "$((16 * dblksz / 40))" true
 
 	# - BTREE
+	echo "+ btree dir"
 	__populate_create_dir "${SCRATCH_MNT}/S_IFDIR.FMT_BTREE" "$((128 * dblksz / 40))" true
 
 	# Symlinks
@@ -180,10 +180,43 @@ _scratch_xfs_populate() {
 	$XFS_IO_PROG -f -c 'fsync' "${SCRATCH_MNT}/unused"
 	rm -rf "${SCRATCH_MNT}/unused"
 
+	# Free space btree
+	echo "+ freesp btree"
+	nr="$((blksz * 2 / 8))"
+	$XFS_IO_PROG -f -c "pwrite -S 0x62 0 $((blksz * nr))" "${SCRATCH_MNT}/BNOBT"
+	./src/punch-alternating "${SCRATCH_MNT}/BNOBT"
+
+	# Reverse-mapping btree
+	is_rmapbt="$(xfs_info "${SCRATCH_MNT}" | grep -c 'rmapbt=1')"
+	if [ $is_rmapbt -gt 0 ]; then
+		echo "+ rmapbt btree"
+		nr="$((blksz * 2 / 24))"
+		$XFS_IO_PROG -f -c "pwrite -S 0x62 0 $((blksz * nr))" "${SCRATCH_MNT}/RMAPBT"
+		./src/punch-alternating "${SCRATCH_MNT}/RMAPBT"
+	fi
+
+	# Realtime Reverse-mapping btree
+	is_rt="$(xfs_info "${SCRATCH_MNT}" | grep -c 'rtextents=[1-9]')"
+	if [ $is_rmapbt -gt 0 ] && [ $is_rt -gt 0 ]; then
+		echo "+ rtrmapbt btree"
+		nr="$((blksz * 2 / 32))"
+		$XFS_IO_PROG -f -R -c "pwrite -S 0x62 0 $((blksz * nr))" "${SCRATCH_MNT}/RTRMAPBT"
+		./src/punch-alternating "${SCRATCH_MNT}/RTRMAPBT"
+	fi
+
+	# Reference-count btree
+	is_reflink="$(xfs_info "${SCRATCH_MNT}" | grep -c 'reflink=1')"
+	if [ $is_reflink -gt 0 ]; then
+		echo "+ reflink btree"
+		nr="$((blksz * 2 / 12))"
+		$XFS_IO_PROG -f -c "pwrite -S 0x62 0 $((blksz * nr))" "${SCRATCH_MNT}/REFCOUNTBT"
+		cp --reflink=always "${SCRATCH_MNT}/REFCOUNTBT" "${SCRATCH_MNT}/REFCOUNTBT2"
+		./src/punch-alternating "${SCRATCH_MNT}/REFCOUNTBT"
+	fi
+
 	# Copy some real files (xfs tests, I guess...)
 	echo "+ real files"
-	#__populate_fill_fs "${SCRATCH_MNT}" 40
-	cp -pRdu --reflink=always "${SCRATCH_MNT}/S_IFREG.FMT_BTREE" "${SCRATCH_MNT}/S_IFREG.FMT_BTREE.REFLINK" 2> /dev/null
+	test $fill -ne 0 && __populate_fill_fs "${SCRATCH_MNT}" 5
 
 	umount "${SCRATCH_MNT}"
 }
@@ -212,9 +245,7 @@ _scratch_ext4_populate() {
 	echo "+ extent tree file"
 	nr="$((blksz * 2 / 12))"
 	$XFS_IO_PROG -f -c "pwrite -S 0x62 0 $((blksz * nr))" "${SCRATCH_MNT}/S_IFREG.FMT_ETREE"
-	for i in $(seq 1 2 ${nr}); do
-		$XFS_IO_PROG -f -c "fpunch $((i * blksz)) ${blksz}" "${SCRATCH_MNT}/S_IFREG.FMT_ETREE"
-	done
+	./src/punch-alternating "${SCRATCH_MNT}/S_IFREG.FMT_ETREE"
 
 	# Directories
 	# - INLINE
@@ -349,6 +380,39 @@ __populate_check_xfs_attr() {
 	esac
 }
 
+# Check that there's at least one per-AG btree with multiple levels
+__populate_check_xfs_agbtree_height() {
+	bt_type="$1"
+	nr_ags=$(_scratch_xfs_db -c 'sb 0' -c 'p agcount' | awk '{print $3}')
+
+	case "${bt_type}" in
+	"bno"|"cnt"|"rmap"|"refcnt")
+		hdr="agf"
+		bt_prefix="${bt_type}"
+		;;
+	"ino")
+		hdr="agi"
+		bt_prefix=""
+		;;
+	"fino")
+		hdr="agi"
+		bt_prefix="free_"
+		;;
+	*)
+		_fail "Don't know about AG btree ${bt_type}"
+		;;
+	esac
+
+	seq 0 $((nr_ags - 1)) | while read ag; do
+		bt_level=$(_scratch_xfs_db -c "${hdr} ${ag}" -c "p ${bt_prefix}level" | awk '{print $3}')
+		if [ "${bt_level}" -gt 1 ]; then
+			return 100
+		fi
+	done
+	test $? -eq 100 || _fail "Failed to create ${bt_type} of sufficient height!"
+	return 1
+}
+
 # Check that populate created all the types of files we wanted
 _scratch_xfs_populate_check() {
 	_scratch_mount
@@ -367,6 +431,9 @@ _scratch_xfs_populate_check() {
 	leaf_attr="$(__populate_find_inode "${SCRATCH_MNT}/ATTR.FMT_LEAF")"
 	node_attr="$(__populate_find_inode "${SCRATCH_MNT}/ATTR.FMT_NODE")"
 	btree_attr="$(__populate_find_inode "${SCRATCH_MNT}/ATTR.FMT_BTREE")"
+	is_finobt=$(xfs_info "${SCRATCH_MNT}" | grep -c 'finobt=1')
+	is_rmapbt=$(xfs_info "${SCRATCH_MNT}" | grep -c 'rmapbt=1')
+	is_reflink=$(xfs_info "${SCRATCH_MNT}" | grep -c 'reflink=1')
 
 	blksz="$(stat -f -c '%s' "${SCRATCH_MNT}")"
 	dblksz="$(xfs_info "${SCRATCH_MNT}" | grep naming.*bsize | sed -e 's/^.*bsize=//g' -e 's/\([0-9]*\).*$/\1/g')"
@@ -389,6 +456,10 @@ _scratch_xfs_populate_check() {
 	__populate_check_xfs_attr "${node_attr}" "node"
 	__populate_check_xfs_attr "${btree_attr}" "btree"
 	__populate_check_xfs_aformat "${btree_attr}" "btree"
+	__populate_check_xfs_agbtree_height "bno"
+	__populate_check_xfs_agbtree_height "cnt"
+	test -n $is_rmapbt && __populate_check_xfs_agbtree_height "rmap"
+	test -n $is_reflink && __populate_check_xfs_agbtree_height "refcnt"
 }
 
 # Check data fork format of ext4 file


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

* [PATCH 2/9] populate: add _require_populate_commands to check for tools
  2016-11-05  0:17 [PATCH v2 0/9] xfstests: online scrub/repair support Darrick J. Wong
  2016-11-05  0:17 ` [PATCH 1/9] populate: create all types of XFS metadata Darrick J. Wong
@ 2016-11-05  0:17 ` Darrick J. Wong
  2016-11-05  0:17 ` [PATCH 3/9] populate: optionally fill the filesystem when populating fs Darrick J. Wong
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 25+ messages in thread
From: Darrick J. Wong @ 2016-11-05  0:17 UTC (permalink / raw)
  To: david, eguan, darrick.wong; +Cc: linux-xfs, fstests

Back when I created common/populate, I thought it was sufficient to
_require the tools that the populate functions need in the main
file.  This turned out to be a bit sloppy, so move them into a
helper function and call it from everything that uses populate.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 common/populate |    9 ++++++---
 tests/ext4/006  |    1 +
 tests/xfs/083   |    3 +--
 tests/xfs/085   |    1 +
 tests/xfs/086   |    1 +
 tests/xfs/087   |    1 +
 tests/xfs/088   |    1 +
 tests/xfs/089   |    1 +
 tests/xfs/091   |    1 +
 tests/xfs/093   |    1 +
 tests/xfs/097   |    1 +
 tests/xfs/098   |    1 +
 tests/xfs/099   |    1 +
 tests/xfs/100   |    1 +
 tests/xfs/101   |    1 +
 tests/xfs/102   |    1 +
 tests/xfs/105   |    1 +
 tests/xfs/112   |    1 +
 tests/xfs/113   |    1 +
 tests/xfs/117   |    1 +
 tests/xfs/120   |    1 +
 tests/xfs/123   |    1 +
 tests/xfs/124   |    1 +
 tests/xfs/125   |    1 +
 tests/xfs/126   |    1 +
 tests/xfs/269   |    1 +
 tests/xfs/273   |    1 +
 27 files changed, 32 insertions(+), 5 deletions(-)


diff --git a/common/populate b/common/populate
index 6ada902..2ac2c22 100644
--- a/common/populate
+++ b/common/populate
@@ -22,9 +22,12 @@
 #  Mountain View, CA 94043, USA, or: http://www.sgi.com
 #-----------------------------------------------------------------------
 
-_require_xfs_io_command "falloc"
-_require_xfs_io_command "fpunch"
-_require_test_program "punch-alternating"
+_require_populate_commands() {
+	_require_xfs_io_command "falloc"
+	_require_xfs_io_command "fpunch"
+	_require_test_program "punch-alternating"
+	_require_command "$XFS_DB_PROG" "xfs_db"
+}
 
 _require_xfs_db_blocktrash_z_command() {
 	test "${FSTYP}" = "xfs" || _notrun "cannot run xfs_db on ${FSTYP}"
diff --git a/tests/ext4/006 b/tests/ext4/006
index f6cca66..9662f50 100755
--- a/tests/ext4/006
+++ b/tests/ext4/006
@@ -54,6 +54,7 @@ _supported_os Linux
 
 _require_scratch
 _require_attrs
+_require_populate_commands
 
 repair_scratch() {
 	fsck_pass="$1"
diff --git a/tests/xfs/083 b/tests/xfs/083
index 040f3b6..39bd75f 100755
--- a/tests/xfs/083
+++ b/tests/xfs/083
@@ -48,12 +48,11 @@ _cleanup()
 _supported_fs xfs
 _supported_os Linux
 
-_require_xfs_io_command "falloc"
-_require_xfs_io_command "fpunch"
 _require_scratch
 #_require_xfs_crc	# checksum not required, but you probably want it anyway...
 #_require_xfs_mkfs_crc
 _require_attrs
+_require_populate_commands
 
 scratch_repair() {
 	fsck_pass="$1"
diff --git a/tests/xfs/085 b/tests/xfs/085
index 1ca5354..0c85850 100755
--- a/tests/xfs/085
+++ b/tests/xfs/085
@@ -50,6 +50,7 @@ _supported_os Linux
 _require_scratch
 test -n "${FORCE_FUZZ}" || _require_scratch_xfs_crc
 _require_attrs
+_require_populate_commands
 _require_xfs_db_blocktrash_z_command
 
 rm -f $seqres.full
diff --git a/tests/xfs/086 b/tests/xfs/086
index cf0a71a..787f886 100755
--- a/tests/xfs/086
+++ b/tests/xfs/086
@@ -50,6 +50,7 @@ _supported_os Linux
 _require_scratch
 test -n "${FORCE_FUZZ}" || _require_scratch_xfs_crc
 _require_attrs
+_require_populate_commands
 _require_xfs_db_blocktrash_z_command
 test -z "${FUZZ_ARGS}" && FUZZ_ARGS="-n 8 -3"
 
diff --git a/tests/xfs/087 b/tests/xfs/087
index 0bb3ec1..58ba958 100755
--- a/tests/xfs/087
+++ b/tests/xfs/087
@@ -50,6 +50,7 @@ _supported_os Linux
 _require_scratch
 test -n "${FORCE_FUZZ}" || _require_scratch_xfs_crc
 _require_attrs
+_require_populate_commands
 _require_xfs_db_blocktrash_z_command
 test -z "${FUZZ_ARGS}" && FUZZ_ARGS="-n 8 -3"
 
diff --git a/tests/xfs/088 b/tests/xfs/088
index d6972a4..36745b2 100755
--- a/tests/xfs/088
+++ b/tests/xfs/088
@@ -50,6 +50,7 @@ _supported_os Linux
 _require_scratch
 test -n "${FORCE_FUZZ}" || _require_scratch_xfs_crc
 _require_attrs
+_require_populate_commands
 _require_xfs_db_blocktrash_z_command
 test -z "${FUZZ_ARGS}" && FUZZ_ARGS="-n 8 -3"
 
diff --git a/tests/xfs/089 b/tests/xfs/089
index 06996a5..52bdd54 100755
--- a/tests/xfs/089
+++ b/tests/xfs/089
@@ -50,6 +50,7 @@ _supported_os Linux
 _require_scratch
 test -n "${FORCE_FUZZ}" || _require_scratch_xfs_crc
 _require_attrs
+_require_populate_commands
 _require_xfs_db_blocktrash_z_command
 test -z "${FUZZ_ARGS}" && FUZZ_ARGS="-n 8 -3"
 
diff --git a/tests/xfs/091 b/tests/xfs/091
index a263cb0..ae62337 100755
--- a/tests/xfs/091
+++ b/tests/xfs/091
@@ -50,6 +50,7 @@ _supported_os Linux
 _require_scratch
 test -n "${FORCE_FUZZ}" || _require_scratch_xfs_crc
 _require_attrs
+_require_populate_commands
 _require_xfs_db_blocktrash_z_command
 test -z "${FUZZ_ARGS}" && FUZZ_ARGS="-n 8 -3"
 
diff --git a/tests/xfs/093 b/tests/xfs/093
index 753231e..0f9311e 100755
--- a/tests/xfs/093
+++ b/tests/xfs/093
@@ -50,6 +50,7 @@ _supported_os Linux
 _require_scratch
 test -n "${FORCE_FUZZ}" || _require_scratch_xfs_crc
 _require_attrs
+_require_populate_commands
 _require_xfs_db_blocktrash_z_command
 test -z "${FUZZ_ARGS}" && FUZZ_ARGS="-n 8 -3"
 
diff --git a/tests/xfs/097 b/tests/xfs/097
index a75f06a..303ad04 100755
--- a/tests/xfs/097
+++ b/tests/xfs/097
@@ -52,6 +52,7 @@ _require_xfs_mkfs_finobt
 _require_xfs_finobt
 test -n "${FORCE_FUZZ}" || _require_scratch_xfs_crc
 _require_attrs
+_require_populate_commands
 _require_xfs_db_blocktrash_z_command
 test -z "${FUZZ_ARGS}" && FUZZ_ARGS="-n 8 -3"
 
diff --git a/tests/xfs/098 b/tests/xfs/098
index 581377e..7873f32 100755
--- a/tests/xfs/098
+++ b/tests/xfs/098
@@ -50,6 +50,7 @@ _supported_os Linux
 _require_scratch
 test -n "${FORCE_FUZZ}" || _require_scratch_xfs_crc
 _require_attrs
+_require_populate_commands
 _require_xfs_db_blocktrash_z_command
 test -z "${FUZZ_ARGS}" && FUZZ_ARGS="-n 8 -3"
 
diff --git a/tests/xfs/099 b/tests/xfs/099
index 85193ab..7835df9 100755
--- a/tests/xfs/099
+++ b/tests/xfs/099
@@ -50,6 +50,7 @@ _supported_os Linux
 _require_scratch
 test -n "${FORCE_FUZZ}" || _require_scratch_xfs_crc
 _require_attrs
+_require_populate_commands
 _require_xfs_db_blocktrash_z_command
 test -z "${FUZZ_ARGS}" && FUZZ_ARGS="-n 8 -3"
 
diff --git a/tests/xfs/100 b/tests/xfs/100
index 3bfafce..ebb656d 100755
--- a/tests/xfs/100
+++ b/tests/xfs/100
@@ -50,6 +50,7 @@ _supported_os Linux
 _require_scratch
 test -n "${FORCE_FUZZ}" || _require_scratch_xfs_crc
 _require_attrs
+_require_populate_commands
 _require_xfs_db_blocktrash_z_command
 test -z "${FUZZ_ARGS}" && FUZZ_ARGS="-n 8 -3"
 
diff --git a/tests/xfs/101 b/tests/xfs/101
index d3abd19..709fc9d 100755
--- a/tests/xfs/101
+++ b/tests/xfs/101
@@ -50,6 +50,7 @@ _supported_os Linux
 _require_scratch
 test -n "${FORCE_FUZZ}" || _require_scratch_xfs_crc
 _require_attrs
+_require_populate_commands
 _require_xfs_db_blocktrash_z_command
 test -z "${FUZZ_ARGS}" && FUZZ_ARGS="-n 8 -3"
 
diff --git a/tests/xfs/102 b/tests/xfs/102
index cf0d7a6..3d51c6a 100755
--- a/tests/xfs/102
+++ b/tests/xfs/102
@@ -50,6 +50,7 @@ _supported_os Linux
 _require_scratch
 test -n "${FORCE_FUZZ}" || _require_scratch_xfs_crc
 _require_attrs
+_require_populate_commands
 _require_xfs_db_blocktrash_z_command
 test -z "${FUZZ_ARGS}" && FUZZ_ARGS="-n 8 -3"
 
diff --git a/tests/xfs/105 b/tests/xfs/105
index 07ccf00..fc91a4f 100755
--- a/tests/xfs/105
+++ b/tests/xfs/105
@@ -50,6 +50,7 @@ _supported_os Linux
 _require_scratch
 test -n "${FORCE_FUZZ}" || _require_scratch_xfs_crc
 _require_attrs
+_require_populate_commands
 _require_xfs_db_blocktrash_z_command
 test -z "${FUZZ_ARGS}" && FUZZ_ARGS="-n 8 -3"
 
diff --git a/tests/xfs/112 b/tests/xfs/112
index 84f1f1d..ae75684 100755
--- a/tests/xfs/112
+++ b/tests/xfs/112
@@ -50,6 +50,7 @@ _supported_os Linux
 _require_scratch
 test -n "${FORCE_FUZZ}" || _require_scratch_xfs_crc
 _require_attrs
+_require_populate_commands
 _require_xfs_db_blocktrash_z_command
 test -z "${FUZZ_ARGS}" && FUZZ_ARGS="-n 8 -3"
 
diff --git a/tests/xfs/113 b/tests/xfs/113
index ec328bc..c347db7 100755
--- a/tests/xfs/113
+++ b/tests/xfs/113
@@ -50,6 +50,7 @@ _supported_os Linux
 _require_scratch
 test -n "${FORCE_FUZZ}" || _require_scratch_xfs_crc
 _require_attrs
+_require_populate_commands
 _require_xfs_db_blocktrash_z_command
 test -z "${FUZZ_ARGS}" && FUZZ_ARGS="-n 8 -3"
 
diff --git a/tests/xfs/117 b/tests/xfs/117
index f251fb3..f0b95aa 100755
--- a/tests/xfs/117
+++ b/tests/xfs/117
@@ -50,6 +50,7 @@ _supported_os Linux
 _require_scratch
 test -n "${FORCE_FUZZ}" || _require_scratch_xfs_crc
 _require_attrs
+_require_populate_commands
 _require_xfs_db_blocktrash_z_command
 test -z "${FUZZ_ARGS}" && FUZZ_ARGS="-n 8 -3"
 
diff --git a/tests/xfs/120 b/tests/xfs/120
index 3deece6..5a38000 100755
--- a/tests/xfs/120
+++ b/tests/xfs/120
@@ -50,6 +50,7 @@ _supported_os Linux
 _require_scratch
 test -n "${FORCE_FUZZ}" || _require_scratch_xfs_crc
 _require_attrs
+_require_populate_commands
 _require_xfs_db_blocktrash_z_command
 test -z "${FUZZ_ARGS}" && FUZZ_ARGS="-n 8 -3"
 
diff --git a/tests/xfs/123 b/tests/xfs/123
index e6cd8e7..7355e86 100755
--- a/tests/xfs/123
+++ b/tests/xfs/123
@@ -50,6 +50,7 @@ _supported_os Linux
 _require_scratch
 test -n "${FORCE_FUZZ}" || _require_scratch_xfs_crc
 _require_attrs
+_require_populate_commands
 _require_xfs_db_blocktrash_z_command
 test -z "${FUZZ_ARGS}" && FUZZ_ARGS="-n 8 -3"
 
diff --git a/tests/xfs/124 b/tests/xfs/124
index cfea2e6..a828dd6 100755
--- a/tests/xfs/124
+++ b/tests/xfs/124
@@ -50,6 +50,7 @@ _supported_os Linux
 _require_scratch
 test -n "${FORCE_FUZZ}" || _require_scratch_xfs_crc
 _require_attrs
+_require_populate_commands
 _require_xfs_db_blocktrash_z_command
 test -z "${FUZZ_ARGS}" && FUZZ_ARGS="-n 8 -3"
 
diff --git a/tests/xfs/125 b/tests/xfs/125
index 3f2f6f0..3afb4cc 100755
--- a/tests/xfs/125
+++ b/tests/xfs/125
@@ -50,6 +50,7 @@ _supported_os Linux
 _require_scratch
 test -n "${FORCE_FUZZ}" || _require_scratch_xfs_crc
 _require_attrs
+_require_populate_commands
 _require_xfs_db_blocktrash_z_command
 test -z "${FUZZ_ARGS}" && FUZZ_ARGS="-n 8 -3"
 
diff --git a/tests/xfs/126 b/tests/xfs/126
index 77779e0..d696ff1 100755
--- a/tests/xfs/126
+++ b/tests/xfs/126
@@ -50,6 +50,7 @@ _supported_os Linux
 _require_scratch
 test -n "${FORCE_FUZZ}" || _require_scratch_xfs_crc
 _require_attrs
+_require_populate_commands
 _require_xfs_db_blocktrash_z_command
 test -z "${FUZZ_ARGS}" && FUZZ_ARGS="-n 8 -3"
 
diff --git a/tests/xfs/269 b/tests/xfs/269
index b51ce64..318dd22 100755
--- a/tests/xfs/269
+++ b/tests/xfs/269
@@ -44,6 +44,7 @@ _cleanup()
 # real QA test starts here
 _supported_os Linux
 _require_scratch
+_require_populate_commands
 _require_test_program "attr-list-by-handle-cursor-test"
 
 rm -f "$seqres.full"
diff --git a/tests/xfs/273 b/tests/xfs/273
index f4b57bb..1a4ee93 100755
--- a/tests/xfs/273
+++ b/tests/xfs/273
@@ -44,6 +44,7 @@ _cleanup()
 _supported_os Linux
 _supported_fs xfs
 _require_scratch
+_require_populate_commands
 _require_xfs_io_command "fsmap"
 
 rm -f "$seqres.full"


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

* [PATCH 3/9] populate: optionally fill the filesystem when populating fs
  2016-11-05  0:17 [PATCH v2 0/9] xfstests: online scrub/repair support Darrick J. Wong
  2016-11-05  0:17 ` [PATCH 1/9] populate: create all types of XFS metadata Darrick J. Wong
  2016-11-05  0:17 ` [PATCH 2/9] populate: add _require_populate_commands to check for tools Darrick J. Wong
@ 2016-11-05  0:17 ` Darrick J. Wong
  2016-11-05  0:17 ` [PATCH 4/9] populate: fix some silly errors when modifying a fs while fuzzing Darrick J. Wong
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 25+ messages in thread
From: Darrick J. Wong @ 2016-11-05  0:17 UTC (permalink / raw)
  To: david, eguan, darrick.wong; +Cc: linux-xfs, fstests

Be a little more flexible in how much we fill up a pre-populated
filesystem.  For the field fuzzing tests, we don't need the extra
space/inode usage and therefore won't want much at all.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 common/populate |   35 ++++++++++++++++++++++++++++-------
 1 file changed, 28 insertions(+), 7 deletions(-)


diff --git a/common/populate b/common/populate
index 2ac2c22..5d451e3 100644
--- a/common/populate
+++ b/common/populate
@@ -73,26 +73,39 @@ __populate_create_attr() {
 	done
 }
 
-# Fill up 60% of the remaining free space
+# Fill up some percentage of the remaining free space
 __populate_fill_fs() {
 	dir="$1"
 	pct="$2"
 	test -z "${pct}" && pct=60
 
-	SRC_SZ="$(du -ks "${SRCDIR}" | cut -f 1)"
+	mkdir -p "${dir}/test/1"
+	cp -pRdu "${dir}"/S_IFREG* "${dir}/test/1/"
+
+	SRC_SZ="$(du -ks "${dir}/test/1" | cut -f 1)"
 	FS_SZ="$(( $(stat -f "${dir}" -c '%a * %S') / 1024 ))"
 
 	NR="$(( (FS_SZ * ${pct} / 100) / SRC_SZ ))"
-	test "${NR}" -lt 1 && NR=1
 
-	seq 1 "${NR}" | while read nr; do
-		cp -pRdu "${SRCDIR}" "${dir}/test.${nr}" >> $seqres.full 2>&1
+	echo "FILL FS"
+	echo "src_sz $SRC_SZ fs_sz $FS_SZ nr $NR"
+	seq 2 "${NR}" | while read nr; do
+		cp -pRdu "${dir}/test/1" "${dir}/test/${nr}"
 	done
 }
 
 # Populate an XFS on the scratch device with (we hope) all known
 # types of metadata block
 _scratch_xfs_populate() {
+	fill=1
+
+	for arg in $@; do
+		case "${arg}" in
+		"nofill")
+			fill=0;;
+		esac
+	done
+
 	_scratch_mount
 	blksz="$(stat -f -c '%s' "${SCRATCH_MNT}")"
 	dblksz="$(xfs_info "${SCRATCH_MNT}" | grep naming.*bsize | sed -e 's/^.*bsize=//g' -e 's/\([0-9]*\).*$/\1/g')"
@@ -227,6 +240,15 @@ _scratch_xfs_populate() {
 # Populate an ext4 on the scratch device with (we hope) all known
 # types of metadata block
 _scratch_ext4_populate() {
+	fill=1
+
+	for arg in $@; do
+		case "${arg}" in
+		"nofill")
+			fill=0;;
+		esac
+	done
+
 	_scratch_mount
 	blksz="$(stat -f -c '%s' "${SCRATCH_MNT}")"
 	dblksz="${blksz}"
@@ -294,8 +316,7 @@ _scratch_ext4_populate() {
 
 	# Copy some real files (xfs tests, I guess...)
 	echo "+ real files"
-	__populate_fill_fs "${SCRATCH_MNT}"
-	cp -pRdu --reflink=always "${SCRATCH_MNT}/S_IFREG.FMT_ETREE" "${SCRATCH_MNT}/S_IREG.FMT_ETREE.REFLINK" 2> /dev/null
+	test $fill -ne 0 && __populate_fill_fs "${SCRATCH_MNT}" 5
 
 	umount "${SCRATCH_MNT}"
 }


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

* [PATCH 4/9] populate: fix some silly errors when modifying a fs while fuzzing
  2016-11-05  0:17 [PATCH v2 0/9] xfstests: online scrub/repair support Darrick J. Wong
                   ` (2 preceding siblings ...)
  2016-11-05  0:17 ` [PATCH 3/9] populate: optionally fill the filesystem when populating fs Darrick J. Wong
@ 2016-11-05  0:17 ` Darrick J. Wong
  2016-11-05  0:17 ` [PATCH 5/9] common/fuzzy: move fuzzing helper functions here Darrick J. Wong
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 25+ messages in thread
From: Darrick J. Wong @ 2016-11-05  0:17 UTC (permalink / raw)
  To: david, eguan, darrick.wong; +Cc: linux-xfs, fstests

There were some silly errors in _scratch_fuzz_modify such that it
wasn't really doing much of anything because of undefined variables.
(Sloppy refactoring when converting xfsfuzz.sh into xfstests.)

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 common/populate |   10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)


diff --git a/common/populate b/common/populate
index 5d451e3..d2df121 100644
--- a/common/populate
+++ b/common/populate
@@ -590,7 +590,7 @@ _scratch_populate() {
 		_scratch_xfs_populate
 		_scratch_xfs_populate_check
 		;;
-	"ext4")
+	"ext2"|"ext3"|"ext4")
 		_scratch_ext4_populate
 		_scratch_ext4_populate_check
 		;;
@@ -606,22 +606,24 @@ _scratch_fuzz_modify() {
 
 	test -z "${nr}" && nr=50000
 	echo "+++ touch ${nr} files"
-	$XFS_IO_PROG -f -c "pwrite -S 0x63 0 ${BLK_SZ}" "/tmp/afile" > /dev/null
+	blk_sz=$(stat -f -c '%s' ${SCRATCH_MNT})
+	$XFS_IO_PROG -f -c "pwrite -S 0x63 0 ${blk_sz}" "/tmp/afile" > /dev/null
 	date="$(date)"
 	find "${SCRATCH_MNT}/" -type f 2> /dev/null | head -n "${nr}" | while read f; do
 		setfattr -n "user.date" -v "${date}" "$f"
 		cat "/tmp/afile" >> "$f"
 		mv "$f" "$f.longer"
 	done
+	sync
 	rm -rf "/tmp/afile"
 
 	echo "+++ create files"
-	cp -pRdu "${SRCDIR}" "${SCRATCH_MNT}/test.moo"
+	mkdir -p "${SCRATCH_MNT}/test.moo"
+	$XFS_IO_PROG -f -c 'pwrite -S 0x80 0 65536' "${SCRATCH_MNT}/test.moo/urk"
 	sync
 
 	echo "+++ remove files"
 	rm -rf "${SCRATCH_MNT}/test.moo"
-	rm -rf "${SCRATCH_MNT}/test.1"
 }
 
 # Try to access files after fuzzing


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

* [PATCH 5/9] common/fuzzy: move fuzzing helper functions here
  2016-11-05  0:17 [PATCH v2 0/9] xfstests: online scrub/repair support Darrick J. Wong
                   ` (3 preceding siblings ...)
  2016-11-05  0:17 ` [PATCH 4/9] populate: fix some silly errors when modifying a fs while fuzzing Darrick J. Wong
@ 2016-11-05  0:17 ` Darrick J. Wong
  2016-11-05  0:17 ` [PATCH 6/9] populate: cache scratch metadata images Darrick J. Wong
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 25+ messages in thread
From: Darrick J. Wong @ 2016-11-05  0:17 UTC (permalink / raw)
  To: david, eguan, darrick.wong; +Cc: linux-xfs, fstests

Move some fuzzing helper functions into a new common/fuzzy file.
We'll add a lot more fuzzing helpers in subsequent patches.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 common/fuzzy    |   83 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 common/populate |   36 ------------------------
 tests/ext4/006  |    1 +
 tests/xfs/083   |    1 +
 4 files changed, 85 insertions(+), 36 deletions(-)
 create mode 100644 common/fuzzy


diff --git a/common/fuzzy b/common/fuzzy
new file mode 100644
index 0000000..20f1d29
--- /dev/null
+++ b/common/fuzzy
@@ -0,0 +1,83 @@
+##/bin/bash
+
+# Routines for fuzzing and scrubbing a filesystem.
+#
+#-----------------------------------------------------------------------
+#  Copyright (c) 2016 Oracle.  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; either version 2 of the License, or
+#  (at your option) any later version.
+#
+#  This program is distributed in the hope that it will 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 to the Free Software
+#  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
+#  USA
+#
+#  Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+#  Mountain View, CA 94043, USA, or: http://www.sgi.com
+#-----------------------------------------------------------------------
+
+# Modify various files after a fuzzing operation
+_scratch_fuzz_modify() {
+	nr="$1"
+
+	test -z "${nr}" && nr=50000
+	echo "+++ touch ${nr} files"
+	blk_sz=$(stat -f -c '%s' ${SCRATCH_MNT})
+	$XFS_IO_PROG -f -c "pwrite -S 0x63 0 ${blk_sz}" "/tmp/afile" > /dev/null
+	date="$(date)"
+	find "${SCRATCH_MNT}/" -type f 2> /dev/null | head -n "${nr}" | while read f; do
+		setfattr -n "user.date" -v "${date}" "$f"
+		cat "/tmp/afile" >> "$f"
+		mv "$f" "$f.longer"
+	done
+	sync
+	rm -rf "/tmp/afile"
+
+	echo "+++ create files"
+	mkdir -p "${SCRATCH_MNT}/test.moo"
+	$XFS_IO_PROG -f -c 'pwrite -S 0x80 0 65536' "${SCRATCH_MNT}/test.moo/urk"
+	sync
+
+	echo "+++ remove files"
+	rm -rf "${SCRATCH_MNT}/test.moo"
+}
+
+# Try to access files after fuzzing
+_scratch_fuzz_test() {
+	echo "+++ ls -laR" >> $seqres.full
+	ls -laR "${SCRATCH_MNT}/test.1/" >/dev/null 2>&1
+
+	echo "+++ cat files" >> $seqres.full
+	(find "${SCRATCH_MNT}/test.1/" -type f -size -1048576k -print0 | xargs -0 cat) >/dev/null 2>&1
+}
+
+# Do we have an online scrub program?
+_require_scrub() {
+	case "${FSTYP}" in
+	"xfs"|"ext4")
+		test -x $XFS_SCRUB_PROG || _notrun "xfs_scrub not found"
+		;;
+	*)
+		_notrun "No online scrub program for ${FSTYP}."
+		;;
+	esac
+}
+
+# Scrub the scratch filesystem (online)
+_scratch_scrub() {
+	case "${FSTYP}" in
+	"xfs"|"ext4")
+		$XFS_SCRUB_PROG -d -T -v "$@" $SCRATCH_MNT
+		;;
+	*)
+		_fail "No online scrub program for ${FSTYP}."
+		;;
+	esac
+}
diff --git a/common/populate b/common/populate
index d2df121..947d74f 100644
--- a/common/populate
+++ b/common/populate
@@ -599,39 +599,3 @@ _scratch_populate() {
 		;;
 	esac
 }
-
-# Modify various files after a fuzzing operation
-_scratch_fuzz_modify() {
-	nr="$1"
-
-	test -z "${nr}" && nr=50000
-	echo "+++ touch ${nr} files"
-	blk_sz=$(stat -f -c '%s' ${SCRATCH_MNT})
-	$XFS_IO_PROG -f -c "pwrite -S 0x63 0 ${blk_sz}" "/tmp/afile" > /dev/null
-	date="$(date)"
-	find "${SCRATCH_MNT}/" -type f 2> /dev/null | head -n "${nr}" | while read f; do
-		setfattr -n "user.date" -v "${date}" "$f"
-		cat "/tmp/afile" >> "$f"
-		mv "$f" "$f.longer"
-	done
-	sync
-	rm -rf "/tmp/afile"
-
-	echo "+++ create files"
-	mkdir -p "${SCRATCH_MNT}/test.moo"
-	$XFS_IO_PROG -f -c 'pwrite -S 0x80 0 65536' "${SCRATCH_MNT}/test.moo/urk"
-	sync
-
-	echo "+++ remove files"
-	rm -rf "${SCRATCH_MNT}/test.moo"
-}
-
-# Try to access files after fuzzing
-_scratch_fuzz_test() {
-	echo "+++ ls -laR" >> $seqres.full
-	ls -laR "${SCRATCH_MNT}/test.1/" >/dev/null 2>&1
-
-	echo "+++ cat files" >> $seqres.full
-	(find "${SCRATCH_MNT}/test.1/" -type f -size -1048576k -print0 | xargs -0 cat) >/dev/null 2>&1
-}
-
diff --git a/tests/ext4/006 b/tests/ext4/006
index 9662f50..bb9b7e5 100755
--- a/tests/ext4/006
+++ b/tests/ext4/006
@@ -43,6 +43,7 @@ _cleanup()
 . ./common/filter
 . ./common/attr
 . ./common/populate
+. ./common/fuzzy
 
 if [ ! -x "$(which e2fuzz)" ]; then
 	_notrun "Couldn't find e2fuzz"
diff --git a/tests/xfs/083 b/tests/xfs/083
index 39bd75f..e2b5f82 100755
--- a/tests/xfs/083
+++ b/tests/xfs/083
@@ -43,6 +43,7 @@ _cleanup()
 . ./common/filter
 . ./common/attr
 . ./common/populate
+. ./common/fuzzy
 
 # real QA test starts here
 _supported_fs xfs


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

* [PATCH 6/9] populate: cache scratch metadata images
  2016-11-05  0:17 [PATCH v2 0/9] xfstests: online scrub/repair support Darrick J. Wong
                   ` (4 preceding siblings ...)
  2016-11-05  0:17 ` [PATCH 5/9] common/fuzzy: move fuzzing helper functions here Darrick J. Wong
@ 2016-11-05  0:17 ` Darrick J. Wong
  2016-11-05  0:17 ` [PATCH 7/9] populate: discover XFS structure fields and fuzz verbs, and use them to fuzz fields Darrick J. Wong
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 25+ messages in thread
From: Darrick J. Wong @ 2016-11-05  0:17 UTC (permalink / raw)
  To: david, eguan, darrick.wong; +Cc: linux-xfs, fstests

Create a helper function to create a populated FS image and dump the
metadata into a file on the test device, with the purpose of allowing
future (fuzzer) invocations of _populate_fs use the cached metadata to
save time.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 common/populate |   44 ++++++++++++++++++++++++++++++++++++++++++++
 common/rc       |    3 ++-
 2 files changed, 46 insertions(+), 1 deletion(-)


diff --git a/common/populate b/common/populate
index 947d74f..15d68fc 100644
--- a/common/populate
+++ b/common/populate
@@ -599,3 +599,47 @@ _scratch_populate() {
 		;;
 	esac
 }
+
+# Populate a scratch FS from scratch or from a cached image.
+_scratch_populate_cached() {
+	POPULATE_METADUMP="${TEST_DIR}/__populate.${FSTYP}"
+	POPULATE_METADUMP_DESCR="${TEST_DIR}/__populate.${FSTYP}.txt"
+
+	# Don't keep metadata images cached for more 48 hours...
+	rm -rf "$(find "${POPULATE_METADUMP}" -mtime +2 2>/dev/null)"
+
+	# Throw away cached image if it doesn't match our spec.
+	meta_descr="FSTYP ${FSTYP} MKFS_OPTIONS ${MKFS_OPTIONS} ARGS $@"
+	cmp -s "${POPULATE_METADUMP_DESCR}" <(echo "${meta_descr}") || rm -rf "${POPULATE_METADUMP}"
+
+	# Do we have a cached image?
+	if [ -r "${POPULATE_METADUMP}" ]; then
+		case "${FSTYP}" in
+		"xfs")
+			xfs_mdrestore "${POPULATE_METADUMP}" "${SCRATCH_DEV}" && return
+			;;
+		"ext2"|"ext3"|"ext4")
+			e2image -r "${POPULATE_METADUMP}" "${SCRATCH_DEV}" && return
+			;;
+		esac
+	fi
+
+	# Oh well, just create one from scratch
+	_scratch_mkfs
+	echo "${meta_descr}" > "${POPULATE_METADUMP_DESCR}"
+	case "${FSTYP}" in
+	"xfs")
+		_scratch_xfs_populate $@
+		_scratch_xfs_populate_check
+		_scratch_metadump "${POPULATE_METADUMP}" -a -o
+		;;
+	"ext2"|"ext3"|"ext4")
+		_scratch_ext4_populate $@
+		_scratch_ext4_populate_check
+		e2image -Q "${SCRATCH_DEV}" "${POPULATE_METADUMP}"
+		;;
+	*)
+		_fail "Don't know how to populate a ${FSTYP} filesystem."
+		;;
+	esac
+}
diff --git a/common/rc b/common/rc
index 69d5c18..d904582 100644
--- a/common/rc
+++ b/common/rc
@@ -415,12 +415,13 @@ _scratch_mkfs_options()
 _scratch_metadump()
 {
 	dumpfile=$1
+	shift
 	options=
 
 	[ "$USE_EXTERNAL" = yes -a ! -z "$SCRATCH_LOGDEV" ] && \
 		options="-l $SCRATCH_LOGDEV"
 
-	xfs_metadump $options $SCRATCH_DEV $dumpfile
+	xfs_metadump $options "$@" $SCRATCH_DEV $dumpfile
 }
 
 _setup_large_xfs_fs()


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

* [PATCH 7/9] populate: discover XFS structure fields and fuzz verbs, and use them to fuzz fields
  2016-11-05  0:17 [PATCH v2 0/9] xfstests: online scrub/repair support Darrick J. Wong
                   ` (5 preceding siblings ...)
  2016-11-05  0:17 ` [PATCH 6/9] populate: cache scratch metadata images Darrick J. Wong
@ 2016-11-05  0:17 ` Darrick J. Wong
  2016-11-09  3:32   ` Eryu Guan
  2016-11-09  3:44   ` Eryu Guan
  2016-11-05  0:18 ` [PATCH 8/9] xfs: fuzz every field of every structure Darrick J. Wong
  2016-11-05  0:18 ` [PATCH 9/9] common/populate: create attrs in different namespaces Darrick J. Wong
  8 siblings, 2 replies; 25+ messages in thread
From: Darrick J. Wong @ 2016-11-05  0:17 UTC (permalink / raw)
  To: david, eguan, darrick.wong; +Cc: linux-xfs, fstests

Create some routines to help us perform targeted fuzzing of individual
fields in various XFS structures.  Specifically, we want the caller to
drop the xfs_db iocursor on the victim field; from there, the scripts
should discover all available fields and fuzzing verbs, and try each
fuzz verb on every available field.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 common/fuzzy |  191 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 191 insertions(+)


diff --git a/common/fuzzy b/common/fuzzy
index 20f1d29..6af47f1 100644
--- a/common/fuzzy
+++ b/common/fuzzy
@@ -81,3 +81,194 @@ _scratch_scrub() {
 		;;
 	esac
 }
+
+# Filter the xfs_db print command's field debug information
+# into field name and type.
+__filter_xfs_db_print_fields() {
+	grep ' = ' | while read key equals value; do
+		fuzzkey="$(echo "${key}" | sed -e 's/\([a-zA-Z0-9_]*\)\[\([0-9]*\)-[0-9]*\]/\1[\2]/g')"
+		if [[ "${value}" == "["* ]]; then
+			echo "${value}" | sed -e 's/^.//g' -e 's/.$//g' -e 's/,/\n/g' | while read subfield; do
+				echo "${fuzzkey}.${subfield}"
+			done
+		else
+			echo "${fuzzkey}"
+		fi
+	done
+}
+
+# Navigate to some part of the filesystem and print the field info.
+_scratch_xfs_list_metadata_fields() {
+	if [ -n "${SCRATCH_XFS_LIST_METADATA_FIELDS}" ]; then
+		echo "${SCRATCH_XFS_LIST_METADATA_FIELDS}" | sed -e 's/ /\n/g'
+		return;
+	fi
+
+	(for arg in "$@"; do
+		echo "${arg}"
+	done
+	echo "print") | _scratch_xfs_db | __filter_xfs_db_print_fields
+}
+
+# Get a metadata field
+_scratch_xfs_get_metadata_field() {
+	key="$1"
+	shift
+
+	grep_key="$(echo "${key}" | tr '[]()' '....')"
+	(for arg in "$@"; do
+		echo "${arg}"
+	done
+	echo "print ${key}") | _scratch_xfs_db | grep "^${grep_key}" | \
+		sed -e 's/^.* = //g'
+}
+
+# Set a metadata field
+_scratch_xfs_set_metadata_field() {
+	key="$1"
+	value="$2"
+	shift; shift
+	(for arg in "$@"; do
+		echo "${arg}"
+	done
+	echo "write -d ${key} ${value}") | _scratch_xfs_db -x
+	echo
+}
+
+# Fuzz a metadata field
+_scratch_xfs_fuzz_metadata_field() {
+	key="$1"
+	value="$2"
+	shift; shift
+
+	if [ "${key}" = "crc" ]; then
+		fuzz_arg="-c"
+	else
+		fuzz_arg="-d"
+	fi
+	oldval="$(_scratch_xfs_get_metadata_field "${key}" "$@")"
+	(for arg in "$@"; do
+		echo "${arg}"
+	done
+	echo "fuzz ${fuzz_arg} ${key} ${value}") | _scratch_xfs_db -x
+	echo
+	newval="$(_scratch_xfs_get_metadata_field "${key}" "$@" 2> /dev/null)"
+	if [ "${oldval}" = "${newval}" ]; then
+		echo "Field ${key} already set to ${oldval}, skipping test."
+		return 1
+	fi
+	return 0
+}
+
+# Try to forcibly unmount the scratch fs
+__scratch_xfs_fuzz_unmount()
+{
+	while _scratch_unmount 2>/dev/null; do sleep 0.2; done
+}
+
+# Restore metadata to scratch device prior to field-fuzzing.
+__scratch_xfs_fuzz_mdrestore()
+{
+	test -e "${POPULATE_METADUMP}" || _fail "Need to set POPULATE_METADUMP"
+
+	__scratch_xfs_fuzz_unmount
+	xfs_mdrestore "${POPULATE_METADUMP}" "${SCRATCH_DEV}"
+}
+
+__fuzz_notify() {
+	echo "$@"
+	test -w /dev/ttyprintk && echo "$@" >> /dev/ttyprintk
+}
+
+# Fuzz one field of some piece of metadata
+__scratch_xfs_fuzz_field_test() {
+	field="$1"
+	fuzzverb="$2"
+	shift; shift
+
+	# Set the new field value
+	__fuzz_notify "+ Fuzz ${field} = ${fuzzverb}"
+	echo "========================"
+	_scratch_xfs_fuzz_metadata_field "${field}" ${fuzzverb} "$@"
+	res=$?
+	test $res -ne 0 && return
+
+	# Try to catch the error with scrub
+	echo "+ Try to catch the error"
+	_scratch_mount 2>&1
+	res=$?
+	if [ $res -eq 0 ]; then
+		_scratch_scrub -a 1 -e continue 2>&1
+		res=$?
+		test $res -eq 0 && \
+			(>&2 echo "scrub didn't fail with ${field} = ${fuzzverb}.")
+
+		# Try modifying the filesystem!
+		__fuzz_notify "++ Try to write filesystem"
+		#_scratch_fuzz_modify 100 2>&1
+		__scratch_xfs_fuzz_unmount
+	fi
+
+	# Repair the filesystem
+	echo "+ Fix the error"
+	_repair_scratch_fs 2>&1
+	res=$?
+	test $res -ne 0 && \
+		(>&2 echo "repair failed ($res) with ${field} = ${fuzzverb}.")
+
+	# See if scrub finds a clean fs
+	echo "+ Make sure error is gone"
+	_scratch_mount 2>&1
+	res=$?
+	if [ $res -eq 0 ]; then
+		_scratch_scrub -e continue 2>&1
+		res=$?
+		test $res -ne 0 && \
+			(>&2 echo "re-scrub ($res) with ${field} = ${fuzzverb}.")
+
+		# Try modifying the filesystem again!
+		__fuzz_notify "++ Try to write filesystem again"
+		_scratch_fuzz_modify 100 2>&1
+		__scratch_xfs_fuzz_unmount
+	else
+		(>&2 echo "re-mount failed ($res) with ${field} = ${fuzzverb}.")
+	fi
+
+	# See if repair finds a clean fs
+	_scratch_xfs_repair -n 2>&1
+	res=$?
+	test $res -ne 0 && \
+		(>&2 echo "re-repair failed ($res) with ${field} = ${fuzzverb}.")
+}
+
+# Make sure we have all the pieces we need for field fuzzing
+_require_scratch_xfs_fuzz_fields()
+{
+	_require_scratch
+	_require_scrub
+	_require_populate_commands
+	_require_command "$XFS_DB_PROG" "xfs_db"
+	_scratch_mkfs_xfs >/dev/null 2>&1
+	_scratch_xfs_db -x -c 'fuzz' 2>&1 | grep -q 'not found' && \
+		_notrun "xfs_db does not have fuzz command"
+}
+
+# Grab the list of available fuzzing verbs
+_scratch_xfs_list_fuzz_verbs() {
+	if [ -n "${SCRATCH_XFS_LIST_FUZZ_VERBS}" ]; then
+		echo "${SCRATCH_XFS_LIST_FUZZ_VERBS}" | sed -e 's/ /\n/g'
+		return;
+	fi
+	_scratch_xfs_db -x -c 'sb 0' -c 'fuzz' | grep '^Verbs:' | \
+		sed -e 's/[,.]//g' -e 's/Verbs: //g' -e 's/ /\n/g'
+}
+
+# Fuzz the fields of some piece of metadata
+_scratch_xfs_fuzz_fields() {
+	_scratch_xfs_list_metadata_fields "$@" | while read field; do
+		_scratch_xfs_list_fuzz_verbs | while read fuzzverb; do
+			__scratch_xfs_fuzz_mdrestore
+			__scratch_xfs_fuzz_field_test "${field}" "${fuzzverb}" "$@"
+		done
+	done
+}


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

* [PATCH 8/9] xfs: fuzz every field of every structure
  2016-11-05  0:17 [PATCH v2 0/9] xfstests: online scrub/repair support Darrick J. Wong
                   ` (6 preceding siblings ...)
  2016-11-05  0:17 ` [PATCH 7/9] populate: discover XFS structure fields and fuzz verbs, and use them to fuzz fields Darrick J. Wong
@ 2016-11-05  0:18 ` Darrick J. Wong
  2016-11-09  8:09     ` Eryu Guan
  2016-11-05  0:18 ` [PATCH 9/9] common/populate: create attrs in different namespaces Darrick J. Wong
  8 siblings, 1 reply; 25+ messages in thread
From: Darrick J. Wong @ 2016-11-05  0:18 UTC (permalink / raw)
  To: david, eguan, darrick.wong; +Cc: linux-xfs, fstests

Previously, our XFS fuzzing efforts were limited to using the xfs_db
blocktrash command to scribble garbage all over a block.  This is
pretty easy to discover; it would be far more interesting if we could
fuzz individual fields looking for unhandled corner cases.  Since we
now have an online scrub tool, use it to check for our targeted
corruptions prior to the usual steps of writing to the FS, taking it
offline, repairing, and re-checking.

These tests use the new xfs_db 'fuzz' command to test corner case
handling of every field.  The 'print' command tells us which fields
are available, and the fuzz command can write zeroes or ones to the
field; set the high, middle, or low bit; add or subtract numbers; or
randomize the field.  We loop through all fields and all fuzz verbs to
see if we can trip up the kernel.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 common/fuzzy        |   49 ++++++++++++++++++++++++++++++------
 common/populate     |   10 ++++---
 common/rc           |   15 +++++++++++
 tests/ext4/1300     |   60 ++++++++++++++++++++++++++++++++++++++++++++
 tests/ext4/1300.out |    3 ++
 tests/ext4/group    |    1 +
 tests/xfs/1300      |   62 ++++++++++++++++++++++++++++++++++++++++++++++
 tests/xfs/1300.out  |    3 ++
 tests/xfs/1301      |   62 ++++++++++++++++++++++++++++++++++++++++++++++
 tests/xfs/1301.out  |    4 +++
 tests/xfs/1302      |   62 ++++++++++++++++++++++++++++++++++++++++++++++
 tests/xfs/1302.out  |    4 +++
 tests/xfs/1303      |   62 ++++++++++++++++++++++++++++++++++++++++++++++
 tests/xfs/1303.out  |    4 +++
 tests/xfs/1304      |   62 ++++++++++++++++++++++++++++++++++++++++++++++
 tests/xfs/1304.out  |    4 +++
 tests/xfs/1305      |   62 ++++++++++++++++++++++++++++++++++++++++++++++
 tests/xfs/1305.out  |    4 +++
 tests/xfs/1306      |   62 ++++++++++++++++++++++++++++++++++++++++++++++
 tests/xfs/1306.out  |    4 +++
 tests/xfs/1307      |   62 ++++++++++++++++++++++++++++++++++++++++++++++
 tests/xfs/1307.out  |    4 +++
 tests/xfs/1308      |   62 ++++++++++++++++++++++++++++++++++++++++++++++
 tests/xfs/1308.out  |    4 +++
 tests/xfs/1309      |   63 +++++++++++++++++++++++++++++++++++++++++++++++
 tests/xfs/1309.out  |    4 +++
 tests/xfs/1310      |   63 +++++++++++++++++++++++++++++++++++++++++++++++
 tests/xfs/1310.out  |    4 +++
 tests/xfs/1311      |   63 +++++++++++++++++++++++++++++++++++++++++++++++
 tests/xfs/1311.out  |    4 +++
 tests/xfs/1312      |   64 +++++++++++++++++++++++++++++++++++++++++++++++
 tests/xfs/1312.out  |    4 +++
 tests/xfs/1313      |   67 ++++++++++++++++++++++++++++++++++++++++++++++++++
 tests/xfs/1313.out  |    5 ++++
 tests/xfs/1314      |   67 ++++++++++++++++++++++++++++++++++++++++++++++++++
 tests/xfs/1314.out  |    5 ++++
 tests/xfs/1315      |   67 ++++++++++++++++++++++++++++++++++++++++++++++++++
 tests/xfs/1315.out  |    5 ++++
 tests/xfs/1316      |   69 +++++++++++++++++++++++++++++++++++++++++++++++++++
 tests/xfs/1316.out  |    5 ++++
 tests/xfs/1317      |   67 ++++++++++++++++++++++++++++++++++++++++++++++++++
 tests/xfs/1317.out  |    5 ++++
 tests/xfs/1318      |   67 ++++++++++++++++++++++++++++++++++++++++++++++++++
 tests/xfs/1318.out  |    5 ++++
 tests/xfs/1319      |   67 ++++++++++++++++++++++++++++++++++++++++++++++++++
 tests/xfs/1319.out  |    5 ++++
 tests/xfs/1320      |   68 ++++++++++++++++++++++++++++++++++++++++++++++++++
 tests/xfs/1320.out  |    5 ++++
 tests/xfs/1321      |   69 +++++++++++++++++++++++++++++++++++++++++++++++++++
 tests/xfs/1321.out  |    5 ++++
 tests/xfs/1322      |   69 +++++++++++++++++++++++++++++++++++++++++++++++++++
 tests/xfs/1322.out  |    5 ++++
 tests/xfs/1323      |   69 +++++++++++++++++++++++++++++++++++++++++++++++++++
 tests/xfs/1323.out  |    5 ++++
 tests/xfs/1324      |   69 +++++++++++++++++++++++++++++++++++++++++++++++++++
 tests/xfs/1324.out  |    5 ++++
 tests/xfs/1325      |   67 ++++++++++++++++++++++++++++++++++++++++++++++++++
 tests/xfs/1325.out  |    5 ++++
 tests/xfs/1326      |   67 ++++++++++++++++++++++++++++++++++++++++++++++++++
 tests/xfs/1326.out  |    5 ++++
 tests/xfs/1327      |   67 ++++++++++++++++++++++++++++++++++++++++++++++++++
 tests/xfs/1327.out  |    5 ++++
 tests/xfs/1328      |   67 ++++++++++++++++++++++++++++++++++++++++++++++++++
 tests/xfs/1328.out  |    5 ++++
 tests/xfs/1329      |   63 +++++++++++++++++++++++++++++++++++++++++++++++
 tests/xfs/1329.out  |    4 +++
 tests/xfs/1330      |   61 +++++++++++++++++++++++++++++++++++++++++++++
 tests/xfs/1330.out  |    4 +++
 tests/xfs/group     |   31 +++++++++++++++++++++++
 69 files changed, 2313 insertions(+), 13 deletions(-)
 create mode 100755 tests/ext4/1300
 create mode 100644 tests/ext4/1300.out
 create mode 100755 tests/xfs/1300
 create mode 100644 tests/xfs/1300.out
 create mode 100755 tests/xfs/1301
 create mode 100644 tests/xfs/1301.out
 create mode 100755 tests/xfs/1302
 create mode 100644 tests/xfs/1302.out
 create mode 100755 tests/xfs/1303
 create mode 100644 tests/xfs/1303.out
 create mode 100755 tests/xfs/1304
 create mode 100644 tests/xfs/1304.out
 create mode 100755 tests/xfs/1305
 create mode 100644 tests/xfs/1305.out
 create mode 100755 tests/xfs/1306
 create mode 100644 tests/xfs/1306.out
 create mode 100755 tests/xfs/1307
 create mode 100644 tests/xfs/1307.out
 create mode 100755 tests/xfs/1308
 create mode 100644 tests/xfs/1308.out
 create mode 100755 tests/xfs/1309
 create mode 100644 tests/xfs/1309.out
 create mode 100755 tests/xfs/1310
 create mode 100644 tests/xfs/1310.out
 create mode 100755 tests/xfs/1311
 create mode 100644 tests/xfs/1311.out
 create mode 100755 tests/xfs/1312
 create mode 100644 tests/xfs/1312.out
 create mode 100755 tests/xfs/1313
 create mode 100644 tests/xfs/1313.out
 create mode 100755 tests/xfs/1314
 create mode 100644 tests/xfs/1314.out
 create mode 100755 tests/xfs/1315
 create mode 100644 tests/xfs/1315.out
 create mode 100755 tests/xfs/1316
 create mode 100644 tests/xfs/1316.out
 create mode 100755 tests/xfs/1317
 create mode 100644 tests/xfs/1317.out
 create mode 100755 tests/xfs/1318
 create mode 100644 tests/xfs/1318.out
 create mode 100755 tests/xfs/1319
 create mode 100644 tests/xfs/1319.out
 create mode 100755 tests/xfs/1320
 create mode 100644 tests/xfs/1320.out
 create mode 100755 tests/xfs/1321
 create mode 100644 tests/xfs/1321.out
 create mode 100755 tests/xfs/1322
 create mode 100644 tests/xfs/1322.out
 create mode 100755 tests/xfs/1323
 create mode 100644 tests/xfs/1323.out
 create mode 100755 tests/xfs/1324
 create mode 100644 tests/xfs/1324.out
 create mode 100755 tests/xfs/1325
 create mode 100644 tests/xfs/1325.out
 create mode 100755 tests/xfs/1326
 create mode 100644 tests/xfs/1326.out
 create mode 100755 tests/xfs/1327
 create mode 100644 tests/xfs/1327.out
 create mode 100755 tests/xfs/1328
 create mode 100644 tests/xfs/1328.out
 create mode 100755 tests/xfs/1329
 create mode 100644 tests/xfs/1329.out
 create mode 100755 tests/xfs/1330
 create mode 100644 tests/xfs/1330.out


diff --git a/common/fuzzy b/common/fuzzy
index 6af47f1..dbff744 100644
--- a/common/fuzzy
+++ b/common/fuzzy
@@ -85,32 +85,47 @@ _scratch_scrub() {
 # Filter the xfs_db print command's field debug information
 # into field name and type.
 __filter_xfs_db_print_fields() {
+	filter="$1"
+	if [ -z "${filter}" ] || [ "${filter}" = "nofilter" ]; then
+		filter='^'
+	fi
 	grep ' = ' | while read key equals value; do
-		fuzzkey="$(echo "${key}" | sed -e 's/\([a-zA-Z0-9_]*\)\[\([0-9]*\)-[0-9]*\]/\1[\2]/g')"
-		if [[ "${value}" == "["* ]]; then
+		# Filter out any keys with an array index >= 10, and
+		# collapse any array range ("[1-195]") to the first item.
+		fuzzkey="$(echo "${key}" | sed -e '/\([a-z]*\)\[\([0-9][0-9]\+\)\].*/d' -e 's/\([a-zA-Z0-9_]*\)\[\([0-9]*\)-[0-9]*\]/\1[\2]/g')"
+		if [ -z "${fuzzkey}" ]; then
+			continue
+		elif [[ "${value}" == "["* ]]; then
 			echo "${value}" | sed -e 's/^.//g' -e 's/.$//g' -e 's/,/\n/g' | while read subfield; do
 				echo "${fuzzkey}.${subfield}"
 			done
 		else
 			echo "${fuzzkey}"
 		fi
-	done
+	done | egrep "${filter}"
 }
 
 # Navigate to some part of the filesystem and print the field info.
+# The first argument is an egrep filter for the fields
+# The rest of the arguments are xfs_db commands to locate the metadata.
 _scratch_xfs_list_metadata_fields() {
+	filter="$1"
+	shift
 	if [ -n "${SCRATCH_XFS_LIST_METADATA_FIELDS}" ]; then
-		echo "${SCRATCH_XFS_LIST_METADATA_FIELDS}" | sed -e 's/ /\n/g'
+		echo "${SCRATCH_XFS_LIST_METADATA_FIELDS}" | \
+			sed -e 's/ /\n/g' | __filter_xfs_db_print_fields "${filter}"
 		return;
 	fi
 
 	(for arg in "$@"; do
 		echo "${arg}"
 	done
-	echo "print") | _scratch_xfs_db | __filter_xfs_db_print_fields
+	echo "print") | _scratch_xfs_db | __filter_xfs_db_print_fields "${filter}"
 }
 
 # Get a metadata field
+# The first arg is the field name
+# The rest of the arguments are xfs_db commands to find the metadata.
 _scratch_xfs_get_metadata_field() {
 	key="$1"
 	shift
@@ -124,6 +139,9 @@ _scratch_xfs_get_metadata_field() {
 }
 
 # Set a metadata field
+# The first arg is the field name
+# The second arg is the new value
+# The rest of the arguments are xfs_db commands to find the metadata.
 _scratch_xfs_set_metadata_field() {
 	key="$1"
 	value="$2"
@@ -136,6 +154,9 @@ _scratch_xfs_set_metadata_field() {
 }
 
 # Fuzz a metadata field
+# The first arg is the field name
+# The second arg is the xfs_db fuzz verb
+# The rest of the arguments are xfs_db commands to find the metadata.
 _scratch_xfs_fuzz_metadata_field() {
 	key="$1"
 	value="$2"
@@ -263,12 +284,24 @@ _scratch_xfs_list_fuzz_verbs() {
 		sed -e 's/[,.]//g' -e 's/Verbs: //g' -e 's/ /\n/g'
 }
 
-# Fuzz the fields of some piece of metadata
-_scratch_xfs_fuzz_fields() {
-	_scratch_xfs_list_metadata_fields "$@" | while read field; do
+# Fuzz some of the fields of some piece of metadata
+# The first argument is an egrep filter
+# The rest of the arguments are xfs_db commands to locate the metadata.
+_scratch_xfs_fuzz_some_fields() {
+	filter="$1"
+	shift
+	echo "Fields we propose to fuzz: $@"
+	_scratch_xfs_list_metadata_fields "${filter}" "$@"
+	_scratch_xfs_list_metadata_fields "${filter}" "$@" | while read field; do
 		_scratch_xfs_list_fuzz_verbs | while read fuzzverb; do
 			__scratch_xfs_fuzz_mdrestore
 			__scratch_xfs_fuzz_field_test "${field}" "${fuzzverb}" "$@"
 		done
 	done
 }
+
+# Fuzz all of the fields of some piece of metadata
+# All arguments are xfs_db commands to locate the metadata.
+_scratch_xfs_fuzz_fields() {
+	_scratch_xfs_fuzz_some_fields '' "$@"
+}
diff --git a/common/populate b/common/populate
index 15d68fc..7d103f0 100644
--- a/common/populate
+++ b/common/populate
@@ -180,13 +180,13 @@ _scratch_xfs_populate() {
 	# FMT_EXTENTS with a remote less-than-a-block value
 	echo "+ attr extents with a remote less-than-a-block value"
 	touch "${SCRATCH_MNT}/ATTR.FMT_EXTENTS_REMOTE3K"
-	$XFS_IO_PROG -f -c "pwrite -S 0x43 0 3k" "${SCRATCH_MNT}/attrvalfile" > /dev/null
+	$XFS_IO_PROG -f -c "pwrite -S 0x43 0 $((blksz - 300))" "${SCRATCH_MNT}/attrvalfile" > /dev/null
 	attr -q -s user.remotebtreeattrname "${SCRATCH_MNT}/ATTR.FMT_EXTENTS_REMOTE3K" < "${SCRATCH_MNT}/attrvalfile"
 
 	# FMT_EXTENTS with a remote block-size value
 	echo "+ attr extents with a remote one-block value"
 	touch "${SCRATCH_MNT}/ATTR.FMT_EXTENTS_REMOTE4K"
-	$XFS_IO_PROG -f -c "pwrite -S 0x44 0 4k" "${SCRATCH_MNT}/attrvalfile" > /dev/null
+	$XFS_IO_PROG -f -c "pwrite -S 0x44 0 ${blksz}" "${SCRATCH_MNT}/attrvalfile" > /dev/null
 	attr -q -s user.remotebtreeattrname "${SCRATCH_MNT}/ATTR.FMT_EXTENTS_REMOTE4K" < "${SCRATCH_MNT}/attrvalfile"
 	rm -rf "${SCRATCH_MNT}/attrvalfile"
 
@@ -482,8 +482,8 @@ _scratch_xfs_populate_check() {
 	__populate_check_xfs_aformat "${btree_attr}" "btree"
 	__populate_check_xfs_agbtree_height "bno"
 	__populate_check_xfs_agbtree_height "cnt"
-	test -n $is_rmapbt && __populate_check_xfs_agbtree_height "rmap"
-	test -n $is_reflink && __populate_check_xfs_agbtree_height "refcnt"
+	test $is_rmapbt -ne 0 && __populate_check_xfs_agbtree_height "rmap"
+	test $is_reflink -ne 0 && __populate_check_xfs_agbtree_height "refcnt"
 }
 
 # Check data fork format of ext4 file
@@ -609,7 +609,7 @@ _scratch_populate_cached() {
 	rm -rf "$(find "${POPULATE_METADUMP}" -mtime +2 2>/dev/null)"
 
 	# Throw away cached image if it doesn't match our spec.
-	meta_descr="FSTYP ${FSTYP} MKFS_OPTIONS ${MKFS_OPTIONS} ARGS $@"
+	meta_descr="FSTYP ${FSTYP} MKFS_OPTIONS $(_scratch_mkfs_options) ARGS $@"
 	cmp -s "${POPULATE_METADUMP_DESCR}" <(echo "${meta_descr}") || rm -rf "${POPULATE_METADUMP}"
 
 	# Do we have a cached image?
diff --git a/common/rc b/common/rc
index d904582..ec1f5de 100644
--- a/common/rc
+++ b/common/rc
@@ -1870,6 +1870,21 @@ _require_xfs_finobt()
 	_scratch_unmount
 }
 
+# Do we have a fre
+_require_scratch_finobt()
+{
+	_require_scratch
+
+	if [ $FSTYP != "xfs" ]; then
+		_notrun "finobt not supported by scratch filesystem type: $FSTYP"
+		return
+	fi
+	_scratch_mkfs > /dev/null
+	_scratch_mount
+	xfs_info $SCRATCH_MNT | grep -q 'finobt=1' || _notrun "finobt not supported by scratch filesystem type: $FSTYP"
+	_scratch_unmount
+}
+
 # this test requires xfs sysfs attribute support
 #
 _require_xfs_sysfs()
diff --git a/tests/ext4/1300 b/tests/ext4/1300
new file mode 100755
index 0000000..3f8135e
--- /dev/null
+++ b/tests/ext4/1300
@@ -0,0 +1,60 @@
+#! /bin/bash
+# FS QA Test No. 1300
+#
+# Populate a ext4 filesystem and ensure that scrub and repair are happy.
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2016 Oracle, Inc.  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	# failure is the default!
+trap "_cleanup; exit \$status" 0 1 2 3 7 15
+
+_cleanup()
+{
+	cd /
+	rm -rf $tmp.*
+}
+
+# get standard environment, filters and checks
+. ./common/rc
+. ./common/filter
+. ./common/populate
+. ./common/fuzzy
+
+# real QA test starts here
+_supported_os Linux
+_supported_fs ext4
+_require_scratch
+_require_scrub
+
+echo "Format and populate"
+_scratch_populate_cached > $seqres.full 2>&1
+
+echo "Scrub"
+_scratch_mount >> $seqres.full 2>&1
+_scratch_scrub >> $seqres.full
+
+# success, all done
+status=0
+exit
diff --git a/tests/ext4/1300.out b/tests/ext4/1300.out
new file mode 100644
index 0000000..8aaa3bb
--- /dev/null
+++ b/tests/ext4/1300.out
@@ -0,0 +1,3 @@
+QA output created by 1300
+Format and populate
+Scrub
diff --git a/tests/ext4/group b/tests/ext4/group
index 53fe03e..9fbaa76 100644
--- a/tests/ext4/group
+++ b/tests/ext4/group
@@ -34,3 +34,4 @@
 306 auto rw resize quick
 307 auto ioctl rw
 308 auto ioctl rw prealloc quick
+1300 auto quick scrub
diff --git a/tests/xfs/1300 b/tests/xfs/1300
new file mode 100755
index 0000000..68befe0
--- /dev/null
+++ b/tests/xfs/1300
@@ -0,0 +1,62 @@
+#! /bin/bash
+# FS QA Test No. 1300
+#
+# Populate a XFS filesystem and ensure that scrub and repair are happy.
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2016 Oracle, Inc.  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	# failure is the default!
+trap "_cleanup; exit \$status" 0 1 2 3 7 15
+
+_cleanup()
+{
+	cd /
+	rm -rf $tmp.*
+}
+
+# get standard environment, filters and checks
+. ./common/rc
+. ./common/filter
+. ./common/populate
+. ./common/fuzzy
+
+# real QA test starts here
+_supported_os Linux
+_supported_fs xfs
+
+_require_scratch
+_require_scrub
+_require_populate_commands
+
+echo "Format and populate"
+_scratch_populate_cached nofill > $seqres.full 2>&1
+
+echo "Scrub"
+_scratch_mount >> $seqres.full 2>&1
+_scratch_scrub >> $seqres.full
+
+# success, all done
+status=0
+exit
diff --git a/tests/xfs/1300.out b/tests/xfs/1300.out
new file mode 100644
index 0000000..8aaa3bb
--- /dev/null
+++ b/tests/xfs/1300.out
@@ -0,0 +1,3 @@
+QA output created by 1300
+Format and populate
+Scrub
diff --git a/tests/xfs/1301 b/tests/xfs/1301
new file mode 100755
index 0000000..4e3885c
--- /dev/null
+++ b/tests/xfs/1301
@@ -0,0 +1,62 @@
+#! /bin/bash
+# FS QA Test No. 1301
+#
+# Populate a XFS filesystem and fuzz every superblock field.
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2016 Oracle, Inc.  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	# failure is the default!
+trap "_cleanup; exit \$status" 0 1 2 3 7 15
+
+_cleanup()
+{
+	cd /
+	rm -rf $tmp.*
+}
+
+# get standard environment, filters and checks
+. ./common/rc
+. ./common/filter
+. ./common/populate
+. ./common/fuzzy
+
+# real QA test starts here
+_supported_os Linux
+_supported_fs xfs
+_require_scratch_xfs_fuzz_fields
+
+echo "Format and populate"
+_scratch_populate_cached nofill > $seqres.full 2>&1
+
+echo "Fields we propose to fuzz: sb 0" >> $seqres.full
+_scratch_xfs_list_metadata_fields 'sb 0' >> $seqres.full
+
+echo "Fuzz superblock"
+_scratch_xfs_fuzz_fields 'sb 0' >> $seqres.full
+echo "Done fuzzing superblock"
+
+# success, all done
+status=0
+exit
diff --git a/tests/xfs/1301.out b/tests/xfs/1301.out
new file mode 100644
index 0000000..f804acc
--- /dev/null
+++ b/tests/xfs/1301.out
@@ -0,0 +1,4 @@
+QA output created by 1301
+Format and populate
+Fuzz superblock
+Done fuzzing superblock
diff --git a/tests/xfs/1302 b/tests/xfs/1302
new file mode 100755
index 0000000..0f53c47
--- /dev/null
+++ b/tests/xfs/1302
@@ -0,0 +1,62 @@
+#! /bin/bash
+# FS QA Test No. 1302
+#
+# Populate a XFS filesystem and fuzz every AGF field.
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2016 Oracle, Inc.  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-1302  USA
+#-----------------------------------------------------------------------
+#
+
+seq=`basename $0`
+seqres=$RESULT_DIR/$seq
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=1	# failure is the default!
+trap "_cleanup; exit \$status" 0 1 2 3 7 15
+
+_cleanup()
+{
+	cd /
+	rm -rf $tmp.*
+}
+
+# get standard environment, filters and checks
+. ./common/rc
+. ./common/filter
+. ./common/populate
+. ./common/fuzzy
+
+# real QA test starts here
+_supported_os Linux
+_supported_fs xfs
+_require_scratch_xfs_fuzz_fields
+
+echo "Format and populate"
+_scratch_populate_cached nofill > $seqres.full 2>&1
+
+echo "Fields we propose to fuzz: agf 0" >> $seqres.full
+_scratch_xfs_list_metadata_fields 'agf 0' >> $seqres.full
+
+echo "Fuzz AGF"
+_scratch_xfs_fuzz_fields 'agf 0' >> $seqres.full
+echo "Done fuzzing AGF"
+
+# success, all done
+status=0
+exit
diff --git a/tests/xfs/1302.out b/tests/xfs/1302.out
new file mode 100644
index 0000000..1e416d5
--- /dev/null
+++ b/tests/xfs/1302.out
@@ -0,0 +1,4 @@
+QA output created by 1302
+Format and populate
+Fuzz AGF
+Done fuzzing AGF
diff --git a/tests/xfs/1303 b/tests/xfs/1303
new file mode 100755
index 0000000..19799c0
--- /dev/null
+++ b/tests/xfs/1303
@@ -0,0 +1,62 @@
+#! /bin/bash
+# FS QA Test No. 1303
+#
+# Populate a XFS filesystem and fuzz every AGFL field.
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2016 Oracle, Inc.  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-1303  USA
+#-----------------------------------------------------------------------
+#
+
+seq=`basename $0`
+seqres=$RESULT_DIR/$seq
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=1	# failure is the default!
+trap "_cleanup; exit \$status" 0 1 2 3 7 15
+
+_cleanup()
+{
+	cd /
+	rm -rf $tmp.*
+}
+
+# get standard environment, filters and checks
+. ./common/rc
+. ./common/filter
+. ./common/populate
+. ./common/fuzzy
+
+# real QA test starts here
+_supported_os Linux
+_supported_fs xfs
+_require_scratch_xfs_fuzz_fields
+
+echo "Format and populate"
+_scratch_populate_cached nofill > $seqres.full 2>&1
+
+echo "Fields we propose to fuzz: agfl 0" >> $seqres.full
+_scratch_xfs_list_metadata_fields 'agfl 0' >> $seqres.full
+
+echo "Fuzz AGFL"
+_scratch_xfs_fuzz_fields 'agfl 0' >> $seqres.full
+echo "Done fuzzing AGFL"
+
+# success, all done
+status=0
+exit
diff --git a/tests/xfs/1303.out b/tests/xfs/1303.out
new file mode 100644
index 0000000..ac6c01b
--- /dev/null
+++ b/tests/xfs/1303.out
@@ -0,0 +1,4 @@
+QA output created by 1303
+Format and populate
+Fuzz AGFL
+Done fuzzing AGFL
diff --git a/tests/xfs/1304 b/tests/xfs/1304
new file mode 100755
index 0000000..71af7bd
--- /dev/null
+++ b/tests/xfs/1304
@@ -0,0 +1,62 @@
+#! /bin/bash
+# FS QA Test No. 1304
+#
+# Populate a XFS filesystem and fuzz every AGI field.
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2016 Oracle, Inc.  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-1303  USA
+#-----------------------------------------------------------------------
+#
+
+seq=`basename $0`
+seqres=$RESULT_DIR/$seq
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=1	# failure is the default!
+trap "_cleanup; exit \$status" 0 1 2 3 7 15
+
+_cleanup()
+{
+	cd /
+	rm -rf $tmp.*
+}
+
+# get standard environment, filters and checks
+. ./common/rc
+. ./common/filter
+. ./common/populate
+. ./common/fuzzy
+
+# real QA test starts here
+_supported_os Linux
+_supported_fs xfs
+_require_scratch_xfs_fuzz_fields
+
+echo "Format and populate"
+_scratch_populate_cached nofill > $seqres.full 2>&1
+
+echo "Fields we propose to fuzz: agi 0" >> $seqres.full
+_scratch_xfs_list_metadata_fields 'agi 0' >> $seqres.full
+
+echo "Fuzz AGI"
+_scratch_xfs_fuzz_fields 'agi 0' >> $seqres.full
+echo "Done fuzzing AGI"
+
+# success, all done
+status=0
+exit
diff --git a/tests/xfs/1304.out b/tests/xfs/1304.out
new file mode 100644
index 0000000..886157b
--- /dev/null
+++ b/tests/xfs/1304.out
@@ -0,0 +1,4 @@
+QA output created by 1304
+Format and populate
+Fuzz AGI
+Done fuzzing AGI
diff --git a/tests/xfs/1305 b/tests/xfs/1305
new file mode 100755
index 0000000..a4c7a68
--- /dev/null
+++ b/tests/xfs/1305
@@ -0,0 +1,62 @@
+#! /bin/bash
+# FS QA Test No. 1305
+#
+# Populate a XFS filesystem and fuzz every bnobt field.
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2016 Oracle, Inc.  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-1303  USA
+#-----------------------------------------------------------------------
+#
+
+seq=`basename $0`
+seqres=$RESULT_DIR/$seq
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=1	# failure is the default!
+trap "_cleanup; exit \$status" 0 1 2 3 7 15
+
+_cleanup()
+{
+	cd /
+	rm -rf $tmp.*
+}
+
+# get standard environment, filters and checks
+. ./common/rc
+. ./common/filter
+. ./common/populate
+. ./common/fuzzy
+
+# real QA test starts here
+_supported_os Linux
+_supported_fs xfs
+_require_scratch_xfs_fuzz_fields
+
+echo "Format and populate"
+_scratch_populate_cached nofill > $seqres.full 2>&1
+
+echo "Fields we propose to fuzz: agf 0 addr bnoroot addr ptrs[1]" >> $seqres.full
+_scratch_xfs_list_metadata_fields 'agf 0' 'addr bnoroot' 'addr ptrs[1]' >> $seqres.full
+
+echo "Fuzz bnobt recs"
+_scratch_xfs_fuzz_fields  'agf 0' 'addr bnoroot' 'addr ptrs[1]' >> $seqres.full
+echo "Done fuzzing bnobt recs"
+
+# success, all done
+status=0
+exit
diff --git a/tests/xfs/1305.out b/tests/xfs/1305.out
new file mode 100644
index 0000000..b2108f1
--- /dev/null
+++ b/tests/xfs/1305.out
@@ -0,0 +1,4 @@
+QA output created by 1305
+Format and populate
+Fuzz bnobt recs
+Done fuzzing bnobt recs
diff --git a/tests/xfs/1306 b/tests/xfs/1306
new file mode 100755
index 0000000..cb8f5e2
--- /dev/null
+++ b/tests/xfs/1306
@@ -0,0 +1,62 @@
+#! /bin/bash
+# FS QA Test No. 1306
+#
+# Populate a XFS filesystem and fuzz every bnobt key/pointer.
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2016 Oracle, Inc.  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-1303  USA
+#-----------------------------------------------------------------------
+#
+
+seq=`basename $0`
+seqres=$RESULT_DIR/$seq
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=1	# failure is the default!
+trap "_cleanup; exit \$status" 0 1 2 3 7 15
+
+_cleanup()
+{
+	cd /
+	rm -rf $tmp.*
+}
+
+# get standard environment, filters and checks
+. ./common/rc
+. ./common/filter
+. ./common/populate
+. ./common/fuzzy
+
+# real QA test starts here
+_supported_os Linux
+_supported_fs xfs
+_require_scratch_xfs_fuzz_fields
+
+echo "Format and populate"
+_scratch_populate_cached nofill > $seqres.full 2>&1
+
+echo "Fields we propose to fuzz: agf 0 addr bnoroot" >> $seqres.full
+_scratch_xfs_list_metadata_fields 'agf 0' 'addr bnoroot' >> $seqres.full
+
+echo "Fuzz bnobt keyptr"
+_scratch_xfs_fuzz_fields  'agf 0' 'addr bnoroot' >> $seqres.full
+echo "Done fuzzing bnobt keyptr"
+
+# success, all done
+status=0
+exit
diff --git a/tests/xfs/1306.out b/tests/xfs/1306.out
new file mode 100644
index 0000000..4b1e0c6
--- /dev/null
+++ b/tests/xfs/1306.out
@@ -0,0 +1,4 @@
+QA output created by 1306
+Format and populate
+Fuzz bnobt keyptr
+Done fuzzing bnobt keyptr
diff --git a/tests/xfs/1307 b/tests/xfs/1307
new file mode 100755
index 0000000..b25c338
--- /dev/null
+++ b/tests/xfs/1307
@@ -0,0 +1,62 @@
+#! /bin/bash
+# FS QA Test No. 1307
+#
+# Populate a XFS filesystem and fuzz every cntbt field.
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2016 Oracle, Inc.  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-1303  USA
+#-----------------------------------------------------------------------
+#
+
+seq=`basename $0`
+seqres=$RESULT_DIR/$seq
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=1	# failure is the default!
+trap "_cleanup; exit \$status" 0 1 2 3 7 15
+
+_cleanup()
+{
+	cd /
+	rm -rf $tmp.*
+}
+
+# get standard environment, filters and checks
+. ./common/rc
+. ./common/filter
+. ./common/populate
+. ./common/fuzzy
+
+# real QA test starts here
+_supported_os Linux
+_supported_fs xfs
+_require_scratch_xfs_fuzz_fields
+
+echo "Format and populate"
+_scratch_populate_cached nofill > $seqres.full 2>&1
+
+echo "Fields we propose to fuzz: agf 0 addr cntroot addr ptrs[1]" >> $seqres.full
+_scratch_xfs_list_metadata_fields 'agf 0' 'addr cntroot' 'addr ptrs[1]' >> $seqres.full
+
+echo "Fuzz cntbt"
+_scratch_xfs_fuzz_fields  'agf 0' 'addr cntroot' 'addr ptrs[1]' >> $seqres.full
+echo "Done fuzzing cntbt"
+
+# success, all done
+status=0
+exit
diff --git a/tests/xfs/1307.out b/tests/xfs/1307.out
new file mode 100644
index 0000000..a7cedf1
--- /dev/null
+++ b/tests/xfs/1307.out
@@ -0,0 +1,4 @@
+QA output created by 1307
+Format and populate
+Fuzz cntbt
+Done fuzzing cntbt
diff --git a/tests/xfs/1308 b/tests/xfs/1308
new file mode 100755
index 0000000..5fae1d1
--- /dev/null
+++ b/tests/xfs/1308
@@ -0,0 +1,62 @@
+#! /bin/bash
+# FS QA Test No. 1308
+#
+# Populate a XFS filesystem and fuzz every inobt field.
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2016 Oracle, Inc.  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-1303  USA
+#-----------------------------------------------------------------------
+#
+
+seq=`basename $0`
+seqres=$RESULT_DIR/$seq
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=1	# failure is the default!
+trap "_cleanup; exit \$status" 0 1 2 3 7 15
+
+_cleanup()
+{
+	cd /
+	rm -rf $tmp.*
+}
+
+# get standard environment, filters and checks
+. ./common/rc
+. ./common/filter
+. ./common/populate
+. ./common/fuzzy
+
+# real QA test starts here
+_supported_os Linux
+_supported_fs xfs
+_require_scratch_xfs_fuzz_fields
+
+echo "Format and populate"
+_scratch_populate_cached nofill > $seqres.full 2>&1
+
+echo "Fields we propose to fuzz: agi 0 addr root" >> $seqres.full
+_scratch_xfs_list_metadata_fields 'agi 0' 'addr root' >> $seqres.full
+
+echo "Fuzz inobt"
+_scratch_xfs_fuzz_fields  'agi 0' 'addr root' >> $seqres.full
+echo "Done fuzzing inobt"
+
+# success, all done
+status=0
+exit
diff --git a/tests/xfs/1308.out b/tests/xfs/1308.out
new file mode 100644
index 0000000..cc72bb7
--- /dev/null
+++ b/tests/xfs/1308.out
@@ -0,0 +1,4 @@
+QA output created by 1308
+Format and populate
+Fuzz inobt
+Done fuzzing inobt
diff --git a/tests/xfs/1309 b/tests/xfs/1309
new file mode 100755
index 0000000..5aa7992
--- /dev/null
+++ b/tests/xfs/1309
@@ -0,0 +1,63 @@
+#! /bin/bash
+# FS QA Test No. 1309
+#
+# Populate a XFS filesystem and fuzz every finobt field.
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2016 Oracle, Inc.  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-1303  USA
+#-----------------------------------------------------------------------
+#
+
+seq=`basename $0`
+seqres=$RESULT_DIR/$seq
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=1	# failure is the default!
+trap "_cleanup; exit \$status" 0 1 2 3 7 15
+
+_cleanup()
+{
+	cd /
+	rm -rf $tmp.*
+}
+
+# get standard environment, filters and checks
+. ./common/rc
+. ./common/filter
+. ./common/populate
+. ./common/fuzzy
+
+# real QA test starts here
+_supported_os Linux
+_supported_fs xfs
+_require_scratch_finobt
+_require_scratch_xfs_fuzz_fields
+
+echo "Format and populate"
+_scratch_populate_cached nofill > $seqres.full 2>&1
+
+echo "Fields we propose to fuzz: agi 0 addr free_root" >> $seqres.full
+_scratch_xfs_list_metadata_fields 'agi 0' 'addr free_root' >> $seqres.full
+
+echo "Fuzz finobt"
+_scratch_xfs_fuzz_fields  'agi 0' 'addr free_root' >> $seqres.full
+echo "Done fuzzing finobt"
+
+# success, all done
+status=0
+exit
diff --git a/tests/xfs/1309.out b/tests/xfs/1309.out
new file mode 100644
index 0000000..b4084ef
--- /dev/null
+++ b/tests/xfs/1309.out
@@ -0,0 +1,4 @@
+QA output created by 1309
+Format and populate
+Fuzz finobt
+Done fuzzing finobt
diff --git a/tests/xfs/1310 b/tests/xfs/1310
new file mode 100755
index 0000000..2756778
--- /dev/null
+++ b/tests/xfs/1310
@@ -0,0 +1,63 @@
+#! /bin/bash
+# FS QA Test No. 1310
+#
+# Populate a XFS filesystem and fuzz every rmapbt field.
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2016 Oracle, Inc.  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-1303  USA
+#-----------------------------------------------------------------------
+#
+
+seq=`basename $0`
+seqres=$RESULT_DIR/$seq
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=1	# failure is the default!
+trap "_cleanup; exit \$status" 0 1 2 3 7 15
+
+_cleanup()
+{
+	cd /
+	rm -rf $tmp.*
+}
+
+# get standard environment, filters and checks
+. ./common/rc
+. ./common/filter
+. ./common/populate
+. ./common/fuzzy
+
+# real QA test starts here
+_supported_os Linux
+_supported_fs xfs
+_require_xfs_scratch_rmapbt
+_require_scratch_xfs_fuzz_fields
+
+echo "Format and populate"
+_scratch_populate_cached nofill > $seqres.full 2>&1
+
+echo "Fields we propose to fuzz: agf 0 addr rmaproot addr ptrs[1]" >> $seqres.full
+_scratch_xfs_list_metadata_fields 'agf 0' 'addr rmaproot' 'addr ptrs[1]' >> $seqres.full
+
+echo "Fuzz rmapbt recs"
+_scratch_xfs_fuzz_fields  'agf 0' 'addr rmaproot' 'addr ptrs[1]' >> $seqres.full
+echo "Done fuzzing rmapbt recs"
+
+# success, all done
+status=0
+exit
diff --git a/tests/xfs/1310.out b/tests/xfs/1310.out
new file mode 100644
index 0000000..e784f8b
--- /dev/null
+++ b/tests/xfs/1310.out
@@ -0,0 +1,4 @@
+QA output created by 1310
+Format and populate
+Fuzz rmapbt recs
+Done fuzzing rmapbt recs
diff --git a/tests/xfs/1311 b/tests/xfs/1311
new file mode 100755
index 0000000..be9fe54
--- /dev/null
+++ b/tests/xfs/1311
@@ -0,0 +1,63 @@
+#! /bin/bash
+# FS QA Test No. 1311
+#
+# Populate a XFS filesystem and fuzz every rmapbt key/pointer field.
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2016 Oracle, Inc.  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-1303  USA
+#-----------------------------------------------------------------------
+#
+
+seq=`basename $0`
+seqres=$RESULT_DIR/$seq
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=1	# failure is the default!
+trap "_cleanup; exit \$status" 0 1 2 3 7 15
+
+_cleanup()
+{
+	cd /
+	rm -rf $tmp.*
+}
+
+# get standard environment, filters and checks
+. ./common/rc
+. ./common/filter
+. ./common/populate
+. ./common/fuzzy
+
+# real QA test starts here
+_supported_os Linux
+_supported_fs xfs
+_require_xfs_scratch_rmapbt
+_require_scratch_xfs_fuzz_fields
+
+echo "Format and populate"
+_scratch_populate_cached nofill > $seqres.full 2>&1
+
+echo "Fields we propose to fuzz: agf 0 addr rmaproot" >> $seqres.full
+_scratch_xfs_list_metadata_fields 'agf 0' 'addr rmaproot' >> $seqres.full
+
+echo "Fuzz rmapbt keyptr"
+_scratch_xfs_fuzz_fields  'agf 0' 'addr rmaproot' >> $seqres.full
+echo "Done fuzzing rmapbt keyptr"
+
+# success, all done
+status=0
+exit
diff --git a/tests/xfs/1311.out b/tests/xfs/1311.out
new file mode 100644
index 0000000..70150a1
--- /dev/null
+++ b/tests/xfs/1311.out
@@ -0,0 +1,4 @@
+QA output created by 1311
+Format and populate
+Fuzz rmapbt keyptr
+Done fuzzing rmapbt keyptr
diff --git a/tests/xfs/1312 b/tests/xfs/1312
new file mode 100755
index 0000000..73ec478
--- /dev/null
+++ b/tests/xfs/1312
@@ -0,0 +1,64 @@
+#! /bin/bash
+# FS QA Test No. 1312
+#
+# Populate a XFS filesystem and fuzz every refcountbt field.
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2016 Oracle, Inc.  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-1303  USA
+#-----------------------------------------------------------------------
+#
+
+seq=`basename $0`
+seqres=$RESULT_DIR/$seq
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=1	# failure is the default!
+trap "_cleanup; exit \$status" 0 1 2 3 7 15
+
+_cleanup()
+{
+	cd /
+	rm -rf $tmp.*
+}
+
+# get standard environment, filters and checks
+. ./common/rc
+. ./common/filter
+. ./common/populate
+. ./common/fuzzy
+. ./common/reflink
+
+# real QA test starts here
+_supported_os Linux
+_supported_fs xfs
+_require_scratch_reflink
+_require_scratch_xfs_fuzz_fields
+
+echo "Format and populate"
+_scratch_populate_cached nofill > $seqres.full 2>&1
+
+echo "Fields we propose to fuzz: agf 0 addr refcntroot" >> $seqres.full
+_scratch_xfs_list_metadata_fields 'agf 0' 'addr refcntroot' >> $seqres.full
+
+echo "Fuzz refcountbt"
+_scratch_xfs_fuzz_fields  'agf 0' 'addr refcntroot' >> $seqres.full
+echo "Done fuzzing refcountbt"
+
+# success, all done
+status=0
+exit
diff --git a/tests/xfs/1312.out b/tests/xfs/1312.out
new file mode 100644
index 0000000..ca40b46
--- /dev/null
+++ b/tests/xfs/1312.out
@@ -0,0 +1,4 @@
+QA output created by 1312
+Format and populate
+Fuzz refcountbt
+Done fuzzing refcountbt
diff --git a/tests/xfs/1313 b/tests/xfs/1313
new file mode 100755
index 0000000..13da0b3
--- /dev/null
+++ b/tests/xfs/1313
@@ -0,0 +1,67 @@
+#! /bin/bash
+# FS QA Test No. 1313
+#
+# Populate a XFS filesystem and fuzz every btree-format directory inode field.
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2016 Oracle, Inc.  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-1303  USA
+#-----------------------------------------------------------------------
+#
+
+seq=`basename $0`
+seqres=$RESULT_DIR/$seq
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=1	# failure is the default!
+trap "_cleanup; exit \$status" 0 1 2 3 7 15
+
+_cleanup()
+{
+	cd /
+	rm -rf $tmp.*
+}
+
+# get standard environment, filters and checks
+. ./common/rc
+. ./common/filter
+. ./common/populate
+. ./common/fuzzy
+
+# real QA test starts here
+_supported_os Linux
+_supported_fs xfs
+_require_scratch_xfs_fuzz_fields
+
+echo "Format and populate"
+_scratch_populate_cached nofill > $seqres.full 2>&1
+
+echo "Find btree-format dir inode"
+_scratch_mount
+inum=$(stat -c '%i' $SCRATCH_MNT/S_IFDIR.FMT_BTREE)
+_scratch_unmount
+
+echo "Fields we propose to fuzz: inode ${inum}" >> $seqres.full
+_scratch_xfs_list_metadata_fields "inode ${inum}" >> $seqres.full
+
+echo "Fuzz inode"
+_scratch_xfs_fuzz_fields  "inode ${inum}" >> $seqres.full
+echo "Done fuzzing inode"
+
+# success, all done
+status=0
+exit
diff --git a/tests/xfs/1313.out b/tests/xfs/1313.out
new file mode 100644
index 0000000..b087a06
--- /dev/null
+++ b/tests/xfs/1313.out
@@ -0,0 +1,5 @@
+QA output created by 1313
+Format and populate
+Find btree-format dir inode
+Fuzz inode
+Done fuzzing inode
diff --git a/tests/xfs/1314 b/tests/xfs/1314
new file mode 100755
index 0000000..a9a552c
--- /dev/null
+++ b/tests/xfs/1314
@@ -0,0 +1,67 @@
+#! /bin/bash
+# FS QA Test No. 1314
+#
+# Populate a XFS filesystem and fuzz every extents-format file inode field.
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2016 Oracle, Inc.  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-1303  USA
+#-----------------------------------------------------------------------
+#
+
+seq=`basename $0`
+seqres=$RESULT_DIR/$seq
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=1	# failure is the default!
+trap "_cleanup; exit \$status" 0 1 2 3 7 15
+
+_cleanup()
+{
+	cd /
+	rm -rf $tmp.*
+}
+
+# get standard environment, filters and checks
+. ./common/rc
+. ./common/filter
+. ./common/populate
+. ./common/fuzzy
+
+# real QA test starts here
+_supported_os Linux
+_supported_fs xfs
+_require_scratch_xfs_fuzz_fields
+
+echo "Format and populate"
+_scratch_populate_cached nofill > $seqres.full 2>&1
+
+echo "Find extents-format file inode"
+_scratch_mount
+inum=$(stat -c '%i' $SCRATCH_MNT/S_IFREG.FMT_EXTENTS)
+_scratch_unmount
+
+echo "Fields we propose to fuzz: inode ${inum}" >> $seqres.full
+_scratch_xfs_list_metadata_fields "inode ${inum}" >> $seqres.full
+
+echo "Fuzz inode"
+_scratch_xfs_fuzz_fields  "inode ${inum}" >> $seqres.full
+echo "Done fuzzing inode"
+
+# success, all done
+status=0
+exit
diff --git a/tests/xfs/1314.out b/tests/xfs/1314.out
new file mode 100644
index 0000000..c5c1a3a
--- /dev/null
+++ b/tests/xfs/1314.out
@@ -0,0 +1,5 @@
+QA output created by 1314
+Format and populate
+Find extents-format file inode
+Fuzz inode
+Done fuzzing inode
diff --git a/tests/xfs/1315 b/tests/xfs/1315
new file mode 100755
index 0000000..1df5b5a
--- /dev/null
+++ b/tests/xfs/1315
@@ -0,0 +1,67 @@
+#! /bin/bash
+# FS QA Test No. 1315
+#
+# Populate a XFS filesystem and fuzz every btree-format file inode field.
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2016 Oracle, Inc.  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-1303  USA
+#-----------------------------------------------------------------------
+#
+
+seq=`basename $0`
+seqres=$RESULT_DIR/$seq
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=1	# failure is the default!
+trap "_cleanup; exit \$status" 0 1 2 3 7 15
+
+_cleanup()
+{
+	cd /
+	rm -rf $tmp.*
+}
+
+# get standard environment, filters and checks
+. ./common/rc
+. ./common/filter
+. ./common/populate
+. ./common/fuzzy
+
+# real QA test starts here
+_supported_os Linux
+_supported_fs xfs
+_require_scratch_xfs_fuzz_fields
+
+echo "Format and populate"
+_scratch_populate_cached nofill > $seqres.full 2>&1
+
+echo "Find btree-format file inode"
+_scratch_mount
+inum=$(stat -c '%i' $SCRATCH_MNT/S_IFREG.FMT_BTREE)
+_scratch_unmount
+
+echo "Fields we propose to fuzz: inode ${inum}" >> $seqres.full
+_scratch_xfs_list_metadata_fields "inode ${inum}" >> $seqres.full
+
+echo "Fuzz inode"
+_scratch_xfs_fuzz_fields  "inode ${inum}" >> $seqres.full
+echo "Done fuzzing inode"
+
+# success, all done
+status=0
+exit
diff --git a/tests/xfs/1315.out b/tests/xfs/1315.out
new file mode 100644
index 0000000..421b645
--- /dev/null
+++ b/tests/xfs/1315.out
@@ -0,0 +1,5 @@
+QA output created by 1315
+Format and populate
+Find btree-format file inode
+Fuzz inode
+Done fuzzing inode
diff --git a/tests/xfs/1316 b/tests/xfs/1316
new file mode 100755
index 0000000..564639b
--- /dev/null
+++ b/tests/xfs/1316
@@ -0,0 +1,69 @@
+#! /bin/bash
+# FS QA Test No. 1316
+#
+# Populate a XFS filesystem and fuzz every bmbt block field.
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2016 Oracle, Inc.  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-1303  USA
+#-----------------------------------------------------------------------
+#
+
+seq=`basename $0`
+seqres=$RESULT_DIR/$seq
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=1	# failure is the default!
+trap "_cleanup; exit \$status" 0 1 2 3 7 15
+
+_cleanup()
+{
+	cd /
+	rm -rf $tmp.*
+}
+
+# get standard environment, filters and checks
+. ./common/rc
+. ./common/filter
+. ./common/populate
+. ./common/fuzzy
+
+# real QA test starts here
+_supported_os Linux
+_supported_fs xfs
+_require_scratch_xfs_fuzz_fields
+
+echo "Format and populate"
+_scratch_populate_cached nofill > $seqres.full 2>&1
+
+echo "Find bmbt block"
+_scratch_mount
+inum=$(stat -c '%i' $SCRATCH_MNT/S_IFREG.FMT_BTREE)
+_scratch_unmount
+
+inode_ver=$(_scratch_xfs_get_metadata_field "core.version" "inode ${inum}")
+
+echo "Fields we propose to fuzz: inode ${inum} addr u${inode_ver}.bmbt.ptrs[1]" >> $seqres.full
+_scratch_xfs_list_metadata_fields "inode ${inum}" "addr u${inode_ver}.bmbt.ptrs[1]" >> $seqres.full
+
+echo "Fuzz bmbt"
+_scratch_xfs_fuzz_fields  "inode ${inum}" "addr u${inode_ver}.bmbt.ptrs[1]" >> $seqres.full
+echo "Done fuzzing bmbt"
+
+# success, all done
+status=0
+exit
diff --git a/tests/xfs/1316.out b/tests/xfs/1316.out
new file mode 100644
index 0000000..1ae75f6
--- /dev/null
+++ b/tests/xfs/1316.out
@@ -0,0 +1,5 @@
+QA output created by 1316
+Format and populate
+Find bmbt block
+Fuzz bmbt
+Done fuzzing bmbt
diff --git a/tests/xfs/1317 b/tests/xfs/1317
new file mode 100755
index 0000000..b8205e9
--- /dev/null
+++ b/tests/xfs/1317
@@ -0,0 +1,67 @@
+#! /bin/bash
+# FS QA Test No. 1317
+#
+# Populate a XFS filesystem and fuzz every symlink remote block field.
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2016 Oracle, Inc.  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-1303  USA
+#-----------------------------------------------------------------------
+#
+
+seq=`basename $0`
+seqres=$RESULT_DIR/$seq
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=1	# failure is the default!
+trap "_cleanup; exit \$status" 0 1 2 3 7 15
+
+_cleanup()
+{
+	cd /
+	rm -rf $tmp.*
+}
+
+# get standard environment, filters and checks
+. ./common/rc
+. ./common/filter
+. ./common/populate
+. ./common/fuzzy
+
+# real QA test starts here
+_supported_os Linux
+_supported_fs xfs
+_require_scratch_xfs_fuzz_fields
+
+echo "Format and populate"
+_scratch_populate_cached nofill > $seqres.full 2>&1
+
+echo "Find symlink remote block"
+_scratch_mount
+inum=$(stat -c '%i' $SCRATCH_MNT/S_IFLNK.FMT_EXTENTS)
+_scratch_unmount
+
+echo "Fields we propose to fuzz: inode ${inum} dblock 0" >> $seqres.full
+_scratch_xfs_list_metadata_fields "inode ${inum}" 'dblock 0' >> $seqres.full
+
+echo "Fuzz symlink remote block"
+_scratch_xfs_fuzz_fields "inode ${inum}" 'dblock 0' >> $seqres.full
+echo "Done fuzzing symlink remote block"
+
+# success, all done
+status=0
+exit
diff --git a/tests/xfs/1317.out b/tests/xfs/1317.out
new file mode 100644
index 0000000..92affb2
--- /dev/null
+++ b/tests/xfs/1317.out
@@ -0,0 +1,5 @@
+QA output created by 1317
+Format and populate
+Find symlink remote block
+Fuzz symlink remote block
+Done fuzzing symlink remote block
diff --git a/tests/xfs/1318 b/tests/xfs/1318
new file mode 100755
index 0000000..b46f333
--- /dev/null
+++ b/tests/xfs/1318
@@ -0,0 +1,67 @@
+#! /bin/bash
+# FS QA Test No. 1318
+#
+# Populate a XFS filesystem and fuzz every inline directory inode field.
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2016 Oracle, Inc.  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-1303  USA
+#-----------------------------------------------------------------------
+#
+
+seq=`basename $0`
+seqres=$RESULT_DIR/$seq
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=1	# failure is the default!
+trap "_cleanup; exit \$status" 0 1 2 3 7 15
+
+_cleanup()
+{
+	cd /
+	rm -rf $tmp.*
+}
+
+# get standard environment, filters and checks
+. ./common/rc
+. ./common/filter
+. ./common/populate
+. ./common/fuzzy
+
+# real QA test starts here
+_supported_os Linux
+_supported_fs xfs
+_require_scratch_xfs_fuzz_fields
+
+echo "Format and populate"
+_scratch_populate_cached nofill > $seqres.full 2>&1
+
+echo "Find inline-format dir inode"
+_scratch_mount
+inum=$(stat -c '%i' $SCRATCH_MNT/S_IFDIR.FMT_INLINE)
+_scratch_unmount
+
+echo "Fields we propose to fuzz: inode ${inum}" >> $seqres.full
+_scratch_xfs_list_metadata_fields "inode ${inum}" >> $seqres.full
+
+echo "Fuzz inline-format dir inode"
+_scratch_xfs_fuzz_fields  "inode ${inum}" >> $seqres.full
+echo "Done fuzzing inline-format dir inode"
+
+# success, all done
+status=0
+exit
diff --git a/tests/xfs/1318.out b/tests/xfs/1318.out
new file mode 100644
index 0000000..c12e336
--- /dev/null
+++ b/tests/xfs/1318.out
@@ -0,0 +1,5 @@
+QA output created by 1318
+Format and populate
+Find inline-format dir inode
+Fuzz inline-format dir inode
+Done fuzzing inline-format dir inode
diff --git a/tests/xfs/1319 b/tests/xfs/1319
new file mode 100755
index 0000000..a891248
--- /dev/null
+++ b/tests/xfs/1319
@@ -0,0 +1,67 @@
+#! /bin/bash
+# FS QA Test No. 1319
+#
+# Populate a XFS filesystem and fuzz every block-format dir block field.
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2016 Oracle, Inc.  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-1303  USA
+#-----------------------------------------------------------------------
+#
+
+seq=`basename $0`
+seqres=$RESULT_DIR/$seq
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=1	# failure is the default!
+trap "_cleanup; exit \$status" 0 1 2 3 7 15
+
+_cleanup()
+{
+	cd /
+	rm -rf $tmp.*
+}
+
+# get standard environment, filters and checks
+. ./common/rc
+. ./common/filter
+. ./common/populate
+. ./common/fuzzy
+
+# real QA test starts here
+_supported_os Linux
+_supported_fs xfs
+_require_scratch_xfs_fuzz_fields
+
+echo "Format and populate"
+_scratch_populate_cached nofill > $seqres.full 2>&1
+
+echo "Find data-format dir block"
+_scratch_mount
+inum=$(stat -c '%i' $SCRATCH_MNT/S_IFDIR.FMT_BLOCK)
+_scratch_unmount
+
+echo "Fields we propose to fuzz: inode ${inum} dblock 0" >> $seqres.full
+_scratch_xfs_list_metadata_fields "inode ${inum}" 'dblock 0' >> $seqres.full
+
+echo "Fuzz data-format dir block"
+_scratch_xfs_fuzz_fields  "inode ${inum}" 'dblock 0' >> $seqres.full
+echo "Done fuzzing data-format dir block"
+
+# success, all done
+status=0
+exit
diff --git a/tests/xfs/1319.out b/tests/xfs/1319.out
new file mode 100644
index 0000000..72ab82a
--- /dev/null
+++ b/tests/xfs/1319.out
@@ -0,0 +1,5 @@
+QA output created by 1319
+Format and populate
+Find data-format dir block
+Fuzz data-format dir block
+Done fuzzing data-format dir block
diff --git a/tests/xfs/1320 b/tests/xfs/1320
new file mode 100755
index 0000000..d2321f8
--- /dev/null
+++ b/tests/xfs/1320
@@ -0,0 +1,68 @@
+#! /bin/bash
+# FS QA Test No. 1320
+#
+# Populate a XFS filesystem and fuzz every data-format dir block field.
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2016 Oracle, Inc.  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-1303  USA
+#-----------------------------------------------------------------------
+#
+
+seq=`basename $0`
+seqres=$RESULT_DIR/$seq
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=1	# failure is the default!
+trap "_cleanup; exit \$status" 0 1 2 3 7 15
+
+_cleanup()
+{
+	cd /
+	rm -rf $tmp.*
+}
+
+# get standard environment, filters and checks
+. ./common/rc
+. ./common/filter
+. ./common/populate
+. ./common/fuzzy
+
+# real QA test starts here
+_supported_os Linux
+_supported_fs xfs
+_require_scratch_xfs_fuzz_fields
+
+echo "Format and populate"
+_scratch_populate_cached nofill > $seqres.full 2>&1
+
+echo "Find data-format dir block"
+_scratch_mount
+inum=$(stat -c '%i' $SCRATCH_MNT/S_IFDIR.FMT_LEAF)
+blk_sz=$(get_block_size $SCRATCH_MNT)
+_scratch_unmount
+
+echo "Fields we propose to fuzz: inode ${inum} dblock 0" >> $seqres.full
+_scratch_xfs_list_metadata_fields "inode ${inum}" "dblock 0" >> $seqres.full
+
+echo "Fuzz data-format dir block"
+_scratch_xfs_fuzz_fields  "inode ${inum}" "dblock 0" >> $seqres.full
+echo "Done fuzzing data-format dir block"
+
+# success, all done
+status=0
+exit
diff --git a/tests/xfs/1320.out b/tests/xfs/1320.out
new file mode 100644
index 0000000..409a25b
--- /dev/null
+++ b/tests/xfs/1320.out
@@ -0,0 +1,5 @@
+QA output created by 1320
+Format and populate
+Find data-format dir block
+Fuzz data-format dir block
+Done fuzzing data-format dir block
diff --git a/tests/xfs/1321 b/tests/xfs/1321
new file mode 100755
index 0000000..ca5474b
--- /dev/null
+++ b/tests/xfs/1321
@@ -0,0 +1,69 @@
+#! /bin/bash
+# FS QA Test No. 1321
+#
+# Populate a XFS filesystem and fuzz every leaf1-format dir block field.
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2016 Oracle, Inc.  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-1303  USA
+#-----------------------------------------------------------------------
+#
+
+seq=`basename $0`
+seqres=$RESULT_DIR/$seq
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=1	# failure is the default!
+trap "_cleanup; exit \$status" 0 1 2 3 7 15
+
+_cleanup()
+{
+	cd /
+	rm -rf $tmp.*
+}
+
+# get standard environment, filters and checks
+. ./common/rc
+. ./common/filter
+. ./common/populate
+. ./common/fuzzy
+
+# real QA test starts here
+_supported_os Linux
+_supported_fs xfs
+_require_scratch_xfs_fuzz_fields
+
+echo "Format and populate"
+_scratch_populate_cached nofill > $seqres.full 2>&1
+
+echo "Find leaf1-format dir block"
+_scratch_mount
+inum=$(stat -c '%i' $SCRATCH_MNT/S_IFDIR.FMT_LEAF)
+blk_sz=$(get_block_size $SCRATCH_MNT)
+_scratch_unmount
+
+leaf_offset=$(( (2 ** 35) / blk_sz))
+echo "Fields we propose to fuzz: inode ${inum} dblock ${leaf_offset}" >> $seqres.full
+_scratch_xfs_list_metadata_fields "inode ${inum}" "dblock ${leaf_offset}" >> $seqres.full
+
+echo "Fuzz leaf1-format dir block"
+_scratch_xfs_fuzz_fields  "inode ${inum}" "dblock ${leaf_offset}" >> $seqres.full
+echo "Done fuzzing leaf1-format dir block"
+
+# success, all done
+status=0
+exit
diff --git a/tests/xfs/1321.out b/tests/xfs/1321.out
new file mode 100644
index 0000000..ef3fa37
--- /dev/null
+++ b/tests/xfs/1321.out
@@ -0,0 +1,5 @@
+QA output created by 1321
+Format and populate
+Find leaf1-format dir block
+Fuzz leaf1-format dir block
+Done fuzzing leaf1-format dir block
diff --git a/tests/xfs/1322 b/tests/xfs/1322
new file mode 100755
index 0000000..dff6e67
--- /dev/null
+++ b/tests/xfs/1322
@@ -0,0 +1,69 @@
+#! /bin/bash
+# FS QA Test No. 1322
+#
+# Populate a XFS filesystem and fuzz every leafn-format dir block field.
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2016 Oracle, Inc.  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-1303  USA
+#-----------------------------------------------------------------------
+#
+
+seq=`basename $0`
+seqres=$RESULT_DIR/$seq
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=1	# failure is the default!
+trap "_cleanup; exit \$status" 0 1 2 3 7 15
+
+_cleanup()
+{
+	cd /
+	rm -rf $tmp.*
+}
+
+# get standard environment, filters and checks
+. ./common/rc
+. ./common/filter
+. ./common/populate
+. ./common/fuzzy
+
+# real QA test starts here
+_supported_os Linux
+_supported_fs xfs
+_require_scratch_xfs_fuzz_fields
+
+echo "Format and populate"
+_scratch_populate_cached nofill > $seqres.full 2>&1
+
+echo "Find leafn-format dir block"
+_scratch_mount
+inum=$(stat -c '%i' $SCRATCH_MNT/S_IFDIR.FMT_NODE)
+blk_sz=$(get_block_size $SCRATCH_MNT)
+_scratch_unmount
+
+leaf_offset=$(( ( (2 ** 35) / blk_sz) + 1))
+echo "Fields we propose to fuzz: inode ${inum} dblock ${leaf_offset}" >> $seqres.full
+_scratch_xfs_list_metadata_fields "inode ${inum}" "dblock ${leaf_offset}" >> $seqres.full
+
+echo "Fuzz leafn-format dir block"
+_scratch_xfs_fuzz_fields  "inode ${inum}" "dblock ${leaf_offset}" >> $seqres.full
+echo "Done fuzzing leafn-format dir block"
+
+# success, all done
+status=0
+exit
diff --git a/tests/xfs/1322.out b/tests/xfs/1322.out
new file mode 100644
index 0000000..d1e0c7d
--- /dev/null
+++ b/tests/xfs/1322.out
@@ -0,0 +1,5 @@
+QA output created by 1322
+Format and populate
+Find leafn-format dir block
+Fuzz leafn-format dir block
+Done fuzzing leafn-format dir block
diff --git a/tests/xfs/1323 b/tests/xfs/1323
new file mode 100755
index 0000000..51a1b0e
--- /dev/null
+++ b/tests/xfs/1323
@@ -0,0 +1,69 @@
+#! /bin/bash
+# FS QA Test No. 1323
+#
+# Populate a XFS filesystem and fuzz every node-format dir block field.
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2016 Oracle, Inc.  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-1303  USA
+#-----------------------------------------------------------------------
+#
+
+seq=`basename $0`
+seqres=$RESULT_DIR/$seq
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=1	# failure is the default!
+trap "_cleanup; exit \$status" 0 1 2 3 7 15
+
+_cleanup()
+{
+	cd /
+	rm -rf $tmp.*
+}
+
+# get standard environment, filters and checks
+. ./common/rc
+. ./common/filter
+. ./common/populate
+. ./common/fuzzy
+
+# real QA test starts here
+_supported_os Linux
+_supported_fs xfs
+_require_scratch_xfs_fuzz_fields
+
+echo "Format and populate"
+_scratch_populate_cached nofill > $seqres.full 2>&1
+
+echo "Find node-format dir block"
+_scratch_mount
+inum=$(stat -c '%i' $SCRATCH_MNT/S_IFDIR.FMT_NODE)
+blk_sz=$(get_block_size $SCRATCH_MNT)
+_scratch_unmount
+
+leaf_offset=$(( (2 ** 35) / blk_sz ))
+echo "Fields we propose to fuzz: inode ${inum} dblock ${leaf_offset}" >> $seqres.full
+_scratch_xfs_list_metadata_fields "inode ${inum}" "dblock ${leaf_offset}" >> $seqres.full
+
+echo "Fuzz node-format dir block"
+_scratch_xfs_fuzz_fields  "inode ${inum}" "dblock ${leaf_offset}" >> $seqres.full
+echo "Done fuzzing node-format dir block"
+
+# success, all done
+status=0
+exit
diff --git a/tests/xfs/1323.out b/tests/xfs/1323.out
new file mode 100644
index 0000000..2debc5c
--- /dev/null
+++ b/tests/xfs/1323.out
@@ -0,0 +1,5 @@
+QA output created by 1323
+Format and populate
+Find node-format dir block
+Fuzz node-format dir block
+Done fuzzing node-format dir block
diff --git a/tests/xfs/1324 b/tests/xfs/1324
new file mode 100755
index 0000000..f968b6d
--- /dev/null
+++ b/tests/xfs/1324
@@ -0,0 +1,69 @@
+#! /bin/bash
+# FS QA Test No. 1324
+#
+# Populate a XFS filesystem and fuzz every freeindex-format dir block field.
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2016 Oracle, Inc.  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-1303  USA
+#-----------------------------------------------------------------------
+#
+
+seq=`basename $0`
+seqres=$RESULT_DIR/$seq
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=1	# failure is the default!
+trap "_cleanup; exit \$status" 0 1 2 3 7 15
+
+_cleanup()
+{
+	cd /
+	rm -rf $tmp.*
+}
+
+# get standard environment, filters and checks
+. ./common/rc
+. ./common/filter
+. ./common/populate
+. ./common/fuzzy
+
+# real QA test starts here
+_supported_os Linux
+_supported_fs xfs
+_require_scratch_xfs_fuzz_fields
+
+echo "Format and populate"
+_scratch_populate_cached nofill > $seqres.full 2>&1
+
+echo "Find freeindex-format dir block"
+_scratch_mount
+inum=$(stat -c '%i' $SCRATCH_MNT/S_IFDIR.FMT_NODE)
+blk_sz=$(get_block_size $SCRATCH_MNT)
+_scratch_unmount
+
+leaf_offset=$(( (2 ** 36) / blk_sz ))
+echo "Fields we propose to fuzz: inode ${inum} dblock ${leaf_offset}" >> $seqres.full
+_scratch_xfs_list_metadata_fields "inode ${inum}" "dblock ${leaf_offset}" >> $seqres.full
+
+echo "Fuzz freeindex-format dir block"
+_scratch_xfs_fuzz_fields  "inode ${inum}" "dblock ${leaf_offset}" >> $seqres.full
+echo "Done fuzzing freeindex-format dir block"
+
+# success, all done
+status=0
+exit
diff --git a/tests/xfs/1324.out b/tests/xfs/1324.out
new file mode 100644
index 0000000..1e373e0
--- /dev/null
+++ b/tests/xfs/1324.out
@@ -0,0 +1,5 @@
+QA output created by 1324
+Format and populate
+Find freeindex-format dir block
+Fuzz freeindex-format dir block
+Done fuzzing freeindex-format dir block
diff --git a/tests/xfs/1325 b/tests/xfs/1325
new file mode 100755
index 0000000..239f342
--- /dev/null
+++ b/tests/xfs/1325
@@ -0,0 +1,67 @@
+#! /bin/bash
+# FS QA Test No. 1325
+#
+# Populate a XFS filesystem and fuzz every inline attr inode field.
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2016 Oracle, Inc.  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-1303  USA
+#-----------------------------------------------------------------------
+#
+
+seq=`basename $0`
+seqres=$RESULT_DIR/$seq
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=1	# failure is the default!
+trap "_cleanup; exit \$status" 0 1 2 3 7 15
+
+_cleanup()
+{
+	cd /
+	rm -rf $tmp.*
+}
+
+# get standard environment, filters and checks
+. ./common/rc
+. ./common/filter
+. ./common/populate
+. ./common/fuzzy
+
+# real QA test starts here
+_supported_os Linux
+_supported_fs xfs
+_require_scratch_xfs_fuzz_fields
+
+echo "Format and populate"
+_scratch_populate_cached nofill > $seqres.full 2>&1
+
+echo "Find inline-format attr inode"
+_scratch_mount
+inum=$(stat -c '%i' $SCRATCH_MNT/ATTR.FMT_LOCAL)
+_scratch_unmount
+
+echo "Fields we propose to fuzz: inode ${inum}" >> $seqres.full
+_scratch_xfs_list_metadata_fields "inode ${inum}" >> $seqres.full
+
+echo "Fuzz inline-format attr inode"
+_scratch_xfs_fuzz_fields  "inode ${inum}" >> $seqres.full
+echo "Done fuzzing inline-format attr inode"
+
+# success, all done
+status=0
+exit
diff --git a/tests/xfs/1325.out b/tests/xfs/1325.out
new file mode 100644
index 0000000..5259fe8
--- /dev/null
+++ b/tests/xfs/1325.out
@@ -0,0 +1,5 @@
+QA output created by 1325
+Format and populate
+Find inline-format attr inode
+Fuzz inline-format attr inode
+Done fuzzing inline-format attr inode
diff --git a/tests/xfs/1326 b/tests/xfs/1326
new file mode 100755
index 0000000..aa6d683
--- /dev/null
+++ b/tests/xfs/1326
@@ -0,0 +1,67 @@
+#! /bin/bash
+# FS QA Test No. 1326
+#
+# Populate a XFS filesystem and fuzz every leaf-format attr block field.
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2016 Oracle, Inc.  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-1303  USA
+#-----------------------------------------------------------------------
+#
+
+seq=`basename $0`
+seqres=$RESULT_DIR/$seq
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=1	# failure is the default!
+trap "_cleanup; exit \$status" 0 1 2 3 7 15
+
+_cleanup()
+{
+	cd /
+	rm -rf $tmp.*
+}
+
+# get standard environment, filters and checks
+. ./common/rc
+. ./common/filter
+. ./common/populate
+. ./common/fuzzy
+
+# real QA test starts here
+_supported_os Linux
+_supported_fs xfs
+_require_scratch_xfs_fuzz_fields
+
+echo "Format and populate"
+_scratch_populate_cached nofill > $seqres.full 2>&1
+
+echo "Find leaf-format attr block"
+_scratch_mount
+inum=$(stat -c '%i' $SCRATCH_MNT/ATTR.FMT_LEAF)
+_scratch_unmount
+
+echo "Fields we propose to fuzz: inode ${inum} ablock 0" >> $seqres.full
+_scratch_xfs_list_metadata_fields "inode ${inum}" 'ablock 0' >> $seqres.full
+
+echo "Fuzz leaf-format attr block"
+_scratch_xfs_fuzz_fields  "inode ${inum}" 'ablock 0' >> $seqres.full
+echo "Done fuzzing leaf-format attr block"
+
+# success, all done
+status=0
+exit
diff --git a/tests/xfs/1326.out b/tests/xfs/1326.out
new file mode 100644
index 0000000..d10cdb7
--- /dev/null
+++ b/tests/xfs/1326.out
@@ -0,0 +1,5 @@
+QA output created by 1326
+Format and populate
+Find leaf-format attr block
+Fuzz leaf-format attr block
+Done fuzzing leaf-format attr block
diff --git a/tests/xfs/1327 b/tests/xfs/1327
new file mode 100755
index 0000000..923c405
--- /dev/null
+++ b/tests/xfs/1327
@@ -0,0 +1,67 @@
+#! /bin/bash
+# FS QA Test No. 1327
+#
+# Populate a XFS filesystem and fuzz every node-format attr block field.
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2016 Oracle, Inc.  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-1303  USA
+#-----------------------------------------------------------------------
+#
+
+seq=`basename $0`
+seqres=$RESULT_DIR/$seq
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=1	# failure is the default!
+trap "_cleanup; exit \$status" 0 1 2 3 7 15
+
+_cleanup()
+{
+	cd /
+	rm -rf $tmp.*
+}
+
+# get standard environment, filters and checks
+. ./common/rc
+. ./common/filter
+. ./common/populate
+. ./common/fuzzy
+
+# real QA test starts here
+_supported_os Linux
+_supported_fs xfs
+_require_scratch_xfs_fuzz_fields
+
+echo "Format and populate"
+_scratch_populate_cached nofill > $seqres.full 2>&1
+
+echo "Find node-format attr block"
+_scratch_mount
+inum=$(stat -c '%i' $SCRATCH_MNT/ATTR.FMT_NODE)
+_scratch_unmount
+
+echo "Fields we propose to fuzz: inode ${inum} ablock 0" >> $seqres.full
+_scratch_xfs_list_metadata_fields "inode ${inum}" "ablock 0" >> $seqres.full
+
+echo "Fuzz node-format attr block"
+_scratch_xfs_fuzz_fields  "inode ${inum}" "ablock 0" >> $seqres.full
+echo "Done fuzzing node-format attr block"
+
+# success, all done
+status=0
+exit
diff --git a/tests/xfs/1327.out b/tests/xfs/1327.out
new file mode 100644
index 0000000..b3a4f1d
--- /dev/null
+++ b/tests/xfs/1327.out
@@ -0,0 +1,5 @@
+QA output created by 1327
+Format and populate
+Find node-format attr block
+Fuzz node-format attr block
+Done fuzzing node-format attr block
diff --git a/tests/xfs/1328 b/tests/xfs/1328
new file mode 100755
index 0000000..a4aad22
--- /dev/null
+++ b/tests/xfs/1328
@@ -0,0 +1,67 @@
+#! /bin/bash
+# FS QA Test No. 1328
+#
+# Populate a XFS filesystem and fuzz every external attr block field.
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2016 Oracle, Inc.  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-1303  USA
+#-----------------------------------------------------------------------
+#
+
+seq=`basename $0`
+seqres=$RESULT_DIR/$seq
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=1	# failure is the default!
+trap "_cleanup; exit \$status" 0 1 2 3 7 15
+
+_cleanup()
+{
+	cd /
+	rm -rf $tmp.*
+}
+
+# get standard environment, filters and checks
+. ./common/rc
+. ./common/filter
+. ./common/populate
+. ./common/fuzzy
+
+# real QA test starts here
+_supported_os Linux
+_supported_fs xfs
+_require_scratch_xfs_fuzz_fields
+
+echo "Format and populate"
+_scratch_populate_cached nofill > $seqres.full 2>&1
+
+echo "Find external attr block"
+_scratch_mount
+inum=$(stat -c '%i' $SCRATCH_MNT/ATTR.FMT_EXTENTS_REMOTE3K)
+_scratch_unmount
+
+echo "Fields we propose to fuzz: inode ${inum} ablock 1" >> $seqres.full
+_scratch_xfs_list_metadata_fields "inode ${inum}" "ablock 1" >> $seqres.full
+
+echo "Fuzz external attr block"
+_scratch_xfs_fuzz_fields  "inode ${inum}" "ablock 1" >> $seqres.full
+echo "Done fuzzing external attr block"
+
+# success, all done
+status=0
+exit
diff --git a/tests/xfs/1328.out b/tests/xfs/1328.out
new file mode 100644
index 0000000..758f322
--- /dev/null
+++ b/tests/xfs/1328.out
@@ -0,0 +1,5 @@
+QA output created by 1328
+Format and populate
+Find external attr block
+Fuzz external attr block
+Done fuzzing external attr block
diff --git a/tests/xfs/1329 b/tests/xfs/1329
new file mode 100755
index 0000000..2e21aeb
--- /dev/null
+++ b/tests/xfs/1329
@@ -0,0 +1,63 @@
+#! /bin/bash
+# FS QA Test No. 1329
+#
+# Populate a XFS filesystem and fuzz every rtrmapbt record field.
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2016 Oracle, Inc.  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-1303  USA
+#-----------------------------------------------------------------------
+#
+
+seq=`basename $0`
+seqres=$RESULT_DIR/$seq
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=1	# failure is the default!
+trap "_cleanup; exit \$status" 0 1 2 3 7 15
+
+_cleanup()
+{
+	cd /
+	rm -rf $tmp.*
+}
+
+# get standard environment, filters and checks
+. ./common/rc
+. ./common/filter
+. ./common/populate
+. ./common/fuzzy
+
+# real QA test starts here
+_supported_os Linux
+_supported_fs xfs
+_require_realtime
+_require_xfs_scratch_rmapbt
+_require_scratch_xfs_fuzz_fields
+
+echo "Format and populate"
+_scratch_populate_cached nofill > $seqres.full 2>&1
+
+inode_ver=$(_scratch_xfs_get_metadata_field "core.version" 'sb 0' 'addr rrmapino')
+
+echo "Fuzz rtrmapbt recs"
+_scratch_xfs_fuzz_fields 'sb 0' 'addr rrmapino' "addr u${inode_ver}.rtrmapbt.ptrs[1]" >> $seqres.full
+echo "Done fuzzing rtrmapbt recs"
+
+# success, all done
+status=0
+exit
diff --git a/tests/xfs/1329.out b/tests/xfs/1329.out
new file mode 100644
index 0000000..d9d8b89
--- /dev/null
+++ b/tests/xfs/1329.out
@@ -0,0 +1,4 @@
+QA output created by 1329
+Format and populate
+Fuzz rtrmapbt recs
+Done fuzzing rtrmapbt recs
diff --git a/tests/xfs/1330 b/tests/xfs/1330
new file mode 100755
index 0000000..3ca44ae
--- /dev/null
+++ b/tests/xfs/1330
@@ -0,0 +1,61 @@
+#! /bin/bash
+# FS QA Test No. 1330
+#
+# Populate a XFS filesystem and fuzz every rtrmapbt keyptr field.
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2016 Oracle, Inc.  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-1303  USA
+#-----------------------------------------------------------------------
+#
+
+seq=`basename $0`
+seqres=$RESULT_DIR/$seq
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=1	# failure is the default!
+trap "_cleanup; exit \$status" 0 1 2 3 7 15
+
+_cleanup()
+{
+	cd /
+	rm -rf $tmp.*
+}
+
+# get standard environment, filters and checks
+. ./common/rc
+. ./common/filter
+. ./common/populate
+. ./common/fuzzy
+
+# real QA test starts here
+_supported_os Linux
+_supported_fs xfs
+_require_realtime
+_require_xfs_scratch_rmapbt
+_require_scratch_xfs_fuzz_fields
+
+echo "Format and populate"
+_scratch_populate_cached nofill > $seqres.full 2>&1
+
+echo "Fuzz rtrmapbt keyptrs"
+_scratch_xfs_fuzz_some_fields '(rtrmapbt)' 'sb 0' 'addr rrmapino' >> $seqres.full
+echo "Done fuzzing rtrmapbt keyptrs"
+
+# success, all done
+status=0
+exit
diff --git a/tests/xfs/1330.out b/tests/xfs/1330.out
new file mode 100644
index 0000000..ce16b43
--- /dev/null
+++ b/tests/xfs/1330.out
@@ -0,0 +1,4 @@
+QA output created by 1330
+Format and populate
+Fuzz rtrmapbt keyptrs
+Done fuzzing rtrmapbt keyptrs
diff --git a/tests/xfs/group b/tests/xfs/group
index 3296eb9..2cbd3e6 100644
--- a/tests/xfs/group
+++ b/tests/xfs/group
@@ -333,3 +333,34 @@
 345 auto quick clone
 346 auto quick clone
 347 auto quick clone
+1300 dangerous_fuzzers scrub
+1301 dangerous_fuzzers scrub
+1302 dangerous_fuzzers scrub
+1303 dangerous_fuzzers scrub
+1304 dangerous_fuzzers scrub
+1305 dangerous_fuzzers scrub
+1306 dangerous_fuzzers scrub
+1307 dangerous_fuzzers scrub
+1308 dangerous_fuzzers scrub
+1309 dangerous_fuzzers scrub
+1310 dangerous_fuzzers scrub
+1311 dangerous_fuzzers scrub
+1312 dangerous_fuzzers scrub
+1313 dangerous_fuzzers scrub
+1314 dangerous_fuzzers scrub
+1315 dangerous_fuzzers scrub
+1316 dangerous_fuzzers scrub
+1317 dangerous_fuzzers scrub
+1318 dangerous_fuzzers scrub
+1319 dangerous_fuzzers scrub
+1320 dangerous_fuzzers scrub
+1321 dangerous_fuzzers scrub
+1322 dangerous_fuzzers scrub
+1323 dangerous_fuzzers scrub
+1324 dangerous_fuzzers scrub
+1325 dangerous_fuzzers scrub
+1326 dangerous_fuzzers scrub
+1327 dangerous_fuzzers scrub
+1328 dangerous_fuzzers scrub
+1329 dangerous_fuzzers scrub
+1330 dangerous_fuzzers scrub


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

* [PATCH 9/9] common/populate: create attrs in different namespaces
  2016-11-05  0:17 [PATCH v2 0/9] xfstests: online scrub/repair support Darrick J. Wong
                   ` (7 preceding siblings ...)
  2016-11-05  0:18 ` [PATCH 8/9] xfs: fuzz every field of every structure Darrick J. Wong
@ 2016-11-05  0:18 ` Darrick J. Wong
  8 siblings, 0 replies; 25+ messages in thread
From: Darrick J. Wong @ 2016-11-05  0:18 UTC (permalink / raw)
  To: david, eguan, darrick.wong; +Cc: linux-xfs, fstests

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 common/populate |   30 ++++++++++++++++++++++++++++++
 1 file changed, 30 insertions(+)


diff --git a/common/populate b/common/populate
index 7d103f0..a1987e7 100644
--- a/common/populate
+++ b/common/populate
@@ -160,6 +160,9 @@ _scratch_xfs_populate() {
 	mknod "${SCRATCH_MNT}/S_IFCHR" c 1 1
 	mknod "${SCRATCH_MNT}/S_IFBLK" c 1 1
 
+	# special file with an xattr
+	setfacl -P -m u:nobody:r ${SCRATCH_MNT}/S_IFCHR
+
 	# Attribute formats
 	# LOCAL
 	echo "+ local attr"
@@ -177,6 +180,18 @@ _scratch_xfs_populate() {
 	echo "+ btree attr"
 	__populate_create_attr "${SCRATCH_MNT}/ATTR.FMT_BTREE" "$((64 * blksz / 40))" true
 
+	# trusted namespace
+	touch ${SCRATCH_MNT}/ATTR.TRUSTED
+	setfattr -n trusted.moo -v urk ${SCRATCH_MNT}/ATTR.TRUSTED
+
+	# security namespace
+	touch ${SCRATCH_MNT}/ATTR.SECURITY
+	setfattr -n security.foo -v bar ${SCRATCH_MNT}/ATTR.SECURITY
+
+	# system namespace
+	touch ${SCRATCH_MNT}/ATTR.SYSTEM
+	setfacl -m u:root:r ${SCRATCH_MNT}/ATTR.SYSTEM
+
 	# FMT_EXTENTS with a remote less-than-a-block value
 	echo "+ attr extents with a remote less-than-a-block value"
 	touch "${SCRATCH_MNT}/ATTR.FMT_EXTENTS_REMOTE3K"
@@ -299,6 +314,9 @@ _scratch_ext4_populate() {
 	mknod "${SCRATCH_MNT}/S_IFCHR" c 1 1
 	mknod "${SCRATCH_MNT}/S_IFBLK" c 1 1
 
+	# special file with an xattr
+	setfacl -P -m u:nobody:r ${SCRATCH_MNT}/S_IFCHR
+
 	# Attribute formats
 	# LOCAL
 	echo "+ local attr"
@@ -308,6 +326,18 @@ _scratch_ext4_populate() {
 	echo "+ block attr"
 	__populate_create_attr "${SCRATCH_MNT}/ATTR.FMT_BLOCK" "$((blksz / 40))"
 
+	# trusted namespace
+	touch ${SCRATCH_MNT}/ATTR.TRUSTED
+	setfattr -n trusted.moo -v urk ${SCRATCH_MNT}/ATTR.TRUSTED
+
+	# security namespace
+	touch ${SCRATCH_MNT}/ATTR.SECURITY
+	setfattr -n security.foo -v bar ${SCRATCH_MNT}/ATTR.SECURITY
+
+	# system namespace
+	touch ${SCRATCH_MNT}/ATTR.SYSTEM
+	setfacl -m u:root:r ${SCRATCH_MNT}/ATTR.SYSTEM
+
 	# Make an unused inode
 	echo "+ empty file"
 	touch "${SCRATCH_MNT}/unused"


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

* Re: [PATCH 1/9] populate: create all types of XFS metadata
  2016-11-05  0:17 ` [PATCH 1/9] populate: create all types of XFS metadata Darrick J. Wong
@ 2016-11-07 15:34   ` Eryu Guan
  2016-11-09  0:29     ` Darrick J. Wong
  0 siblings, 1 reply; 25+ messages in thread
From: Eryu Guan @ 2016-11-07 15:34 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: david, linux-xfs, fstests

On Fri, Nov 04, 2016 at 05:17:16PM -0700, Darrick J. Wong wrote:
> We have three new metadata types -- rmapbt, rtrmapbt, and refcountbt.
> Ensure that we populate the scratch fs with all three.
> 
> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
> ---
>  common/populate |   87 ++++++++++++++++++++++++++++++++++++++++++++++++++-----
>  1 file changed, 79 insertions(+), 8 deletions(-)
> 
> 
> diff --git a/common/populate b/common/populate
> index d0003c5..6ada902 100644
> --- a/common/populate
> +++ b/common/populate
> @@ -24,6 +24,7 @@
>  
>  _require_xfs_io_command "falloc"
>  _require_xfs_io_command "fpunch"
> +_require_test_program "punch-alternating"
>  
>  _require_xfs_db_blocktrash_z_command() {
>  	test "${FSTYP}" = "xfs" || _notrun "cannot run xfs_db on ${FSTYP}"
> @@ -106,9 +107,7 @@ _scratch_xfs_populate() {
>  	echo "+ btree extents file"
>  	nr="$((blksz * 2 / 16))"
>  	$XFS_IO_PROG -f -c "pwrite -S 0x62 0 $((blksz * nr))" "${SCRATCH_MNT}/S_IFREG.FMT_BTREE"
> -	for i in $(seq 1 2 ${nr}); do
> -		$XFS_IO_PROG -f -c "fpunch $((i * blksz)) ${blksz}" "${SCRATCH_MNT}/S_IFREG.FMT_BTREE"
> -	done
> +	./src/punch-alternating "${SCRATCH_MNT}/S_IFREG.FMT_BTREE"
>  
>  	# Directories
>  	# - INLINE
> @@ -128,6 +127,7 @@ _scratch_xfs_populate() {
>  	__populate_create_dir "${SCRATCH_MNT}/S_IFDIR.FMT_NODE" "$((16 * dblksz / 40))" true
>  
>  	# - BTREE
> +	echo "+ btree dir"
>  	__populate_create_dir "${SCRATCH_MNT}/S_IFDIR.FMT_BTREE" "$((128 * dblksz / 40))" true
>  
>  	# Symlinks
> @@ -180,10 +180,43 @@ _scratch_xfs_populate() {
>  	$XFS_IO_PROG -f -c 'fsync' "${SCRATCH_MNT}/unused"
>  	rm -rf "${SCRATCH_MNT}/unused"
>  
> +	# Free space btree
> +	echo "+ freesp btree"
> +	nr="$((blksz * 2 / 8))"
> +	$XFS_IO_PROG -f -c "pwrite -S 0x62 0 $((blksz * nr))" "${SCRATCH_MNT}/BNOBT"
> +	./src/punch-alternating "${SCRATCH_MNT}/BNOBT"
> +
> +	# Reverse-mapping btree
> +	is_rmapbt="$(xfs_info "${SCRATCH_MNT}" | grep -c 'rmapbt=1')"
> +	if [ $is_rmapbt -gt 0 ]; then
> +		echo "+ rmapbt btree"
> +		nr="$((blksz * 2 / 24))"
> +		$XFS_IO_PROG -f -c "pwrite -S 0x62 0 $((blksz * nr))" "${SCRATCH_MNT}/RMAPBT"
> +		./src/punch-alternating "${SCRATCH_MNT}/RMAPBT"
> +	fi
> +
> +	# Realtime Reverse-mapping btree
> +	is_rt="$(xfs_info "${SCRATCH_MNT}" | grep -c 'rtextents=[1-9]')"
> +	if [ $is_rmapbt -gt 0 ] && [ $is_rt -gt 0 ]; then
> +		echo "+ rtrmapbt btree"
> +		nr="$((blksz * 2 / 32))"
> +		$XFS_IO_PROG -f -R -c "pwrite -S 0x62 0 $((blksz * nr))" "${SCRATCH_MNT}/RTRMAPBT"
> +		./src/punch-alternating "${SCRATCH_MNT}/RTRMAPBT"
> +	fi
> +
> +	# Reference-count btree
> +	is_reflink="$(xfs_info "${SCRATCH_MNT}" | grep -c 'reflink=1')"
> +	if [ $is_reflink -gt 0 ]; then
> +		echo "+ reflink btree"
> +		nr="$((blksz * 2 / 12))"
> +		$XFS_IO_PROG -f -c "pwrite -S 0x62 0 $((blksz * nr))" "${SCRATCH_MNT}/REFCOUNTBT"
> +		cp --reflink=always "${SCRATCH_MNT}/REFCOUNTBT" "${SCRATCH_MNT}/REFCOUNTBT2"
> +		./src/punch-alternating "${SCRATCH_MNT}/REFCOUNTBT"
> +	fi
> +
>  	# Copy some real files (xfs tests, I guess...)
>  	echo "+ real files"
> -	#__populate_fill_fs "${SCRATCH_MNT}" 40
> -	cp -pRdu --reflink=always "${SCRATCH_MNT}/S_IFREG.FMT_BTREE" "${SCRATCH_MNT}/S_IFREG.FMT_BTREE.REFLINK" 2> /dev/null
> +	test $fill -ne 0 && __populate_fill_fs "${SCRATCH_MNT}" 5

Seems this hunk belongs to patch 3/9? There's no "fill" in this context.

>  
>  	umount "${SCRATCH_MNT}"
>  }
> @@ -212,9 +245,7 @@ _scratch_ext4_populate() {
>  	echo "+ extent tree file"
>  	nr="$((blksz * 2 / 12))"
>  	$XFS_IO_PROG -f -c "pwrite -S 0x62 0 $((blksz * nr))" "${SCRATCH_MNT}/S_IFREG.FMT_ETREE"
> -	for i in $(seq 1 2 ${nr}); do
> -		$XFS_IO_PROG -f -c "fpunch $((i * blksz)) ${blksz}" "${SCRATCH_MNT}/S_IFREG.FMT_ETREE"
> -	done
> +	./src/punch-alternating "${SCRATCH_MNT}/S_IFREG.FMT_ETREE"
>  
>  	# Directories
>  	# - INLINE
> @@ -349,6 +380,39 @@ __populate_check_xfs_attr() {
>  	esac
>  }
>  
> +# Check that there's at least one per-AG btree with multiple levels
> +__populate_check_xfs_agbtree_height() {
> +	bt_type="$1"
> +	nr_ags=$(_scratch_xfs_db -c 'sb 0' -c 'p agcount' | awk '{print $3}')
> +
> +	case "${bt_type}" in
> +	"bno"|"cnt"|"rmap"|"refcnt")
> +		hdr="agf"
> +		bt_prefix="${bt_type}"
> +		;;
> +	"ino")
> +		hdr="agi"
> +		bt_prefix=""
> +		;;
> +	"fino")
> +		hdr="agi"
> +		bt_prefix="free_"
> +		;;
> +	*)
> +		_fail "Don't know about AG btree ${bt_type}"
> +		;;
> +	esac
> +
> +	seq 0 $((nr_ags - 1)) | while read ag; do
> +		bt_level=$(_scratch_xfs_db -c "${hdr} ${ag}" -c "p ${bt_prefix}level" | awk '{print $3}')
> +		if [ "${bt_level}" -gt 1 ]; then
> +			return 100
> +		fi
> +	done
> +	test $? -eq 100 || _fail "Failed to create ${bt_type} of sufficient height!"

I'm a bit confused here, why test against 100? Because of the
"return 100" above? That should exit the function and return to caller
already.

Thanks,
Eryu

> +	return 1
> +}
> +
>  # Check that populate created all the types of files we wanted
>  _scratch_xfs_populate_check() {
>  	_scratch_mount
> @@ -367,6 +431,9 @@ _scratch_xfs_populate_check() {
>  	leaf_attr="$(__populate_find_inode "${SCRATCH_MNT}/ATTR.FMT_LEAF")"
>  	node_attr="$(__populate_find_inode "${SCRATCH_MNT}/ATTR.FMT_NODE")"
>  	btree_attr="$(__populate_find_inode "${SCRATCH_MNT}/ATTR.FMT_BTREE")"
> +	is_finobt=$(xfs_info "${SCRATCH_MNT}" | grep -c 'finobt=1')
> +	is_rmapbt=$(xfs_info "${SCRATCH_MNT}" | grep -c 'rmapbt=1')
> +	is_reflink=$(xfs_info "${SCRATCH_MNT}" | grep -c 'reflink=1')
>  
>  	blksz="$(stat -f -c '%s' "${SCRATCH_MNT}")"
>  	dblksz="$(xfs_info "${SCRATCH_MNT}" | grep naming.*bsize | sed -e 's/^.*bsize=//g' -e 's/\([0-9]*\).*$/\1/g')"
> @@ -389,6 +456,10 @@ _scratch_xfs_populate_check() {
>  	__populate_check_xfs_attr "${node_attr}" "node"
>  	__populate_check_xfs_attr "${btree_attr}" "btree"
>  	__populate_check_xfs_aformat "${btree_attr}" "btree"
> +	__populate_check_xfs_agbtree_height "bno"
> +	__populate_check_xfs_agbtree_height "cnt"
> +	test -n $is_rmapbt && __populate_check_xfs_agbtree_height "rmap"
> +	test -n $is_reflink && __populate_check_xfs_agbtree_height "refcnt"
>  }
>  
>  # Check data fork format of ext4 file
> 

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

* Re: [PATCH 1/9] populate: create all types of XFS metadata
  2016-11-07 15:34   ` Eryu Guan
@ 2016-11-09  0:29     ` Darrick J. Wong
  0 siblings, 0 replies; 25+ messages in thread
From: Darrick J. Wong @ 2016-11-09  0:29 UTC (permalink / raw)
  To: Eryu Guan; +Cc: david, linux-xfs, fstests

On Mon, Nov 07, 2016 at 11:34:13PM +0800, Eryu Guan wrote:
> On Fri, Nov 04, 2016 at 05:17:16PM -0700, Darrick J. Wong wrote:
> > We have three new metadata types -- rmapbt, rtrmapbt, and refcountbt.
> > Ensure that we populate the scratch fs with all three.
> > 
> > Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
> > ---
> >  common/populate |   87 ++++++++++++++++++++++++++++++++++++++++++++++++++-----
> >  1 file changed, 79 insertions(+), 8 deletions(-)
> > 
> > 
> > diff --git a/common/populate b/common/populate
> > index d0003c5..6ada902 100644
> > --- a/common/populate
> > +++ b/common/populate
> > @@ -24,6 +24,7 @@
> >  
> >  _require_xfs_io_command "falloc"
> >  _require_xfs_io_command "fpunch"
> > +_require_test_program "punch-alternating"
> >  
> >  _require_xfs_db_blocktrash_z_command() {
> >  	test "${FSTYP}" = "xfs" || _notrun "cannot run xfs_db on ${FSTYP}"
> > @@ -106,9 +107,7 @@ _scratch_xfs_populate() {
> >  	echo "+ btree extents file"
> >  	nr="$((blksz * 2 / 16))"
> >  	$XFS_IO_PROG -f -c "pwrite -S 0x62 0 $((blksz * nr))" "${SCRATCH_MNT}/S_IFREG.FMT_BTREE"
> > -	for i in $(seq 1 2 ${nr}); do
> > -		$XFS_IO_PROG -f -c "fpunch $((i * blksz)) ${blksz}" "${SCRATCH_MNT}/S_IFREG.FMT_BTREE"
> > -	done
> > +	./src/punch-alternating "${SCRATCH_MNT}/S_IFREG.FMT_BTREE"
> >  
> >  	# Directories
> >  	# - INLINE
> > @@ -128,6 +127,7 @@ _scratch_xfs_populate() {
> >  	__populate_create_dir "${SCRATCH_MNT}/S_IFDIR.FMT_NODE" "$((16 * dblksz / 40))" true
> >  
> >  	# - BTREE
> > +	echo "+ btree dir"
> >  	__populate_create_dir "${SCRATCH_MNT}/S_IFDIR.FMT_BTREE" "$((128 * dblksz / 40))" true
> >  
> >  	# Symlinks
> > @@ -180,10 +180,43 @@ _scratch_xfs_populate() {
> >  	$XFS_IO_PROG -f -c 'fsync' "${SCRATCH_MNT}/unused"
> >  	rm -rf "${SCRATCH_MNT}/unused"
> >  
> > +	# Free space btree
> > +	echo "+ freesp btree"
> > +	nr="$((blksz * 2 / 8))"
> > +	$XFS_IO_PROG -f -c "pwrite -S 0x62 0 $((blksz * nr))" "${SCRATCH_MNT}/BNOBT"
> > +	./src/punch-alternating "${SCRATCH_MNT}/BNOBT"
> > +
> > +	# Reverse-mapping btree
> > +	is_rmapbt="$(xfs_info "${SCRATCH_MNT}" | grep -c 'rmapbt=1')"
> > +	if [ $is_rmapbt -gt 0 ]; then
> > +		echo "+ rmapbt btree"
> > +		nr="$((blksz * 2 / 24))"
> > +		$XFS_IO_PROG -f -c "pwrite -S 0x62 0 $((blksz * nr))" "${SCRATCH_MNT}/RMAPBT"
> > +		./src/punch-alternating "${SCRATCH_MNT}/RMAPBT"
> > +	fi
> > +
> > +	# Realtime Reverse-mapping btree
> > +	is_rt="$(xfs_info "${SCRATCH_MNT}" | grep -c 'rtextents=[1-9]')"
> > +	if [ $is_rmapbt -gt 0 ] && [ $is_rt -gt 0 ]; then
> > +		echo "+ rtrmapbt btree"
> > +		nr="$((blksz * 2 / 32))"
> > +		$XFS_IO_PROG -f -R -c "pwrite -S 0x62 0 $((blksz * nr))" "${SCRATCH_MNT}/RTRMAPBT"
> > +		./src/punch-alternating "${SCRATCH_MNT}/RTRMAPBT"
> > +	fi
> > +
> > +	# Reference-count btree
> > +	is_reflink="$(xfs_info "${SCRATCH_MNT}" | grep -c 'reflink=1')"
> > +	if [ $is_reflink -gt 0 ]; then
> > +		echo "+ reflink btree"
> > +		nr="$((blksz * 2 / 12))"
> > +		$XFS_IO_PROG -f -c "pwrite -S 0x62 0 $((blksz * nr))" "${SCRATCH_MNT}/REFCOUNTBT"
> > +		cp --reflink=always "${SCRATCH_MNT}/REFCOUNTBT" "${SCRATCH_MNT}/REFCOUNTBT2"
> > +		./src/punch-alternating "${SCRATCH_MNT}/REFCOUNTBT"
> > +	fi
> > +
> >  	# Copy some real files (xfs tests, I guess...)
> >  	echo "+ real files"
> > -	#__populate_fill_fs "${SCRATCH_MNT}" 40
> > -	cp -pRdu --reflink=always "${SCRATCH_MNT}/S_IFREG.FMT_BTREE" "${SCRATCH_MNT}/S_IFREG.FMT_BTREE.REFLINK" 2> /dev/null
> > +	test $fill -ne 0 && __populate_fill_fs "${SCRATCH_MNT}" 5
> 
> Seems this hunk belongs to patch 3/9? There's no "fill" in this context.

Yep.  I'll fix this.

> >  	umount "${SCRATCH_MNT}"
> >  }
> > @@ -212,9 +245,7 @@ _scratch_ext4_populate() {
> >  	echo "+ extent tree file"
> >  	nr="$((blksz * 2 / 12))"
> >  	$XFS_IO_PROG -f -c "pwrite -S 0x62 0 $((blksz * nr))" "${SCRATCH_MNT}/S_IFREG.FMT_ETREE"
> > -	for i in $(seq 1 2 ${nr}); do
> > -		$XFS_IO_PROG -f -c "fpunch $((i * blksz)) ${blksz}" "${SCRATCH_MNT}/S_IFREG.FMT_ETREE"
> > -	done
> > +	./src/punch-alternating "${SCRATCH_MNT}/S_IFREG.FMT_ETREE"
> >  
> >  	# Directories
> >  	# - INLINE
> > @@ -349,6 +380,39 @@ __populate_check_xfs_attr() {
> >  	esac
> >  }
> >  
> > +# Check that there's at least one per-AG btree with multiple levels
> > +__populate_check_xfs_agbtree_height() {
> > +	bt_type="$1"
> > +	nr_ags=$(_scratch_xfs_db -c 'sb 0' -c 'p agcount' | awk '{print $3}')
> > +
> > +	case "${bt_type}" in
> > +	"bno"|"cnt"|"rmap"|"refcnt")
> > +		hdr="agf"
> > +		bt_prefix="${bt_type}"
> > +		;;
> > +	"ino")
> > +		hdr="agi"
> > +		bt_prefix=""
> > +		;;
> > +	"fino")
> > +		hdr="agi"
> > +		bt_prefix="free_"
> > +		;;
> > +	*)
> > +		_fail "Don't know about AG btree ${bt_type}"
> > +		;;
> > +	esac
> > +
> > +	seq 0 $((nr_ags - 1)) | while read ag; do
> > +		bt_level=$(_scratch_xfs_db -c "${hdr} ${ag}" -c "p ${bt_prefix}level" | awk '{print $3}')
> > +		if [ "${bt_level}" -gt 1 ]; then
> > +			return 100
> > +		fi
> > +	done
> > +	test $? -eq 100 || _fail "Failed to create ${bt_type} of sufficient height!"
> 
> I'm a bit confused here, why test against 100? Because of the
> "return 100" above? That should exit the function and return to caller
> already.

The while loop+body executes in a subshell because of the "seq ... |
while" behavior, so the 'return 100' exits the subshell with a return
code of 100, depositing us at the first statement after the "done"
clause.  That's the "test $? -eq 100" statement, which is how
__populate_check_xfs_agbtree_height catches the early loop termination
so that we can _fail the test.  We can't call _fail from inside the
subshell because that will only abort the loop, not the whole test.

FWIW all that is unnecessary if we do:

for ag in $(seq 0 $((nr_ags - 1)) ); do
	...
done 

But I prefer to code that a little more defensively when possible since
that could result in a very long command line.

--D

> 
> Thanks,
> Eryu
> 
> > +	return 1
> > +}
> > +
> >  # Check that populate created all the types of files we wanted
> >  _scratch_xfs_populate_check() {
> >  	_scratch_mount
> > @@ -367,6 +431,9 @@ _scratch_xfs_populate_check() {
> >  	leaf_attr="$(__populate_find_inode "${SCRATCH_MNT}/ATTR.FMT_LEAF")"
> >  	node_attr="$(__populate_find_inode "${SCRATCH_MNT}/ATTR.FMT_NODE")"
> >  	btree_attr="$(__populate_find_inode "${SCRATCH_MNT}/ATTR.FMT_BTREE")"
> > +	is_finobt=$(xfs_info "${SCRATCH_MNT}" | grep -c 'finobt=1')
> > +	is_rmapbt=$(xfs_info "${SCRATCH_MNT}" | grep -c 'rmapbt=1')
> > +	is_reflink=$(xfs_info "${SCRATCH_MNT}" | grep -c 'reflink=1')
> >  
> >  	blksz="$(stat -f -c '%s' "${SCRATCH_MNT}")"
> >  	dblksz="$(xfs_info "${SCRATCH_MNT}" | grep naming.*bsize | sed -e 's/^.*bsize=//g' -e 's/\([0-9]*\).*$/\1/g')"
> > @@ -389,6 +456,10 @@ _scratch_xfs_populate_check() {
> >  	__populate_check_xfs_attr "${node_attr}" "node"
> >  	__populate_check_xfs_attr "${btree_attr}" "btree"
> >  	__populate_check_xfs_aformat "${btree_attr}" "btree"
> > +	__populate_check_xfs_agbtree_height "bno"
> > +	__populate_check_xfs_agbtree_height "cnt"
> > +	test -n $is_rmapbt && __populate_check_xfs_agbtree_height "rmap"
> > +	test -n $is_reflink && __populate_check_xfs_agbtree_height "refcnt"
> >  }
> >  
> >  # Check data fork format of ext4 file
> > 

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

* Re: [PATCH 7/9] populate: discover XFS structure fields and fuzz verbs, and use them to fuzz fields
  2016-11-05  0:17 ` [PATCH 7/9] populate: discover XFS structure fields and fuzz verbs, and use them to fuzz fields Darrick J. Wong
@ 2016-11-09  3:32   ` Eryu Guan
  2016-11-09  7:52     ` Darrick J. Wong
  2016-11-09  3:44   ` Eryu Guan
  1 sibling, 1 reply; 25+ messages in thread
From: Eryu Guan @ 2016-11-09  3:32 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: david, linux-xfs, fstests

On Fri, Nov 04, 2016 at 05:17:54PM -0700, Darrick J. Wong wrote:
> Create some routines to help us perform targeted fuzzing of individual
> fields in various XFS structures.  Specifically, we want the caller to
> drop the xfs_db iocursor on the victim field; from there, the scripts
> should discover all available fields and fuzzing verbs, and try each
> fuzz verb on every available field.
> 
> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
> ---
>  common/fuzzy |  191 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 191 insertions(+)
> 
> 
> diff --git a/common/fuzzy b/common/fuzzy
> index 20f1d29..6af47f1 100644
> --- a/common/fuzzy
> +++ b/common/fuzzy
> @@ -81,3 +81,194 @@ _scratch_scrub() {
>  		;;
>  	esac
>  }
> +
> +# Filter the xfs_db print command's field debug information
> +# into field name and type.
> +__filter_xfs_db_print_fields() {
> +	grep ' = ' | while read key equals value; do
> +		fuzzkey="$(echo "${key}" | sed -e 's/\([a-zA-Z0-9_]*\)\[\([0-9]*\)-[0-9]*\]/\1[\2]/g')"
> +		if [[ "${value}" == "["* ]]; then
> +			echo "${value}" | sed -e 's/^.//g' -e 's/.$//g' -e 's/,/\n/g' | while read subfield; do
> +				echo "${fuzzkey}.${subfield}"
> +			done
> +		else
> +			echo "${fuzzkey}"
> +		fi
> +	done
> +}
> +
> +# Navigate to some part of the filesystem and print the field info.
> +_scratch_xfs_list_metadata_fields() {
> +	if [ -n "${SCRATCH_XFS_LIST_METADATA_FIELDS}" ]; then
> +		echo "${SCRATCH_XFS_LIST_METADATA_FIELDS}" | sed -e 's/ /\n/g'
> +		return;
> +	fi
> +
> +	(for arg in "$@"; do
> +		echo "${arg}"
> +	done
> +	echo "print") | _scratch_xfs_db | __filter_xfs_db_print_fields
> +}
> +
> +# Get a metadata field
> +_scratch_xfs_get_metadata_field() {
> +	key="$1"
> +	shift
> +
> +	grep_key="$(echo "${key}" | tr '[]()' '....')"
> +	(for arg in "$@"; do
> +		echo "${arg}"
> +	done
> +	echo "print ${key}") | _scratch_xfs_db | grep "^${grep_key}" | \
> +		sed -e 's/^.* = //g'
> +}
> +
> +# Set a metadata field
> +_scratch_xfs_set_metadata_field() {
> +	key="$1"
> +	value="$2"
> +	shift; shift
> +	(for arg in "$@"; do
> +		echo "${arg}"
> +	done
> +	echo "write -d ${key} ${value}") | _scratch_xfs_db -x
> +	echo
> +}
> +
> +# Fuzz a metadata field
> +_scratch_xfs_fuzz_metadata_field() {
> +	key="$1"
> +	value="$2"
> +	shift; shift
> +
> +	if [ "${key}" = "crc" ]; then
> +		fuzz_arg="-c"
> +	else
> +		fuzz_arg="-d"
> +	fi
> +	oldval="$(_scratch_xfs_get_metadata_field "${key}" "$@")"
> +	(for arg in "$@"; do
> +		echo "${arg}"
> +	done
> +	echo "fuzz ${fuzz_arg} ${key} ${value}") | _scratch_xfs_db -x
> +	echo
> +	newval="$(_scratch_xfs_get_metadata_field "${key}" "$@" 2> /dev/null)"
> +	if [ "${oldval}" = "${newval}" ]; then
> +		echo "Field ${key} already set to ${oldval}, skipping test."
> +		return 1
> +	fi
> +	return 0
> +}
> +
> +# Try to forcibly unmount the scratch fs
> +__scratch_xfs_fuzz_unmount()
> +{
> +	while _scratch_unmount 2>/dev/null; do sleep 0.2; done

Shouldn't this be

while ! _scratch_unmount 2>/dev/null; do sleep 0.2; done

so it only sleeps and try again if umount failed?

Thanks,
Eryu

> +}
> +
> +# Restore metadata to scratch device prior to field-fuzzing.
> +__scratch_xfs_fuzz_mdrestore()
> +{
> +	test -e "${POPULATE_METADUMP}" || _fail "Need to set POPULATE_METADUMP"
> +
> +	__scratch_xfs_fuzz_unmount
> +	xfs_mdrestore "${POPULATE_METADUMP}" "${SCRATCH_DEV}"
> +}
> +
> +__fuzz_notify() {
> +	echo "$@"
> +	test -w /dev/ttyprintk && echo "$@" >> /dev/ttyprintk
> +}
> +
> +# Fuzz one field of some piece of metadata
> +__scratch_xfs_fuzz_field_test() {
> +	field="$1"
> +	fuzzverb="$2"
> +	shift; shift
> +
> +	# Set the new field value
> +	__fuzz_notify "+ Fuzz ${field} = ${fuzzverb}"
> +	echo "========================"
> +	_scratch_xfs_fuzz_metadata_field "${field}" ${fuzzverb} "$@"
> +	res=$?
> +	test $res -ne 0 && return
> +
> +	# Try to catch the error with scrub
> +	echo "+ Try to catch the error"
> +	_scratch_mount 2>&1
> +	res=$?
> +	if [ $res -eq 0 ]; then
> +		_scratch_scrub -a 1 -e continue 2>&1
> +		res=$?
> +		test $res -eq 0 && \
> +			(>&2 echo "scrub didn't fail with ${field} = ${fuzzverb}.")
> +
> +		# Try modifying the filesystem!
> +		__fuzz_notify "++ Try to write filesystem"
> +		#_scratch_fuzz_modify 100 2>&1
> +		__scratch_xfs_fuzz_unmount
> +	fi
> +
> +	# Repair the filesystem
> +	echo "+ Fix the error"
> +	_repair_scratch_fs 2>&1
> +	res=$?
> +	test $res -ne 0 && \
> +		(>&2 echo "repair failed ($res) with ${field} = ${fuzzverb}.")
> +
> +	# See if scrub finds a clean fs
> +	echo "+ Make sure error is gone"
> +	_scratch_mount 2>&1
> +	res=$?
> +	if [ $res -eq 0 ]; then
> +		_scratch_scrub -e continue 2>&1
> +		res=$?
> +		test $res -ne 0 && \
> +			(>&2 echo "re-scrub ($res) with ${field} = ${fuzzverb}.")
> +
> +		# Try modifying the filesystem again!
> +		__fuzz_notify "++ Try to write filesystem again"
> +		_scratch_fuzz_modify 100 2>&1
> +		__scratch_xfs_fuzz_unmount
> +	else
> +		(>&2 echo "re-mount failed ($res) with ${field} = ${fuzzverb}.")
> +	fi
> +
> +	# See if repair finds a clean fs
> +	_scratch_xfs_repair -n 2>&1
> +	res=$?
> +	test $res -ne 0 && \
> +		(>&2 echo "re-repair failed ($res) with ${field} = ${fuzzverb}.")
> +}
> +
> +# Make sure we have all the pieces we need for field fuzzing
> +_require_scratch_xfs_fuzz_fields()
> +{
> +	_require_scratch
> +	_require_scrub
> +	_require_populate_commands
> +	_require_command "$XFS_DB_PROG" "xfs_db"
> +	_scratch_mkfs_xfs >/dev/null 2>&1
> +	_scratch_xfs_db -x -c 'fuzz' 2>&1 | grep -q 'not found' && \
> +		_notrun "xfs_db does not have fuzz command"
> +}
> +
> +# Grab the list of available fuzzing verbs
> +_scratch_xfs_list_fuzz_verbs() {
> +	if [ -n "${SCRATCH_XFS_LIST_FUZZ_VERBS}" ]; then
> +		echo "${SCRATCH_XFS_LIST_FUZZ_VERBS}" | sed -e 's/ /\n/g'
> +		return;
> +	fi
> +	_scratch_xfs_db -x -c 'sb 0' -c 'fuzz' | grep '^Verbs:' | \
> +		sed -e 's/[,.]//g' -e 's/Verbs: //g' -e 's/ /\n/g'
> +}
> +
> +# Fuzz the fields of some piece of metadata
> +_scratch_xfs_fuzz_fields() {
> +	_scratch_xfs_list_metadata_fields "$@" | while read field; do
> +		_scratch_xfs_list_fuzz_verbs | while read fuzzverb; do
> +			__scratch_xfs_fuzz_mdrestore
> +			__scratch_xfs_fuzz_field_test "${field}" "${fuzzverb}" "$@"
> +		done
> +	done
> +}
> 

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

* Re: [PATCH 7/9] populate: discover XFS structure fields and fuzz verbs, and use them to fuzz fields
  2016-11-05  0:17 ` [PATCH 7/9] populate: discover XFS structure fields and fuzz verbs, and use them to fuzz fields Darrick J. Wong
  2016-11-09  3:32   ` Eryu Guan
@ 2016-11-09  3:44   ` Eryu Guan
  2016-11-09  7:53     ` Darrick J. Wong
  1 sibling, 1 reply; 25+ messages in thread
From: Eryu Guan @ 2016-11-09  3:44 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: david, linux-xfs, fstests

[sorry, more comments on this patch]

On Fri, Nov 04, 2016 at 05:17:54PM -0700, Darrick J. Wong wrote:
> Create some routines to help us perform targeted fuzzing of individual
> fields in various XFS structures.  Specifically, we want the caller to
> drop the xfs_db iocursor on the victim field; from there, the scripts
> should discover all available fields and fuzzing verbs, and try each
> fuzz verb on every available field.
> 
> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
> ---
>  common/fuzzy |  191 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 191 insertions(+)
> 
> 
[snip]
> +
> +# Make sure we have all the pieces we need for field fuzzing
> +_require_scratch_xfs_fuzz_fields()
> +{
> +	_require_scratch
> +	_require_scrub
> +	_require_populate_commands
> +	_require_command "$XFS_DB_PROG" "xfs_db"

This is included in _require_populate_commands, not needed here.

> +	_scratch_mkfs_xfs >/dev/null 2>&1
> +	_scratch_xfs_db -x -c 'fuzz' 2>&1 | grep -q 'not found' && \
> +		_notrun "xfs_db does not have fuzz command"

Does _require_xfs_db_command work here?

Thanks,
Eryu

> +}
> +
> +# Grab the list of available fuzzing verbs
> +_scratch_xfs_list_fuzz_verbs() {
> +	if [ -n "${SCRATCH_XFS_LIST_FUZZ_VERBS}" ]; then
> +		echo "${SCRATCH_XFS_LIST_FUZZ_VERBS}" | sed -e 's/ /\n/g'
> +		return;
> +	fi
> +	_scratch_xfs_db -x -c 'sb 0' -c 'fuzz' | grep '^Verbs:' | \
> +		sed -e 's/[,.]//g' -e 's/Verbs: //g' -e 's/ /\n/g'
> +}
> +
> +# Fuzz the fields of some piece of metadata
> +_scratch_xfs_fuzz_fields() {
> +	_scratch_xfs_list_metadata_fields "$@" | while read field; do
> +		_scratch_xfs_list_fuzz_verbs | while read fuzzverb; do
> +			__scratch_xfs_fuzz_mdrestore
> +			__scratch_xfs_fuzz_field_test "${field}" "${fuzzverb}" "$@"
> +		done
> +	done
> +}
> 

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

* Re: [PATCH 7/9] populate: discover XFS structure fields and fuzz verbs, and use them to fuzz fields
  2016-11-09  3:32   ` Eryu Guan
@ 2016-11-09  7:52     ` Darrick J. Wong
  0 siblings, 0 replies; 25+ messages in thread
From: Darrick J. Wong @ 2016-11-09  7:52 UTC (permalink / raw)
  To: Eryu Guan; +Cc: david, linux-xfs, fstests

On Wed, Nov 09, 2016 at 11:32:02AM +0800, Eryu Guan wrote:
> On Fri, Nov 04, 2016 at 05:17:54PM -0700, Darrick J. Wong wrote:
> > Create some routines to help us perform targeted fuzzing of individual
> > fields in various XFS structures.  Specifically, we want the caller to
> > drop the xfs_db iocursor on the victim field; from there, the scripts
> > should discover all available fields and fuzzing verbs, and try each
> > fuzz verb on every available field.
> > 
> > Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
> > ---
> >  common/fuzzy |  191 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> >  1 file changed, 191 insertions(+)
> > 
> > 
> > diff --git a/common/fuzzy b/common/fuzzy
> > index 20f1d29..6af47f1 100644
> > --- a/common/fuzzy
> > +++ b/common/fuzzy
> > @@ -81,3 +81,194 @@ _scratch_scrub() {
> >  		;;
> >  	esac
> >  }
> > +
> > +# Filter the xfs_db print command's field debug information
> > +# into field name and type.
> > +__filter_xfs_db_print_fields() {
> > +	grep ' = ' | while read key equals value; do
> > +		fuzzkey="$(echo "${key}" | sed -e 's/\([a-zA-Z0-9_]*\)\[\([0-9]*\)-[0-9]*\]/\1[\2]/g')"
> > +		if [[ "${value}" == "["* ]]; then
> > +			echo "${value}" | sed -e 's/^.//g' -e 's/.$//g' -e 's/,/\n/g' | while read subfield; do
> > +				echo "${fuzzkey}.${subfield}"
> > +			done
> > +		else
> > +			echo "${fuzzkey}"
> > +		fi
> > +	done
> > +}
> > +
> > +# Navigate to some part of the filesystem and print the field info.
> > +_scratch_xfs_list_metadata_fields() {
> > +	if [ -n "${SCRATCH_XFS_LIST_METADATA_FIELDS}" ]; then
> > +		echo "${SCRATCH_XFS_LIST_METADATA_FIELDS}" | sed -e 's/ /\n/g'
> > +		return;
> > +	fi
> > +
> > +	(for arg in "$@"; do
> > +		echo "${arg}"
> > +	done
> > +	echo "print") | _scratch_xfs_db | __filter_xfs_db_print_fields
> > +}
> > +
> > +# Get a metadata field
> > +_scratch_xfs_get_metadata_field() {
> > +	key="$1"
> > +	shift
> > +
> > +	grep_key="$(echo "${key}" | tr '[]()' '....')"
> > +	(for arg in "$@"; do
> > +		echo "${arg}"
> > +	done
> > +	echo "print ${key}") | _scratch_xfs_db | grep "^${grep_key}" | \
> > +		sed -e 's/^.* = //g'
> > +}
> > +
> > +# Set a metadata field
> > +_scratch_xfs_set_metadata_field() {
> > +	key="$1"
> > +	value="$2"
> > +	shift; shift
> > +	(for arg in "$@"; do
> > +		echo "${arg}"
> > +	done
> > +	echo "write -d ${key} ${value}") | _scratch_xfs_db -x
> > +	echo
> > +}
> > +
> > +# Fuzz a metadata field
> > +_scratch_xfs_fuzz_metadata_field() {
> > +	key="$1"
> > +	value="$2"
> > +	shift; shift
> > +
> > +	if [ "${key}" = "crc" ]; then
> > +		fuzz_arg="-c"
> > +	else
> > +		fuzz_arg="-d"
> > +	fi
> > +	oldval="$(_scratch_xfs_get_metadata_field "${key}" "$@")"
> > +	(for arg in "$@"; do
> > +		echo "${arg}"
> > +	done
> > +	echo "fuzz ${fuzz_arg} ${key} ${value}") | _scratch_xfs_db -x
> > +	echo
> > +	newval="$(_scratch_xfs_get_metadata_field "${key}" "$@" 2> /dev/null)"
> > +	if [ "${oldval}" = "${newval}" ]; then
> > +		echo "Field ${key} already set to ${oldval}, skipping test."
> > +		return 1
> > +	fi
> > +	return 0
> > +}
> > +
> > +# Try to forcibly unmount the scratch fs
> > +__scratch_xfs_fuzz_unmount()
> > +{
> > +	while _scratch_unmount 2>/dev/null; do sleep 0.2; done
> 
> Shouldn't this be
> 
> while ! _scratch_unmount 2>/dev/null; do sleep 0.2; done
> 
> so it only sleeps and try again if umount failed?

Err, yes, and now you've gotten me wondering just how that hasn't shown up...

--D

> 
> Thanks,
> Eryu
> 
> > +}
> > +
> > +# Restore metadata to scratch device prior to field-fuzzing.
> > +__scratch_xfs_fuzz_mdrestore()
> > +{
> > +	test -e "${POPULATE_METADUMP}" || _fail "Need to set POPULATE_METADUMP"
> > +
> > +	__scratch_xfs_fuzz_unmount
> > +	xfs_mdrestore "${POPULATE_METADUMP}" "${SCRATCH_DEV}"
> > +}
> > +
> > +__fuzz_notify() {
> > +	echo "$@"
> > +	test -w /dev/ttyprintk && echo "$@" >> /dev/ttyprintk
> > +}
> > +
> > +# Fuzz one field of some piece of metadata
> > +__scratch_xfs_fuzz_field_test() {
> > +	field="$1"
> > +	fuzzverb="$2"
> > +	shift; shift
> > +
> > +	# Set the new field value
> > +	__fuzz_notify "+ Fuzz ${field} = ${fuzzverb}"
> > +	echo "========================"
> > +	_scratch_xfs_fuzz_metadata_field "${field}" ${fuzzverb} "$@"
> > +	res=$?
> > +	test $res -ne 0 && return
> > +
> > +	# Try to catch the error with scrub
> > +	echo "+ Try to catch the error"
> > +	_scratch_mount 2>&1
> > +	res=$?
> > +	if [ $res -eq 0 ]; then
> > +		_scratch_scrub -a 1 -e continue 2>&1
> > +		res=$?
> > +		test $res -eq 0 && \
> > +			(>&2 echo "scrub didn't fail with ${field} = ${fuzzverb}.")
> > +
> > +		# Try modifying the filesystem!
> > +		__fuzz_notify "++ Try to write filesystem"
> > +		#_scratch_fuzz_modify 100 2>&1
> > +		__scratch_xfs_fuzz_unmount
> > +	fi
> > +
> > +	# Repair the filesystem
> > +	echo "+ Fix the error"
> > +	_repair_scratch_fs 2>&1
> > +	res=$?
> > +	test $res -ne 0 && \
> > +		(>&2 echo "repair failed ($res) with ${field} = ${fuzzverb}.")
> > +
> > +	# See if scrub finds a clean fs
> > +	echo "+ Make sure error is gone"
> > +	_scratch_mount 2>&1
> > +	res=$?
> > +	if [ $res -eq 0 ]; then
> > +		_scratch_scrub -e continue 2>&1
> > +		res=$?
> > +		test $res -ne 0 && \
> > +			(>&2 echo "re-scrub ($res) with ${field} = ${fuzzverb}.")
> > +
> > +		# Try modifying the filesystem again!
> > +		__fuzz_notify "++ Try to write filesystem again"
> > +		_scratch_fuzz_modify 100 2>&1
> > +		__scratch_xfs_fuzz_unmount
> > +	else
> > +		(>&2 echo "re-mount failed ($res) with ${field} = ${fuzzverb}.")
> > +	fi
> > +
> > +	# See if repair finds a clean fs
> > +	_scratch_xfs_repair -n 2>&1
> > +	res=$?
> > +	test $res -ne 0 && \
> > +		(>&2 echo "re-repair failed ($res) with ${field} = ${fuzzverb}.")
> > +}
> > +
> > +# Make sure we have all the pieces we need for field fuzzing
> > +_require_scratch_xfs_fuzz_fields()
> > +{
> > +	_require_scratch
> > +	_require_scrub
> > +	_require_populate_commands
> > +	_require_command "$XFS_DB_PROG" "xfs_db"
> > +	_scratch_mkfs_xfs >/dev/null 2>&1
> > +	_scratch_xfs_db -x -c 'fuzz' 2>&1 | grep -q 'not found' && \
> > +		_notrun "xfs_db does not have fuzz command"
> > +}
> > +
> > +# Grab the list of available fuzzing verbs
> > +_scratch_xfs_list_fuzz_verbs() {
> > +	if [ -n "${SCRATCH_XFS_LIST_FUZZ_VERBS}" ]; then
> > +		echo "${SCRATCH_XFS_LIST_FUZZ_VERBS}" | sed -e 's/ /\n/g'
> > +		return;
> > +	fi
> > +	_scratch_xfs_db -x -c 'sb 0' -c 'fuzz' | grep '^Verbs:' | \
> > +		sed -e 's/[,.]//g' -e 's/Verbs: //g' -e 's/ /\n/g'
> > +}
> > +
> > +# Fuzz the fields of some piece of metadata
> > +_scratch_xfs_fuzz_fields() {
> > +	_scratch_xfs_list_metadata_fields "$@" | while read field; do
> > +		_scratch_xfs_list_fuzz_verbs | while read fuzzverb; do
> > +			__scratch_xfs_fuzz_mdrestore
> > +			__scratch_xfs_fuzz_field_test "${field}" "${fuzzverb}" "$@"
> > +		done
> > +	done
> > +}
> > 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-xfs" 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] 25+ messages in thread

* Re: [PATCH 7/9] populate: discover XFS structure fields and fuzz verbs, and use them to fuzz fields
  2016-11-09  3:44   ` Eryu Guan
@ 2016-11-09  7:53     ` Darrick J. Wong
  0 siblings, 0 replies; 25+ messages in thread
From: Darrick J. Wong @ 2016-11-09  7:53 UTC (permalink / raw)
  To: Eryu Guan; +Cc: david, linux-xfs, fstests

On Wed, Nov 09, 2016 at 11:44:11AM +0800, Eryu Guan wrote:
> [sorry, more comments on this patch]
> 
> On Fri, Nov 04, 2016 at 05:17:54PM -0700, Darrick J. Wong wrote:
> > Create some routines to help us perform targeted fuzzing of individual
> > fields in various XFS structures.  Specifically, we want the caller to
> > drop the xfs_db iocursor on the victim field; from there, the scripts
> > should discover all available fields and fuzzing verbs, and try each
> > fuzz verb on every available field.
> > 
> > Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
> > ---
> >  common/fuzzy |  191 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> >  1 file changed, 191 insertions(+)
> > 
> > 
> [snip]
> > +
> > +# Make sure we have all the pieces we need for field fuzzing
> > +_require_scratch_xfs_fuzz_fields()
> > +{
> > +	_require_scratch
> > +	_require_scrub
> > +	_require_populate_commands
> > +	_require_command "$XFS_DB_PROG" "xfs_db"
> 
> This is included in _require_populate_commands, not needed here.

<nod>

> > +	_scratch_mkfs_xfs >/dev/null 2>&1
> > +	_scratch_xfs_db -x -c 'fuzz' 2>&1 | grep -q 'not found' && \
> > +		_notrun "xfs_db does not have fuzz command"
> 
> Does _require_xfs_db_command work here?

Apparently I forgot to update this after inventing _require_xfs_db_command.

Good catch!

--D

> 
> Thanks,
> Eryu
> 
> > +}
> > +
> > +# Grab the list of available fuzzing verbs
> > +_scratch_xfs_list_fuzz_verbs() {
> > +	if [ -n "${SCRATCH_XFS_LIST_FUZZ_VERBS}" ]; then
> > +		echo "${SCRATCH_XFS_LIST_FUZZ_VERBS}" | sed -e 's/ /\n/g'
> > +		return;
> > +	fi
> > +	_scratch_xfs_db -x -c 'sb 0' -c 'fuzz' | grep '^Verbs:' | \
> > +		sed -e 's/[,.]//g' -e 's/Verbs: //g' -e 's/ /\n/g'
> > +}
> > +
> > +# Fuzz the fields of some piece of metadata
> > +_scratch_xfs_fuzz_fields() {
> > +	_scratch_xfs_list_metadata_fields "$@" | while read field; do
> > +		_scratch_xfs_list_fuzz_verbs | while read fuzzverb; do
> > +			__scratch_xfs_fuzz_mdrestore
> > +			__scratch_xfs_fuzz_field_test "${field}" "${fuzzverb}" "$@"
> > +		done
> > +	done
> > +}
> > 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-xfs" 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] 25+ messages in thread

* Re: [PATCH 8/9] xfs: fuzz every field of every structure
  2016-11-05  0:18 ` [PATCH 8/9] xfs: fuzz every field of every structure Darrick J. Wong
@ 2016-11-09  8:09     ` Eryu Guan
  0 siblings, 0 replies; 25+ messages in thread
From: Eryu Guan @ 2016-11-09  8:09 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: david, linux-xfs, fstests

On Fri, Nov 04, 2016 at 05:18:00PM -0700, Darrick J. Wong wrote:
> Previously, our XFS fuzzing efforts were limited to using the xfs_db
> blocktrash command to scribble garbage all over a block.  This is
> pretty easy to discover; it would be far more interesting if we could
> fuzz individual fields looking for unhandled corner cases.  Since we
> now have an online scrub tool, use it to check for our targeted
> corruptions prior to the usual steps of writing to the FS, taking it
> offline, repairing, and re-checking.
> 
> These tests use the new xfs_db 'fuzz' command to test corner case
> handling of every field.  The 'print' command tells us which fields
> are available, and the fuzz command can write zeroes or ones to the
> field; set the high, middle, or low bit; add or subtract numbers; or
> randomize the field.  We loop through all fields and all fuzz verbs to
> see if we can trip up the kernel.
> 
> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>

The first test gave me a kernel crash :) xfs/1300 crashed your kernel
djwong-devel branch. I appended the console log at the end of this mail
if you have interest to see it.

And another xfs/1300 run gave me this failure message:

    +/mnt/testarea/scratch: Kernel lacks GETFSMAP; scrub will be less efficient. (xfs.c line 661)
    +/mnt/testarea/scratch: Kernel cannot help scrub metadata; scrub will be incomplete. (xfs.c line 661)
    +/mnt/testarea/scratch: Kernel cannot help scrub inodes; scrub will be incomplete. (xfs.c line 661)
    +/mnt/testarea/scratch: Kernel cannot help scrub extent map; scrub will be less efficient. (xfs.c line 661)

Is this known issue or something should be filtered out in the test?

And ext4/1300 generated large .out.bad file (51M), containing something
like:

+/mnt/testarea/scratch/test/68/S_IFREG.FMT_ETREE: extent (1101381632/2469888/4096) ends past end of filesystem at 31457280. (generic.c line 272)
+/mnt/testarea/scratch/test/68/S_IFREG.FMT_ETREE: extent (1101389824/2478080/4096) starts past end of filesystem at 31457280. (generic.c line 264)
+/mnt/testarea/scratch/test/68/S_IFREG.FMT_ETREE: extent (1101389824/2478080/4096) ends past end of filesystem at 31457280. (generic.c line 272)
+/mnt/testarea/scratch/test/68/S_IFREG.FMT_ETREE: extent (1101398016/2486272/4096) starts past end of filesystem at 31457280. (generic.c line 264)
+/mnt/testarea/scratch/test/68/S_IFREG.FMT_ETREE: extent (1101398016/2486272/4096) ends past end of filesystem at 31457280. (generic.c line 272)
+/mnt/testarea/scratch/test/68/S_IFREG.FMT_ETREE: extent (1101406208/2494464/4096) starts past end of filesystem at 31457280. (generic.c line 264)
+/mnt/testarea/scratch/test/68/S_IFREG.FMT_ETREE: extent (1101406208/2494464/4096) ends past end of filesystem at 31457280. (generic.c line 272)
+/mnt/testarea/scratch/test/68/S_IFREG.FMT_ETREE: extent (1101414400/2502656/4096) starts past end of filesystem at 31457280. (generic.c line 264)
+/mnt/testarea/scratch/test/68/S_IFREG.FMT_ETREE: extent (1101414400/2502656/4096) ends past end of filesystem at 31457280. (generic.c line 272)

Seems like scrub found something wrong (real problems) and became very
noisy?

More comments inline below.

> ---
>  common/fuzzy        |   49 ++++++++++++++++++++++++++++++------
>  common/populate     |   10 ++++---
>  common/rc           |   15 +++++++++++
>  tests/ext4/1300     |   60 ++++++++++++++++++++++++++++++++++++++++++++
[snip]
> 
> diff --git a/common/fuzzy b/common/fuzzy
> index 6af47f1..dbff744 100644
> --- a/common/fuzzy
> +++ b/common/fuzzy
> @@ -85,32 +85,47 @@ _scratch_scrub() {
>  # Filter the xfs_db print command's field debug information
>  # into field name and type.
>  __filter_xfs_db_print_fields() {
> +	filter="$1"
> +	if [ -z "${filter}" ] || [ "${filter}" = "nofilter" ]; then
> +		filter='^'
> +	fi
>  	grep ' = ' | while read key equals value; do
> -		fuzzkey="$(echo "${key}" | sed -e 's/\([a-zA-Z0-9_]*\)\[\([0-9]*\)-[0-9]*\]/\1[\2]/g')"
> -		if [[ "${value}" == "["* ]]; then
> +		# Filter out any keys with an array index >= 10, and
> +		# collapse any array range ("[1-195]") to the first item.
> +		fuzzkey="$(echo "${key}" | sed -e '/\([a-z]*\)\[\([0-9][0-9]\+\)\].*/d' -e 's/\([a-zA-Z0-9_]*\)\[\([0-9]*\)-[0-9]*\]/\1[\2]/g')"
> +		if [ -z "${fuzzkey}" ]; then
> +			continue
> +		elif [[ "${value}" == "["* ]]; then
>  			echo "${value}" | sed -e 's/^.//g' -e 's/.$//g' -e 's/,/\n/g' | while read subfield; do
>  				echo "${fuzzkey}.${subfield}"
>  			done
>  		else
>  			echo "${fuzzkey}"
>  		fi
> -	done
> +	done | egrep "${filter}"
>  }
>  
>  # Navigate to some part of the filesystem and print the field info.
> +# The first argument is an egrep filter for the fields
> +# The rest of the arguments are xfs_db commands to locate the metadata.
>  _scratch_xfs_list_metadata_fields() {
> +	filter="$1"
> +	shift
>  	if [ -n "${SCRATCH_XFS_LIST_METADATA_FIELDS}" ]; then
> -		echo "${SCRATCH_XFS_LIST_METADATA_FIELDS}" | sed -e 's/ /\n/g'
> +		echo "${SCRATCH_XFS_LIST_METADATA_FIELDS}" | \
> +			sed -e 's/ /\n/g' | __filter_xfs_db_print_fields "${filter}"
>  		return;
>  	fi
>  
>  	(for arg in "$@"; do
>  		echo "${arg}"
>  	done
> -	echo "print") | _scratch_xfs_db | __filter_xfs_db_print_fields
> +	echo "print") | _scratch_xfs_db | __filter_xfs_db_print_fields "${filter}"
>  }
>  
>  # Get a metadata field
> +# The first arg is the field name
> +# The rest of the arguments are xfs_db commands to find the metadata.
>  _scratch_xfs_get_metadata_field() {
>  	key="$1"
>  	shift
> @@ -124,6 +139,9 @@ _scratch_xfs_get_metadata_field() {
>  }
>  
>  # Set a metadata field
> +# The first arg is the field name
> +# The second arg is the new value
> +# The rest of the arguments are xfs_db commands to find the metadata.
>  _scratch_xfs_set_metadata_field() {
>  	key="$1"
>  	value="$2"
> @@ -136,6 +154,9 @@ _scratch_xfs_set_metadata_field() {
>  }
>  
>  # Fuzz a metadata field
> +# The first arg is the field name
> +# The second arg is the xfs_db fuzz verb
> +# The rest of the arguments are xfs_db commands to find the metadata.
>  _scratch_xfs_fuzz_metadata_field() {
>  	key="$1"
>  	value="$2"
> @@ -263,12 +284,24 @@ _scratch_xfs_list_fuzz_verbs() {
>  		sed -e 's/[,.]//g' -e 's/Verbs: //g' -e 's/ /\n/g'
>  }
>  
> -# Fuzz the fields of some piece of metadata
> -_scratch_xfs_fuzz_fields() {
> -	_scratch_xfs_list_metadata_fields "$@" | while read field; do
> +# Fuzz some of the fields of some piece of metadata
> +# The first argument is an egrep filter
> +# The rest of the arguments are xfs_db commands to locate the metadata.
> +_scratch_xfs_fuzz_some_fields() {
> +	filter="$1"
> +	shift
> +	echo "Fields we propose to fuzz: $@"
> +	_scratch_xfs_list_metadata_fields "${filter}" "$@"
> +	_scratch_xfs_list_metadata_fields "${filter}" "$@" | while read field; do
>  		_scratch_xfs_list_fuzz_verbs | while read fuzzverb; do
>  			__scratch_xfs_fuzz_mdrestore
>  			__scratch_xfs_fuzz_field_test "${field}" "${fuzzverb}" "$@"
>  		done
>  	done
>  }
> +
> +# Fuzz all of the fields of some piece of metadata
> +# All arguments are xfs_db commands to locate the metadata.
> +_scratch_xfs_fuzz_fields() {
> +	_scratch_xfs_fuzz_some_fields '' "$@"
> +}

I think all the fuzz update here should be folded to patch 7/9.

> diff --git a/common/populate b/common/populate
> index 15d68fc..7d103f0 100644
> --- a/common/populate
> +++ b/common/populate
> @@ -180,13 +180,13 @@ _scratch_xfs_populate() {
>  	# FMT_EXTENTS with a remote less-than-a-block value
>  	echo "+ attr extents with a remote less-than-a-block value"
>  	touch "${SCRATCH_MNT}/ATTR.FMT_EXTENTS_REMOTE3K"
> -	$XFS_IO_PROG -f -c "pwrite -S 0x43 0 3k" "${SCRATCH_MNT}/attrvalfile" > /dev/null
> +	$XFS_IO_PROG -f -c "pwrite -S 0x43 0 $((blksz - 300))" "${SCRATCH_MNT}/attrvalfile" > /dev/null
>  	attr -q -s user.remotebtreeattrname "${SCRATCH_MNT}/ATTR.FMT_EXTENTS_REMOTE3K" < "${SCRATCH_MNT}/attrvalfile"
>  
>  	# FMT_EXTENTS with a remote block-size value
>  	echo "+ attr extents with a remote one-block value"
>  	touch "${SCRATCH_MNT}/ATTR.FMT_EXTENTS_REMOTE4K"
> -	$XFS_IO_PROG -f -c "pwrite -S 0x44 0 4k" "${SCRATCH_MNT}/attrvalfile" > /dev/null
> +	$XFS_IO_PROG -f -c "pwrite -S 0x44 0 ${blksz}" "${SCRATCH_MNT}/attrvalfile" > /dev/null
>  	attr -q -s user.remotebtreeattrname "${SCRATCH_MNT}/ATTR.FMT_EXTENTS_REMOTE4K" < "${SCRATCH_MNT}/attrvalfile"
>  	rm -rf "${SCRATCH_MNT}/attrvalfile"
>  
> @@ -482,8 +482,8 @@ _scratch_xfs_populate_check() {
>  	__populate_check_xfs_aformat "${btree_attr}" "btree"
>  	__populate_check_xfs_agbtree_height "bno"
>  	__populate_check_xfs_agbtree_height "cnt"
> -	test -n $is_rmapbt && __populate_check_xfs_agbtree_height "rmap"
> -	test -n $is_reflink && __populate_check_xfs_agbtree_height "refcnt"
> +	test $is_rmapbt -ne 0 && __populate_check_xfs_agbtree_height "rmap"
> +	test $is_reflink -ne 0 && __populate_check_xfs_agbtree_height "refcnt"
>  }

And these folded to patch 1/9?

>  
>  # Check data fork format of ext4 file
> @@ -609,7 +609,7 @@ _scratch_populate_cached() {
>  	rm -rf "$(find "${POPULATE_METADUMP}" -mtime +2 2>/dev/null)"
>  
>  	# Throw away cached image if it doesn't match our spec.
> -	meta_descr="FSTYP ${FSTYP} MKFS_OPTIONS ${MKFS_OPTIONS} ARGS $@"
> +	meta_descr="FSTYP ${FSTYP} MKFS_OPTIONS $(_scratch_mkfs_options) ARGS $@"
>  	cmp -s "${POPULATE_METADUMP_DESCR}" <(echo "${meta_descr}") || rm -rf "${POPULATE_METADUMP}"
>  
>  	# Do we have a cached image?

This to patch 6/9?

Because we usually don't introduce something in patch 1 and fix them in
patch 2, I think :)

> diff --git a/common/rc b/common/rc
> index d904582..ec1f5de 100644
> --- a/common/rc
> +++ b/common/rc
> @@ -1870,6 +1870,21 @@ _require_xfs_finobt()
>  	_scratch_unmount
>  }
>  
> +# Do we have a fre
> +_require_scratch_finobt()
> +{
> +	_require_scratch
> +
> +	if [ $FSTYP != "xfs" ]; then
> +		_notrun "finobt not supported by scratch filesystem type: $FSTYP"
> +		return
> +	fi
> +	_scratch_mkfs > /dev/null
> +	_scratch_mount
> +	xfs_info $SCRATCH_MNT | grep -q 'finobt=1' || _notrun "finobt not supported by scratch filesystem type: $FSTYP"
> +	_scratch_unmount
> +}
> +
>  # this test requires xfs sysfs attribute support
>  #
>  _require_xfs_sysfs()
> diff --git a/tests/ext4/1300 b/tests/ext4/1300
> new file mode 100755
> index 0000000..3f8135e
> --- /dev/null
> +++ b/tests/ext4/1300

[all the tests look fine to me, snip]

> --- a/tests/xfs/group
> +++ b/tests/xfs/group
> @@ -333,3 +333,34 @@
>  345 auto quick clone
>  346 auto quick clone
>  347 auto quick clone
> +1300 dangerous_fuzzers scrub

ext4/1300 is "auto quick scrub", I think xfs/1300 should be in auto
group too?

Thanks,
Eryu

P.S. console log of xfs/1300 crash

[165877.766244] BUG: unable to handle kernel NULL pointer dereference at 0000000000000038
[165877.774197] IP: [<ffffffffa0680c13>] xfs_scrub_get_inode+0xc3/0x1c0 [xfs]
[165877.781162] PGD 179c1b067 [165877.783784] PUD 14d994067
PMD 0 [165877.787130]
[165877.788722] Oops: 0000 [#1] SMP
[165877.791951] Modules linked in: dm_delay dm_zero btrfs xor raid6_pq dm_thin_pool dm_persistent_data dm_bio_prison dm_snapshot dm_bufio loop dm_flakey xfs libcrc32c binfmt_misc ip6t_rpfilter ipt_REJECT nf_reject_ipv4 nf_conntrack_ipv4 nf_defrag_ipv4 ip6t_REJECT nf_reject_ipv6 nf_conntrack_ipv6 nf_defrag_ipv6 xt_conntrack nf_conntrack ip_set nfnetlink ebtable_nat ebtable_broute bridge stp llc ip6table_mangle ip6table_security ip6table_raw iptable_mangle iptable_security iptable_raw ebtable_filter ebtables ip6table_filter ip6_tables iptable_filter coretemp kvm_intel kvm irqbypass crc32_pclmul ghash_clmulni_intel aesni_intel lrw iTCO_wdt gf128mul glue_helper ipmi_devintf cdc_ether iTCO_vendor_support ablk_helper cryptd usbnet i2c_i801 lpc_ich mii pcspkr i2c_smbus sg i7core_edac mfd_core ipmi_si edac_core ipmi_msghandler shpchp ioatdma dca acpi_cpufreq nfsd auth_rpcgss nfs_acl lockd grace sunrpc ip_tables ext4 jbd2 mbcache sr_mod sd_mod cdrom mgag200 i2c_algo_bit drm_kms_helpe!
 r syscopyarea sysfillrect sysimgblt fb_sys_fops ttm ata_generic pata_acpi drm ata_piix libata crc32c_intel megaraid_sas serio_raw i2c_core bnx2 dm_mirror dm_region_hash dm_log dm_mod [last unloaded: scsi_debug]
[165877.898708] CPU: 5 PID: 26242 Comm: xfs_scrub Tainted: G        W       4.9.0-rc3.djwong+ #16
[165877.907308] Hardware name: IBM System x3550 M3 -[7944OEJ]-/90Y4784     , BIOS -[D6E150CUS-1.11]- 02/08/2011
[165877.917124] task: ffff88017a286a40 task.stack: ffffc9000cca0000
[165877.923126] RIP: 0010:[<ffffffffa0680c13>]  [<ffffffffa0680c13>] xfs_scrub_get_inode+0xc3/0x1c0 [xfs]
[165877.932503] RSP: 0018:ffffc9000cca3ad0  EFLAGS: 00010246
[165877.937898] RAX: 0000000000000000 RBX: fffffffffffffffe RCX: 0000000000000017
[165877.945111] RDX: 0000000000000000 RSI: ffffc9000cca3ce8 RDI: 0000000000001123
[165877.952328] RBP: ffffc9000cca3b20 R08: 0000000000000003 R09: 0000000000000014
[165877.959544] R10: 0000000000000000 R11: 0000000000000000 R12: ffff880278f59680
[165877.966759] R13: ffffc9000cca3ba8 R14: ffffc9000cca3ce8 R15: 0000000000000000
[165877.973976] FS:  00007f3d099f9700(0000) GS:ffff88017bb00000(0000) knlGS:0000000000000000
[165877.982143] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[165877.987969] CR2: 0000000000000038 CR3: 000000016ad2d000 CR4: 00000000000006e0
[165877.995185] Stack:
[165877.997286]  ffff880278f59680 0000000000000000 ffff880220cc5c00 ffff880265190780
[165878.004840]  ffff880101a67800 ffffc9000cca3ba8 ffff880278f59680 ffff88025a9e6000
[165878.012396]  ffffc9000cca3ce8 0000000000000000 ffffc9000cca3b58 ffffffffa0681a61
[165878.019950] Call Trace:
[165878.022551]  [<ffffffffa0681a61>] __xfs_scrub_setup_inode.isra.63+0x81/0x280 [xfs]
[165878.030236]  [<ffffffffa0681c70>] xfs_scrub_setup_inode+0x10/0x20 [xfs]
[165878.036963]  [<ffffffffa068f57f>] xfs_scrub_metadata+0x2ff/0x450 [xfs]
[165878.043607]  [<ffffffffa066aa1d>] xfs_ioc_scrub_metadata+0x4d/0x80 [xfs]
[165878.050424]  [<ffffffffa066d029>] xfs_file_ioctl+0x9c9/0xb10 [xfs]
[165878.056689]  [<ffffffff8110692f>] ? get_futex_key+0x1df/0x360
[165878.062516]  [<ffffffff81106b31>] ? futex_wake+0x81/0x150
[165878.068003]  [<ffffffff812189c6>] do_vfs_ioctl+0x96/0x5b0
[165878.073482]  [<ffffffff81218f59>] SyS_ioctl+0x79/0x90
[165878.078621]  [<ffffffff81003997>] do_syscall_64+0x67/0x180
[165878.084191]  [<ffffffff816a6c2b>] entry_SYSCALL64_slow_path+0x25/0x25
[165878.090714] Code: 8b 14 24 49 8b 75 00 85 c0 41 89 c7 44 0f b6 82 93 00 00 00 44 0f b6 8a 94 00 00 00 0f b6 8a 53 02 00 00 49 8b 55 08 48 8b 7e 08 <4c> 8b 62 38 75 38 48 8b 7d d0 8b 46 10 39 87 98 03 00 00 74 21
[165878.110930] RIP  [<ffffffffa0680c13>] xfs_scrub_get_inode+0xc3/0x1c0 [xfs]
[165878.117938]  RSP <ffffc9000cca3ad0>
[165878.121512] CR2: 0000000000000038
[165878.129219] ---[ end trace d23e56c58f53ccb9 ]---

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

* Re: [PATCH 8/9] xfs: fuzz every field of every structure
@ 2016-11-09  8:09     ` Eryu Guan
  0 siblings, 0 replies; 25+ messages in thread
From: Eryu Guan @ 2016-11-09  8:09 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: david, linux-xfs, fstests

On Fri, Nov 04, 2016 at 05:18:00PM -0700, Darrick J. Wong wrote:
> Previously, our XFS fuzzing efforts were limited to using the xfs_db
> blocktrash command to scribble garbage all over a block.  This is
> pretty easy to discover; it would be far more interesting if we could
> fuzz individual fields looking for unhandled corner cases.  Since we
> now have an online scrub tool, use it to check for our targeted
> corruptions prior to the usual steps of writing to the FS, taking it
> offline, repairing, and re-checking.
> 
> These tests use the new xfs_db 'fuzz' command to test corner case
> handling of every field.  The 'print' command tells us which fields
> are available, and the fuzz command can write zeroes or ones to the
> field; set the high, middle, or low bit; add or subtract numbers; or
> randomize the field.  We loop through all fields and all fuzz verbs to
> see if we can trip up the kernel.
> 
> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>

The first test gave me a kernel crash :) xfs/1300 crashed your kernel
djwong-devel branch. I appended the console log at the end of this mail
if you have interest to see it.

And another xfs/1300 run gave me this failure message:

    +/mnt/testarea/scratch: Kernel lacks GETFSMAP; scrub will be less efficient. (xfs.c line 661)
    +/mnt/testarea/scratch: Kernel cannot help scrub metadata; scrub will be incomplete. (xfs.c line 661)
    +/mnt/testarea/scratch: Kernel cannot help scrub inodes; scrub will be incomplete. (xfs.c line 661)
    +/mnt/testarea/scratch: Kernel cannot help scrub extent map; scrub will be less efficient. (xfs.c line 661)

Is this known issue or something should be filtered out in the test?

And ext4/1300 generated large .out.bad file (51M), containing something
like:

+/mnt/testarea/scratch/test/68/S_IFREG.FMT_ETREE: extent (1101381632/2469888/4096) ends past end of filesystem at 31457280. (generic.c line 272)
+/mnt/testarea/scratch/test/68/S_IFREG.FMT_ETREE: extent (1101389824/2478080/4096) starts past end of filesystem at 31457280. (generic.c line 264)
+/mnt/testarea/scratch/test/68/S_IFREG.FMT_ETREE: extent (1101389824/2478080/4096) ends past end of filesystem at 31457280. (generic.c line 272)
+/mnt/testarea/scratch/test/68/S_IFREG.FMT_ETREE: extent (1101398016/2486272/4096) starts past end of filesystem at 31457280. (generic.c line 264)
+/mnt/testarea/scratch/test/68/S_IFREG.FMT_ETREE: extent (1101398016/2486272/4096) ends past end of filesystem at 31457280. (generic.c line 272)
+/mnt/testarea/scratch/test/68/S_IFREG.FMT_ETREE: extent (1101406208/2494464/4096) starts past end of filesystem at 31457280. (generic.c line 264)
+/mnt/testarea/scratch/test/68/S_IFREG.FMT_ETREE: extent (1101406208/2494464/4096) ends past end of filesystem at 31457280. (generic.c line 272)
+/mnt/testarea/scratch/test/68/S_IFREG.FMT_ETREE: extent (1101414400/2502656/4096) starts past end of filesystem at 31457280. (generic.c line 264)
+/mnt/testarea/scratch/test/68/S_IFREG.FMT_ETREE: extent (1101414400/2502656/4096) ends past end of filesystem at 31457280. (generic.c line 272)

Seems like scrub found something wrong (real problems) and became very
noisy?

More comments inline below.

> ---
>  common/fuzzy        |   49 ++++++++++++++++++++++++++++++------
>  common/populate     |   10 ++++---
>  common/rc           |   15 +++++++++++
>  tests/ext4/1300     |   60 ++++++++++++++++++++++++++++++++++++++++++++
[snip]
> 
> diff --git a/common/fuzzy b/common/fuzzy
> index 6af47f1..dbff744 100644
> --- a/common/fuzzy
> +++ b/common/fuzzy
> @@ -85,32 +85,47 @@ _scratch_scrub() {
>  # Filter the xfs_db print command's field debug information
>  # into field name and type.
>  __filter_xfs_db_print_fields() {
> +	filter="$1"
> +	if [ -z "${filter}" ] || [ "${filter}" = "nofilter" ]; then
> +		filter='^'
> +	fi
>  	grep ' = ' | while read key equals value; do
> -		fuzzkey="$(echo "${key}" | sed -e 's/\([a-zA-Z0-9_]*\)\[\([0-9]*\)-[0-9]*\]/\1[\2]/g')"
> -		if [[ "${value}" == "["* ]]; then
> +		# Filter out any keys with an array index >= 10, and
> +		# collapse any array range ("[1-195]") to the first item.
> +		fuzzkey="$(echo "${key}" | sed -e '/\([a-z]*\)\[\([0-9][0-9]\+\)\].*/d' -e 's/\([a-zA-Z0-9_]*\)\[\([0-9]*\)-[0-9]*\]/\1[\2]/g')"
> +		if [ -z "${fuzzkey}" ]; then
> +			continue
> +		elif [[ "${value}" == "["* ]]; then
>  			echo "${value}" | sed -e 's/^.//g' -e 's/.$//g' -e 's/,/\n/g' | while read subfield; do
>  				echo "${fuzzkey}.${subfield}"
>  			done
>  		else
>  			echo "${fuzzkey}"
>  		fi
> -	done
> +	done | egrep "${filter}"
>  }
>  
>  # Navigate to some part of the filesystem and print the field info.
> +# The first argument is an egrep filter for the fields
> +# The rest of the arguments are xfs_db commands to locate the metadata.
>  _scratch_xfs_list_metadata_fields() {
> +	filter="$1"
> +	shift
>  	if [ -n "${SCRATCH_XFS_LIST_METADATA_FIELDS}" ]; then
> -		echo "${SCRATCH_XFS_LIST_METADATA_FIELDS}" | sed -e 's/ /\n/g'
> +		echo "${SCRATCH_XFS_LIST_METADATA_FIELDS}" | \
> +			sed -e 's/ /\n/g' | __filter_xfs_db_print_fields "${filter}"
>  		return;
>  	fi
>  
>  	(for arg in "$@"; do
>  		echo "${arg}"
>  	done
> -	echo "print") | _scratch_xfs_db | __filter_xfs_db_print_fields
> +	echo "print") | _scratch_xfs_db | __filter_xfs_db_print_fields "${filter}"
>  }
>  
>  # Get a metadata field
> +# The first arg is the field name
> +# The rest of the arguments are xfs_db commands to find the metadata.
>  _scratch_xfs_get_metadata_field() {
>  	key="$1"
>  	shift
> @@ -124,6 +139,9 @@ _scratch_xfs_get_metadata_field() {
>  }
>  
>  # Set a metadata field
> +# The first arg is the field name
> +# The second arg is the new value
> +# The rest of the arguments are xfs_db commands to find the metadata.
>  _scratch_xfs_set_metadata_field() {
>  	key="$1"
>  	value="$2"
> @@ -136,6 +154,9 @@ _scratch_xfs_set_metadata_field() {
>  }
>  
>  # Fuzz a metadata field
> +# The first arg is the field name
> +# The second arg is the xfs_db fuzz verb
> +# The rest of the arguments are xfs_db commands to find the metadata.
>  _scratch_xfs_fuzz_metadata_field() {
>  	key="$1"
>  	value="$2"
> @@ -263,12 +284,24 @@ _scratch_xfs_list_fuzz_verbs() {
>  		sed -e 's/[,.]//g' -e 's/Verbs: //g' -e 's/ /\n/g'
>  }
>  
> -# Fuzz the fields of some piece of metadata
> -_scratch_xfs_fuzz_fields() {
> -	_scratch_xfs_list_metadata_fields "$@" | while read field; do
> +# Fuzz some of the fields of some piece of metadata
> +# The first argument is an egrep filter
> +# The rest of the arguments are xfs_db commands to locate the metadata.
> +_scratch_xfs_fuzz_some_fields() {
> +	filter="$1"
> +	shift
> +	echo "Fields we propose to fuzz: $@"
> +	_scratch_xfs_list_metadata_fields "${filter}" "$@"
> +	_scratch_xfs_list_metadata_fields "${filter}" "$@" | while read field; do
>  		_scratch_xfs_list_fuzz_verbs | while read fuzzverb; do
>  			__scratch_xfs_fuzz_mdrestore
>  			__scratch_xfs_fuzz_field_test "${field}" "${fuzzverb}" "$@"
>  		done
>  	done
>  }
> +
> +# Fuzz all of the fields of some piece of metadata
> +# All arguments are xfs_db commands to locate the metadata.
> +_scratch_xfs_fuzz_fields() {
> +	_scratch_xfs_fuzz_some_fields '' "$@"
> +}

I think all the fuzz update here should be folded to patch 7/9.

> diff --git a/common/populate b/common/populate
> index 15d68fc..7d103f0 100644
> --- a/common/populate
> +++ b/common/populate
> @@ -180,13 +180,13 @@ _scratch_xfs_populate() {
>  	# FMT_EXTENTS with a remote less-than-a-block value
>  	echo "+ attr extents with a remote less-than-a-block value"
>  	touch "${SCRATCH_MNT}/ATTR.FMT_EXTENTS_REMOTE3K"
> -	$XFS_IO_PROG -f -c "pwrite -S 0x43 0 3k" "${SCRATCH_MNT}/attrvalfile" > /dev/null
> +	$XFS_IO_PROG -f -c "pwrite -S 0x43 0 $((blksz - 300))" "${SCRATCH_MNT}/attrvalfile" > /dev/null
>  	attr -q -s user.remotebtreeattrname "${SCRATCH_MNT}/ATTR.FMT_EXTENTS_REMOTE3K" < "${SCRATCH_MNT}/attrvalfile"
>  
>  	# FMT_EXTENTS with a remote block-size value
>  	echo "+ attr extents with a remote one-block value"
>  	touch "${SCRATCH_MNT}/ATTR.FMT_EXTENTS_REMOTE4K"
> -	$XFS_IO_PROG -f -c "pwrite -S 0x44 0 4k" "${SCRATCH_MNT}/attrvalfile" > /dev/null
> +	$XFS_IO_PROG -f -c "pwrite -S 0x44 0 ${blksz}" "${SCRATCH_MNT}/attrvalfile" > /dev/null
>  	attr -q -s user.remotebtreeattrname "${SCRATCH_MNT}/ATTR.FMT_EXTENTS_REMOTE4K" < "${SCRATCH_MNT}/attrvalfile"
>  	rm -rf "${SCRATCH_MNT}/attrvalfile"
>  
> @@ -482,8 +482,8 @@ _scratch_xfs_populate_check() {
>  	__populate_check_xfs_aformat "${btree_attr}" "btree"
>  	__populate_check_xfs_agbtree_height "bno"
>  	__populate_check_xfs_agbtree_height "cnt"
> -	test -n $is_rmapbt && __populate_check_xfs_agbtree_height "rmap"
> -	test -n $is_reflink && __populate_check_xfs_agbtree_height "refcnt"
> +	test $is_rmapbt -ne 0 && __populate_check_xfs_agbtree_height "rmap"
> +	test $is_reflink -ne 0 && __populate_check_xfs_agbtree_height "refcnt"
>  }

And these folded to patch 1/9?

>  
>  # Check data fork format of ext4 file
> @@ -609,7 +609,7 @@ _scratch_populate_cached() {
>  	rm -rf "$(find "${POPULATE_METADUMP}" -mtime +2 2>/dev/null)"
>  
>  	# Throw away cached image if it doesn't match our spec.
> -	meta_descr="FSTYP ${FSTYP} MKFS_OPTIONS ${MKFS_OPTIONS} ARGS $@"
> +	meta_descr="FSTYP ${FSTYP} MKFS_OPTIONS $(_scratch_mkfs_options) ARGS $@"
>  	cmp -s "${POPULATE_METADUMP_DESCR}" <(echo "${meta_descr}") || rm -rf "${POPULATE_METADUMP}"
>  
>  	# Do we have a cached image?

This to patch 6/9?

Because we usually don't introduce something in patch 1 and fix them in
patch 2, I think :)

> diff --git a/common/rc b/common/rc
> index d904582..ec1f5de 100644
> --- a/common/rc
> +++ b/common/rc
> @@ -1870,6 +1870,21 @@ _require_xfs_finobt()
>  	_scratch_unmount
>  }
>  
> +# Do we have a fre
> +_require_scratch_finobt()
> +{
> +	_require_scratch
> +
> +	if [ $FSTYP != "xfs" ]; then
> +		_notrun "finobt not supported by scratch filesystem type: $FSTYP"
> +		return
> +	fi
> +	_scratch_mkfs > /dev/null
> +	_scratch_mount
> +	xfs_info $SCRATCH_MNT | grep -q 'finobt=1' || _notrun "finobt not supported by scratch filesystem type: $FSTYP"
> +	_scratch_unmount
> +}
> +
>  # this test requires xfs sysfs attribute support
>  #
>  _require_xfs_sysfs()
> diff --git a/tests/ext4/1300 b/tests/ext4/1300
> new file mode 100755
> index 0000000..3f8135e
> --- /dev/null
> +++ b/tests/ext4/1300

[all the tests look fine to me, snip]

> --- a/tests/xfs/group
> +++ b/tests/xfs/group
> @@ -333,3 +333,34 @@
>  345 auto quick clone
>  346 auto quick clone
>  347 auto quick clone
> +1300 dangerous_fuzzers scrub

ext4/1300 is "auto quick scrub", I think xfs/1300 should be in auto
group too?

Thanks,
Eryu

P.S. console log of xfs/1300 crash

[165877.766244] BUG: unable to handle kernel NULL pointer dereference at 0000000000000038
[165877.774197] IP: [<ffffffffa0680c13>] xfs_scrub_get_inode+0xc3/0x1c0 [xfs]
[165877.781162] PGD 179c1b067 [165877.783784] PUD 14d994067
PMD 0 [165877.787130]
[165877.788722] Oops: 0000 [#1] SMP
[165877.791951] Modules linked in: dm_delay dm_zero btrfs xor raid6_pq dm_thin_pool dm_persistent_data dm_bio_prison dm_snapshot dm_bufio loop dm_flakey xfs libcrc32c binfmt_misc ip6t_rpfilter ipt_REJECT nf_reject_ipv4 nf_conntrack_ipv4 nf_defrag_ipv4 ip6t_REJECT nf_reject_ipv6 nf_conntrack_ipv6 nf_defrag_ipv6 xt_conntrack nf_conntrack ip_set nfnetlink ebtable_nat ebtable_broute bridge stp llc ip6table_mangle ip6table_security ip6table_raw iptable_mangle iptable_security iptable_raw ebtable_filter ebtables ip6table_filter ip6_tables iptable_filter coretemp kvm_intel kvm irqbypass crc32_pclmul ghash_clmulni_intel aesni_intel lrw iTCO_wdt gf128mul glue_helper ipmi_devintf cdc_ether iTCO_vendor_support ablk_helper cryptd usbnet i2c_i801 lpc_ich mii pcspkr i2c_smbus sg i7core_edac mfd_core ipmi_si edac_core ipmi_msghandler shpchp ioatdma dca acpi_cpufreq nfsd auth_rpcgss nfs_acl lockd grace sunrpc ip_tables ext4 jbd2 mbcache sr_mod sd_mod cdrom mgag200 i2c_algo_bit drm_kms_helper syscopyarea sysfillrect sysimgblt fb_sys_fops ttm ata_generic pata_acpi drm ata_piix libata crc32c_intel megaraid_sas serio_raw i2c_core bnx2 dm_mirror dm_region_hash dm_log dm_mod [last unloaded: scsi_debug]
[165877.898708] CPU: 5 PID: 26242 Comm: xfs_scrub Tainted: G        W       4.9.0-rc3.djwong+ #16
[165877.907308] Hardware name: IBM System x3550 M3 -[7944OEJ]-/90Y4784     , BIOS -[D6E150CUS-1.11]- 02/08/2011
[165877.917124] task: ffff88017a286a40 task.stack: ffffc9000cca0000
[165877.923126] RIP: 0010:[<ffffffffa0680c13>]  [<ffffffffa0680c13>] xfs_scrub_get_inode+0xc3/0x1c0 [xfs]
[165877.932503] RSP: 0018:ffffc9000cca3ad0  EFLAGS: 00010246
[165877.937898] RAX: 0000000000000000 RBX: fffffffffffffffe RCX: 0000000000000017
[165877.945111] RDX: 0000000000000000 RSI: ffffc9000cca3ce8 RDI: 0000000000001123
[165877.952328] RBP: ffffc9000cca3b20 R08: 0000000000000003 R09: 0000000000000014
[165877.959544] R10: 0000000000000000 R11: 0000000000000000 R12: ffff880278f59680
[165877.966759] R13: ffffc9000cca3ba8 R14: ffffc9000cca3ce8 R15: 0000000000000000
[165877.973976] FS:  00007f3d099f9700(0000) GS:ffff88017bb00000(0000) knlGS:0000000000000000
[165877.982143] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[165877.987969] CR2: 0000000000000038 CR3: 000000016ad2d000 CR4: 00000000000006e0
[165877.995185] Stack:
[165877.997286]  ffff880278f59680 0000000000000000 ffff880220cc5c00 ffff880265190780
[165878.004840]  ffff880101a67800 ffffc9000cca3ba8 ffff880278f59680 ffff88025a9e6000
[165878.012396]  ffffc9000cca3ce8 0000000000000000 ffffc9000cca3b58 ffffffffa0681a61
[165878.019950] Call Trace:
[165878.022551]  [<ffffffffa0681a61>] __xfs_scrub_setup_inode.isra.63+0x81/0x280 [xfs]
[165878.030236]  [<ffffffffa0681c70>] xfs_scrub_setup_inode+0x10/0x20 [xfs]
[165878.036963]  [<ffffffffa068f57f>] xfs_scrub_metadata+0x2ff/0x450 [xfs]
[165878.043607]  [<ffffffffa066aa1d>] xfs_ioc_scrub_metadata+0x4d/0x80 [xfs]
[165878.050424]  [<ffffffffa066d029>] xfs_file_ioctl+0x9c9/0xb10 [xfs]
[165878.056689]  [<ffffffff8110692f>] ? get_futex_key+0x1df/0x360
[165878.062516]  [<ffffffff81106b31>] ? futex_wake+0x81/0x150
[165878.068003]  [<ffffffff812189c6>] do_vfs_ioctl+0x96/0x5b0
[165878.073482]  [<ffffffff81218f59>] SyS_ioctl+0x79/0x90
[165878.078621]  [<ffffffff81003997>] do_syscall_64+0x67/0x180
[165878.084191]  [<ffffffff816a6c2b>] entry_SYSCALL64_slow_path+0x25/0x25
[165878.090714] Code: 8b 14 24 49 8b 75 00 85 c0 41 89 c7 44 0f b6 82 93 00 00 00 44 0f b6 8a 94 00 00 00 0f b6 8a 53 02 00 00 49 8b 55 08 48 8b 7e 08 <4c> 8b 62 38 75 38 48 8b 7d d0 8b 46 10 39 87 98 03 00 00 74 21
[165878.110930] RIP  [<ffffffffa0680c13>] xfs_scrub_get_inode+0xc3/0x1c0 [xfs]
[165878.117938]  RSP <ffffc9000cca3ad0>
[165878.121512] CR2: 0000000000000038
[165878.129219] ---[ end trace d23e56c58f53ccb9 ]---

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

* Re: [PATCH 8/9] xfs: fuzz every field of every structure
  2016-11-09  8:09     ` Eryu Guan
@ 2016-11-09  8:52       ` Darrick J. Wong
  -1 siblings, 0 replies; 25+ messages in thread
From: Darrick J. Wong @ 2016-11-09  8:52 UTC (permalink / raw)
  To: Eryu Guan; +Cc: david, linux-xfs, fstests

On Wed, Nov 09, 2016 at 04:09:24PM +0800, Eryu Guan wrote:
> On Fri, Nov 04, 2016 at 05:18:00PM -0700, Darrick J. Wong wrote:
> > Previously, our XFS fuzzing efforts were limited to using the xfs_db
> > blocktrash command to scribble garbage all over a block.  This is
> > pretty easy to discover; it would be far more interesting if we could
> > fuzz individual fields looking for unhandled corner cases.  Since we
> > now have an online scrub tool, use it to check for our targeted
> > corruptions prior to the usual steps of writing to the FS, taking it
> > offline, repairing, and re-checking.
> > 
> > These tests use the new xfs_db 'fuzz' command to test corner case
> > handling of every field.  The 'print' command tells us which fields
> > are available, and the fuzz command can write zeroes or ones to the
> > field; set the high, middle, or low bit; add or subtract numbers; or
> > randomize the field.  We loop through all fields and all fuzz verbs to
> > see if we can trip up the kernel.
> > 
> > Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
> 
> The first test gave me a kernel crash :) xfs/1300 crashed your kernel
> djwong-devel branch. I appended the console log at the end of this mail
> if you have interest to see it.
> 
> And another xfs/1300 run gave me this failure message:
> 
>     +/mnt/testarea/scratch: Kernel lacks GETFSMAP; scrub will be less efficient. (xfs.c line 661)
>     +/mnt/testarea/scratch: Kernel cannot help scrub metadata; scrub will be incomplete. (xfs.c line 661)
>     +/mnt/testarea/scratch: Kernel cannot help scrub inodes; scrub will be incomplete. (xfs.c line 661)
>     +/mnt/testarea/scratch: Kernel cannot help scrub extent map; scrub will be less efficient. (xfs.c line 661)
> 
> Is this known issue or something should be filtered out in the test?

That's strange, the djwong-devel branch should have getfsmap & scrub in it...

...are you running the djwong-devel kernel and xfsprogs code?  The scrub
ioctl structure has shifted some over the past few months, though GETFSMAP
hasn't changed in ages.

Wait, "another xfs/1300 run" ... so after the first crash, did you go
back to a vanilla kernel without all my crazypatches? :)

> And ext4/1300 generated large .out.bad file (51M), containing something
> like:
> 
> +/mnt/testarea/scratch/test/68/S_IFREG.FMT_ETREE: extent (1101381632/2469888/4096) ends past end of filesystem at 31457280. (generic.c line 272)
> +/mnt/testarea/scratch/test/68/S_IFREG.FMT_ETREE: extent (1101389824/2478080/4096) starts past end of filesystem at 31457280. (generic.c line 264)
> +/mnt/testarea/scratch/test/68/S_IFREG.FMT_ETREE: extent (1101389824/2478080/4096) ends past end of filesystem at 31457280. (generic.c line 272)
> +/mnt/testarea/scratch/test/68/S_IFREG.FMT_ETREE: extent (1101398016/2486272/4096) starts past end of filesystem at 31457280. (generic.c line 264)
> +/mnt/testarea/scratch/test/68/S_IFREG.FMT_ETREE: extent (1101398016/2486272/4096) ends past end of filesystem at 31457280. (generic.c line 272)
> +/mnt/testarea/scratch/test/68/S_IFREG.FMT_ETREE: extent (1101406208/2494464/4096) starts past end of filesystem at 31457280. (generic.c line 264)
> +/mnt/testarea/scratch/test/68/S_IFREG.FMT_ETREE: extent (1101406208/2494464/4096) ends past end of filesystem at 31457280. (generic.c line 272)
> +/mnt/testarea/scratch/test/68/S_IFREG.FMT_ETREE: extent (1101414400/2502656/4096) starts past end of filesystem at 31457280. (generic.c line 264)
> +/mnt/testarea/scratch/test/68/S_IFREG.FMT_ETREE: extent (1101414400/2502656/4096) ends past end of filesystem at 31457280. (generic.c line 272)
> 
> Seems like scrub found something wrong (real problems) and became very
> noisy?

Hmm that's even stranger.  I'll try to reproduce tomorrow.

> More comments inline below.
> 
> > ---
> >  common/fuzzy        |   49 ++++++++++++++++++++++++++++++------
> >  common/populate     |   10 ++++---
> >  common/rc           |   15 +++++++++++
> >  tests/ext4/1300     |   60 ++++++++++++++++++++++++++++++++++++++++++++
> [snip]
> > 
> > diff --git a/common/fuzzy b/common/fuzzy
> > index 6af47f1..dbff744 100644
> > --- a/common/fuzzy
> > +++ b/common/fuzzy
> > @@ -85,32 +85,47 @@ _scratch_scrub() {
> >  # Filter the xfs_db print command's field debug information
> >  # into field name and type.
> >  __filter_xfs_db_print_fields() {
> > +	filter="$1"
> > +	if [ -z "${filter}" ] || [ "${filter}" = "nofilter" ]; then
> > +		filter='^'
> > +	fi
> >  	grep ' = ' | while read key equals value; do
> > -		fuzzkey="$(echo "${key}" | sed -e 's/\([a-zA-Z0-9_]*\)\[\([0-9]*\)-[0-9]*\]/\1[\2]/g')"
> > -		if [[ "${value}" == "["* ]]; then
> > +		# Filter out any keys with an array index >= 10, and
> > +		# collapse any array range ("[1-195]") to the first item.
> > +		fuzzkey="$(echo "${key}" | sed -e '/\([a-z]*\)\[\([0-9][0-9]\+\)\].*/d' -e 's/\([a-zA-Z0-9_]*\)\[\([0-9]*\)-[0-9]*\]/\1[\2]/g')"
> > +		if [ -z "${fuzzkey}" ]; then
> > +			continue
> > +		elif [[ "${value}" == "["* ]]; then
> >  			echo "${value}" | sed -e 's/^.//g' -e 's/.$//g' -e 's/,/\n/g' | while read subfield; do
> >  				echo "${fuzzkey}.${subfield}"
> >  			done
> >  		else
> >  			echo "${fuzzkey}"
> >  		fi
> > -	done
> > +	done | egrep "${filter}"
> >  }
> >  
> >  # Navigate to some part of the filesystem and print the field info.
> > +# The first argument is an egrep filter for the fields
> > +# The rest of the arguments are xfs_db commands to locate the metadata.
> >  _scratch_xfs_list_metadata_fields() {
> > +	filter="$1"
> > +	shift
> >  	if [ -n "${SCRATCH_XFS_LIST_METADATA_FIELDS}" ]; then
> > -		echo "${SCRATCH_XFS_LIST_METADATA_FIELDS}" | sed -e 's/ /\n/g'
> > +		echo "${SCRATCH_XFS_LIST_METADATA_FIELDS}" | \
> > +			sed -e 's/ /\n/g' | __filter_xfs_db_print_fields "${filter}"
> >  		return;
> >  	fi
> >  
> >  	(for arg in "$@"; do
> >  		echo "${arg}"
> >  	done
> > -	echo "print") | _scratch_xfs_db | __filter_xfs_db_print_fields
> > +	echo "print") | _scratch_xfs_db | __filter_xfs_db_print_fields "${filter}"
> >  }
> >  
> >  # Get a metadata field
> > +# The first arg is the field name
> > +# The rest of the arguments are xfs_db commands to find the metadata.
> >  _scratch_xfs_get_metadata_field() {
> >  	key="$1"
> >  	shift
> > @@ -124,6 +139,9 @@ _scratch_xfs_get_metadata_field() {
> >  }
> >  
> >  # Set a metadata field
> > +# The first arg is the field name
> > +# The second arg is the new value
> > +# The rest of the arguments are xfs_db commands to find the metadata.
> >  _scratch_xfs_set_metadata_field() {
> >  	key="$1"
> >  	value="$2"
> > @@ -136,6 +154,9 @@ _scratch_xfs_set_metadata_field() {
> >  }
> >  
> >  # Fuzz a metadata field
> > +# The first arg is the field name
> > +# The second arg is the xfs_db fuzz verb
> > +# The rest of the arguments are xfs_db commands to find the metadata.
> >  _scratch_xfs_fuzz_metadata_field() {
> >  	key="$1"
> >  	value="$2"
> > @@ -263,12 +284,24 @@ _scratch_xfs_list_fuzz_verbs() {
> >  		sed -e 's/[,.]//g' -e 's/Verbs: //g' -e 's/ /\n/g'
> >  }
> >  
> > -# Fuzz the fields of some piece of metadata
> > -_scratch_xfs_fuzz_fields() {
> > -	_scratch_xfs_list_metadata_fields "$@" | while read field; do
> > +# Fuzz some of the fields of some piece of metadata
> > +# The first argument is an egrep filter
> > +# The rest of the arguments are xfs_db commands to locate the metadata.
> > +_scratch_xfs_fuzz_some_fields() {
> > +	filter="$1"
> > +	shift
> > +	echo "Fields we propose to fuzz: $@"
> > +	_scratch_xfs_list_metadata_fields "${filter}" "$@"
> > +	_scratch_xfs_list_metadata_fields "${filter}" "$@" | while read field; do
> >  		_scratch_xfs_list_fuzz_verbs | while read fuzzverb; do
> >  			__scratch_xfs_fuzz_mdrestore
> >  			__scratch_xfs_fuzz_field_test "${field}" "${fuzzverb}" "$@"
> >  		done
> >  	done
> >  }
> > +
> > +# Fuzz all of the fields of some piece of metadata
> > +# All arguments are xfs_db commands to locate the metadata.
> > +_scratch_xfs_fuzz_fields() {
> > +	_scratch_xfs_fuzz_some_fields '' "$@"
> > +}
> 
> I think all the fuzz update here should be folded to patch 7/9.

(I'll look at the patch fixes in a separate reply tomorrow.)

> > diff --git a/common/populate b/common/populate
> > index 15d68fc..7d103f0 100644
> > --- a/common/populate
> > +++ b/common/populate
> > @@ -180,13 +180,13 @@ _scratch_xfs_populate() {
> >  	# FMT_EXTENTS with a remote less-than-a-block value
> >  	echo "+ attr extents with a remote less-than-a-block value"
> >  	touch "${SCRATCH_MNT}/ATTR.FMT_EXTENTS_REMOTE3K"
> > -	$XFS_IO_PROG -f -c "pwrite -S 0x43 0 3k" "${SCRATCH_MNT}/attrvalfile" > /dev/null
> > +	$XFS_IO_PROG -f -c "pwrite -S 0x43 0 $((blksz - 300))" "${SCRATCH_MNT}/attrvalfile" > /dev/null
> >  	attr -q -s user.remotebtreeattrname "${SCRATCH_MNT}/ATTR.FMT_EXTENTS_REMOTE3K" < "${SCRATCH_MNT}/attrvalfile"
> >  
> >  	# FMT_EXTENTS with a remote block-size value
> >  	echo "+ attr extents with a remote one-block value"
> >  	touch "${SCRATCH_MNT}/ATTR.FMT_EXTENTS_REMOTE4K"
> > -	$XFS_IO_PROG -f -c "pwrite -S 0x44 0 4k" "${SCRATCH_MNT}/attrvalfile" > /dev/null
> > +	$XFS_IO_PROG -f -c "pwrite -S 0x44 0 ${blksz}" "${SCRATCH_MNT}/attrvalfile" > /dev/null
> >  	attr -q -s user.remotebtreeattrname "${SCRATCH_MNT}/ATTR.FMT_EXTENTS_REMOTE4K" < "${SCRATCH_MNT}/attrvalfile"
> >  	rm -rf "${SCRATCH_MNT}/attrvalfile"
> >  
> > @@ -482,8 +482,8 @@ _scratch_xfs_populate_check() {
> >  	__populate_check_xfs_aformat "${btree_attr}" "btree"
> >  	__populate_check_xfs_agbtree_height "bno"
> >  	__populate_check_xfs_agbtree_height "cnt"
> > -	test -n $is_rmapbt && __populate_check_xfs_agbtree_height "rmap"
> > -	test -n $is_reflink && __populate_check_xfs_agbtree_height "refcnt"
> > +	test $is_rmapbt -ne 0 && __populate_check_xfs_agbtree_height "rmap"
> > +	test $is_reflink -ne 0 && __populate_check_xfs_agbtree_height "refcnt"
> >  }
> 
> And these folded to patch 1/9?
> 
> >  
> >  # Check data fork format of ext4 file
> > @@ -609,7 +609,7 @@ _scratch_populate_cached() {
> >  	rm -rf "$(find "${POPULATE_METADUMP}" -mtime +2 2>/dev/null)"
> >  
> >  	# Throw away cached image if it doesn't match our spec.
> > -	meta_descr="FSTYP ${FSTYP} MKFS_OPTIONS ${MKFS_OPTIONS} ARGS $@"
> > +	meta_descr="FSTYP ${FSTYP} MKFS_OPTIONS $(_scratch_mkfs_options) ARGS $@"
> >  	cmp -s "${POPULATE_METADUMP_DESCR}" <(echo "${meta_descr}") || rm -rf "${POPULATE_METADUMP}"
> >  
> >  	# Do we have a cached image?
> 
> This to patch 6/9?
> 
> Because we usually don't introduce something in patch 1 and fix them in
> patch 2, I think :)

Generally, yes. :)

> > diff --git a/common/rc b/common/rc
> > index d904582..ec1f5de 100644
> > --- a/common/rc
> > +++ b/common/rc
> > @@ -1870,6 +1870,21 @@ _require_xfs_finobt()
> >  	_scratch_unmount
> >  }
> >  
> > +# Do we have a fre
> > +_require_scratch_finobt()
> > +{
> > +	_require_scratch
> > +
> > +	if [ $FSTYP != "xfs" ]; then
> > +		_notrun "finobt not supported by scratch filesystem type: $FSTYP"
> > +		return
> > +	fi
> > +	_scratch_mkfs > /dev/null
> > +	_scratch_mount
> > +	xfs_info $SCRATCH_MNT | grep -q 'finobt=1' || _notrun "finobt not supported by scratch filesystem type: $FSTYP"
> > +	_scratch_unmount
> > +}
> > +
> >  # this test requires xfs sysfs attribute support
> >  #
> >  _require_xfs_sysfs()
> > diff --git a/tests/ext4/1300 b/tests/ext4/1300
> > new file mode 100755
> > index 0000000..3f8135e
> > --- /dev/null
> > +++ b/tests/ext4/1300
> 
> [all the tests look fine to me, snip]
> 
> > --- a/tests/xfs/group
> > +++ b/tests/xfs/group
> > @@ -333,3 +333,34 @@
> >  345 auto quick clone
> >  346 auto quick clone
> >  347 auto quick clone
> > +1300 dangerous_fuzzers scrub
> 
> ext4/1300 is "auto quick scrub", I think xfs/1300 should be in auto
> group too?
> 
> Thanks,
> Eryu
> 
> P.S. console log of xfs/1300 crash
> 
> [165877.766244] BUG: unable to handle kernel NULL pointer dereference at 0000000000000038
> [165877.774197] IP: [<ffffffffa0680c13>] xfs_scrub_get_inode+0xc3/0x1c0 [xfs]
> [165877.781162] PGD 179c1b067 [165877.783784] PUD 14d994067

Ohhh... I suspect this happens when xfs_scrub_op_ok tries to use sc->tp 
after some error happens, which we can't do because this function is
used in the process of initializing sc.

Gonna go cry in my beer for a day or two or something,

--D

> PMD 0 [165877.787130]
> [165877.788722] Oops: 0000 [#1] SMP
> [165877.791951] Modules linked in: dm_delay dm_zero btrfs xor raid6_pq dm_thin_pool dm_persistent_data dm_bio_prison dm_snapshot dm_bufio loop dm_flakey xfs libcrc32c binfmt_misc ip6t_rpfilter ipt_REJECT nf_reject_ipv4 nf_conntrack_ipv4 nf_defrag_ipv4 ip6t_REJECT nf_reject_ipv6 nf_conntrack_ipv6 nf_defrag_ipv6 xt_conntrack nf_conntrack ip_set nfnetlink ebtable_nat ebtable_broute bridge stp llc ip6table_mangle ip6table_security ip6table_raw iptable_mangle iptable_security iptable_raw ebtable_filter ebtables ip6table_filter ip6_tables iptable_filter coretemp kvm_intel kvm irqbypass crc32_pclmul ghash_clmulni_intel aesni_intel lrw iTCO_wdt gf128mul glue_helper ipmi_devintf cdc_ether iTCO_vendor_support ablk_helper cryptd usbnet i2c_i801 lpc_ich mii pcspkr i2c_smbus sg i7core_edac mfd_core ipmi_si edac_core ipmi_msghandler shpchp ioatdma dca acpi_cpufreq nfsd auth_rpcgss nfs_acl lockd grace sunrpc ip_tables ext4 jbd2 mbcache sr_mod sd_mod cdrom mgag200 i2c_algo_bit drm_kms_hel!
 pe!
>  r syscopyarea sysfillrect sysimgblt fb_sys_fops ttm ata_generic pata_acpi drm ata_piix libata crc32c_intel megaraid_sas serio_raw i2c_core bnx2 dm_mirror dm_region_hash dm_log dm_mod [last unloaded: scsi_debug]
> [165877.898708] CPU: 5 PID: 26242 Comm: xfs_scrub Tainted: G        W       4.9.0-rc3.djwong+ #16
> [165877.907308] Hardware name: IBM System x3550 M3 -[7944OEJ]-/90Y4784     , BIOS -[D6E150CUS-1.11]- 02/08/2011
> [165877.917124] task: ffff88017a286a40 task.stack: ffffc9000cca0000
> [165877.923126] RIP: 0010:[<ffffffffa0680c13>]  [<ffffffffa0680c13>] xfs_scrub_get_inode+0xc3/0x1c0 [xfs]
> [165877.932503] RSP: 0018:ffffc9000cca3ad0  EFLAGS: 00010246
> [165877.937898] RAX: 0000000000000000 RBX: fffffffffffffffe RCX: 0000000000000017
> [165877.945111] RDX: 0000000000000000 RSI: ffffc9000cca3ce8 RDI: 0000000000001123
> [165877.952328] RBP: ffffc9000cca3b20 R08: 0000000000000003 R09: 0000000000000014
> [165877.959544] R10: 0000000000000000 R11: 0000000000000000 R12: ffff880278f59680
> [165877.966759] R13: ffffc9000cca3ba8 R14: ffffc9000cca3ce8 R15: 0000000000000000
> [165877.973976] FS:  00007f3d099f9700(0000) GS:ffff88017bb00000(0000) knlGS:0000000000000000
> [165877.982143] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
> [165877.987969] CR2: 0000000000000038 CR3: 000000016ad2d000 CR4: 00000000000006e0
> [165877.995185] Stack:
> [165877.997286]  ffff880278f59680 0000000000000000 ffff880220cc5c00 ffff880265190780
> [165878.004840]  ffff880101a67800 ffffc9000cca3ba8 ffff880278f59680 ffff88025a9e6000
> [165878.012396]  ffffc9000cca3ce8 0000000000000000 ffffc9000cca3b58 ffffffffa0681a61
> [165878.019950] Call Trace:
> [165878.022551]  [<ffffffffa0681a61>] __xfs_scrub_setup_inode.isra.63+0x81/0x280 [xfs]
> [165878.030236]  [<ffffffffa0681c70>] xfs_scrub_setup_inode+0x10/0x20 [xfs]
> [165878.036963]  [<ffffffffa068f57f>] xfs_scrub_metadata+0x2ff/0x450 [xfs]
> [165878.043607]  [<ffffffffa066aa1d>] xfs_ioc_scrub_metadata+0x4d/0x80 [xfs]
> [165878.050424]  [<ffffffffa066d029>] xfs_file_ioctl+0x9c9/0xb10 [xfs]
> [165878.056689]  [<ffffffff8110692f>] ? get_futex_key+0x1df/0x360
> [165878.062516]  [<ffffffff81106b31>] ? futex_wake+0x81/0x150
> [165878.068003]  [<ffffffff812189c6>] do_vfs_ioctl+0x96/0x5b0
> [165878.073482]  [<ffffffff81218f59>] SyS_ioctl+0x79/0x90
> [165878.078621]  [<ffffffff81003997>] do_syscall_64+0x67/0x180
> [165878.084191]  [<ffffffff816a6c2b>] entry_SYSCALL64_slow_path+0x25/0x25
> [165878.090714] Code: 8b 14 24 49 8b 75 00 85 c0 41 89 c7 44 0f b6 82 93 00 00 00 44 0f b6 8a 94 00 00 00 0f b6 8a 53 02 00 00 49 8b 55 08 48 8b 7e 08 <4c> 8b 62 38 75 38 48 8b 7d d0 8b 46 10 39 87 98 03 00 00 74 21
> [165878.110930] RIP  [<ffffffffa0680c13>] xfs_scrub_get_inode+0xc3/0x1c0 [xfs]
> [165878.117938]  RSP <ffffc9000cca3ad0>
> [165878.121512] CR2: 0000000000000038
> [165878.129219] ---[ end trace d23e56c58f53ccb9 ]---
> --
> To unsubscribe from this list: send the line "unsubscribe linux-xfs" 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] 25+ messages in thread

* Re: [PATCH 8/9] xfs: fuzz every field of every structure
@ 2016-11-09  8:52       ` Darrick J. Wong
  0 siblings, 0 replies; 25+ messages in thread
From: Darrick J. Wong @ 2016-11-09  8:52 UTC (permalink / raw)
  To: Eryu Guan; +Cc: david, linux-xfs, fstests

On Wed, Nov 09, 2016 at 04:09:24PM +0800, Eryu Guan wrote:
> On Fri, Nov 04, 2016 at 05:18:00PM -0700, Darrick J. Wong wrote:
> > Previously, our XFS fuzzing efforts were limited to using the xfs_db
> > blocktrash command to scribble garbage all over a block.  This is
> > pretty easy to discover; it would be far more interesting if we could
> > fuzz individual fields looking for unhandled corner cases.  Since we
> > now have an online scrub tool, use it to check for our targeted
> > corruptions prior to the usual steps of writing to the FS, taking it
> > offline, repairing, and re-checking.
> > 
> > These tests use the new xfs_db 'fuzz' command to test corner case
> > handling of every field.  The 'print' command tells us which fields
> > are available, and the fuzz command can write zeroes or ones to the
> > field; set the high, middle, or low bit; add or subtract numbers; or
> > randomize the field.  We loop through all fields and all fuzz verbs to
> > see if we can trip up the kernel.
> > 
> > Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
> 
> The first test gave me a kernel crash :) xfs/1300 crashed your kernel
> djwong-devel branch. I appended the console log at the end of this mail
> if you have interest to see it.
> 
> And another xfs/1300 run gave me this failure message:
> 
>     +/mnt/testarea/scratch: Kernel lacks GETFSMAP; scrub will be less efficient. (xfs.c line 661)
>     +/mnt/testarea/scratch: Kernel cannot help scrub metadata; scrub will be incomplete. (xfs.c line 661)
>     +/mnt/testarea/scratch: Kernel cannot help scrub inodes; scrub will be incomplete. (xfs.c line 661)
>     +/mnt/testarea/scratch: Kernel cannot help scrub extent map; scrub will be less efficient. (xfs.c line 661)
> 
> Is this known issue or something should be filtered out in the test?

That's strange, the djwong-devel branch should have getfsmap & scrub in it...

...are you running the djwong-devel kernel and xfsprogs code?  The scrub
ioctl structure has shifted some over the past few months, though GETFSMAP
hasn't changed in ages.

Wait, "another xfs/1300 run" ... so after the first crash, did you go
back to a vanilla kernel without all my crazypatches? :)

> And ext4/1300 generated large .out.bad file (51M), containing something
> like:
> 
> +/mnt/testarea/scratch/test/68/S_IFREG.FMT_ETREE: extent (1101381632/2469888/4096) ends past end of filesystem at 31457280. (generic.c line 272)
> +/mnt/testarea/scratch/test/68/S_IFREG.FMT_ETREE: extent (1101389824/2478080/4096) starts past end of filesystem at 31457280. (generic.c line 264)
> +/mnt/testarea/scratch/test/68/S_IFREG.FMT_ETREE: extent (1101389824/2478080/4096) ends past end of filesystem at 31457280. (generic.c line 272)
> +/mnt/testarea/scratch/test/68/S_IFREG.FMT_ETREE: extent (1101398016/2486272/4096) starts past end of filesystem at 31457280. (generic.c line 264)
> +/mnt/testarea/scratch/test/68/S_IFREG.FMT_ETREE: extent (1101398016/2486272/4096) ends past end of filesystem at 31457280. (generic.c line 272)
> +/mnt/testarea/scratch/test/68/S_IFREG.FMT_ETREE: extent (1101406208/2494464/4096) starts past end of filesystem at 31457280. (generic.c line 264)
> +/mnt/testarea/scratch/test/68/S_IFREG.FMT_ETREE: extent (1101406208/2494464/4096) ends past end of filesystem at 31457280. (generic.c line 272)
> +/mnt/testarea/scratch/test/68/S_IFREG.FMT_ETREE: extent (1101414400/2502656/4096) starts past end of filesystem at 31457280. (generic.c line 264)
> +/mnt/testarea/scratch/test/68/S_IFREG.FMT_ETREE: extent (1101414400/2502656/4096) ends past end of filesystem at 31457280. (generic.c line 272)
> 
> Seems like scrub found something wrong (real problems) and became very
> noisy?

Hmm that's even stranger.  I'll try to reproduce tomorrow.

> More comments inline below.
> 
> > ---
> >  common/fuzzy        |   49 ++++++++++++++++++++++++++++++------
> >  common/populate     |   10 ++++---
> >  common/rc           |   15 +++++++++++
> >  tests/ext4/1300     |   60 ++++++++++++++++++++++++++++++++++++++++++++
> [snip]
> > 
> > diff --git a/common/fuzzy b/common/fuzzy
> > index 6af47f1..dbff744 100644
> > --- a/common/fuzzy
> > +++ b/common/fuzzy
> > @@ -85,32 +85,47 @@ _scratch_scrub() {
> >  # Filter the xfs_db print command's field debug information
> >  # into field name and type.
> >  __filter_xfs_db_print_fields() {
> > +	filter="$1"
> > +	if [ -z "${filter}" ] || [ "${filter}" = "nofilter" ]; then
> > +		filter='^'
> > +	fi
> >  	grep ' = ' | while read key equals value; do
> > -		fuzzkey="$(echo "${key}" | sed -e 's/\([a-zA-Z0-9_]*\)\[\([0-9]*\)-[0-9]*\]/\1[\2]/g')"
> > -		if [[ "${value}" == "["* ]]; then
> > +		# Filter out any keys with an array index >= 10, and
> > +		# collapse any array range ("[1-195]") to the first item.
> > +		fuzzkey="$(echo "${key}" | sed -e '/\([a-z]*\)\[\([0-9][0-9]\+\)\].*/d' -e 's/\([a-zA-Z0-9_]*\)\[\([0-9]*\)-[0-9]*\]/\1[\2]/g')"
> > +		if [ -z "${fuzzkey}" ]; then
> > +			continue
> > +		elif [[ "${value}" == "["* ]]; then
> >  			echo "${value}" | sed -e 's/^.//g' -e 's/.$//g' -e 's/,/\n/g' | while read subfield; do
> >  				echo "${fuzzkey}.${subfield}"
> >  			done
> >  		else
> >  			echo "${fuzzkey}"
> >  		fi
> > -	done
> > +	done | egrep "${filter}"
> >  }
> >  
> >  # Navigate to some part of the filesystem and print the field info.
> > +# The first argument is an egrep filter for the fields
> > +# The rest of the arguments are xfs_db commands to locate the metadata.
> >  _scratch_xfs_list_metadata_fields() {
> > +	filter="$1"
> > +	shift
> >  	if [ -n "${SCRATCH_XFS_LIST_METADATA_FIELDS}" ]; then
> > -		echo "${SCRATCH_XFS_LIST_METADATA_FIELDS}" | sed -e 's/ /\n/g'
> > +		echo "${SCRATCH_XFS_LIST_METADATA_FIELDS}" | \
> > +			sed -e 's/ /\n/g' | __filter_xfs_db_print_fields "${filter}"
> >  		return;
> >  	fi
> >  
> >  	(for arg in "$@"; do
> >  		echo "${arg}"
> >  	done
> > -	echo "print") | _scratch_xfs_db | __filter_xfs_db_print_fields
> > +	echo "print") | _scratch_xfs_db | __filter_xfs_db_print_fields "${filter}"
> >  }
> >  
> >  # Get a metadata field
> > +# The first arg is the field name
> > +# The rest of the arguments are xfs_db commands to find the metadata.
> >  _scratch_xfs_get_metadata_field() {
> >  	key="$1"
> >  	shift
> > @@ -124,6 +139,9 @@ _scratch_xfs_get_metadata_field() {
> >  }
> >  
> >  # Set a metadata field
> > +# The first arg is the field name
> > +# The second arg is the new value
> > +# The rest of the arguments are xfs_db commands to find the metadata.
> >  _scratch_xfs_set_metadata_field() {
> >  	key="$1"
> >  	value="$2"
> > @@ -136,6 +154,9 @@ _scratch_xfs_set_metadata_field() {
> >  }
> >  
> >  # Fuzz a metadata field
> > +# The first arg is the field name
> > +# The second arg is the xfs_db fuzz verb
> > +# The rest of the arguments are xfs_db commands to find the metadata.
> >  _scratch_xfs_fuzz_metadata_field() {
> >  	key="$1"
> >  	value="$2"
> > @@ -263,12 +284,24 @@ _scratch_xfs_list_fuzz_verbs() {
> >  		sed -e 's/[,.]//g' -e 's/Verbs: //g' -e 's/ /\n/g'
> >  }
> >  
> > -# Fuzz the fields of some piece of metadata
> > -_scratch_xfs_fuzz_fields() {
> > -	_scratch_xfs_list_metadata_fields "$@" | while read field; do
> > +# Fuzz some of the fields of some piece of metadata
> > +# The first argument is an egrep filter
> > +# The rest of the arguments are xfs_db commands to locate the metadata.
> > +_scratch_xfs_fuzz_some_fields() {
> > +	filter="$1"
> > +	shift
> > +	echo "Fields we propose to fuzz: $@"
> > +	_scratch_xfs_list_metadata_fields "${filter}" "$@"
> > +	_scratch_xfs_list_metadata_fields "${filter}" "$@" | while read field; do
> >  		_scratch_xfs_list_fuzz_verbs | while read fuzzverb; do
> >  			__scratch_xfs_fuzz_mdrestore
> >  			__scratch_xfs_fuzz_field_test "${field}" "${fuzzverb}" "$@"
> >  		done
> >  	done
> >  }
> > +
> > +# Fuzz all of the fields of some piece of metadata
> > +# All arguments are xfs_db commands to locate the metadata.
> > +_scratch_xfs_fuzz_fields() {
> > +	_scratch_xfs_fuzz_some_fields '' "$@"
> > +}
> 
> I think all the fuzz update here should be folded to patch 7/9.

(I'll look at the patch fixes in a separate reply tomorrow.)

> > diff --git a/common/populate b/common/populate
> > index 15d68fc..7d103f0 100644
> > --- a/common/populate
> > +++ b/common/populate
> > @@ -180,13 +180,13 @@ _scratch_xfs_populate() {
> >  	# FMT_EXTENTS with a remote less-than-a-block value
> >  	echo "+ attr extents with a remote less-than-a-block value"
> >  	touch "${SCRATCH_MNT}/ATTR.FMT_EXTENTS_REMOTE3K"
> > -	$XFS_IO_PROG -f -c "pwrite -S 0x43 0 3k" "${SCRATCH_MNT}/attrvalfile" > /dev/null
> > +	$XFS_IO_PROG -f -c "pwrite -S 0x43 0 $((blksz - 300))" "${SCRATCH_MNT}/attrvalfile" > /dev/null
> >  	attr -q -s user.remotebtreeattrname "${SCRATCH_MNT}/ATTR.FMT_EXTENTS_REMOTE3K" < "${SCRATCH_MNT}/attrvalfile"
> >  
> >  	# FMT_EXTENTS with a remote block-size value
> >  	echo "+ attr extents with a remote one-block value"
> >  	touch "${SCRATCH_MNT}/ATTR.FMT_EXTENTS_REMOTE4K"
> > -	$XFS_IO_PROG -f -c "pwrite -S 0x44 0 4k" "${SCRATCH_MNT}/attrvalfile" > /dev/null
> > +	$XFS_IO_PROG -f -c "pwrite -S 0x44 0 ${blksz}" "${SCRATCH_MNT}/attrvalfile" > /dev/null
> >  	attr -q -s user.remotebtreeattrname "${SCRATCH_MNT}/ATTR.FMT_EXTENTS_REMOTE4K" < "${SCRATCH_MNT}/attrvalfile"
> >  	rm -rf "${SCRATCH_MNT}/attrvalfile"
> >  
> > @@ -482,8 +482,8 @@ _scratch_xfs_populate_check() {
> >  	__populate_check_xfs_aformat "${btree_attr}" "btree"
> >  	__populate_check_xfs_agbtree_height "bno"
> >  	__populate_check_xfs_agbtree_height "cnt"
> > -	test -n $is_rmapbt && __populate_check_xfs_agbtree_height "rmap"
> > -	test -n $is_reflink && __populate_check_xfs_agbtree_height "refcnt"
> > +	test $is_rmapbt -ne 0 && __populate_check_xfs_agbtree_height "rmap"
> > +	test $is_reflink -ne 0 && __populate_check_xfs_agbtree_height "refcnt"
> >  }
> 
> And these folded to patch 1/9?
> 
> >  
> >  # Check data fork format of ext4 file
> > @@ -609,7 +609,7 @@ _scratch_populate_cached() {
> >  	rm -rf "$(find "${POPULATE_METADUMP}" -mtime +2 2>/dev/null)"
> >  
> >  	# Throw away cached image if it doesn't match our spec.
> > -	meta_descr="FSTYP ${FSTYP} MKFS_OPTIONS ${MKFS_OPTIONS} ARGS $@"
> > +	meta_descr="FSTYP ${FSTYP} MKFS_OPTIONS $(_scratch_mkfs_options) ARGS $@"
> >  	cmp -s "${POPULATE_METADUMP_DESCR}" <(echo "${meta_descr}") || rm -rf "${POPULATE_METADUMP}"
> >  
> >  	# Do we have a cached image?
> 
> This to patch 6/9?
> 
> Because we usually don't introduce something in patch 1 and fix them in
> patch 2, I think :)

Generally, yes. :)

> > diff --git a/common/rc b/common/rc
> > index d904582..ec1f5de 100644
> > --- a/common/rc
> > +++ b/common/rc
> > @@ -1870,6 +1870,21 @@ _require_xfs_finobt()
> >  	_scratch_unmount
> >  }
> >  
> > +# Do we have a fre
> > +_require_scratch_finobt()
> > +{
> > +	_require_scratch
> > +
> > +	if [ $FSTYP != "xfs" ]; then
> > +		_notrun "finobt not supported by scratch filesystem type: $FSTYP"
> > +		return
> > +	fi
> > +	_scratch_mkfs > /dev/null
> > +	_scratch_mount
> > +	xfs_info $SCRATCH_MNT | grep -q 'finobt=1' || _notrun "finobt not supported by scratch filesystem type: $FSTYP"
> > +	_scratch_unmount
> > +}
> > +
> >  # this test requires xfs sysfs attribute support
> >  #
> >  _require_xfs_sysfs()
> > diff --git a/tests/ext4/1300 b/tests/ext4/1300
> > new file mode 100755
> > index 0000000..3f8135e
> > --- /dev/null
> > +++ b/tests/ext4/1300
> 
> [all the tests look fine to me, snip]
> 
> > --- a/tests/xfs/group
> > +++ b/tests/xfs/group
> > @@ -333,3 +333,34 @@
> >  345 auto quick clone
> >  346 auto quick clone
> >  347 auto quick clone
> > +1300 dangerous_fuzzers scrub
> 
> ext4/1300 is "auto quick scrub", I think xfs/1300 should be in auto
> group too?
> 
> Thanks,
> Eryu
> 
> P.S. console log of xfs/1300 crash
> 
> [165877.766244] BUG: unable to handle kernel NULL pointer dereference at 0000000000000038
> [165877.774197] IP: [<ffffffffa0680c13>] xfs_scrub_get_inode+0xc3/0x1c0 [xfs]
> [165877.781162] PGD 179c1b067 [165877.783784] PUD 14d994067

Ohhh... I suspect this happens when xfs_scrub_op_ok tries to use sc->tp 
after some error happens, which we can't do because this function is
used in the process of initializing sc.

Gonna go cry in my beer for a day or two or something,

--D

> PMD 0 [165877.787130]
> [165877.788722] Oops: 0000 [#1] SMP
> [165877.791951] Modules linked in: dm_delay dm_zero btrfs xor raid6_pq dm_thin_pool dm_persistent_data dm_bio_prison dm_snapshot dm_bufio loop dm_flakey xfs libcrc32c binfmt_misc ip6t_rpfilter ipt_REJECT nf_reject_ipv4 nf_conntrack_ipv4 nf_defrag_ipv4 ip6t_REJECT nf_reject_ipv6 nf_conntrack_ipv6 nf_defrag_ipv6 xt_conntrack nf_conntrack ip_set nfnetlink ebtable_nat ebtable_broute bridge stp llc ip6table_mangle ip6table_security ip6table_raw iptable_mangle iptable_security iptable_raw ebtable_filter ebtables ip6table_filter ip6_tables iptable_filter coretemp kvm_intel kvm irqbypass crc32_pclmul ghash_clmulni_intel aesni_intel lrw iTCO_wdt gf128mul glue_helper ipmi_devintf cdc_ether iTCO_vendor_support ablk_helper cryptd usbnet i2c_i801 lpc_ich mii pcspkr i2c_smbus sg i7core_edac mfd_core ipmi_si edac_core ipmi_msghandler shpchp ioatdma dca acpi_cpufreq nfsd auth_rpcgss nfs_acl lockd grace sunrpc ip_tables ext4 jbd2 mbcache sr_mod sd_mod cdrom mgag200 i2c_algo_bit drm_kms_helpe!
>  r syscopyarea sysfillrect sysimgblt fb_sys_fops ttm ata_generic pata_acpi drm ata_piix libata crc32c_intel megaraid_sas serio_raw i2c_core bnx2 dm_mirror dm_region_hash dm_log dm_mod [last unloaded: scsi_debug]
> [165877.898708] CPU: 5 PID: 26242 Comm: xfs_scrub Tainted: G        W       4.9.0-rc3.djwong+ #16
> [165877.907308] Hardware name: IBM System x3550 M3 -[7944OEJ]-/90Y4784     , BIOS -[D6E150CUS-1.11]- 02/08/2011
> [165877.917124] task: ffff88017a286a40 task.stack: ffffc9000cca0000
> [165877.923126] RIP: 0010:[<ffffffffa0680c13>]  [<ffffffffa0680c13>] xfs_scrub_get_inode+0xc3/0x1c0 [xfs]
> [165877.932503] RSP: 0018:ffffc9000cca3ad0  EFLAGS: 00010246
> [165877.937898] RAX: 0000000000000000 RBX: fffffffffffffffe RCX: 0000000000000017
> [165877.945111] RDX: 0000000000000000 RSI: ffffc9000cca3ce8 RDI: 0000000000001123
> [165877.952328] RBP: ffffc9000cca3b20 R08: 0000000000000003 R09: 0000000000000014
> [165877.959544] R10: 0000000000000000 R11: 0000000000000000 R12: ffff880278f59680
> [165877.966759] R13: ffffc9000cca3ba8 R14: ffffc9000cca3ce8 R15: 0000000000000000
> [165877.973976] FS:  00007f3d099f9700(0000) GS:ffff88017bb00000(0000) knlGS:0000000000000000
> [165877.982143] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
> [165877.987969] CR2: 0000000000000038 CR3: 000000016ad2d000 CR4: 00000000000006e0
> [165877.995185] Stack:
> [165877.997286]  ffff880278f59680 0000000000000000 ffff880220cc5c00 ffff880265190780
> [165878.004840]  ffff880101a67800 ffffc9000cca3ba8 ffff880278f59680 ffff88025a9e6000
> [165878.012396]  ffffc9000cca3ce8 0000000000000000 ffffc9000cca3b58 ffffffffa0681a61
> [165878.019950] Call Trace:
> [165878.022551]  [<ffffffffa0681a61>] __xfs_scrub_setup_inode.isra.63+0x81/0x280 [xfs]
> [165878.030236]  [<ffffffffa0681c70>] xfs_scrub_setup_inode+0x10/0x20 [xfs]
> [165878.036963]  [<ffffffffa068f57f>] xfs_scrub_metadata+0x2ff/0x450 [xfs]
> [165878.043607]  [<ffffffffa066aa1d>] xfs_ioc_scrub_metadata+0x4d/0x80 [xfs]
> [165878.050424]  [<ffffffffa066d029>] xfs_file_ioctl+0x9c9/0xb10 [xfs]
> [165878.056689]  [<ffffffff8110692f>] ? get_futex_key+0x1df/0x360
> [165878.062516]  [<ffffffff81106b31>] ? futex_wake+0x81/0x150
> [165878.068003]  [<ffffffff812189c6>] do_vfs_ioctl+0x96/0x5b0
> [165878.073482]  [<ffffffff81218f59>] SyS_ioctl+0x79/0x90
> [165878.078621]  [<ffffffff81003997>] do_syscall_64+0x67/0x180
> [165878.084191]  [<ffffffff816a6c2b>] entry_SYSCALL64_slow_path+0x25/0x25
> [165878.090714] Code: 8b 14 24 49 8b 75 00 85 c0 41 89 c7 44 0f b6 82 93 00 00 00 44 0f b6 8a 94 00 00 00 0f b6 8a 53 02 00 00 49 8b 55 08 48 8b 7e 08 <4c> 8b 62 38 75 38 48 8b 7d d0 8b 46 10 39 87 98 03 00 00 74 21
> [165878.110930] RIP  [<ffffffffa0680c13>] xfs_scrub_get_inode+0xc3/0x1c0 [xfs]
> [165878.117938]  RSP <ffffc9000cca3ad0>
> [165878.121512] CR2: 0000000000000038
> [165878.129219] ---[ end trace d23e56c58f53ccb9 ]---
> --
> To unsubscribe from this list: send the line "unsubscribe linux-xfs" 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] 25+ messages in thread

* Re: [PATCH 8/9] xfs: fuzz every field of every structure
  2016-11-09  8:52       ` Darrick J. Wong
  (?)
@ 2016-11-09  9:13       ` Eryu Guan
  2016-11-09  9:25         ` Darrick J. Wong
  -1 siblings, 1 reply; 25+ messages in thread
From: Eryu Guan @ 2016-11-09  9:13 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: david, linux-xfs, fstests

On Wed, Nov 09, 2016 at 12:52:36AM -0800, Darrick J. Wong wrote:
> On Wed, Nov 09, 2016 at 04:09:24PM +0800, Eryu Guan wrote:
> > On Fri, Nov 04, 2016 at 05:18:00PM -0700, Darrick J. Wong wrote:
> > > Previously, our XFS fuzzing efforts were limited to using the xfs_db
> > > blocktrash command to scribble garbage all over a block.  This is
> > > pretty easy to discover; it would be far more interesting if we could
> > > fuzz individual fields looking for unhandled corner cases.  Since we
> > > now have an online scrub tool, use it to check for our targeted
> > > corruptions prior to the usual steps of writing to the FS, taking it
> > > offline, repairing, and re-checking.
> > > 
> > > These tests use the new xfs_db 'fuzz' command to test corner case
> > > handling of every field.  The 'print' command tells us which fields
> > > are available, and the fuzz command can write zeroes or ones to the
> > > field; set the high, middle, or low bit; add or subtract numbers; or
> > > randomize the field.  We loop through all fields and all fuzz verbs to
> > > see if we can trip up the kernel.
> > > 
> > > Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
> > 
> > The first test gave me a kernel crash :) xfs/1300 crashed your kernel
> > djwong-devel branch. I appended the console log at the end of this mail
> > if you have interest to see it.
> > 
> > And another xfs/1300 run gave me this failure message:
> > 
> >     +/mnt/testarea/scratch: Kernel lacks GETFSMAP; scrub will be less efficient. (xfs.c line 661)
> >     +/mnt/testarea/scratch: Kernel cannot help scrub metadata; scrub will be incomplete. (xfs.c line 661)
> >     +/mnt/testarea/scratch: Kernel cannot help scrub inodes; scrub will be incomplete. (xfs.c line 661)
> >     +/mnt/testarea/scratch: Kernel cannot help scrub extent map; scrub will be less efficient. (xfs.c line 661)
> > 
> > Is this known issue or something should be filtered out in the test?
> 
> That's strange, the djwong-devel branch should have getfsmap & scrub in it...
> 
> ...are you running the djwong-devel kernel and xfsprogs code?  The scrub
> ioctl structure has shifted some over the past few months, though GETFSMAP
> hasn't changed in ages.
> 
> Wait, "another xfs/1300 run" ... so after the first crash, did you go
> back to a vanilla kernel without all my crazypatches? :)

Ahh, you're right! It booted into 4.9-rc4 vanilla kernel, sorry about
that.. But xfs/1300 crashed djwong-devel for the second time in my
second try, seems the crash is reliable reproduced, with reflink
enabled.

> 
> > And ext4/1300 generated large .out.bad file (51M), containing something
> > like:
> > 
> > +/mnt/testarea/scratch/test/68/S_IFREG.FMT_ETREE: extent (1101381632/2469888/4096) ends past end of filesystem at 31457280. (generic.c line 272)
> > +/mnt/testarea/scratch/test/68/S_IFREG.FMT_ETREE: extent (1101389824/2478080/4096) starts past end of filesystem at 31457280. (generic.c line 264)
> > +/mnt/testarea/scratch/test/68/S_IFREG.FMT_ETREE: extent (1101389824/2478080/4096) ends past end of filesystem at 31457280. (generic.c line 272)
> > +/mnt/testarea/scratch/test/68/S_IFREG.FMT_ETREE: extent (1101398016/2486272/4096) starts past end of filesystem at 31457280. (generic.c line 264)
> > +/mnt/testarea/scratch/test/68/S_IFREG.FMT_ETREE: extent (1101398016/2486272/4096) ends past end of filesystem at 31457280. (generic.c line 272)
> > +/mnt/testarea/scratch/test/68/S_IFREG.FMT_ETREE: extent (1101406208/2494464/4096) starts past end of filesystem at 31457280. (generic.c line 264)
> > +/mnt/testarea/scratch/test/68/S_IFREG.FMT_ETREE: extent (1101406208/2494464/4096) ends past end of filesystem at 31457280. (generic.c line 272)
> > +/mnt/testarea/scratch/test/68/S_IFREG.FMT_ETREE: extent (1101414400/2502656/4096) starts past end of filesystem at 31457280. (generic.c line 264)
> > +/mnt/testarea/scratch/test/68/S_IFREG.FMT_ETREE: extent (1101414400/2502656/4096) ends past end of filesystem at 31457280. (generic.c line 272)
> > 
> > Seems like scrub found something wrong (real problems) and became very
> > noisy?
> 
> Hmm that's even stranger.  I'll try to reproduce tomorrow.

So this ext4 noise came from the vanilla kernel too, retested with
djwong-devel kernel & userspace ext4/1300 passed without problems. Sorry
for my noise..

Thanks,
Eryu

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

* Re: [PATCH 8/9] xfs: fuzz every field of every structure
  2016-11-09  9:13       ` Eryu Guan
@ 2016-11-09  9:25         ` Darrick J. Wong
  2016-11-09 10:04           ` Eryu Guan
  0 siblings, 1 reply; 25+ messages in thread
From: Darrick J. Wong @ 2016-11-09  9:25 UTC (permalink / raw)
  To: Eryu Guan; +Cc: david, linux-xfs, fstests

On Wed, Nov 09, 2016 at 05:13:44PM +0800, Eryu Guan wrote:
> On Wed, Nov 09, 2016 at 12:52:36AM -0800, Darrick J. Wong wrote:
> > On Wed, Nov 09, 2016 at 04:09:24PM +0800, Eryu Guan wrote:
> > > On Fri, Nov 04, 2016 at 05:18:00PM -0700, Darrick J. Wong wrote:
> > > > Previously, our XFS fuzzing efforts were limited to using the xfs_db
> > > > blocktrash command to scribble garbage all over a block.  This is
> > > > pretty easy to discover; it would be far more interesting if we could
> > > > fuzz individual fields looking for unhandled corner cases.  Since we
> > > > now have an online scrub tool, use it to check for our targeted
> > > > corruptions prior to the usual steps of writing to the FS, taking it
> > > > offline, repairing, and re-checking.
> > > > 
> > > > These tests use the new xfs_db 'fuzz' command to test corner case
> > > > handling of every field.  The 'print' command tells us which fields
> > > > are available, and the fuzz command can write zeroes or ones to the
> > > > field; set the high, middle, or low bit; add or subtract numbers; or
> > > > randomize the field.  We loop through all fields and all fuzz verbs to
> > > > see if we can trip up the kernel.
> > > > 
> > > > Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
> > > 
> > > The first test gave me a kernel crash :) xfs/1300 crashed your kernel
> > > djwong-devel branch. I appended the console log at the end of this mail
> > > if you have interest to see it.
> > > 
> > > And another xfs/1300 run gave me this failure message:
> > > 
> > >     +/mnt/testarea/scratch: Kernel lacks GETFSMAP; scrub will be less efficient. (xfs.c line 661)
> > >     +/mnt/testarea/scratch: Kernel cannot help scrub metadata; scrub will be incomplete. (xfs.c line 661)
> > >     +/mnt/testarea/scratch: Kernel cannot help scrub inodes; scrub will be incomplete. (xfs.c line 661)
> > >     +/mnt/testarea/scratch: Kernel cannot help scrub extent map; scrub will be less efficient. (xfs.c line 661)
> > > 
> > > Is this known issue or something should be filtered out in the test?
> > 
> > That's strange, the djwong-devel branch should have getfsmap & scrub in it...
> > 
> > ...are you running the djwong-devel kernel and xfsprogs code?  The scrub
> > ioctl structure has shifted some over the past few months, though GETFSMAP
> > hasn't changed in ages.
> > 
> > Wait, "another xfs/1300 run" ... so after the first crash, did you go
> > back to a vanilla kernel without all my crazypatches? :)
> 
> Ahh, you're right! It booted into 4.9-rc4 vanilla kernel, sorry about
> that.. But xfs/1300 crashed djwong-devel for the second time in my
> second try, seems the crash is reliable reproduced, with reflink
> enabled.

I think if you change the XFS_SCRUB_OP_ERROR_GOTO at line 2237 of
xfs_scrub_get_inode() to "if (error) goto out_err;" that ought to clear it up.

> > > And ext4/1300 generated large .out.bad file (51M), containing something
> > > like:
> > > 
> > > +/mnt/testarea/scratch/test/68/S_IFREG.FMT_ETREE: extent (1101381632/2469888/4096) ends past end of filesystem at 31457280. (generic.c line 272)
> > > +/mnt/testarea/scratch/test/68/S_IFREG.FMT_ETREE: extent (1101389824/2478080/4096) starts past end of filesystem at 31457280. (generic.c line 264)
> > > +/mnt/testarea/scratch/test/68/S_IFREG.FMT_ETREE: extent (1101389824/2478080/4096) ends past end of filesystem at 31457280. (generic.c line 272)
> > > +/mnt/testarea/scratch/test/68/S_IFREG.FMT_ETREE: extent (1101398016/2486272/4096) starts past end of filesystem at 31457280. (generic.c line 264)
> > > +/mnt/testarea/scratch/test/68/S_IFREG.FMT_ETREE: extent (1101398016/2486272/4096) ends past end of filesystem at 31457280. (generic.c line 272)
> > > +/mnt/testarea/scratch/test/68/S_IFREG.FMT_ETREE: extent (1101406208/2494464/4096) starts past end of filesystem at 31457280. (generic.c line 264)
> > > +/mnt/testarea/scratch/test/68/S_IFREG.FMT_ETREE: extent (1101406208/2494464/4096) ends past end of filesystem at 31457280. (generic.c line 272)
> > > +/mnt/testarea/scratch/test/68/S_IFREG.FMT_ETREE: extent (1101414400/2502656/4096) starts past end of filesystem at 31457280. (generic.c line 264)
> > > +/mnt/testarea/scratch/test/68/S_IFREG.FMT_ETREE: extent (1101414400/2502656/4096) ends past end of filesystem at 31457280. (generic.c line 272)
> > > 
> > > Seems like scrub found something wrong (real problems) and became very
> > > noisy?
> > 
> > Hmm that's even stranger.  I'll try to reproduce tomorrow.
> 
> So this ext4 noise came from the vanilla kernel too, retested with
> djwong-devel kernel & userspace ext4/1300 passed without problems. Sorry
> for my noise..

But that's even more weird; there haven't been any changes to ext4 that
would explain why this breaks on a vanilla 4.9-rc4 kernel...

--D

> 
> Thanks,
> Eryu

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

* Re: [PATCH 8/9] xfs: fuzz every field of every structure
  2016-11-09  9:25         ` Darrick J. Wong
@ 2016-11-09 10:04           ` Eryu Guan
  0 siblings, 0 replies; 25+ messages in thread
From: Eryu Guan @ 2016-11-09 10:04 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: david, linux-xfs, fstests

On Wed, Nov 09, 2016 at 01:25:23AM -0800, Darrick J. Wong wrote:
> On Wed, Nov 09, 2016 at 05:13:44PM +0800, Eryu Guan wrote:
> > On Wed, Nov 09, 2016 at 12:52:36AM -0800, Darrick J. Wong wrote:
> > > On Wed, Nov 09, 2016 at 04:09:24PM +0800, Eryu Guan wrote:
> > > > On Fri, Nov 04, 2016 at 05:18:00PM -0700, Darrick J. Wong wrote:
> > > > > Previously, our XFS fuzzing efforts were limited to using the xfs_db
> > > > > blocktrash command to scribble garbage all over a block.  This is
> > > > > pretty easy to discover; it would be far more interesting if we could
> > > > > fuzz individual fields looking for unhandled corner cases.  Since we
> > > > > now have an online scrub tool, use it to check for our targeted
> > > > > corruptions prior to the usual steps of writing to the FS, taking it
> > > > > offline, repairing, and re-checking.
> > > > > 
> > > > > These tests use the new xfs_db 'fuzz' command to test corner case
> > > > > handling of every field.  The 'print' command tells us which fields
> > > > > are available, and the fuzz command can write zeroes or ones to the
> > > > > field; set the high, middle, or low bit; add or subtract numbers; or
> > > > > randomize the field.  We loop through all fields and all fuzz verbs to
> > > > > see if we can trip up the kernel.
> > > > > 
> > > > > Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
> > > > 
> > > > The first test gave me a kernel crash :) xfs/1300 crashed your kernel
> > > > djwong-devel branch. I appended the console log at the end of this mail
> > > > if you have interest to see it.
> > > > 
> > > > And another xfs/1300 run gave me this failure message:
> > > > 
> > > >     +/mnt/testarea/scratch: Kernel lacks GETFSMAP; scrub will be less efficient. (xfs.c line 661)
> > > >     +/mnt/testarea/scratch: Kernel cannot help scrub metadata; scrub will be incomplete. (xfs.c line 661)
> > > >     +/mnt/testarea/scratch: Kernel cannot help scrub inodes; scrub will be incomplete. (xfs.c line 661)
> > > >     +/mnt/testarea/scratch: Kernel cannot help scrub extent map; scrub will be less efficient. (xfs.c line 661)
> > > > 
> > > > Is this known issue or something should be filtered out in the test?
> > > 
> > > That's strange, the djwong-devel branch should have getfsmap & scrub in it...
> > > 
> > > ...are you running the djwong-devel kernel and xfsprogs code?  The scrub
> > > ioctl structure has shifted some over the past few months, though GETFSMAP
> > > hasn't changed in ages.
> > > 
> > > Wait, "another xfs/1300 run" ... so after the first crash, did you go
> > > back to a vanilla kernel without all my crazypatches? :)
> > 
> > Ahh, you're right! It booted into 4.9-rc4 vanilla kernel, sorry about
> > that.. But xfs/1300 crashed djwong-devel for the second time in my
> > second try, seems the crash is reliable reproduced, with reflink
> > enabled.
> 
> I think if you change the XFS_SCRUB_OP_ERROR_GOTO at line 2237 of
> xfs_scrub_get_inode() to "if (error) goto out_err;" that ought to clear it up.
> 
> > > > And ext4/1300 generated large .out.bad file (51M), containing something
> > > > like:
> > > > 
> > > > +/mnt/testarea/scratch/test/68/S_IFREG.FMT_ETREE: extent (1101381632/2469888/4096) ends past end of filesystem at 31457280. (generic.c line 272)
> > > > +/mnt/testarea/scratch/test/68/S_IFREG.FMT_ETREE: extent (1101389824/2478080/4096) starts past end of filesystem at 31457280. (generic.c line 264)
> > > > +/mnt/testarea/scratch/test/68/S_IFREG.FMT_ETREE: extent (1101389824/2478080/4096) ends past end of filesystem at 31457280. (generic.c line 272)
> > > > +/mnt/testarea/scratch/test/68/S_IFREG.FMT_ETREE: extent (1101398016/2486272/4096) starts past end of filesystem at 31457280. (generic.c line 264)
> > > > +/mnt/testarea/scratch/test/68/S_IFREG.FMT_ETREE: extent (1101398016/2486272/4096) ends past end of filesystem at 31457280. (generic.c line 272)
> > > > +/mnt/testarea/scratch/test/68/S_IFREG.FMT_ETREE: extent (1101406208/2494464/4096) starts past end of filesystem at 31457280. (generic.c line 264)
> > > > +/mnt/testarea/scratch/test/68/S_IFREG.FMT_ETREE: extent (1101406208/2494464/4096) ends past end of filesystem at 31457280. (generic.c line 272)
> > > > +/mnt/testarea/scratch/test/68/S_IFREG.FMT_ETREE: extent (1101414400/2502656/4096) starts past end of filesystem at 31457280. (generic.c line 264)
> > > > +/mnt/testarea/scratch/test/68/S_IFREG.FMT_ETREE: extent (1101414400/2502656/4096) ends past end of filesystem at 31457280. (generic.c line 272)
> > > > 
> > > > Seems like scrub found something wrong (real problems) and became very
> > > > noisy?
> > > 
> > > Hmm that's even stranger.  I'll try to reproduce tomorrow.
> > 
> > So this ext4 noise came from the vanilla kernel too, retested with
> > djwong-devel kernel & userspace ext4/1300 passed without problems. Sorry
> > for my noise..
> 
> But that's even more weird; there haven't been any changes to ext4 that
> would explain why this breaks on a vanilla 4.9-rc4 kernel...

Puzzle resolved, I somehow switched back to mainline xfsprogs or some
other wrong xfsprogs version after booted into 4.9-rc4 vanilla kernel.
After updating xfsprogs to djwong-devel, ext4/1300 showed no problem on
4.9-rc4 kernel too.

Sorry again for the mess!

Eryu

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

* [PATCH 7/9] populate: discover XFS structure fields and fuzz verbs, and use them to fuzz fields
  2017-01-21  8:10 [PATCH v5 0/9] xfstests: online scrub/repair support Darrick J. Wong
@ 2017-01-21  8:11 ` Darrick J. Wong
  0 siblings, 0 replies; 25+ messages in thread
From: Darrick J. Wong @ 2017-01-21  8:11 UTC (permalink / raw)
  To: eguan, darrick.wong; +Cc: linux-xfs, fstests

Create some routines to help us perform targeted fuzzing of individual
fields in various XFS structures.  Specifically, we want the caller to
drop the xfs_db iocursor on the victim field; from there, the scripts
should discover all available fields and fuzzing verbs, and try each
fuzz verb on every available field.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
--
v2: fix some errors found by Eryu Guan.
v3: allow tests to blacklist certain fields, and allow the user to
force fuzz certain fields using certain fuzz verbs.
---
 common/fuzzy |  264 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 264 insertions(+)


diff --git a/common/fuzzy b/common/fuzzy
index d4f8274..2df7222 100644
--- a/common/fuzzy
+++ b/common/fuzzy
@@ -78,3 +78,267 @@ _scratch_scrub() {
 		;;
 	esac
 }
+
+# Filter the xfs_db print command's field debug information
+# into field name and type.
+__filter_xfs_db_print_fields() {
+	filter="$1"
+	if [ -z "${filter}" ] || [ "${filter}" = "nofilter" ]; then
+		filter='^'
+	fi
+	grep ' = ' | while read key equals value; do
+		# Filter out any keys with an array index >= 10, and
+		# collapse any array range ("[1-195]") to the first item.
+		fuzzkey="$(echo "${key}" | sed -e '/\([a-z]*\)\[\([0-9][0-9]\+\)\].*/d' -e 's/\([a-zA-Z0-9_]*\)\[\([0-9]*\)-[0-9]*\]/\1[\2]/g')"
+		if [ -z "${fuzzkey}" ]; then
+			continue
+		elif [[ "${value}" == "["* ]]; then
+			echo "${value}" | sed -e 's/^.//g' -e 's/.$//g' -e 's/,/\n/g' | while read subfield; do
+				echo "${fuzzkey}.${subfield}"
+			done
+		else
+			echo "${fuzzkey}"
+		fi
+	done | egrep "${filter}"
+}
+
+# Navigate to some part of the filesystem and print the field info.
+# The first argument is an egrep filter for the fields
+# The rest of the arguments are xfs_db commands to locate the metadata.
+_scratch_xfs_list_metadata_fields() {
+	filter="$1"
+	shift
+	if [ -n "${SCRATCH_XFS_LIST_METADATA_FIELDS}" ]; then
+		echo "${SCRATCH_XFS_LIST_METADATA_FIELDS}" | tr '[ ,]' '[\n\n]'
+		return;
+	fi
+
+	local cmds=()
+	for arg in "$@"; do
+		cmds+=("-c" "${arg}")
+	done
+	_scratch_xfs_db "${cmds[@]}" -c print | __filter_xfs_db_print_fields "${filter}"
+}
+
+# Get a metadata field
+# The first arg is the field name
+# The rest of the arguments are xfs_db commands to find the metadata.
+_scratch_xfs_get_metadata_field() {
+	key="$1"
+	shift
+
+	grep_key="$(echo "${key}" | tr '[]()' '....')"
+	local cmds=()
+	for arg in "$@"; do
+		cmds+=("-c" "${arg}")
+	done
+	_scratch_xfs_db "${cmds[@]}" -c "print ${key}" | grep "^${grep_key}" | \
+		sed -e 's/^.* = //g'
+}
+
+# Set a metadata field
+# The first arg is the field name
+# The second arg is the new value
+# The rest of the arguments are xfs_db commands to find the metadata.
+_scratch_xfs_set_metadata_field() {
+	key="$1"
+	value="$2"
+	shift; shift
+
+	local cmds=()
+	for arg in "$@"; do
+		cmds+=("-c" "${arg}")
+	done
+	_scratch_xfs_db -x "${cmds[@]}" -c "write -d ${key} ${value}"
+	echo
+}
+
+# Fuzz a metadata field
+# The first arg is the field name
+# The second arg is the xfs_db fuzz verb
+# The rest of the arguments are xfs_db commands to find the metadata.
+_scratch_xfs_fuzz_metadata_field() {
+	key="$1"
+	value="$2"
+	shift; shift
+
+	if [[ "${key}" == *crc ]]; then
+		fuzz_arg="-c"
+	else
+		fuzz_arg="-d"
+	fi
+	oldval="$(_scratch_xfs_get_metadata_field "${key}" "$@")"
+
+	local cmds=()
+	for arg in "$@"; do
+		cmds+=("-c" "${arg}")
+	done
+	_scratch_xfs_db -x "${cmds[@]}" -c "fuzz ${fuzz_arg} ${key} ${value}"
+	echo
+	newval="$(_scratch_xfs_get_metadata_field "${key}" "$@" 2> /dev/null)"
+	if [ "${oldval}" = "${newval}" ]; then
+		echo "Field ${key} already set to ${newval}, skipping test."
+		return 1
+	fi
+	return 0
+}
+
+# Try to forcibly unmount the scratch fs
+__scratch_xfs_fuzz_unmount()
+{
+	while _scratch_unmount 2>/dev/null; do sleep 0.2; done
+}
+
+# Restore metadata to scratch device prior to field-fuzzing.
+__scratch_xfs_fuzz_mdrestore()
+{
+	test -e "${POPULATE_METADUMP}" || _fail "Need to set POPULATE_METADUMP"
+
+	__scratch_xfs_fuzz_unmount
+	xfs_mdrestore "${POPULATE_METADUMP}" "${SCRATCH_DEV}"
+}
+
+__fuzz_notify() {
+	echo "$@"
+	test -w /dev/ttyprintk && echo "$@" >> /dev/ttyprintk
+}
+
+# Fuzz one field of some piece of metadata.
+# First arg is the field name
+# Second arg is the fuzz verb (ones, zeroes, random, add, sub...)
+# Third arg is the repair mode (online, offline, both)
+__scratch_xfs_fuzz_field_test() {
+	field="$1"
+	fuzzverb="$2"
+	repair="$3"
+	shift; shift; shift
+
+	# Set the new field value
+	__fuzz_notify "+ Fuzz ${field} = ${fuzzverb}"
+	echo "========================"
+	_scratch_xfs_fuzz_metadata_field "${field}" ${fuzzverb} "$@"
+	res=$?
+	test $res -ne 0 && return
+
+	# Try to catch the error with scrub
+	echo "+ Try to catch the error"
+	_scratch_mount 2>&1
+	res=$?
+	if [ $res -eq 0 ]; then
+		# Try an online scrub unless we're fuzzing ag 0's sb,
+		# which scrub doesn't know how to fix.
+		echo "++ Online scrub"
+		if [ "$1" != "sb 0" ]; then
+			_scratch_scrub -n -a 1 -e continue 2>&1
+			res=$?
+			test $res -eq 0 && \
+				(>&2 echo "scrub didn't fail with ${field} = ${fuzzverb}.")
+		fi
+
+		# Try fixing the filesystem online?!
+		if [ "${repair}" = "online" ] || [ "${repair}" = "both" ]; then
+			__fuzz_notify "++ Try to repair filesystem online"
+			_scratch_scrub -y 2>&1
+			res=$?
+			test $res -ne 0 && \
+				(>&2 echo "online repair failed ($res) with ${field} = ${fuzzverb}.")
+		fi
+
+		__scratch_xfs_fuzz_unmount
+	elif [ "${repair}" = "online" ] || [ "${repair}" = "both" ]; then
+		(>&2 echo "mount failed ($res) with ${field} = ${fuzzverb}.")
+	fi
+
+	# Repair the filesystem offline?
+	if [ "${repair}" = "offline" ] || [ "${repair}" = "both" ]; then
+		echo "+ Try to repair the filesystem offline"
+		_repair_scratch_fs 2>&1
+		res=$?
+		test $res -ne 0 && \
+			(>&2 echo "offline repair failed ($res) with ${field} = ${fuzzverb}.")
+	fi
+
+	# See if repair finds a clean fs
+	echo "+ Make sure error is gone (offline)"
+        _scratch_xfs_repair -n 2>&1
+	res=$?
+	test $res -ne 0 && \
+		(>&2 echo "offline re-scrub ($res) with ${field} = ${fuzzverb}.")
+
+	# See if scrub finds a clean fs
+	echo "+ Make sure error is gone (online)"
+	_scratch_mount 2>&1
+	res=$?
+	if [ $res -eq 0 ]; then
+		# Try an online scrub unless we're fuzzing ag 0's sb,
+		# which scrub doesn't know how to fix.
+		echo "++ Online scrub"
+		if [ "$1" != "sb 0" ]; then
+			_scratch_scrub -e continue 2>&1
+			res=$?
+			test $res -ne 0 && \
+				(>&2 echo "online re-scrub ($res) with ${field} = ${fuzzverb}.")
+		fi
+
+		# Try modifying the filesystem again!
+		__fuzz_notify "++ Try to write filesystem again"
+		_scratch_fuzz_modify 100 2>&1
+		__scratch_xfs_fuzz_unmount
+	else
+		(>&2 echo "re-mount failed ($res) with ${field} = ${fuzzverb}.")
+	fi
+
+	# See if repair finds a clean fs
+	echo "+ Re-check the filesystem (offline)"
+	_scratch_xfs_repair -n 2>&1
+	res=$?
+	test $res -ne 0 && \
+		(>&2 echo "re-repair failed ($res) with ${field} = ${fuzzverb}.")
+}
+
+# Make sure we have all the pieces we need for field fuzzing
+_require_scratch_xfs_fuzz_fields()
+{
+	_require_scratch_nocheck
+	_require_scrub
+	_require_populate_commands
+	_scratch_mkfs_xfs >/dev/null 2>&1
+	_require_xfs_db_command "fuzz"
+}
+
+# Grab the list of available fuzzing verbs
+_scratch_xfs_list_fuzz_verbs() {
+	if [ -n "${SCRATCH_XFS_LIST_FUZZ_VERBS}" ]; then
+		echo "${SCRATCH_XFS_LIST_FUZZ_VERBS}" | tr '[ ,]' '[\n\n]'
+		return;
+	fi
+	_scratch_xfs_db -x -c 'sb 0' -c 'fuzz' | grep '^Verbs:' | \
+		sed -e 's/[,.]//g' -e 's/Verbs: //g' -e 's/ /\n/g'
+}
+
+# Fuzz some of the fields of some piece of metadata
+# The first argument is an egrep filter for the field names
+# The second argument is the repair mode (online, offline, both)
+# The rest of the arguments are xfs_db commands to locate the metadata.
+#
+# Users can specify the fuzz verbs via SCRATCH_XFS_LIST_FUZZ_VERBS
+# They can specify the fields via SCRATCH_XFS_LIST_METADATA_FIELDS
+_scratch_xfs_fuzz_metadata() {
+	filter="$1"
+	repair="$2"
+	shift; shift
+
+	fields="$(_scratch_xfs_list_metadata_fields "${filter}" "$@")"
+	verbs="$(_scratch_xfs_list_fuzz_verbs)"
+	echo "Fields we propose to fuzz under: $@"
+	echo $(echo "${fields}")
+	echo "Verbs we propose to fuzz with:"
+	echo $(echo "${verbs}")
+
+	echo "${fields}" | while read field; do
+		echo "${verbs}" | while read fuzzverb; do
+			__scratch_xfs_fuzz_mdrestore
+			__scratch_xfs_fuzz_field_test "${field}" "${fuzzverb}" "${repair}" "$@"
+		done
+	done
+}


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

* [PATCH 7/9] populate: discover XFS structure fields and fuzz verbs, and use them to fuzz fields
  2017-01-05  1:17 [PATCH v4 0/9] xfstests: online scrub/repair support Darrick J. Wong
@ 2017-01-05  1:17 ` Darrick J. Wong
  0 siblings, 0 replies; 25+ messages in thread
From: Darrick J. Wong @ 2017-01-05  1:17 UTC (permalink / raw)
  To: eguan, darrick.wong; +Cc: linux-xfs, fstests

Create some routines to help us perform targeted fuzzing of individual
fields in various XFS structures.  Specifically, we want the caller to
drop the xfs_db iocursor on the victim field; from there, the scripts
should discover all available fields and fuzzing verbs, and try each
fuzz verb on every available field.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
--
v2: fix some errors found by Eryu Guan.
---
 common/fuzzy |  189 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 189 insertions(+)


diff --git a/common/fuzzy b/common/fuzzy
index 1cc1d5e..2edcd9f 100644
--- a/common/fuzzy
+++ b/common/fuzzy
@@ -81,3 +81,192 @@ _scratch_scrub() {
 		;;
 	esac
 }
+
+# Filter the xfs_db print command's field debug information
+# into field name and type.
+__filter_xfs_db_print_fields() {
+	grep ' = ' | while read key equals value; do
+		fuzzkey="$(echo "${key}" | sed -e 's/\([a-zA-Z0-9_]*\)\[\([0-9]*\)-[0-9]*\]/\1[\2]/g')"
+		if [[ "${value}" == "["* ]]; then
+			echo "${value}" | sed -e 's/^.//g' -e 's/.$//g' -e 's/,/\n/g' | while read subfield; do
+				echo "${fuzzkey}.${subfield}"
+			done
+		else
+			echo "${fuzzkey}"
+		fi
+	done
+}
+
+# Navigate to some part of the filesystem and print the field info.
+_scratch_xfs_list_metadata_fields() {
+	if [ -n "${SCRATCH_XFS_LIST_METADATA_FIELDS}" ]; then
+		echo "${SCRATCH_XFS_LIST_METADATA_FIELDS}" | sed -e 's/ /\n/g'
+		return;
+	fi
+
+	(for arg in "$@"; do
+		echo "${arg}"
+	done
+	echo "print") | _scratch_xfs_db | __filter_xfs_db_print_fields
+}
+
+# Get a metadata field
+_scratch_xfs_get_metadata_field() {
+	key="$1"
+	shift
+
+	grep_key="$(echo "${key}" | tr '[]()' '....')"
+	(for arg in "$@"; do
+		echo "${arg}"
+	done
+	echo "print ${key}") | _scratch_xfs_db | grep "^${grep_key}" | \
+		sed -e 's/^.* = //g'
+}
+
+# Set a metadata field
+_scratch_xfs_set_metadata_field() {
+	key="$1"
+	value="$2"
+	shift; shift
+	(for arg in "$@"; do
+		echo "${arg}"
+	done
+	echo "write -d ${key} ${value}") | _scratch_xfs_db -x
+	echo
+}
+
+# Fuzz a metadata field
+_scratch_xfs_fuzz_metadata_field() {
+	key="$1"
+	value="$2"
+	shift; shift
+
+	if [ "${key}" = "crc" ]; then
+		fuzz_arg="-c"
+	else
+		fuzz_arg="-d"
+	fi
+	oldval="$(_scratch_xfs_get_metadata_field "${key}" "$@")"
+	(for arg in "$@"; do
+		echo "${arg}"
+	done
+	echo "fuzz ${fuzz_arg} ${key} ${value}") | _scratch_xfs_db -x
+	echo
+	newval="$(_scratch_xfs_get_metadata_field "${key}" "$@" 2> /dev/null)"
+	if [ "${oldval}" = "${newval}" ]; then
+		echo "Field ${key} already set to ${oldval}, skipping test."
+		return 1
+	fi
+	return 0
+}
+
+# Try to forcibly unmount the scratch fs
+__scratch_xfs_fuzz_unmount()
+{
+	while ! _scratch_unmount 2>/dev/null; do sleep 0.2; done
+}
+
+# Restore metadata to scratch device prior to field-fuzzing.
+__scratch_xfs_fuzz_mdrestore()
+{
+	test -e "${POPULATE_METADUMP}" || _fail "Need to set POPULATE_METADUMP"
+
+	__scratch_xfs_fuzz_unmount
+	xfs_mdrestore "${POPULATE_METADUMP}" "${SCRATCH_DEV}"
+}
+
+__fuzz_notify() {
+	echo "$@"
+	test -w /dev/ttyprintk && echo "$@" >> /dev/ttyprintk
+}
+
+# Fuzz one field of some piece of metadata
+__scratch_xfs_fuzz_field_test() {
+	field="$1"
+	fuzzverb="$2"
+	shift; shift
+
+	# Set the new field value
+	__fuzz_notify "+ Fuzz ${field} = ${fuzzverb}"
+	echo "========================"
+	_scratch_xfs_fuzz_metadata_field "${field}" ${fuzzverb} "$@"
+	res=$?
+	test $res -ne 0 && return
+
+	# Try to catch the error with scrub
+	echo "+ Try to catch the error"
+	_scratch_mount 2>&1
+	res=$?
+	if [ $res -eq 0 ]; then
+		_scratch_scrub -a 1 -e continue 2>&1
+		res=$?
+		test $res -eq 0 && \
+			(>&2 echo "scrub didn't fail with ${field} = ${fuzzverb}.")
+
+		# Try modifying the filesystem!
+		__fuzz_notify "++ Try to write filesystem"
+		#_scratch_fuzz_modify 100 2>&1
+		__scratch_xfs_fuzz_unmount
+	fi
+
+	# Repair the filesystem
+	echo "+ Fix the error"
+	_repair_scratch_fs 2>&1
+	res=$?
+	test $res -ne 0 && \
+		(>&2 echo "repair failed ($res) with ${field} = ${fuzzverb}.")
+
+	# See if scrub finds a clean fs
+	echo "+ Make sure error is gone"
+	_scratch_mount 2>&1
+	res=$?
+	if [ $res -eq 0 ]; then
+		_scratch_scrub -e continue 2>&1
+		res=$?
+		test $res -ne 0 && \
+			(>&2 echo "re-scrub ($res) with ${field} = ${fuzzverb}.")
+
+		# Try modifying the filesystem again!
+		__fuzz_notify "++ Try to write filesystem again"
+		_scratch_fuzz_modify 100 2>&1
+		__scratch_xfs_fuzz_unmount
+	else
+		(>&2 echo "re-mount failed ($res) with ${field} = ${fuzzverb}.")
+	fi
+
+	# See if repair finds a clean fs
+	_scratch_xfs_repair -n 2>&1
+	res=$?
+	test $res -ne 0 && \
+		(>&2 echo "re-repair failed ($res) with ${field} = ${fuzzverb}.")
+}
+
+# Make sure we have all the pieces we need for field fuzzing
+_require_scratch_xfs_fuzz_fields()
+{
+	_require_scratch
+	_require_scrub
+	_require_populate_commands
+	_scratch_mkfs_xfs >/dev/null 2>&1
+	_require_xfs_db_command "fuzz"
+}
+
+# Grab the list of available fuzzing verbs
+_scratch_xfs_list_fuzz_verbs() {
+	if [ -n "${SCRATCH_XFS_LIST_FUZZ_VERBS}" ]; then
+		echo "${SCRATCH_XFS_LIST_FUZZ_VERBS}" | sed -e 's/ /\n/g'
+		return;
+	fi
+	_scratch_xfs_db -x -c 'sb 0' -c 'fuzz' | grep '^Verbs:' | \
+		sed -e 's/[,.]//g' -e 's/Verbs: //g' -e 's/ /\n/g'
+}
+
+# Fuzz the fields of some piece of metadata
+_scratch_xfs_fuzz_fields() {
+	_scratch_xfs_list_metadata_fields "$@" | while read field; do
+		_scratch_xfs_list_fuzz_verbs | while read fuzzverb; do
+			__scratch_xfs_fuzz_mdrestore
+			__scratch_xfs_fuzz_field_test "${field}" "${fuzzverb}" "$@"
+		done
+	done
+}


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

end of thread, other threads:[~2017-01-21  8:11 UTC | newest]

Thread overview: 25+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-11-05  0:17 [PATCH v2 0/9] xfstests: online scrub/repair support Darrick J. Wong
2016-11-05  0:17 ` [PATCH 1/9] populate: create all types of XFS metadata Darrick J. Wong
2016-11-07 15:34   ` Eryu Guan
2016-11-09  0:29     ` Darrick J. Wong
2016-11-05  0:17 ` [PATCH 2/9] populate: add _require_populate_commands to check for tools Darrick J. Wong
2016-11-05  0:17 ` [PATCH 3/9] populate: optionally fill the filesystem when populating fs Darrick J. Wong
2016-11-05  0:17 ` [PATCH 4/9] populate: fix some silly errors when modifying a fs while fuzzing Darrick J. Wong
2016-11-05  0:17 ` [PATCH 5/9] common/fuzzy: move fuzzing helper functions here Darrick J. Wong
2016-11-05  0:17 ` [PATCH 6/9] populate: cache scratch metadata images Darrick J. Wong
2016-11-05  0:17 ` [PATCH 7/9] populate: discover XFS structure fields and fuzz verbs, and use them to fuzz fields Darrick J. Wong
2016-11-09  3:32   ` Eryu Guan
2016-11-09  7:52     ` Darrick J. Wong
2016-11-09  3:44   ` Eryu Guan
2016-11-09  7:53     ` Darrick J. Wong
2016-11-05  0:18 ` [PATCH 8/9] xfs: fuzz every field of every structure Darrick J. Wong
2016-11-09  8:09   ` Eryu Guan
2016-11-09  8:09     ` Eryu Guan
2016-11-09  8:52     ` Darrick J. Wong
2016-11-09  8:52       ` Darrick J. Wong
2016-11-09  9:13       ` Eryu Guan
2016-11-09  9:25         ` Darrick J. Wong
2016-11-09 10:04           ` Eryu Guan
2016-11-05  0:18 ` [PATCH 9/9] common/populate: create attrs in different namespaces Darrick J. Wong
2017-01-05  1:17 [PATCH v4 0/9] xfstests: online scrub/repair support Darrick J. Wong
2017-01-05  1:17 ` [PATCH 7/9] populate: discover XFS structure fields and fuzz verbs, and use them to fuzz fields Darrick J. Wong
2017-01-21  8:10 [PATCH v5 0/9] xfstests: online scrub/repair support Darrick J. Wong
2017-01-21  8:11 ` [PATCH 7/9] populate: discover XFS structure fields and fuzz verbs, and use them to fuzz fields Darrick J. Wong

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.