summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorNicholas D Steeves <nsteeves@gmail.com>2016-04-23 00:41:30 +0100
committerNicholas D Steeves <nsteeves@gmail.com>2016-04-23 00:41:30 +0100
commitcec572daccafa1e912cbed363df6f84687778c6f (patch)
tree7d99ab9f73d25c1ed8eaf6393f6374edf5316b03 /tests
btrfs-progs (4.4.1-1.1) unstable; urgency=medium
* Non-maintainer upload. * New upstream release. * Rename package to btrfs-progs (Closes: #780081) * Update standards version to 3.9.7 (no changes needed). * debian/control: Add "Breaks" per Gianfranco Costamagna's suggestion * Change lintian override to reflect package rename * Switch from using postinst and postrm to using triggers per Christian Seiler's recommendation. # imported from the archive
Diffstat (limited to 'tests')
-rw-r--r--tests/README.md136
-rwxr-xr-xtests/clean-tests.sh24
-rw-r--r--tests/common240
-rw-r--r--tests/convert-tests.sh86
-rwxr-xr-xtests/fsck-tests.sh68
-rw-r--r--tests/fsck-tests/001-bad-file-extent-bytenr/default_case.imgbin0 -> 4096 bytes
-rw-r--r--tests/fsck-tests/002-bad-transid/default_case.imgbin0 -> 4096 bytes
-rw-r--r--tests/fsck-tests/003-shift-offsets/default_case.imgbin0 -> 4096 bytes
-rw-r--r--tests/fsck-tests/004-no-dir-index/default_case.imgbin0 -> 4096 bytes
-rw-r--r--tests/fsck-tests/005-bad-item-offset/default_case.imgbin0 -> 398336 bytes
-rw-r--r--tests/fsck-tests/006-bad-root-items/default_case.tar.xzbin0 -> 24980 bytes
-rw-r--r--tests/fsck-tests/006-bad-root-items/skinny_case.tar.xzbin0 -> 26520 bytes
-rwxr-xr-xtests/fsck-tests/006-bad-root-items/test.sh17
-rw-r--r--tests/fsck-tests/007-bad-offset-snapshots/default_case.imgbin0 -> 249856 bytes
-rw-r--r--tests/fsck-tests/008-bad-dir-index-name/default_case.imgbin0 -> 4096 bytes
-rw-r--r--tests/fsck-tests/009-no-dir-item-or-index/default_case.imgbin0 -> 4953088 bytes
-rw-r--r--tests/fsck-tests/010-no-rootdir-inode-item/default_case.imgbin0 -> 398336 bytes
-rw-r--r--tests/fsck-tests/011-no-inode-item/default_case.imgbin0 -> 398336 bytes
-rw-r--r--tests/fsck-tests/012-leaf-corruption/no_data_extent.tar.xzbin0 -> 130260 bytes
-rwxr-xr-xtests/fsck-tests/012-leaf-corruption/test.sh117
-rwxr-xr-xtests/fsck-tests/013-extent-tree-rebuild/test.sh44
-rw-r--r--tests/fsck-tests/014-no-extent-info/default_case.imgbin0 -> 4096 bytes
-rw-r--r--tests/fsck-tests/015-check-bad-memory-access/bko-97171-btrfs-image.raw.txt254
-rw-r--r--tests/fsck-tests/015-check-bad-memory-access/bko-97171-btrfs-image.raw.xzbin0 -> 6748 bytes
-rw-r--r--tests/fsck-tests/016-wrong-inode-nbytes/default_case.img.xzbin0 -> 1996 bytes
-rw-r--r--tests/fsck-tests/017-missing-all-file-extent/default_case.img.xzbin0 -> 1104 bytes
-rw-r--r--tests/fsck-tests/018-leaf-crossing-stripes/default_case.raw.xzbin0 -> 105064 bytes
-rwxr-xr-xtests/fsck-tests/018-leaf-crossing-stripes/test.sh12
-rw-r--r--tests/fsck-tests/019-non-skinny-false-alert/default_case.img.xzbin0 -> 15236 bytes
-rwxr-xr-xtests/fsck-tests/019-non-skinny-false-alert/test.sh23
-rwxr-xr-xtests/fuzz-tests.sh41
-rwxr-xr-xtests/fuzz-tests/001-simple-unmounted/test.sh20
-rw-r--r--tests/fuzz-tests/images/bad-superblock-1.raw.xzbin0 -> 228 bytes
-rw-r--r--tests/fuzz-tests/images/bad-superblock-2.raw.xzbin0 -> 228 bytes
-rw-r--r--tests/fuzz-tests/images/bad-superblock-3.raw.xzbin0 -> 228 bytes
-rw-r--r--tests/fuzz-tests/images/bad-superblock.txt17
-rw-r--r--tests/fuzz-tests/images/bko-104131-fsck-oob-read.raw.xzbin0 -> 192 bytes
-rw-r--r--tests/fuzz-tests/images/bko-104131-fsck-oob-read.txt31
-rw-r--r--tests/fuzz-tests/images/bko-104141-fsck-exception.raw.xzbin0 -> 196 bytes
-rw-r--r--tests/fuzz-tests/images/bko-104141-fsck-exception.txt9
-rw-r--r--tests/fuzz-tests/images/bko-97191-btrfs-image.raw.txt137
-rw-r--r--tests/fuzz-tests/images/bko-97191-btrfs-image.raw.xzbin0 -> 7076 bytes
-rw-r--r--tests/fuzz-tests/images/bko-97271-btrfs-image.raw.txt54
-rw-r--r--tests/fuzz-tests/images/bko-97271-btrfs-image.raw.xzbin0 -> 6580 bytes
-rw-r--r--tests/fuzz-tests/images/sys-array-num-stripes-0.raw.txt30
-rw-r--r--tests/fuzz-tests/images/sys-array-num-stripes-0.raw.xzbin0 -> 8364 bytes
-rwxr-xr-xtests/misc-tests.sh47
-rwxr-xr-xtests/misc-tests/001-btrfstune-features/test.sh46
-rwxr-xr-xtests/misc-tests/002-uuid-rewrite/test.sh66
-rwxr-xr-xtests/misc-tests/003-zero-log/test.sh52
-rwxr-xr-xtests/misc-tests/004-shrink-fs/test.sh72
-rwxr-xr-xtests/misc-tests/005-convert-progress-thread-crash/test.sh15
-rwxr-xr-xtests/misc-tests/006-image-on-missing-device/test.sh78
-rwxr-xr-xtests/misc-tests/007-subvolume-sync/test.sh32
-rwxr-xr-xtests/misc-tests/008-leaf-crossing-stripes/test.sh25
-rwxr-xr-xtests/misc-tests/009-subvolume-sync-must-wait/test.sh52
-rwxr-xr-xtests/misc-tests/010-convert-delete-ext2-subvol/test.sh26
-rwxr-xr-xtests/misc-tests/011-delete-missing-device/test.sh83
-rw-r--r--tests/misc-tests/012-find-root-no-result/first_meta_chunk.btrfs-imagebin0 -> 4096 bytes
-rwxr-xr-xtests/misc-tests/012-find-root-no-result/test.sh24
-rwxr-xr-xtests/mkfs-tests.sh44
-rwxr-xr-xtests/mkfs-tests/001-basic-profiles/test.sh91
-rwxr-xr-xtests/mkfs-tests/002-no-force-mixed-on-small-volume/test.sh13
-rwxr-xr-xtests/mkfs-tests/003-mixed-with-wrong-nodesize/test.sh12
-rwxr-xr-xtests/mkfs-tests/004-rootdir-keeps-size/test.sh31
-rwxr-xr-xtests/mkfs-tests/005-long-device-name-for-ssd/test.sh40
-rw-r--r--tests/mkfs-tests/006-partitioned-loopdev/partition-1g-1gbin0 -> 512 bytes
-rwxr-xr-xtests/mkfs-tests/006-partitioned-loopdev/test.sh27
-rwxr-xr-xtests/mkfs-tests/007-mix-nodesize-sectorsize/test.sh36
-rwxr-xr-xtests/mkfs-tests/008-secorsize-nodesize-combination/test.sh50
70 files changed, 2322 insertions, 0 deletions
diff --git a/tests/README.md b/tests/README.md
new file mode 100644
index 00000000..be3bda82
--- /dev/null
+++ b/tests/README.md
@@ -0,0 +1,136 @@
+# Btrfs-progs tests
+
+Run the tests from the top directory:
+
+```shell
+$ make test
+$ make test-fsck
+$ make test-convert
+```
+
+or selectively from the `tests/` directory:
+
+```shell
+$ ./fsck-tests.sh
+$ ./misc-tests.sh
+```
+
+The verbose output of the tests is logged into a file named after the test
+category, eg. `fsck-tests-results.txt`.
+
+## Selective testing
+
+The test are prefixed by a number for ordering and uniquenes. To run a
+particular test use:
+
+```shell
+$ make TEST=MASK test
+```
+
+where `MASK` is a glob expression that will execute only tests
+that match the MASK. Here the test number comes handy:
+
+```shell
+$ make TEST=001\* test-fsck
+$ TEST=001\* ./fsck-tests.sh
+```
+
+will run the first test in fsck-tests subdirectory.
+
+
+## Test structure
+
+*tests/fsck-tests/:*
+
+ * tests targeted at bugs that are fixable by fsck
+
+*tests/convert-tests/:*
+
+ * coverage tests of ext2/3/4 and btrfs-convert options
+
+*tests/fuzz-tests/:*
+
+ * collection of fuzzed or crafted images
+ * tests that are supposed to run various utilities on the images and not
+ crash
+
+*tests/misc-tests/:*
+
+ * anything that does not fit to the above, the test driver script will only
+ execute `./test.sh` in the test directory
+
+*tests/common:*
+
+ * script with helpers
+
+*tests/test.img:*
+
+ * default testing image, the file is never deleted by the scripts but
+ truncated to 0 bytes, so it keeps it's permissions. It's eg. possible to
+ host it on NFS, make it `chmod a+w` for root.
+
+
+## Other tuning, environment variables
+
+### Instrumentation
+
+It's possible to wrap the tested commands to utilities that might do more
+checking or catch failures at runtime. This can be done by setting the
+`INSTRUMENT` environment variable:
+
+```shell
+INSTRUMENT=valgrind ./fuzz-tests.sh # in tests/
+make INSTRUMENT=valgrind test-fuzz # in the top directory
+```
+
+The variable is prepended to the command *unquoted*, all sorts of shell tricks
+are possible.
+
+Note: instrumentation is not applied to privileged commands (anything that uses
+the root helper).
+
+### Verbosity
+
+Setting the variable `TEST_LOG=tty` will print all commands executed by some of
+the wrappers (`run_check` etc), other commands are silent.
+
+### Permissions
+
+Some commands require root privileges (to mount/umount, access loop devices).
+It is assumed that `sudo` will work in some way (no password, password asked
+and cached). Note that instrumentation is not applied in this case, for safety
+reasons. You need to modify the test script instead.
+
+### Cleanup
+
+The tests are supposed to cleanup after themselves if they pass. In case of
+failure, the rest of the tests are skipped and intermediate files, mounts and
+loop devices are kept. This should help to investigate the test failure but at
+least the mounts and loop devices need to be cleaned before the next run.
+
+This is partially done by the script `clean-tests.sh`, you may want to check
+the loop devices as they are managed on a per-test basis.
+
+## New test
+
+1. Pick the category for the new test or fallback to `misc-tests` if not sure. For
+an easy start copy an existing `test.sh` script from some test that might be
+close to the purpose of your new test.
+
+* Use the highest unused number in the sequence, write a short descriptive title
+and join by dashes `-`.
+
+* Write a short description of the bug and how it's teste to the comment at the
+begining of `test.sh`.
+
+* Write the test commands, comment anything that's not obvious.
+
+* Test your test. Use the `TEST` variable to jump right to your test:
+```shell
+$ make TEST=012\* tests-misc # from top directory
+$ TEST=012\* ./misc-tests.sh # from tests/
+```
+
+* The commit changelog should reference a commit that either introduced or
+ fixed the bug (or both). Subject line of the shall mention the name of the
+ new directory for ease of search, eg. `btrfs-progs: tests: add 012-subvolume-sync-must-wait`
diff --git a/tests/clean-tests.sh b/tests/clean-tests.sh
new file mode 100755
index 00000000..f7fefdda
--- /dev/null
+++ b/tests/clean-tests.sh
@@ -0,0 +1,24 @@
+#!/bin/sh
+# remove all intermediate files from tests
+
+SCRIPT_DIR=$(dirname $(readlink -f $0))
+TOP=$(readlink -f $SCRIPT_DIR/../)
+source $TOP/tests/common
+
+setup_root_helper
+
+if [ "$BUILD_VERBOSE" = 1 ]; then
+ verbose=-print
+fi
+
+$SUDO_HELPER umount "$TEST_MNT" &>/dev/null
+
+if ! cd $TOP/tests; then
+ echo "ERROR: cannot cd to $TOP/tests"
+ exit 1
+fi
+
+find fsck-tests -type f -name '*.restored' $verbose -delete
+
+# do not remove, the file could have special permissions set
+echo -n > test.img
diff --git a/tests/common b/tests/common
new file mode 100644
index 00000000..61780486
--- /dev/null
+++ b/tests/common
@@ -0,0 +1,240 @@
+#!/bin/bash
+#
+# Common routines for all tests
+#
+
+_fail()
+{
+ echo "$*" | tee -a $RESULTS
+ exit 1
+}
+
+# log a message to the results file
+_log()
+{
+ echo "$*" | tee -a $RESULTS
+}
+
+_not_run()
+{
+ echo " [NOTRUN] $*"
+ exit 0
+}
+
+run_check()
+{
+ echo "############### $@" >> $RESULTS 2>&1
+ if [ "$TEST_LOG" = 'tty' ]; then echo "CMD: $@" > /dev/tty; fi
+ if [ "$1" = 'root_helper' ]; then
+ "$@" >> $RESULTS 2>&1 || _fail "failed: $@"
+ else
+ $INSTRUMENT "$@" >> $RESULTS 2>&1 || _fail "failed: $@"
+ fi
+}
+
+# same as run_check but the stderr+stdout output is duplicated on stdout and
+# can be processed further
+run_check_stdout()
+{
+ echo "############### $@" >> $RESULTS 2>&1
+ if [ "$TEST_LOG" = 'tty' ]; then echo "CMD(stdout): $@" > /dev/tty; fi
+ if [ "$1" = 'root_helper' ]; then
+ "$@" 2>&1 | tee -a $RESULTS || _fail "failed: $@"
+ else
+ $INSTRUMENT "$@" 2>&1 | tee -a $RESULTS || _fail "failed: $@"
+ fi
+}
+
+# same as run_check but does not fail the test, output is logged
+run_mayfail()
+{
+ echo "############### $@" >> $RESULTS 2>&1
+ if [ "$TEST_LOG" = 'tty' ]; then echo "CMD(mayfail): $@" > /dev/tty; fi
+ if [ "$1" = 'root_helper' ]; then
+ "$@" >> $RESULTS 2>&1
+ else
+ $INSTRUMENT "$@" >> $RESULTS 2>&1
+ fi
+ if [ $? != 0 ]; then
+ echo "failed (ignored): $@" >> $RESULTS
+ return 1
+ fi
+}
+
+check_prereq()
+{
+ if ! [ -f $TOP/$1 ]; then
+ _fail "Failed prerequisities: $1";
+ fi
+}
+
+check_image()
+{
+ local image
+
+ image=$1
+ echo "testing image $(basename $image)" >> $RESULTS
+ $TOP/btrfs check $image >> $RESULTS 2>&1
+ [ $? -eq 0 ] && _fail "btrfs check should have detected corruption"
+
+ run_check $TOP/btrfs check --repair $image
+ run_check $TOP/btrfs check $image
+}
+
+# Extract a usable image from packed formats
+# - raw btrfs filesystem images, suffix .raw
+# - dtto compressed by XZ, suffix .raw.xz
+# - meta-dump images with suffix .img
+# - dtto compressed by XZ, suffix .img.xz
+extract_image()
+{
+ local image
+ local cleanme
+
+ image="$1"
+ case "$image" in
+ *.img)
+ rm -f $image.restored
+ : ;;
+ *.img.xz)
+ xz --decompress --keep "$image" || \
+ _fail "failed to decompress image $image" >&2
+ image=${image%%.xz}
+ rm -f $image.restored
+ cleanme=$image
+ ;;
+ *.raw)
+ cp --sparse=auto $image $image.restored
+ ;;
+ *.raw.xz)
+ xz --decompress --keep "$image" || \
+ _fail "failed to decompress image $image" >&2
+ image=${image%%.xz}
+ mv "$image" "$image".restored
+ ;;
+ esac
+
+ if ! [ -f $image.restored ]; then
+ echo "restoring image $(basename $image)" >> $RESULTS
+ $TOP/btrfs-image -r $image $image.restored \
+ &>> $RESULTS \
+ || _fail "failed to restore image $image" >&2
+ fi
+
+ [ -f "$cleanme" ] && rm -f "$cleanme"
+
+ echo "$image.restored"
+}
+
+# Process all image dumps in a given directory
+check_all_images()
+{
+ local dir
+ local extracted
+
+ dir="$1"
+ for image in $(find $dir \( -iname '*.img' -o \
+ -iname '*.img.xz' -o \
+ -iname '*.raw' -o \
+ -iname '*.raw.xz' \) | sort)
+ do
+ extracted=$(extract_image "$image")
+ check_image "$extracted"
+ rm -f "$extracted"
+ done
+}
+
+# some tests need to mount the recovered image and do verifications call
+# 'setup_root_helper' and then check for have_root_helper == 1 if the test
+# needs to fail otherwise; using sudo by default for now
+SUDO_HELPER=
+NEED_SUDO_VALIDATE=unknown
+export SUDO_HELPER
+export NEED_SUDO_VALIDATE
+root_helper()
+{
+ if [ $UID -eq 0 ]; then
+ "$@"
+ else
+ if [ "$NEED_SUDO_VALIDATE" = 'yes' ]; then
+ sudo -v -n &>/dev/null || \
+ _not_run "Need to validate sudo credentials"
+ sudo -n "$@"
+ elif [ "$NEED_SUDO_VALIDATE" = 'no' ]; then
+ sudo -n /bin/true &> /dev/null || \
+ _not_run "Need to validate sudo user settings"
+ sudo -n "$@"
+ else
+ # should not happen
+ _not_run "Need to validate root privileges"
+ fi
+ fi
+}
+
+setup_root_helper()
+{
+ if [ $UID -eq 0 -o -n "$SUDO_HELPER" ]; then
+ return
+ fi
+
+ # Test for old sudo or special settings, which make sudo -v fail even
+ # if user setting is NOPASSWD
+ sudo -n /bin/true &>/dev/null && NEED_SUDO_VALIDATE=no
+
+ # Newer sudo or default sudo setting
+ sudo -v -n &>/dev/null && NEED_SUDO_VALIDATE=yes
+
+ if [ "$NEED_SUDO_VALIDATE" = 'unknown' ]; then
+ _not_run "Need to validate root privileges"
+ fi
+ SUDO_HELPER=root_helper
+}
+
+prepare_test_dev()
+{
+ # num[K/M/G/T...]
+ local size="$1"
+
+ [[ "$TEST_DEV" ]] && return
+ [[ "$size" ]] || size='2G'
+
+ echo "\$TEST_DEV not given, use $TOP/test/test.img as fallback" >> \
+ $RESULTS
+ TEST_DEV="$TOP/tests/test.img"
+
+ truncate -s "$size" "$TEST_DEV" || _not_run "create file for loop device failed"
+}
+
+run_check_mount_test_dev()
+{
+ setup_root_helper
+
+ local loop_opt
+ if [[ -b "$TEST_DEV" ]]; then
+ loop_opt=""
+ elif [[ -f "$TEST_DEV" ]]; then
+ loop_opt="-o loop"
+ else
+ _fail "Invalid \$TEST_DEV: $TEST_DEV"
+ fi
+
+ [[ -d "$TEST_MNT" ]] || {
+ _fail "Invalid \$TEST_MNT: $TEST_MNT"
+ }
+
+ run_check $SUDO_HELPER mount $loop_opt "$@" "$TEST_DEV" "$TEST_MNT"
+}
+
+run_check_umount_test_dev()
+{
+ setup_root_helper
+ run_check $SUDO_HELPER umount "$@" "$TEST_DEV"
+}
+
+init_env()
+{
+ TEST_MNT="${TEST_MNT:-$TOP/tests/mnt}"
+ export TEST_MNT
+ mkdir -p "$TEST_MNT" || { echo "Failed mkdir -p $TEST_MNT"; exit 1; }
+}
+init_env
diff --git a/tests/convert-tests.sh b/tests/convert-tests.sh
new file mode 100644
index 00000000..0bfb41f8
--- /dev/null
+++ b/tests/convert-tests.sh
@@ -0,0 +1,86 @@
+#!/bin/bash
+#
+# convert ext2/3/4 images to btrfs images, and make sure the results are
+# clean.
+#
+
+unset TOP
+unset LANG
+LANG=C
+SCRIPT_DIR=$(dirname $(readlink -f $0))
+TOP=$(readlink -f $SCRIPT_DIR/../)
+RESULTS="$TOP/tests/convert-tests-results.txt"
+
+source $TOP/tests/common
+
+rm -f $RESULTS
+
+setup_root_helper
+prepare_test_dev 256M
+
+CHECKSUMTMP=$(mktemp --tmpdir btrfs-progs-convert.XXXXXXXXXX)
+
+convert_test() {
+ local features
+ local nodesize
+
+ features="$1"
+ shift
+
+ if [ -z "$features" ]; then
+ echo " [TEST/conv] $1, btrfs defaults"
+ else
+ echo " [TEST/conv] $1, btrfs $features"
+ fi
+ nodesize=$2
+ shift 2
+ echo "creating ext image with: $*" >> $RESULTS
+ # TEST_DEV not removed as the file might have special permissions, eg.
+ # when test image is on NFS and would not be writable for root
+ run_check truncate -s 0 $TEST_DEV
+ # 256MB is the smallest acceptable btrfs image.
+ run_check truncate -s 256M $TEST_DEV
+ run_check $* -F $TEST_DEV
+
+ # create a file to check btrfs-convert can convert regular file
+ # correct
+ run_check_mount_test_dev
+ run_check $SUDO_HELPER dd if=/dev/zero of=$TEST_MNT/test bs=$nodesize \
+ count=1 1>/dev/null 2>&1
+ run_check_stdout md5sum $TEST_MNT/test > $CHECKSUMTMP
+ run_check_umount_test_dev
+
+ run_check $TOP/btrfs-convert ${features:+-O "$features"} -N "$nodesize" $TEST_DEV
+ run_check $TOP/btrfs check $TEST_DEV
+ run_check $TOP/btrfs-show-super $TEST_DEV
+
+ run_check_mount_test_dev
+ run_check_stdout md5sum -c $CHECKSUMTMP |
+ grep -q 'OK' || _fail "file validation failed."
+ run_check_umount_test_dev
+}
+
+if ! [ -z "$TEST" ]; then
+ echo " [TEST/conv] skipped all convert tests, TEST=$TEST"
+ exit 0
+fi
+
+for feature in '' 'extref' 'skinny-metadata' 'no-holes'; do
+ convert_test "$feature" "ext2 4k nodesize" 4096 mke2fs -b 4096
+ convert_test "$feature" "ext3 4k nodesize" 4096 mke2fs -j -b 4096
+ convert_test "$feature" "ext4 4k nodesize" 4096 mke2fs -t ext4 -b 4096
+ convert_test "$feature" "ext2 8k nodesize" 8192 mke2fs -b 4096
+ convert_test "$feature" "ext3 8k nodesize" 8192 mke2fs -j -b 4096
+ convert_test "$feature" "ext4 8k nodesize" 8192 mke2fs -t ext4 -b 4096
+ convert_test "$feature" "ext2 16k nodesize" 16384 mke2fs -b 4096
+ convert_test "$feature" "ext3 16k nodesize" 16384 mke2fs -j -b 4096
+ convert_test "$feature" "ext4 16k nodesize" 16384 mke2fs -t ext4 -b 4096
+ convert_test "$feature" "ext2 32k nodesize" 32768 mke2fs -b 4096
+ convert_test "$feature" "ext3 32k nodesize" 32768 mke2fs -j -b 4096
+ convert_test "$feature" "ext4 32k nodesize" 32768 mke2fs -t ext4 -b 4096
+ convert_test "$feature" "ext2 64k nodesize" 65536 mke2fs -b 4096
+ convert_test "$feature" "ext3 64k nodesize" 65536 mke2fs -j -b 4096
+ convert_test "$feature" "ext4 64k nodesize" 65536 mke2fs -t ext4 -b 4096
+done
+
+rm $CHECKSUMTMP
diff --git a/tests/fsck-tests.sh b/tests/fsck-tests.sh
new file mode 100755
index 00000000..2aab4ff2
--- /dev/null
+++ b/tests/fsck-tests.sh
@@ -0,0 +1,68 @@
+#!/bin/bash
+#
+# loop through all of our bad images and make sure fsck repairs them properly
+#
+# It's GPL, same as everything else in this tree.
+#
+
+unset TOP
+unset LANG
+LANG=C
+SCRIPT_DIR=$(dirname $(readlink -f $0))
+TOP=$(readlink -f $SCRIPT_DIR/../)
+TEST_DEV=${TEST_DEV:-}
+RESULTS="$TOP/tests/fsck-tests-results.txt"
+
+source $TOP/tests/common
+
+# Allow child test to use $TOP and $RESULTS
+export TOP
+export RESULTS
+# For custom script needs to verfiy recovery
+export LANG
+
+rm -f $RESULTS
+
+# test rely on corrupting blocks tool
+check_prereq btrfs-corrupt-block
+check_prereq btrfs-image
+check_prereq btrfs
+
+run_one_test() {
+ local testname
+
+ testname="$1"
+ echo " [TEST/fsck] $(basename $testname)"
+ cd $testname
+ echo "=== Entering $testname" >> $RESULTS
+ if [ -x test.sh ]; then
+ # Type 2
+ ./test.sh
+ if [ $? -ne 0 ]; then
+ _fail "test failed for case $(basename $testname)"
+ fi
+ else
+ # Type 1
+ check_all_images `pwd`
+ fi
+ cd $TOP
+}
+
+# Each dir contains one type of error for btrfsck test.
+# Each dir must be one of the following 2 types:
+# 1) Only btrfs-image dump
+# Only contains one or several btrfs-image dumps (.img)
+# Each image will be tested by generic test routine
+# (btrfsck --repair and btrfsck).
+# This is for case that btree-healthy images.
+# 2) Custom test script
+# This dir contains test.sh which will do custom image
+# generation/check/verification.
+# This is for case btrfs-image can't dump or case needs extra
+# check/verify
+
+for i in $(find $TOP/tests/fsck-tests -maxdepth 1 -mindepth 1 -type d \
+ ${TEST:+-name "$TEST"} | sort)
+do
+ run_one_test "$i"
+done
diff --git a/tests/fsck-tests/001-bad-file-extent-bytenr/default_case.img b/tests/fsck-tests/001-bad-file-extent-bytenr/default_case.img
new file mode 100644
index 00000000..d2a05bb8
--- /dev/null
+++ b/tests/fsck-tests/001-bad-file-extent-bytenr/default_case.img
Binary files differ
diff --git a/tests/fsck-tests/002-bad-transid/default_case.img b/tests/fsck-tests/002-bad-transid/default_case.img
new file mode 100644
index 00000000..85bd87cd
--- /dev/null
+++ b/tests/fsck-tests/002-bad-transid/default_case.img
Binary files differ
diff --git a/tests/fsck-tests/003-shift-offsets/default_case.img b/tests/fsck-tests/003-shift-offsets/default_case.img
new file mode 100644
index 00000000..ce23f673
--- /dev/null
+++ b/tests/fsck-tests/003-shift-offsets/default_case.img
Binary files differ
diff --git a/tests/fsck-tests/004-no-dir-index/default_case.img b/tests/fsck-tests/004-no-dir-index/default_case.img
new file mode 100644
index 00000000..6f2483e6
--- /dev/null
+++ b/tests/fsck-tests/004-no-dir-index/default_case.img
Binary files differ
diff --git a/tests/fsck-tests/005-bad-item-offset/default_case.img b/tests/fsck-tests/005-bad-item-offset/default_case.img
new file mode 100644
index 00000000..e11e1e32
--- /dev/null
+++ b/tests/fsck-tests/005-bad-item-offset/default_case.img
Binary files differ
diff --git a/tests/fsck-tests/006-bad-root-items/default_case.tar.xz b/tests/fsck-tests/006-bad-root-items/default_case.tar.xz
new file mode 100644
index 00000000..125d8e7d
--- /dev/null
+++ b/tests/fsck-tests/006-bad-root-items/default_case.tar.xz
Binary files differ
diff --git a/tests/fsck-tests/006-bad-root-items/skinny_case.tar.xz b/tests/fsck-tests/006-bad-root-items/skinny_case.tar.xz
new file mode 100644
index 00000000..ed99dc4d
--- /dev/null
+++ b/tests/fsck-tests/006-bad-root-items/skinny_case.tar.xz
Binary files differ
diff --git a/tests/fsck-tests/006-bad-root-items/test.sh b/tests/fsck-tests/006-bad-root-items/test.sh
new file mode 100755
index 00000000..84332348
--- /dev/null
+++ b/tests/fsck-tests/006-bad-root-items/test.sh
@@ -0,0 +1,17 @@
+#!/bin/bash
+
+source $TOP/tests/common
+
+check_prereq btrfs
+
+echo "extracting image default_case.tar.xz" >> $RESULTS
+tar --no-same-owner -xJf default_case.tar.xz || \
+ _fail "failed to extract default_case.tar.xz"
+check_image test.img
+
+echo "extracting image skinny_case.tar.xz" >> $RESULTS
+tar --no-same-owner -xJf skinny_case.tar.xz || \
+ _fail "failed to extract skinny_case.tar.xz"
+check_image test.img
+
+rm test.img
diff --git a/tests/fsck-tests/007-bad-offset-snapshots/default_case.img b/tests/fsck-tests/007-bad-offset-snapshots/default_case.img
new file mode 100644
index 00000000..b87e9977
--- /dev/null
+++ b/tests/fsck-tests/007-bad-offset-snapshots/default_case.img
Binary files differ
diff --git a/tests/fsck-tests/008-bad-dir-index-name/default_case.img b/tests/fsck-tests/008-bad-dir-index-name/default_case.img
new file mode 100644
index 00000000..e004737f
--- /dev/null
+++ b/tests/fsck-tests/008-bad-dir-index-name/default_case.img
Binary files differ
diff --git a/tests/fsck-tests/009-no-dir-item-or-index/default_case.img b/tests/fsck-tests/009-no-dir-item-or-index/default_case.img
new file mode 100644
index 00000000..d7f22692
--- /dev/null
+++ b/tests/fsck-tests/009-no-dir-item-or-index/default_case.img
Binary files differ
diff --git a/tests/fsck-tests/010-no-rootdir-inode-item/default_case.img b/tests/fsck-tests/010-no-rootdir-inode-item/default_case.img
new file mode 100644
index 00000000..6b66fdad
--- /dev/null
+++ b/tests/fsck-tests/010-no-rootdir-inode-item/default_case.img
Binary files differ
diff --git a/tests/fsck-tests/011-no-inode-item/default_case.img b/tests/fsck-tests/011-no-inode-item/default_case.img
new file mode 100644
index 00000000..352fc021
--- /dev/null
+++ b/tests/fsck-tests/011-no-inode-item/default_case.img
Binary files differ
diff --git a/tests/fsck-tests/012-leaf-corruption/no_data_extent.tar.xz b/tests/fsck-tests/012-leaf-corruption/no_data_extent.tar.xz
new file mode 100644
index 00000000..547e5455
--- /dev/null
+++ b/tests/fsck-tests/012-leaf-corruption/no_data_extent.tar.xz
Binary files differ
diff --git a/tests/fsck-tests/012-leaf-corruption/test.sh b/tests/fsck-tests/012-leaf-corruption/test.sh
new file mode 100755
index 00000000..a308727d
--- /dev/null
+++ b/tests/fsck-tests/012-leaf-corruption/test.sh
@@ -0,0 +1,117 @@
+#!/bin/bash
+
+source $TOP/tests/common
+
+check_prereq btrfs-image
+
+# Check file list for leaf corruption, no regular/preallocated
+# file extent case.
+# Corrupted leaf is 20832256, which contains inode 1862~1872
+#
+# 1862, ref from leaf 20828160 key 24(DIR_ITEM)
+# 1863, ref from leaf 605388 item key 11(DIR_ITEM)
+# 1864, no ref to rebuild, no need to rebuild
+# 1865, ref from leaf 19767296 key 23(DIR_ITEM)
+# 1866-1868 no ref to rebuild, all refs in corrupted leaf
+# 1869, ref from leaf 4976640 key 22(DIR_ITEM)
+# 1870 no ref to rebuild, all refs in corrupted leaf
+# 1871, ref from leaf 19746816 key 38(DIR_ITEM)
+# 1872, ref from leaf 19767296 key 14(DIR_ITEM)
+# The list format is:
+# INO SIZE MODE NAME
+# INO: inode number
+# SIZE: file size, only checked for regular file
+# MODE: raw file mode, get from stat
+# NAME: file name
+leaf_no_data_ext_list=(
+ 1862 0 40700 "install.d"
+ 1862 0 40700 "install.d"
+ 1863 0 40700 "gdb"
+ 1865 0 40700 "iptables"
+ 1869 0 40700 "snmp"
+ 1871 0 100700 "machine-id"
+ 1872 0 100700 "adjtime"
+ 1877 0 40700 "del"
+)
+
+generate_leaf_corrupt_no_data_ext()
+{
+ dest=$1
+ echo "generating leaf_corrupt_no_data_ext.btrfs-image" >> $RESULTS
+ tar --no-same-owner -xJf ./no_data_extent.tar.xz || \
+ _fail "failed to extract leaf_corrupt_no_data_ext.btrfs-image"
+ $TOP/btrfs-image -r test.img.btrfs-image $dest || \
+ _fail "failed to extract leaf_corrupt_no_data_ext.btrfs-image"
+
+ # leaf at 4206592 and 20905984 contains no regular data
+ # extent, clear its csum to corrupt the leaf.
+ for x in 4206592 20905984; do
+ dd if=/dev/zero of=$dest bs=1 count=32 conv=notrunc seek=$x \
+ 1>/dev/null 2>&1
+ done
+}
+
+check_inode()
+{
+ path=$1
+ ino=$2
+ size=$3
+ mode=$4
+ name=$5
+
+ # Check whether the inode exists
+ exists=$($SUDO_HELPER find $path -inum $ino)
+ if [ -z "$exists" ]; then
+ _fail "inode $ino not recovered correctly"
+ fi
+
+ # Check inode type
+ found_mode=$(printf "%o" 0x$($SUDO_HELPER stat $exists -c %f))
+ if [ $found_mode -ne $mode ]; then
+ echo "$found_mode"
+ _fail "inode $ino modes not recovered"
+ fi
+
+ # Check inode size
+ found_size=$($SUDO_HELPER stat $exists -c %s)
+ if [ $mode -ne 41700 -a $found_size -ne $size ]; then
+ _fail "inode $ino size not recovered correctly"
+ fi
+
+ # Check inode name
+ if [ "$(basename $exists)" != "$name" ]; then
+ _fail "inode $ino name not recovered correctly"
+ else
+ return 0
+ fi
+}
+
+# Check salvaged data in the recovered image
+check_leaf_corrupt_no_data_ext()
+{
+ image=$1
+ $SUDO_HELPER mount -o loop $image -o ro $TEST_MNT
+
+ i=0
+ while [ $i -lt ${#leaf_no_data_ext_list[@]} ]; do
+ check_inode $TEST_MNT/lost+found \
+ ${leaf_no_data_ext_list[i]} \
+ ${leaf_no_data_ext_list[i + 1]} \
+ ${leaf_no_data_ext_list[i + 2]} \
+ ${leaf_no_data_ext_list[i + 3]} \
+ ${leaf_no_data_ext_list[i + 4]}
+ ((i+=4))
+ done
+ $SUDO_HELPER umount $TEST_MNT
+}
+
+setup_root_helper
+
+generate_leaf_corrupt_no_data_ext test.img
+check_image test.img
+check_leaf_corrupt_no_data_ext test.img
+
+rm test.img
+rm test.img.btrfs-image
+# Not used, its function is the same as generate_leaf_corrupt_no_data_ext()
+rm generate_image.sh
diff --git a/tests/fsck-tests/013-extent-tree-rebuild/test.sh b/tests/fsck-tests/013-extent-tree-rebuild/test.sh
new file mode 100755
index 00000000..ff7d28e5
--- /dev/null
+++ b/tests/fsck-tests/013-extent-tree-rebuild/test.sh
@@ -0,0 +1,44 @@
+#!/bin/bash
+
+source $TOP/tests/common
+
+check_prereq btrfs-corrupt-block
+check_prereq btrfs-debug-tree
+check_prereq mkfs.btrfs
+check_prereq btrfs
+
+setup_root_helper
+prepare_test_dev 1G
+
+# test whether fsck can rebuild a corrupted extent tree
+test_extent_tree_rebuild()
+{
+ run_check $SUDO_HELPER $TOP/mkfs.btrfs -f $TEST_DEV
+
+ run_check_mount_test_dev
+ run_check $SUDO_HELPER cp -aR /lib/modules/`uname -r`/ $TEST_MNT
+
+ for i in `seq 1 100`;do
+ run_check $SUDO_HELPER $TOP/btrfs sub snapshot $TEST_MNT \
+ $TEST_MNT/snapaaaaaaa_$i
+ done
+ run_check_umount_test_dev
+
+ # get extent root bytenr
+ extent_root_bytenr=`$SUDO_HELPER $TOP/btrfs-debug-tree -r $TEST_DEV | \
+ grep extent | awk '{print $7}'`
+ if [ -z $extent_root_bytenr ];then
+ _fail "fail to get extent root bytenr"
+ fi
+
+ # corrupt extent root node block
+ run_check $SUDO_HELPER $TOP/btrfs-corrupt-block -l $extent_root_bytenr \
+ -b 4096 $TEST_DEV
+
+ $SUDO_HELPER $TOP/btrfs check $TEST_DEV >& /dev/null && \
+ _fail "btrfs check should detect failure"
+ run_check $SUDO_HELPER $TOP/btrfs check --init-extent-tree $TEST_DEV
+ run_check $SUDO_HELPER $TOP/btrfs check $TEST_DEV
+}
+
+test_extent_tree_rebuild
diff --git a/tests/fsck-tests/014-no-extent-info/default_case.img b/tests/fsck-tests/014-no-extent-info/default_case.img
new file mode 100644
index 00000000..1ff27434
--- /dev/null
+++ b/tests/fsck-tests/014-no-extent-info/default_case.img
Binary files differ
diff --git a/tests/fsck-tests/015-check-bad-memory-access/bko-97171-btrfs-image.raw.txt b/tests/fsck-tests/015-check-bad-memory-access/bko-97171-btrfs-image.raw.txt
new file mode 100644
index 00000000..9685ed46
--- /dev/null
+++ b/tests/fsck-tests/015-check-bad-memory-access/bko-97171-btrfs-image.raw.txt
@@ -0,0 +1,254 @@
+URL: https://bugzilla.kernel.org/show_bug.cgi?id=97171
+
+The btrfs-image attached to this bug causes the btrfs-userland tool to use
+uninitialized memory and ultimately overwrite what seems to be arbitrary memory
+locations, dying in the process. Reproduced on x86-64 and i686.
+
+The kernel seems to be less affected and fails to mount the image. If
+/usr/sbin/btrfs is not setuid (which it probably never is), things should be
+safe. I didn't investigate further though.
+
+gdb output:
+
+GNU gdb (GDB) Fedora 7.8.2-38.fc21
+[... lots of other errors...]
+Ignoring transid failure
+root 5 inode 260 errors 1000, some csum missing
+ unresolved ref dir 256 index 7 namelen 5 name b.bin filetype 1 errors 2, no dir index
+ unresolved ref dir 256 index 7 namelen 5 name b.fin filetype 1 errors 5, no dir item, no inode ref
+root 5 inode 261 errors 200, dir isize wrong
+
+Program received signal SIGSEGV, Segmentation fault.
+0x000000000089bb70 in ?? ()
+(gdb) bt
+#0 0x000000000089bb70 in ?? ()
+#1 0x00007fffffffdb50 in ?? ()
+#2 0x0000000000894b20 in ?? ()
+#3 0x00000032629b88e0 in _IO_2_1_stdout_ () from /lib64/libc.so.6
+#4 0x000000000088c010 in ?? ()
+#5 0x0000000000000000 in ?? ()
+
+
+valgrind output:
+
+[...lots of errors...]
+==12638== Conditional jump or move depends on uninitialised value(s)
+==12638== at 0x436E77: check_block.part.14 (ctree.c:548)
+==12638== by 0x438954: UnknownInlinedFun (kerncompat.h:91)
+==12638== by 0x438954: btrfs_search_slot (ctree.c:1120)
+==12638== by 0x40DD1F: count_csum_range (cmds-check.c:1419)
+==12638== by 0x40DD1F: process_file_extent (cmds-check.c:1551)
+==12638== by 0x40DD1F: process_one_leaf (cmds-check.c:1617)
+==12638== by 0x40DD1F: walk_down_tree (cmds-check.c:1742)
+==12638== by 0x40DD1F: check_fs_root (cmds-check.c:3380)
+==12638== by 0x40DD1F: check_fs_roots.isra.51 (cmds-check.c:3516)
+==12638== by 0x4C64B0F: ???
+==12638== by 0x4C30A2F: ???
+==12638== by 0x4C468CF: ???
+==12638== by 0x32629B88DF: ??? (in /usr/lib64/libc-2.20.so)
+==12638== by 0x4C3657F: ???
+==12638==
+==12638== Conditional jump or move depends on uninitialised value(s)
+==12638== at 0x4A0B0E7: memcpy@@GLIBC_2.14 (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
+==12638== by 0x436E99: UnknownInlinedFun (ctree.h:1613)
+==12638== by 0x436E99: check_block.part.14 (ctree.c:550)
+==12638== by 0x438954: UnknownInlinedFun (kerncompat.h:91)
+==12638== by 0x438954: btrfs_search_slot (ctree.c:1120)
+==12638== by 0x40DD1F: count_csum_range (cmds-check.c:1419)
+==12638== by 0x40DD1F: process_file_extent (cmds-check.c:1551)
+==12638== by 0x40DD1F: process_one_leaf (cmds-check.c:1617)
+==12638== by 0x40DD1F: walk_down_tree (cmds-check.c:1742)
+==12638== by 0x40DD1F: check_fs_root (cmds-check.c:3380)
+==12638== by 0x40DD1F: check_fs_roots.isra.51 (cmds-check.c:3516)
+==12638== by 0x4C64B0F: ???
+==12638== by 0x4C30A2F: ???
+==12638== by 0x4C468CF: ???
+==12638== by 0x32629B88DF: ??? (in /usr/lib64/libc-2.20.so)
+==12638== by 0x4C3657F: ???
+==12638==
+==12638== Conditional jump or move depends on uninitialised value(s)
+==12638== at 0x4A0B2AC: memcpy@@GLIBC_2.14 (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
+==12638== by 0x436E99: UnknownInlinedFun (ctree.h:1613)
+==12638== by 0x436E99: check_block.part.14 (ctree.c:550)
+==12638== by 0x438954: UnknownInlinedFun (kerncompat.h:91)
+==12638== by 0x438954: btrfs_search_slot (ctree.c:1120)
+==12638== by 0x40DD1F: count_csum_range (cmds-check.c:1419)
+==12638== by 0x40DD1F: process_file_extent (cmds-check.c:1551)
+==12638== by 0x40DD1F: process_one_leaf (cmds-check.c:1617)
+==12638== by 0x40DD1F: walk_down_tree (cmds-check.c:1742)
+==12638== by 0x40DD1F: check_fs_root (cmds-check.c:3380)
+==12638== by 0x40DD1F: check_fs_roots.isra.51 (cmds-check.c:3516)
+==12638== by 0x4C64B0F: ???
+==12638== by 0x4C30A2F: ???
+==12638== by 0x4C468CF: ???
+==12638== by 0x32629B88DF: ??? (in /usr/lib64/libc-2.20.so)
+==12638== by 0x4C3657F: ???
+==12638==
+==12638== Conditional jump or move depends on uninitialised value(s)
+==12638== at 0x4A0B151: memcpy@@GLIBC_2.14 (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
+==12638== by 0x436E99: UnknownInlinedFun (ctree.h:1613)
+==12638== by 0x436E99: check_block.part.14 (ctree.c:550)
+==12638== by 0x438954: UnknownInlinedFun (kerncompat.h:91)
+==12638== by 0x438954: btrfs_search_slot (ctree.c:1120)
+==12638== by 0x40DD1F: count_csum_range (cmds-check.c:1419)
+==12638== by 0x40DD1F: process_file_extent (cmds-check.c:1551)
+==12638== by 0x40DD1F: process_one_leaf (cmds-check.c:1617)
+==12638== by 0x40DD1F: walk_down_tree (cmds-check.c:1742)
+==12638== by 0x40DD1F: check_fs_root (cmds-check.c:3380)
+==12638== by 0x40DD1F: check_fs_roots.isra.51 (cmds-check.c:3516)
+==12638== by 0x4C64B0F: ???
+==12638== by 0x4C30A2F: ???
+==12638== by 0x4C468CF: ???
+==12638== by 0x32629B88DF: ??? (in /usr/lib64/libc-2.20.so)
+==12638== by 0x4C3657F: ???
+==12638==
+==12638== Conditional jump or move depends on uninitialised value(s)
+==12638== at 0x4A0B162: memcpy@@GLIBC_2.14 (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
+==12638== by 0x436E99: UnknownInlinedFun (ctree.h:1613)
+==12638== by 0x436E99: check_block.part.14 (ctree.c:550)
+==12638== by 0x438954: UnknownInlinedFun (kerncompat.h:91)
+==12638== by 0x438954: btrfs_search_slot (ctree.c:1120)
+==12638== by 0x40DD1F: count_csum_range (cmds-check.c:1419)
+==12638== by 0x40DD1F: process_file_extent (cmds-check.c:1551)
+==12638== by 0x40DD1F: process_one_leaf (cmds-check.c:1617)
+==12638== by 0x40DD1F: walk_down_tree (cmds-check.c:1742)
+==12638== by 0x40DD1F: check_fs_root (cmds-check.c:3380)
+==12638== by 0x40DD1F: check_fs_roots.isra.51 (cmds-check.c:3516)
+==12638== by 0x4C64B0F: ???
+==12638== by 0x4C30A2F: ???
+==12638== by 0x4C468CF: ???
+==12638== by 0x32629B88DF: ??? (in /usr/lib64/libc-2.20.so)
+==12638== by 0x4C3657F: ???
+==12638==
+==12638== Conditional jump or move depends on uninitialised value(s)
+==12638== at 0x4A0B176: memcpy@@GLIBC_2.14 (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
+==12638== by 0x436E99: UnknownInlinedFun (ctree.h:1613)
+==12638== by 0x436E99: check_block.part.14 (ctree.c:550)
+==12638== by 0x438954: UnknownInlinedFun (kerncompat.h:91)
+==12638== by 0x438954: btrfs_search_slot (ctree.c:1120)
+==12638== by 0x40DD1F: count_csum_range (cmds-check.c:1419)
+==12638== by 0x40DD1F: process_file_extent (cmds-check.c:1551)
+==12638== by 0x40DD1F: process_one_leaf (cmds-check.c:1617)
+==12638== by 0x40DD1F: walk_down_tree (cmds-check.c:1742)
+==12638== by 0x40DD1F: check_fs_root (cmds-check.c:3380)
+==12638== by 0x40DD1F: check_fs_roots.isra.51 (cmds-check.c:3516)
+==12638== by 0x4C64B0F: ???
+==12638== by 0x4C30A2F: ???
+==12638== by 0x4C468CF: ???
+==12638== by 0x32629B88DF: ??? (in /usr/lib64/libc-2.20.so)
+==12638== by 0x4C3657F: ???
+==12638==
+==12638== Conditional jump or move depends on uninitialised value(s)
+==12638== at 0x4A0B2CE: memcpy@@GLIBC_2.14 (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
+==12638== by 0x436E99: UnknownInlinedFun (ctree.h:1613)
+==12638== by 0x436E99: check_block.part.14 (ctree.c:550)
+==12638== by 0x438954: UnknownInlinedFun (kerncompat.h:91)
+==12638== by 0x438954: btrfs_search_slot (ctree.c:1120)
+==12638== by 0x40DD1F: count_csum_range (cmds-check.c:1419)
+==12638== by 0x40DD1F: process_file_extent (cmds-check.c:1551)
+==12638== by 0x40DD1F: process_one_leaf (cmds-check.c:1617)
+==12638== by 0x40DD1F: walk_down_tree (cmds-check.c:1742)
+==12638== by 0x40DD1F: check_fs_root (cmds-check.c:3380)
+==12638== by 0x40DD1F: check_fs_roots.isra.51 (cmds-check.c:3516)
+==12638== by 0x4C64B0F: ???
+==12638== by 0x4C30A2F: ???
+==12638== by 0x4C468CF: ???
+==12638== by 0x32629B88DF: ??? (in /usr/lib64/libc-2.20.so)
+==12638== by 0x4C3657F: ???
+==12638==
+==12638== Conditional jump or move depends on uninitialised value(s)
+==12638== at 0x4A0B34A: memcpy@@GLIBC_2.14 (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
+==12638== by 0x436E99: UnknownInlinedFun (ctree.h:1613)
+==12638== by 0x436E99: check_block.part.14 (ctree.c:550)
+==12638== by 0x438954: UnknownInlinedFun (kerncompat.h:91)
+==12638== by 0x438954: btrfs_search_slot (ctree.c:1120)
+==12638== by 0x40DD1F: count_csum_range (cmds-check.c:1419)
+==12638== by 0x40DD1F: process_file_extent (cmds-check.c:1551)
+==12638== by 0x40DD1F: process_one_leaf (cmds-check.c:1617)
+==12638== by 0x40DD1F: walk_down_tree (cmds-check.c:1742)
+==12638== by 0x40DD1F: check_fs_root (cmds-check.c:3380)
+==12638== by 0x40DD1F: check_fs_roots.isra.51 (cmds-check.c:3516)
+==12638== by 0x4C64B0F: ???
+==12638== by 0x4C30A2F: ???
+==12638== by 0x4C468CF: ???
+==12638== by 0x32629B88DF: ??? (in /usr/lib64/libc-2.20.so)
+==12638== by 0x4C3657F: ???
+==12638==
+==12638== Use of uninitialised value of size 8
+==12638== at 0x4A0B3A0: memcpy@@GLIBC_2.14 (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
+==12638== by 0x436E99: UnknownInlinedFun (ctree.h:1613)
+==12638== by 0x436E99: check_block.part.14 (ctree.c:550)
+==12638== by 0x438954: UnknownInlinedFun (kerncompat.h:91)
+==12638== by 0x438954: btrfs_search_slot (ctree.c:1120)
+==12638== by 0x40DD1F: count_csum_range (cmds-check.c:1419)
+==12638== by 0x40DD1F: process_file_extent (cmds-check.c:1551)
+==12638== by 0x40DD1F: process_one_leaf (cmds-check.c:1617)
+==12638== by 0x40DD1F: walk_down_tree (cmds-check.c:1742)
+==12638== by 0x40DD1F: check_fs_root (cmds-check.c:3380)
+==12638== by 0x40DD1F: check_fs_roots.isra.51 (cmds-check.c:3516)
+==12638== by 0x4C64B0F: ???
+==12638== by 0x4C30A2F: ???
+==12638== by 0x4C468CF: ???
+==12638== by 0x32629B88DF: ??? (in /usr/lib64/libc-2.20.so)
+==12638== by 0x4C3657F: ???
+==12638==
+==12638== Invalid read of size 1
+==12638== at 0x4A0B3A0: memcpy@@GLIBC_2.14 (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
+==12638== by 0x436E99: UnknownInlinedFun (ctree.h:1613)
+==12638== by 0x436E99: check_block.part.14 (ctree.c:550)
+==12638== by 0x438954: UnknownInlinedFun (kerncompat.h:91)
+==12638== by 0x438954: btrfs_search_slot (ctree.c:1120)
+==12638== by 0x40DD1F: count_csum_range (cmds-check.c:1419)
+==12638== by 0x40DD1F: process_file_extent (cmds-check.c:1551)
+==12638== by 0x40DD1F: process_one_leaf (cmds-check.c:1617)
+==12638== by 0x40DD1F: walk_down_tree (cmds-check.c:1742)
+==12638== by 0x40DD1F: check_fs_root (cmds-check.c:3380)
+==12638== by 0x40DD1F: check_fs_roots.isra.51 (cmds-check.c:3516)
+==12638== by 0x4C64B0F: ???
+==12638== by 0x4C30A2F: ???
+==12638== by 0x4C468CF: ???
+==12638== by 0x32629B88DF: ??? (in /usr/lib64/libc-2.20.so)
+==12638== by 0x4C3657F: ???
+==12638== Address 0xa25c9de9 is not stack'd, malloc'd or (recently) free'd
+==12638==
+==12638==
+==12638== Process terminating with default action of signal 11 (SIGSEGV)
+==12638== Access not within mapped region at address 0xA25C9DE9
+==12638== at 0x4A0B3A0: memcpy@@GLIBC_2.14 (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
+==12638== by 0x436E99: UnknownInlinedFun (ctree.h:1613)
+==12638== by 0x436E99: check_block.part.14 (ctree.c:550)
+==12638== by 0x438954: UnknownInlinedFun (kerncompat.h:91)
+==12638== by 0x438954: btrfs_search_slot (ctree.c:1120)
+==12638== by 0x40DD1F: count_csum_range (cmds-check.c:1419)
+==12638== by 0x40DD1F: process_file_extent (cmds-check.c:1551)
+==12638== by 0x40DD1F: process_one_leaf (cmds-check.c:1617)
+==12638== by 0x40DD1F: walk_down_tree (cmds-check.c:1742)
+==12638== by 0x40DD1F: check_fs_root (cmds-check.c:3380)
+==12638== by 0x40DD1F: check_fs_roots.isra.51 (cmds-check.c:3516)
+==12638== by 0x4C64B0F: ???
+==12638== by 0x4C30A2F: ???
+==12638== by 0x4C468CF: ???
+==12638== by 0x32629B88DF: ??? (in /usr/lib64/libc-2.20.so)
+==12638== by 0x4C3657F: ???
+==12638== If you believe this happened as a result of a stack
+==12638== overflow in your program's main thread (unlikely but
+==12638== possible), you can try to increase the size of the
+==12638== main thread stack using the --main-stacksize= flag.
+==12638== The main thread stack size used in this run was 8388608.
+==12638==
+==12638== HEAP SUMMARY:
+==12638== in use at exit: 46,260 bytes in 56 blocks
+==12638== total heap usage: 380 allocs, 324 frees, 218,054 bytes allocated
+==12638==
+==12638== LEAK SUMMARY:
+==12638== definitely lost: 272 bytes in 2 blocks
+==12638== indirectly lost: 800 bytes in 8 blocks
+==12638== possibly lost: 88 bytes in 1 blocks
+==12638== still reachable: 45,100 bytes in 45 blocks
+==12638== suppressed: 0 bytes in 0 blocks
+==12638== Rerun with --leak-check=full to see details of leaked memory
+==12638==
+==12638== For counts of detected and suppressed errors, rerun with: -v
+==12638== Use --track-origins=yes to see where uninitialised values come from
+==12638== ERROR SUMMARY: 10 errors from 10 contexts (suppressed: 0 from 0)
+[1] 12638 segmentation fault valgrind btrfs check btrfs_fukked_memorycorruption.bin
diff --git a/tests/fsck-tests/015-check-bad-memory-access/bko-97171-btrfs-image.raw.xz b/tests/fsck-tests/015-check-bad-memory-access/bko-97171-btrfs-image.raw.xz
new file mode 100644
index 00000000..f3f0944d
--- /dev/null
+++ b/tests/fsck-tests/015-check-bad-memory-access/bko-97171-btrfs-image.raw.xz
Binary files differ
diff --git a/tests/fsck-tests/016-wrong-inode-nbytes/default_case.img.xz b/tests/fsck-tests/016-wrong-inode-nbytes/default_case.img.xz
new file mode 100644
index 00000000..d513acf5
--- /dev/null
+++ b/tests/fsck-tests/016-wrong-inode-nbytes/default_case.img.xz
Binary files differ
diff --git a/tests/fsck-tests/017-missing-all-file-extent/default_case.img.xz b/tests/fsck-tests/017-missing-all-file-extent/default_case.img.xz
new file mode 100644
index 00000000..10cd4c78
--- /dev/null
+++ b/tests/fsck-tests/017-missing-all-file-extent/default_case.img.xz
Binary files differ
diff --git a/tests/fsck-tests/018-leaf-crossing-stripes/default_case.raw.xz b/tests/fsck-tests/018-leaf-crossing-stripes/default_case.raw.xz
new file mode 100644
index 00000000..60eb2f97
--- /dev/null
+++ b/tests/fsck-tests/018-leaf-crossing-stripes/default_case.raw.xz
Binary files differ
diff --git a/tests/fsck-tests/018-leaf-crossing-stripes/test.sh b/tests/fsck-tests/018-leaf-crossing-stripes/test.sh
new file mode 100755
index 00000000..c453ab5c
--- /dev/null
+++ b/tests/fsck-tests/018-leaf-crossing-stripes/test.sh
@@ -0,0 +1,12 @@
+#!/bin/bash
+
+source $TOP/tests/common
+
+check_prereq btrfs
+
+image=$(extract_image "./default_case.raw.xz")
+run_check_stdout $TOP/btrfs check "$image" 2>&1 |
+ grep -q "crossing stripe boundary" ||
+ _fail "no expected error message in the output"
+
+rm -f "$image"
diff --git a/tests/fsck-tests/019-non-skinny-false-alert/default_case.img.xz b/tests/fsck-tests/019-non-skinny-false-alert/default_case.img.xz
new file mode 100644
index 00000000..c35f8bc6
--- /dev/null
+++ b/tests/fsck-tests/019-non-skinny-false-alert/default_case.img.xz
Binary files differ
diff --git a/tests/fsck-tests/019-non-skinny-false-alert/test.sh b/tests/fsck-tests/019-non-skinny-false-alert/test.sh
new file mode 100755
index 00000000..a7f8e862
--- /dev/null
+++ b/tests/fsck-tests/019-non-skinny-false-alert/test.sh
@@ -0,0 +1,23 @@
+#!/bin/bash
+#
+# $ btrfs check img
+# Checking filesystem on img
+# UUID: 17f2bf15-f4c2-4ebc-b1f7-39b7af26257a
+# checking extents
+# bad extent [29376512, 29392896), type mismatch with chunk
+# bad extent [29442048, 29458432), type mismatch with chunk
+# bad extent [29589504, 29605888), type mismatch with chunk
+# ...
+#
+# a buggy check leads to the above messages
+
+source $TOP/tests/common
+
+check_prereq btrfs
+
+image=$(extract_image "./default_case.img.xz")
+run_check_stdout $TOP/btrfs check "$image" 2>&1 |
+ grep -q "type mismatch with chunk" &&
+ _fail "unexpected error message in the output"
+
+rm -f "$image"
diff --git a/tests/fuzz-tests.sh b/tests/fuzz-tests.sh
new file mode 100755
index 00000000..204dce2d
--- /dev/null
+++ b/tests/fuzz-tests.sh
@@ -0,0 +1,41 @@
+#!/bin/bash
+#
+# misc tests on fuzzed or crafted images
+
+unset TOP
+unset LANG
+LANG=C
+SCRIPT_DIR=$(dirname $(readlink -f $0))
+TOP=$(readlink -f $SCRIPT_DIR/../)
+TEST_DEV=${TEST_DEV:-}
+RESULTS="$TOP/tests/fuzz-tests-results.txt"
+IMAGE="$TOP/tests/test.img"
+
+source $TOP/tests/common
+
+export TOP
+export RESULTS
+export LANG
+export IMAGE
+
+rm -f $RESULTS
+
+check_prereq btrfs
+
+# The tests are driven by their custom script called 'test.sh'
+
+for i in $(find $TOP/tests/fuzz-tests -maxdepth 1 -mindepth 1 -type d \
+ ${TEST:+-name "$TEST"} | sort)
+do
+ name=$(basename $i)
+ cd $i
+ if [ -x test.sh ]; then
+ echo "=== Entering $i" >> $RESULTS
+ echo " [TEST/fuzz] $name"
+ ./test.sh
+ if [ $? -ne 0 ]; then
+ _fail "test failed for case $(basename $i)"
+ fi
+ fi
+ cd $TOP
+done
diff --git a/tests/fuzz-tests/001-simple-unmounted/test.sh b/tests/fuzz-tests/001-simple-unmounted/test.sh
new file mode 100755
index 00000000..bf01a3a4
--- /dev/null
+++ b/tests/fuzz-tests/001-simple-unmounted/test.sh
@@ -0,0 +1,20 @@
+#!/bin/sh
+
+# iterate over all fuzzed images and run 'btrfs check'
+
+source $TOP/tests/common
+
+setup_root_helper
+check_prereq btrfs
+
+# redefine the one provided by common
+check_image() {
+ local image
+
+ image=$1
+ run_mayfail $TOP/btrfs check "$image"
+}
+
+check_all_images $TOP/tests/fuzz-tests/images
+
+exit 0
diff --git a/tests/fuzz-tests/images/bad-superblock-1.raw.xz b/tests/fuzz-tests/images/bad-superblock-1.raw.xz
new file mode 100644
index 00000000..3d6358f0
--- /dev/null
+++ b/tests/fuzz-tests/images/bad-superblock-1.raw.xz
Binary files differ
diff --git a/tests/fuzz-tests/images/bad-superblock-2.raw.xz b/tests/fuzz-tests/images/bad-superblock-2.raw.xz
new file mode 100644
index 00000000..7db7610b
--- /dev/null
+++ b/tests/fuzz-tests/images/bad-superblock-2.raw.xz
Binary files differ
diff --git a/tests/fuzz-tests/images/bad-superblock-3.raw.xz b/tests/fuzz-tests/images/bad-superblock-3.raw.xz
new file mode 100644
index 00000000..4aa31483
--- /dev/null
+++ b/tests/fuzz-tests/images/bad-superblock-3.raw.xz
Binary files differ
diff --git a/tests/fuzz-tests/images/bad-superblock.txt b/tests/fuzz-tests/images/bad-superblock.txt
new file mode 100644
index 00000000..f7dd9aa0
--- /dev/null
+++ b/tests/fuzz-tests/images/bad-superblock.txt
@@ -0,0 +1,17 @@
+bad-superblock-*.txt
+
+Crafted images from Jiri Slaby, produced by some symbolic execution framework
+that finds unhandled cases at mount time.
+
+Relevant kernel patches to backport:
+
+e3540eab29e1b2260bc4b9b3979a49a00e3e3af8
+btrfs: add more checks to btrfs_read_sys_array
+
+ce7fca5f57ed0fcd7e7b3d7b1a3e1791f8e56fa3
+btrfs: add checks for sys_chunk_array sizes
+
+75d6ad382bb91f363452119d34238e156589ca2d
+btrfs: more superblock checks, lower bounds on devices and sectorsize/nodesize
+
+(and more from fs/btrfs/super.c)
diff --git a/tests/fuzz-tests/images/bko-104131-fsck-oob-read.raw.xz b/tests/fuzz-tests/images/bko-104131-fsck-oob-read.raw.xz
new file mode 100644
index 00000000..7848f8b1
--- /dev/null
+++ b/tests/fuzz-tests/images/bko-104131-fsck-oob-read.raw.xz
Binary files differ
diff --git a/tests/fuzz-tests/images/bko-104131-fsck-oob-read.txt b/tests/fuzz-tests/images/bko-104131-fsck-oob-read.txt
new file mode 100644
index 00000000..0e829c2e
--- /dev/null
+++ b/tests/fuzz-tests/images/bko-104131-fsck-oob-read.txt
@@ -0,0 +1,31 @@
+URL: https://bugzilla.kernel.org/show_bug.cgi?id=104131
+Hanno Boeck 2015-09-07 07:24:32 UTC
+
+Created attachment 186941 [details]
+malformed btrfs filesystem causing oob read
+
+The attached malformed filesystem image will cause an invalid heap out of bounds memory read in btrfsck.
+
+This was found while fuzzing btrfs-progs with american fuzzy lop.
+
+Stack trace from Address Sanitizer:
+==31289==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60f00000f003 at pc 0x0000005d0dbb bp 0x7ffdf444c180 sp 0x7ffdf444c178
+READ of size 8 at 0x60f00000f003 thread T0
+ #0 0x5d0dba in btrfs_header_bytenr /mnt/ram/btrfs-progs-v4.1.2/./ctree.h:1797:1
+ #1 0x5d0dba in check_tree_block /mnt/ram/btrfs-progs-v4.1.2/disk-io.c:60
+ #2 0x5d0dba in read_tree_block /mnt/ram/btrfs-progs-v4.1.2/disk-io.c:337
+ #3 0x5dc00e in btrfs_setup_chunk_tree_and_device_map /mnt/ram/btrfs-progs-v4.1.2/disk-io.c:1169:30
+ #4 0x5dcf89 in __open_ctree_fd /mnt/ram/btrfs-progs-v4.1.2/disk-io.c:1261:8
+ #5 0x5dc50a in open_ctree_fs_info /mnt/ram/btrfs-progs-v4.1.2/disk-io.c:1302:9
+ #6 0x52f22f in cmd_check /mnt/ram/btrfs-progs-v4.1.2/cmds-check.c:9333:9
+ #7 0x4e7bcc in main /mnt/ram/btrfs-progs-v4.1.2/btrfs.c:245:7
+ #8 0x7f98bb101f9f in __libc_start_main /var/tmp/portage/sys-libs/glibc-2.20-r2/work/glibc-2.20/csu/libc-start.c:289
+ #9 0x41f748 in _start (/mnt/ram/btrfs/btrfs+0x41f748)
+
+0x60f00000f003 is located 3 bytes to the right of 176-byte region [0x60f00000ef50,0x60f00000f000)
+allocated by thread T0 here:
+ #0 0x4bade8 in malloc (/mnt/ram/btrfs/btrfs+0x4bade8)
+ #1 0x622c24 in __alloc_extent_buffer /mnt/ram/btrfs-progs-v4.1.2/extent_io.c:541:7
+ #2 0x622c24 in alloc_extent_buffer /mnt/ram/btrfs-progs-v4.1.2/extent_io.c:648
+ #3 0x5cf436 in btrfs_find_create_tree_block /mnt/ram/btrfs-progs-v4.1.2/disk-io.c:186:9
+ #4 0x5cf436 in read_tree_block /mnt/ram/btrfs-progs-v4.1.2/disk-io.c:314
diff --git a/tests/fuzz-tests/images/bko-104141-fsck-exception.raw.xz b/tests/fuzz-tests/images/bko-104141-fsck-exception.raw.xz
new file mode 100644
index 00000000..d24a32f8
--- /dev/null
+++ b/tests/fuzz-tests/images/bko-104141-fsck-exception.raw.xz
Binary files differ
diff --git a/tests/fuzz-tests/images/bko-104141-fsck-exception.txt b/tests/fuzz-tests/images/bko-104141-fsck-exception.txt
new file mode 100644
index 00000000..aed91909
--- /dev/null
+++ b/tests/fuzz-tests/images/bko-104141-fsck-exception.txt
@@ -0,0 +1,9 @@
+URL: https://bugzilla.kernel.org/show_bug.cgi?id=104141
+Hanno Boeck 2015-09-07 07:27:58 UTC
+
+Created attachment 186951 [details]
+malformed filesystem causing floating point exception
+
+The attacked file will cause a floating point exception in btrfsck.
+
+This was found while fuzzing btrfs-progs with american fuzzy lop.
diff --git a/tests/fuzz-tests/images/bko-97191-btrfs-image.raw.txt b/tests/fuzz-tests/images/bko-97191-btrfs-image.raw.txt
new file mode 100644
index 00000000..f0d81894
--- /dev/null
+++ b/tests/fuzz-tests/images/bko-97191-btrfs-image.raw.txt
@@ -0,0 +1,137 @@
+URL: https://bugzilla.kernel.org/show_bug.cgi?id=97191
+Lukas Lueg 2015-04-23 22:20:35 UTC
+
+Running btrfs-progs v3.19.1
+
+The btrfs-image attached to this bug causes the btrfs-userland tool to
+overflow some data structures, leading to unallocated memory being written to
+and read from. A segfault results shortly after. Reproduced on x86-64 and
+i686.
+
+The kernel seems to be less affected and fails to mount the image. I didn't
+investigate whether the reads/writes could be used to gain control over $EIP.
+Since the first invalid write of 8 bytes seems to run into adjacent heap
+blocks (crash in unlink()), it may be possible though.
+
+gdb output:
+
+Program received signal SIGSEGV, Segmentation fault.
+malloc_consolidate (av=av@entry=0x32629b7cc0 <main_arena>) at malloc.c:4151
+4151 unlink(av, p, bck, fwd);
+(gdb) bt
+#0 malloc_consolidate (av=av@entry=0x32629b7cc0 <main_arena>) at malloc.c:4151
+#1 0x0000003262680628 in _int_malloc (av=av@entry=0x32629b7cc0 <main_arena>, bytes=bytes@entry=4224) at malloc.c:3420
+#2 0x000000326268315e in __GI___libc_malloc (bytes=4224) at malloc.c:2896
+#3 0x0000000000449d15 in __alloc_extent_buffer (tree=0x88c078, bytenr=4288512, blocksize=4096) at extent_io.c:541
+#4 0x000000000044a8b4 in alloc_extent_buffer (tree=0x88c078, bytenr=4288512, blocksize=4096) at extent_io.c:648
+#5 0x000000000043b1a0 in btrfs_find_create_tree_block (root=root@entry=0x895840, bytenr=<optimized out>,
+ blocksize=<optimized out>) at disk-io.c:159
+#6 0x000000000043ca4e in read_tree_block (root=root@entry=0x895840, bytenr=<optimized out>, blocksize=<optimized out>,
+ parent_transid=13) at disk-io.c:287
+#7 0x000000000043ccb7 in find_and_setup_root (tree_root=0x88c250, fs_info=<optimized out>, objectid=5, root=0x895840)
+ at disk-io.c:557
+#8 0x000000000043ce92 in btrfs_read_fs_root_no_cache (fs_info=fs_info@entry=0x88c010, location=location@entry=0x7fffffffd960)
+ at disk-io.c:640
+#9 0x000000000043d060 in btrfs_read_fs_root (fs_info=fs_info@entry=0x88c010, location=location@entry=0x7fffffffd960)
+ at disk-io.c:739
+#10 0x000000000043d48c in btrfs_setup_all_roots (fs_info=fs_info@entry=0x88c010, root_tree_bytenr=<optimized out>,
+ root_tree_bytenr@entry=0, flags=flags@entry=OPEN_CTREE_EXCLUSIVE) at disk-io.c:988
+#11 0x000000000043d802 in __open_ctree_fd (fp=fp@entry=3, path=path@entry=0x7fffffffe20d "ramdisk/btrfs_fukked.bin",
+ sb_bytenr=65536, sb_bytenr@entry=0, root_tree_bytenr=root_tree_bytenr@entry=0, flags=flags@entry=OPEN_CTREE_EXCLUSIVE)
+ at disk-io.c:1199
+#12 0x000000000043d965 in open_ctree_fs_info (filename=0x7fffffffe20d "ramdisk/btrfs_fukked.bin", sb_bytenr=sb_bytenr@entry=0,
+ root_tree_bytenr=root_tree_bytenr@entry=0, flags=flags@entry=OPEN_CTREE_EXCLUSIVE) at disk-io.c:1231
+#13 0x0000000000427bf5 in cmd_check (argc=1, argv=0x7fffffffdea0) at cmds-check.c:9326
+#14 0x000000000040e5a2 in main (argc=2, argv=0x7fffffffdea0) at btrfs.c:245
+
+
+valgrind output:
+
+==32463== Memcheck, a memory error detector
+==32463== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
+==32463== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
+==32463== Command: btrfs check ramdisk/btrfs_fukked.bin
+==32463==
+==32463== Invalid write of size 8
+==32463== at 0x4386FB: btrfs_search_slot (ctree.c:1119)
+==32463== by 0x4427F7: UnknownInlinedFun (extent-tree.c:3117)
+==32463== by 0x4427F7: btrfs_read_block_groups (extent-tree.c:3167)
+==32463== by 0x43D4F2: btrfs_setup_all_roots (disk-io.c:983)
+==32463== by 0x43D801: __open_ctree_fd (disk-io.c:1199)
+==32463== by 0x43D964: open_ctree_fs_info (disk-io.c:1231)
+==32463== by 0x427BF4: cmd_check (cmds-check.c:9326)
+==32463== by 0x40E5A1: main (btrfs.c:245)
+==32463== Address 0x4c409f0 is 16 bytes after a block of size 144 alloc'd
+==32463== at 0x4A08946: calloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
+==32463== by 0x4427AB: btrfs_read_block_groups (extent-tree.c:3162)
+==32463== by 0x43D4F2: btrfs_setup_all_roots (disk-io.c:983)
+==32463== by 0x43D801: __open_ctree_fd (disk-io.c:1199)
+==32463== by 0x43D964: open_ctree_fs_info (disk-io.c:1231)
+==32463== by 0x427BF4: cmd_check (cmds-check.c:9326)
+==32463== by 0x40E5A1: main (btrfs.c:245)
+==32463==
+==32463== Invalid read of size 8
+==32463== at 0x436E70: check_block.part.14 (ctree.c:548)
+==32463== by 0x438954: UnknownInlinedFun (kerncompat.h:91)
+==32463== by 0x438954: btrfs_search_slot (ctree.c:1120)
+==32463== by 0x4427F7: UnknownInlinedFun (extent-tree.c:3117)
+==32463== by 0x4427F7: btrfs_read_block_groups (extent-tree.c:3167)
+==32463== by 0x43D4F2: btrfs_setup_all_roots (disk-io.c:983)
+==32463== by 0x43D801: __open_ctree_fd (disk-io.c:1199)
+==32463== by 0x43D964: open_ctree_fs_info (disk-io.c:1231)
+==32463== by 0x427BF4: cmd_check (cmds-check.c:9326)
+==32463== by 0x40E5A1: main (btrfs.c:245)
+==32463== Address 0x4c409f8 is 24 bytes after a block of size 144 in arena "client"
+==32463==
+==32463== Invalid read of size 4
+==32463== at 0x436E84: UnknownInlinedFun (ctree.h:1605)
+==32463== by 0x436E84: UnknownInlinedFun (ctree.h:1612)
+==32463== by 0x436E84: check_block.part.14 (ctree.c:550)
+==32463== by 0x438954: UnknownInlinedFun (kerncompat.h:91)
+==32463== by 0x438954: btrfs_search_slot (ctree.c:1120)
+==32463== by 0x4427F7: UnknownInlinedFun (extent-tree.c:3117)
+==32463== by 0x4427F7: btrfs_read_block_groups (extent-tree.c:3167)
+==32463== by 0x43D4F2: btrfs_setup_all_roots (disk-io.c:983)
+==32463== by 0x43D801: __open_ctree_fd (disk-io.c:1199)
+==32463== by 0x43D964: open_ctree_fs_info (disk-io.c:1231)
+==32463== by 0x427BF4: cmd_check (cmds-check.c:9326)
+==32463== by 0x40E5A1: main (btrfs.c:245)
+==32463== Address 0x4c409e4 is 4 bytes after a block of size 144 alloc'd
+==32463== at 0x4A08946: calloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
+==32463== by 0x4427AB: btrfs_read_block_groups (extent-tree.c:3162)
+==32463== by 0x43D4F2: btrfs_setup_all_roots (disk-io.c:983)
+==32463== by 0x43D801: __open_ctree_fd (disk-io.c:1199)
+==32463== by 0x43D964: open_ctree_fs_info (disk-io.c:1231)
+==32463== by 0x427BF4: cmd_check (cmds-check.c:9326)
+==32463== by 0x40E5A1: main (btrfs.c:245)
+==32463==
+==32463== Invalid read of size 1
+==32463== at 0x4A0B3A0: memcpy@@GLIBC_2.14 (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
+==32463== by 0x436E99: UnknownInlinedFun (ctree.h:1613)
+==32463== by 0x436E99: check_block.part.14 (ctree.c:550)
+==32463== by 0x438954: UnknownInlinedFun (kerncompat.h:91)
+==32463== by 0x438954: btrfs_search_slot (ctree.c:1120)
+==32463== by 0x4427F7: UnknownInlinedFun (extent-tree.c:3117)
+==32463== by 0x4427F7: btrfs_read_block_groups (extent-tree.c:3167)
+==32463== by 0x43D4F2: btrfs_setup_all_roots (disk-io.c:983)
+==32463== by 0x43D801: __open_ctree_fd (disk-io.c:1199)
+==32463== by 0x43D964: open_ctree_fs_info (disk-io.c:1231)
+==32463== by 0x427BF4: cmd_check (cmds-check.c:9326)
+==32463== by 0x40E5A1: main (btrfs.c:245)
+==32463== Address 0x1b1 is not stack'd, malloc'd or (recently) free'd
+==32463==
+==32463==
+==32463== Process terminating with default action of signal 11 (SIGSEGV)
+==32463== Access not within mapped region at address 0x1B1
+==32463== at 0x4A0B3A0: memcpy@@GLIBC_2.14 (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
+==32463== by 0x436E99: UnknownInlinedFun (ctree.h:1613)
+==32463== by 0x436E99: check_block.part.14 (ctree.c:550)
+==32463== by 0x438954: UnknownInlinedFun (kerncompat.h:91)
+==32463== by 0x438954: btrfs_search_slot (ctree.c:1120)
+==32463== by 0x4427F7: UnknownInlinedFun (extent-tree.c:3117)
+==32463== by 0x4427F7: btrfs_read_block_groups (extent-tree.c:3167)
+==32463== by 0x43D4F2: btrfs_setup_all_roots (disk-io.c:983)
+==32463== by 0x43D801: __open_ctree_fd (disk-io.c:1199)
+==32463== by 0x43D964: open_ctree_fs_info (disk-io.c:1231)
+==32463== by 0x427BF4: cmd_check (cmds-check.c:9326)
+==32463== by 0x40E5A1: main (btrfs.c:245)
diff --git a/tests/fuzz-tests/images/bko-97191-btrfs-image.raw.xz b/tests/fuzz-tests/images/bko-97191-btrfs-image.raw.xz
new file mode 100644
index 00000000..b2e48c08
--- /dev/null
+++ b/tests/fuzz-tests/images/bko-97191-btrfs-image.raw.xz
Binary files differ
diff --git a/tests/fuzz-tests/images/bko-97271-btrfs-image.raw.txt b/tests/fuzz-tests/images/bko-97271-btrfs-image.raw.txt
new file mode 100644
index 00000000..67f20968
--- /dev/null
+++ b/tests/fuzz-tests/images/bko-97271-btrfs-image.raw.txt
@@ -0,0 +1,54 @@
+URL: https://bugzilla.kernel.org/show_bug.cgi?id=97271
+Lukas Lueg 2015-04-25 20:34:39 UTC
+
+The attached btrfs-image causes "btrfs check" to write outside of allocated
+memory locations and ultimately die due to a segfault. An adjacent heap block's
+control structure is overwritten with a `struct extent_buffer *`, which is not
+controllable by the user.
+
+"btrfs version" is v3.19.1. Running "btrfs check" immediately dies with
+
+*** Error in `btrfs': double free or corruption (!prev): 0x0000000002396ec0 ***
+*** Error in `btrfs': malloc(): memory corruption: 0x0000000002396f60 ***
+
+Debugging with valgrind and gdb gives
+
+==11670== Invalid write of size 8
+==11670== at 0x4386FB: btrfs_search_slot (ctree.c:1119)
+==11670== by 0x44E16E: btrfs_read_chunk_tree (volumes.c:1814)
+==11670== by 0x43D654: btrfs_setup_chunk_tree_and_device_map (disk-io.c:1115)
+==11670== by 0x43D7D0: __open_ctree_fd (disk-io.c:1190)
+==11670== by 0x43D964: open_ctree_fs_info (disk-io.c:1231)
+==11670== by 0x427BF4: cmd_check (cmds-check.c:9326)
+==11670== by 0x40E5A1: main (btrfs.c:245)
+==11670== Address 0x4c3bb98 is 8 bytes after a block of size 144 alloc'd
+==11670== at 0x4A08946: calloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
+==11670== by 0x44E133: btrfs_read_chunk_tree (volumes.c:1801)
+==11670== by 0x43D654: btrfs_setup_chunk_tree_and_device_map (disk-io.c:1115)
+==11670== by 0x43D7D0: __open_ctree_fd (disk-io.c:1190)
+==11670== by 0x43D964: open_ctree_fs_info (disk-io.c:1231)
+==11670== by 0x427BF4: cmd_check (cmds-check.c:9326)
+==11670== by 0x40E5A1: main (btrfs.c:245)
+
+Program received signal SIGTRAP, Trace/breakpoint trap.
+btrfs_search_slot (trans=trans@entry=0x0, root=root@entry=0x4c36d30, key=key@entry=0xffefff830, p=p@entry=0x4c3bb00,
+ ins_len=ins_len@entry=0, cow=cow@entry=0) at ctree.c:1119
+1119 p->nodes[level] = b;
+(gdb) p p->nodes
+$1 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}
+(gdb) p p
+$2 = (struct btrfs_path *) 0x4c3bb00
+(gdb) p b
+$3 = (struct extent_buffer *) 0x4c3a990
+
+
+The corresponding part in ctree.c:btrfs_search_slot() seems to fail to check if `level` overflows outside of `node`:
+
+level = btrfs_header_level(b);
+...
+if (level != btrfs_header_level(b))
+ WARN_ON(1);
+level = btrfs_header_level(b);
+p->nodes[level] = b; // <- Illegal write
+
+Maybe the repeated calls to btrfs_header_level() were meant to do something once, they seem to be noise.
diff --git a/tests/fuzz-tests/images/bko-97271-btrfs-image.raw.xz b/tests/fuzz-tests/images/bko-97271-btrfs-image.raw.xz
new file mode 100644
index 00000000..3c79edb5
--- /dev/null
+++ b/tests/fuzz-tests/images/bko-97271-btrfs-image.raw.xz
Binary files differ
diff --git a/tests/fuzz-tests/images/sys-array-num-stripes-0.raw.txt b/tests/fuzz-tests/images/sys-array-num-stripes-0.raw.txt
new file mode 100644
index 00000000..bdde4e70
--- /dev/null
+++ b/tests/fuzz-tests/images/sys-array-num-stripes-0.raw.txt
@@ -0,0 +1,30 @@
+URL: http://article.gmane.org/gmane.comp.file-systems.btrfs/50230
+Vegard Nossum, 2015-11-15
+
+If sys_array::num_stripes == 0, we hit a BUG_ON during mount:
+
+BTRFS: device fsid 9006933e-2a9a-44f0-917f-514252aeec2c devid 1 transid 7 /dev/loop0
+BTRFS info (device loop0): disk space caching is enabled
+BUG: failure at fs/btrfs/ctree.h:337/btrfs_chunk_item_size()!
+Kernel panic - not syncing: BUG!
+CPU: 0 PID: 313 Comm: mount Not tainted 4.2.5-00657-ge047887-dirty #25
+Stack:
+ 637af890 60062489 602aeb2e 604192ba
+ 60387961 00000011 637af8a0 6038a835
+ 637af9c0 6038776b 634ef32b 00000000
+Call Trace:
+ [<6001c86d>] show_stack+0xfe/0x15b
+ [<6038a835>] dump_stack+0x2a/0x2c
+ [<6038776b>] panic+0x13e/0x2b3
+ [<6020f099>] btrfs_read_sys_array+0x25d/0x2ff
+ [<601cfbbe>] open_ctree+0x192d/0x27af
+ [<6019c2c1>] btrfs_mount+0x8f5/0xb9a
+ [<600bc9a7>] mount_fs+0x11/0xf3
+ [<600d5167>] vfs_kern_mount+0x75/0x11a
+ [<6019bcb0>] btrfs_mount+0x2e4/0xb9a
+ [<600bc9a7>] mount_fs+0x11/0xf3
+ [<600d5167>] vfs_kern_mount+0x75/0x11a
+ [<600d710b>] do_mount+0xa35/0xbc9
+ [<600d7557>] SyS_mount+0x95/0xc8
+
+Fixed by patch (kernel and btrfs-progs): btrfs: handle invalid num_stripes in sys_array
diff --git a/tests/fuzz-tests/images/sys-array-num-stripes-0.raw.xz b/tests/fuzz-tests/images/sys-array-num-stripes-0.raw.xz
new file mode 100644
index 00000000..d64fb300
--- /dev/null
+++ b/tests/fuzz-tests/images/sys-array-num-stripes-0.raw.xz
Binary files differ
diff --git a/tests/misc-tests.sh b/tests/misc-tests.sh
new file mode 100755
index 00000000..2a7f57c5
--- /dev/null
+++ b/tests/misc-tests.sh
@@ -0,0 +1,47 @@
+#!/bin/bash
+#
+# Misc tests
+
+unset TOP
+unset LANG
+LANG=C
+SCRIPT_DIR=$(dirname $(readlink -f $0))
+TOP=$(readlink -f $SCRIPT_DIR/../)
+TEST_DEV=${TEST_DEV:-}
+RESULTS="$TOP/tests/misc-tests-results.txt"
+IMAGE="$TOP/tests/test.img"
+
+source $TOP/tests/common
+
+# Allow child test to use $TOP and $RESULTS
+export TOP
+export RESULTS
+# For custom script needs to verfiy recovery
+export LANG
+# For tests that only use a loop device
+export IMAGE
+
+rm -f $RESULTS
+
+# test rely on corrupting blocks tool
+check_prereq btrfs-corrupt-block
+check_prereq btrfs-image
+check_prereq btrfstune
+check_prereq btrfs
+
+# The tests are driven by their custom script called 'test.sh'
+
+for i in $(find $TOP/tests/misc-tests -maxdepth 1 -mindepth 1 -type d \
+ ${TEST:+-name "$TEST"} | sort)
+do
+ echo " [TEST/misc] $(basename $i)"
+ cd $i
+ echo "=== Entering $i" >> $RESULTS
+ if [ -x test.sh ]; then
+ ./test.sh
+ if [ $? -ne 0 ]; then
+ _fail "test failed for case $(basename $i)"
+ fi
+ fi
+ cd $TOP
+done
diff --git a/tests/misc-tests/001-btrfstune-features/test.sh b/tests/misc-tests/001-btrfstune-features/test.sh
new file mode 100755
index 00000000..c858d701
--- /dev/null
+++ b/tests/misc-tests/001-btrfstune-features/test.sh
@@ -0,0 +1,46 @@
+#!/bin/bash
+# test btrfstune options that enable filesystem features
+
+source $TOP/tests/common
+
+check_prereq btrfs-debug-tree
+check_prereq btrfs-show-super
+check_prereq mkfs.btrfs
+check_prereq btrfstune
+check_prereq btrfs
+
+setup_root_helper
+prepare_test_dev
+
+# test whether fsck can rebuild a corrupted extent tree
+# parameters:
+# - option for mkfs.btrfs -O, empty for defaults
+# - option for btrfstune
+# - string representing the feature in btrfs-show-super dump
+test_feature()
+{
+ local mkfsfeatures
+ local tuneopt
+ local sbflag
+
+ mkfsfeatures=${1:+-O ^$1}
+ tuneopt="$2"
+ sbflag="$3"
+
+ run_check $SUDO_HELPER $TOP/mkfs.btrfs -f $mkfsfeatures $TEST_DEV
+ if run_check_stdout $TOP/btrfs-show-super $TEST_DEV | \
+ grep -q "$sbflag"; then
+ _fail "FAIL: feature $sbflag must not be set on the base image"
+ fi
+ run_check $TOP/btrfstune $tuneopt $TEST_DEV
+ if ! run_check_stdout $TOP/btrfs-show-super $TEST_DEV | \
+ grep -q "$sbflag"; then
+ _fail "FAIL: feature $sbflag not set"
+ fi
+ run_check $SUDO_HELPER $TOP/btrfs check $TEST_DEV
+}
+
+test_feature extref -r EXTENDED_IREF
+test_feature skinny-metadata -x SKINNY_METADATA
+test_feature no-holes -n NO_HOLES
+test_feature '' '-S 1' SEEDING
diff --git a/tests/misc-tests/002-uuid-rewrite/test.sh b/tests/misc-tests/002-uuid-rewrite/test.sh
new file mode 100755
index 00000000..d84ec6ca
--- /dev/null
+++ b/tests/misc-tests/002-uuid-rewrite/test.sh
@@ -0,0 +1,66 @@
+#!/bin/bash
+# test btrfstune uuid rewriting options
+
+source $TOP/tests/common
+
+check_prereq btrfs-debug-tree
+check_prereq btrfs-show-super
+check_prereq mkfs.btrfs
+check_prereq btrfstune
+check_prereq btrfs
+
+prepare_test_dev
+
+get_fs_uuid() {
+ local image
+
+ image="$1"
+ run_check_stdout $TOP/btrfs-show-super "$image" | \
+ grep '^fsid' | awk '{print $2}'
+}
+
+test_uuid_random()
+{
+ local origuuid
+
+ origuuid=11111111-a101-4031-b29a-379d4f8b7a2d
+
+ run_check $SUDO_HELPER $TOP/mkfs.btrfs -f \
+ --uuid $origuuid \
+ --rootdir $TOP/Documentation \
+ $TEST_DEV
+ run_check $TOP/btrfs-show-super "$TEST_DEV"
+ currentfsid=$(run_check_stdout $TOP/btrfstune -f -u $TEST_DEV | \
+ grep -i 'current fsid:' | awk '{print $3}')
+ if ! [ $currentfsid = $origuuid ]; then
+ _fail "FAIL: current UUID mismatch"
+ fi
+ run_check $TOP/btrfs-show-super "$TEST_DEV"
+ run_check $SUDO_HELPER $TOP/btrfs check $TEST_DEV
+}
+
+test_uuid_user()
+{
+ local origuuid
+ local newuuid
+
+ origuuid=22222222-d324-4f92-80e9-7658bf3b845f
+ newuuid=33333333-bfc9-4045-9399-a396dc6893b3
+
+ run_check $SUDO_HELPER $TOP/mkfs.btrfs -f \
+ --uuid $origuuid \
+ --rootdir $TOP/Documentation \
+ $TEST_DEV
+ run_check $TOP/btrfs-show-super "$TEST_DEV"
+ run_check $TOP/btrfstune -f -U $newuuid \
+ $TEST_DEV
+ # btrfs-show-super is called within get_fs_uuid
+ fsid=$(get_fs_uuid $TEST_DEV)
+ if ! [ $fsid = $newuuid ]; then
+ _fail "FAIL: UUID not rewritten"
+ fi
+ run_check $SUDO_HELPER $TOP/btrfs check $TEST_DEV
+}
+
+test_uuid_random
+test_uuid_user
diff --git a/tests/misc-tests/003-zero-log/test.sh b/tests/misc-tests/003-zero-log/test.sh
new file mode 100755
index 00000000..b650930e
--- /dev/null
+++ b/tests/misc-tests/003-zero-log/test.sh
@@ -0,0 +1,52 @@
+#!/bin/bash
+# test zero-log
+
+source $TOP/tests/common
+
+check_prereq btrfs-show-super
+check_prereq mkfs.btrfs
+check_prereq btrfs
+prepare_test_dev
+
+get_log_root()
+{
+ local image
+
+ image="$1"
+ $TOP/btrfs-show-super "$image" | \
+ grep '^log_root\>' | awk '{print $2}'
+}
+get_log_root_level() {
+ local image
+
+ image="$1"
+ $TOP/btrfs-show-super "$image" | \
+ grep '^log_root_level' | awk '{print $2}'
+}
+
+test_zero_log()
+{
+ # FIXME: we need an image with existing log_root
+ run_check $SUDO_HELPER $TOP/mkfs.btrfs -f \
+ --rootdir $TOP/Documentation \
+ $TEST_DEV
+ run_check $TOP/btrfs-show-super $TEST_DEV
+ if [ "$1" = 'standalone' ]; then
+ run_check $TOP/btrfs rescue zero-log $TEST_DEV
+ else
+ run_check $TOP/btrfs-zero-log $TEST_DEV
+ fi
+ log_root=$(get_log_root $TEST_DEV)
+ log_root_level=$(get_log_root $TEST_DEV)
+ if [ "$log_root" != 0 ]; then
+ _fail "FAIL: log_root not reset"
+ fi
+ if [ "$log_root_level" != 0 ]; then
+ _fail "FAIL: log_root_level not reset"
+ fi
+ run_check $TOP/btrfs-show-super $TEST_DEV
+ run_check $SUDO_HELPER $TOP/btrfs check $TEST_DEV
+}
+
+test_zero_log standalone
+test_zero_log internal
diff --git a/tests/misc-tests/004-shrink-fs/test.sh b/tests/misc-tests/004-shrink-fs/test.sh
new file mode 100755
index 00000000..88740358
--- /dev/null
+++ b/tests/misc-tests/004-shrink-fs/test.sh
@@ -0,0 +1,72 @@
+#!/bin/bash
+#
+# Test getting the minimum size a filesystem can be resized to and verify we
+# are able to resize (shrink) it to that size.
+#
+
+source $TOP/tests/common
+
+check_prereq mkfs.btrfs
+check_prereq btrfs
+
+setup_root_helper
+
+# Optionally take id of the device to shrink
+shrink_test()
+{
+ min_size=$(run_check_stdout $SUDO_HELPER $TOP/btrfs inspect-internal min-dev-size ${1:+--id $1} $TEST_MNT)
+ min_size=$(echo $min_size | cut -d ' ' -f 1)
+ echo "min size = ${min_size}" >> $RESULTS
+ if [ -z "$min_size" ]; then
+ _fail "Failed to parse minimum size"
+ fi
+ run_check $SUDO_HELPER $TOP/btrfs filesystem resize $min_size $TEST_MNT
+}
+
+run_check truncate -s 20G $IMAGE
+run_check $TOP/mkfs.btrfs -f $IMAGE
+run_check $SUDO_HELPER mount $IMAGE $TEST_MNT
+run_check $SUDO_HELPER chmod a+rw $TEST_MNT
+
+# Create 7 data block groups, each with a size of 1Gb.
+for ((i = 1; i <= 7; i++)); do
+ run_check fallocate -l 1G $TEST_MNT/foo$i
+done
+
+# Make sure they are persisted (all the chunk, device and block group items
+# added to the chunk/dev/extent trees).
+run_check $TOP/btrfs filesystem sync $TEST_MNT
+
+# Now remove 3 of those 1G files. This will result in 3 block groups becoming
+# unused, which will be automatically deleted by the cleaner kthread, and this
+# will result in 3 holes (unallocated space) in the device (each with a size
+# of 1Gb).
+
+run_check rm -f $TEST_MNT/foo2
+run_check rm -f $TEST_MNT/foo4
+run_check rm -f $TEST_MNT/foo6
+
+# Sync once to wake up the cleaner kthread which will delete the unused block
+# groups - it could have been sleeping when they became unused. Then wait a bit
+# to allow the cleaner kthread to delete them and then finally ensure the
+# transaction started by the cleaner kthread is committed.
+run_check $TOP/btrfs filesystem sync $TEST_MNT
+sleep 3
+run_check $TOP/btrfs filesystem sync $TEST_MNT
+
+# Now attempt to get the minimum size we can resize the filesystem to and verify
+# the resize operation succeeds. This size closely matches the sum of the size
+# of all the allocated device extents.
+for ((i = 1; i <= 3; i++)); do
+ shrink_test
+done
+
+# Now convert metadata and system chunks to the single profile and check we are
+# still able to get a correct minimum size and shrink to that size.
+run_check $SUDO_HELPER $TOP/btrfs balance start -mconvert=single \
+ -sconvert=single -f $TEST_MNT
+for ((i = 1; i <= 3; i++)); do
+ shrink_test 1
+done
+
+run_check $SUDO_HELPER umount $TEST_MNT
diff --git a/tests/misc-tests/005-convert-progress-thread-crash/test.sh b/tests/misc-tests/005-convert-progress-thread-crash/test.sh
new file mode 100755
index 00000000..054069c2
--- /dev/null
+++ b/tests/misc-tests/005-convert-progress-thread-crash/test.sh
@@ -0,0 +1,15 @@
+#!/bin/bash
+# test convert-thread-conflict
+
+source $TOP/tests/common
+
+check_prereq btrfs-convert
+
+mkfs.ext4 -V &>/dev/null || _not_run "mkfs.ext4 not found"
+prepare_test_dev 1G
+
+for ((i = 0; i < 20; i++)); do
+ echo "loop $i" >>$RESULTS
+ mkfs.ext4 -F "$TEST_DEV" &>>$RESULTS || _not_run "mkfs.ext4 failed"
+ run_check $TOP/btrfs-convert "$TEST_DEV"
+done
diff --git a/tests/misc-tests/006-image-on-missing-device/test.sh b/tests/misc-tests/006-image-on-missing-device/test.sh
new file mode 100755
index 00000000..8680a707
--- /dev/null
+++ b/tests/misc-tests/006-image-on-missing-device/test.sh
@@ -0,0 +1,78 @@
+#!/bin/bash
+# test btrfs-image with a missing device (uses loop devices)
+#
+# - btrfs-image must not loop indefinetelly
+# - btrfs-image will expectedly fail to produce the dump
+
+source $TOP/tests/common
+
+check_prereq btrfs-show-super
+check_prereq btrfs-image
+check_prereq mkfs.btrfs
+check_prereq btrfs
+
+ndevs=2
+declare -a devs
+dev1=
+dev2=
+
+setup_root_helper
+
+
+# TODO: move the helpers to common
+
+prepare_devices()
+{
+ for i in `seq $ndevs`; do
+ touch img$i
+ chmod a+rw img$i
+ truncate -s0 img$i
+ truncate -s2g img$i
+ devs[$i]=`run_check_stdout $SUDO_HELPER losetup --find --show img$i`
+ done
+}
+
+cleanup_devices()
+{
+ for dev in ${devs[@]}; do
+ run_mayfail $SUDO_HELPER losetup -d $dev
+ done
+ for i in `seq $ndevs`; do
+ truncate -s0 img$i
+ done
+ run_check $SUDO_HELPER losetup --list
+}
+
+test_image_dump()
+{
+ run_check $SUDO_HELPER $TOP/btrfs check $dev1
+ # the output file will be deleted
+ run_mayfail $SUDO_HELPER $TOP/btrfs-image $dev1 /tmp/test-img.dump
+}
+
+test_run()
+{
+ run_check $SUDO_HELPER $TOP/mkfs.btrfs -f -d raid1 -m raid1 $dev1 $dev2
+
+ # we need extents to trigger reading from all devices
+ run_check $SUDO_HELPER mount $dev1 $TEST_MNT
+ run_check $SUDO_HELPER dd if=/dev/zero of=$TEST_MNT/a bs=1M count=10
+ run_check $SUDO_HELPER dd if=/dev/zero of=$TEST_MNT/b bs=4k count=1000 conv=sync
+ run_check $SUDO_HELPER umount $TEST_MNT
+
+ test_image_dump
+ run_check btrfs fi show $dev1
+ # create a degraded raid1 filesystem, check must succeed
+ # btrfs-image must not loop
+ run_mayfail wipefs -a $dev2
+ run_check $SUDO_HELPER losetup -d $dev2
+ run_check btrfs fi show $dev1
+
+ test_image_dump
+}
+
+prepare_devices
+dev1=${devs[1]}
+dev2=${devs[2]}
+test_run
+cleanup_devices
diff --git a/tests/misc-tests/007-subvolume-sync/test.sh b/tests/misc-tests/007-subvolume-sync/test.sh
new file mode 100755
index 00000000..a745fb56
--- /dev/null
+++ b/tests/misc-tests/007-subvolume-sync/test.sh
@@ -0,0 +1,32 @@
+#!/bin/bash
+# test btrfs subvolume run normally with more than one subvolume
+#
+# - btrfs subvolume must not loop indefinetelly
+# - btrfs subvolume return 0 in normal case
+
+source $TOP/tests/common
+
+check_prereq mkfs.btrfs
+check_prereq btrfs
+
+setup_root_helper
+prepare_test_dev
+
+run_check $SUDO_HELPER $TOP/mkfs.btrfs -f "$TEST_DEV"
+run_check_mount_test_dev
+
+# to check following thing in both 1 and multiple subvolume case:
+# 1: is subvolume sync loop indefinetelly
+# 2: is return value right
+#
+run_check $SUDO_HELPER $TOP/btrfs subvolume create "$TEST_MNT"/mysubvol1
+run_check $SUDO_HELPER $TOP/btrfs subvolume create "$TEST_MNT"/mysubvol2
+run_check $SUDO_HELPER $TOP/btrfs subvolume delete "$TEST_MNT"/mysubvol1
+run_check $SUDO_HELPER $TOP/btrfs subvolume delete "$TEST_MNT"/mysubvol2
+run_check $SUDO_HELPER $TOP/btrfs subvolume sync "$TEST_MNT"
+
+run_check $SUDO_HELPER $TOP/btrfs subvolume create "$TEST_MNT"/mysubvol
+run_check $SUDO_HELPER $TOP/btrfs subvolume delete "$TEST_MNT"/mysubvol
+run_check $SUDO_HELPER $TOP/btrfs subvolume sync "$TEST_MNT"
+
+run_check_umount_test_dev
diff --git a/tests/misc-tests/008-leaf-crossing-stripes/test.sh b/tests/misc-tests/008-leaf-crossing-stripes/test.sh
new file mode 100755
index 00000000..03818062
--- /dev/null
+++ b/tests/misc-tests/008-leaf-crossing-stripes/test.sh
@@ -0,0 +1,25 @@
+#!/bin/bash
+# test if btrfs-convert creates a filesystem without leaf crossing stripes
+
+source $TOP/tests/common
+
+check_prereq btrfs-convert
+check_prereq btrfs
+
+# In my test, it happened in 514M~560M, 737M~769M, 929M~917M,
+# and HAVE_ERROR=((size + 1) / 2) % 2 if size >= 970
+#
+SIZE_FROM=514
+SIZE_END=560
+A_PRIME_NUM=17
+for ((size = SIZE_FROM; size <= SIZE_END; size += A_PRIME_NUM)); do
+ run_check truncate -s "$size"M "$IMAGE"
+ run_check mkfs.ext4 -F "$IMAGE"
+ run_check $TOP/btrfs-convert "$IMAGE"
+ run_check_stdout $TOP/btrfs check "$IMAGE" 2>&1 |
+ grep -q "crossing stripe boundary" &&
+ _fail "leaf crossing stripes after btrfs-convert"
+done
+
+# grep will expectedly fail
+exit 0
diff --git a/tests/misc-tests/009-subvolume-sync-must-wait/test.sh b/tests/misc-tests/009-subvolume-sync-must-wait/test.sh
new file mode 100755
index 00000000..056584e5
--- /dev/null
+++ b/tests/misc-tests/009-subvolume-sync-must-wait/test.sh
@@ -0,0 +1,52 @@
+#!/bin/bash
+#
+# Verify that subovolume sync waits until the subvolume is cleaned
+
+source $TOP/tests/common
+
+check_prereq mkfs.btrfs
+check_prereq btrfs
+
+setup_root_helper
+
+run_check truncate -s 2G $IMAGE
+run_check $TOP/mkfs.btrfs -f $IMAGE
+run_check $SUDO_HELPER mount $IMAGE $TEST_MNT
+run_check $SUDO_HELPER chmod a+rw $TEST_MNT
+
+cd $TEST_MNT
+
+for i in `seq 5`; do
+ run_check dd if=/dev/zero of=file$i bs=1M count=10
+done
+
+for sn in `seq 4`;do
+ run_check $SUDO_HELPER $TOP/btrfs subvolume snapshot . snap$sn
+ for i in `seq 10`; do
+ run_check dd if=/dev/zero of=snap$sn/file$i bs=1M count=10
+ done
+done
+
+run_check $SUDO_HELPER $TOP/btrfs subvolume list .
+run_check $SUDO_HELPER $TOP/btrfs subvolume list -d .
+
+idtodel=`run_check_stdout $SUDO_HELPER $TOP/btrfs inspect-internal rootid snap3`
+
+# delete, sync after some time
+run_check $SUDO_HELPER $TOP/btrfs subvolume delete -c snap3
+{ sleep 5; run_check $TOP/btrfs filesystem sync $TEST_MNT; } &
+
+run_check $SUDO_HELPER $TOP/btrfs subvolume sync . $idtodel
+
+if run_check_stdout $SUDO_HELPER $TOP/btrfs subvolume list -d . |
+ grep -q "ID $idtodel.*DELETED"; then
+ _fail "sync did not wait for the subvolume cleanup"
+fi
+
+run_check $TOP/btrfs filesystem sync $TEST_MNT
+run_check $SUDO_HELPER $TOP/btrfs subvolume list -d .
+
+wait
+cd ..
+
+run_check $SUDO_HELPER umount $TEST_MNT
diff --git a/tests/misc-tests/010-convert-delete-ext2-subvol/test.sh b/tests/misc-tests/010-convert-delete-ext2-subvol/test.sh
new file mode 100755
index 00000000..451e453a
--- /dev/null
+++ b/tests/misc-tests/010-convert-delete-ext2-subvol/test.sh
@@ -0,0 +1,26 @@
+#!/bin/bash
+#
+# verify that convert rollback finds the ext2_subvolume intact and fails if it
+# was partially deleted
+
+source $TOP/tests/common
+
+check_prereq btrfs-convert
+check_prereq btrfs-debug-tree
+check_prereq btrfs
+
+setup_root_helper
+prepare_test_dev
+
+run_check truncate -s 2G "$TEST_DEV"
+run_check mkfs.ext4 -F "$TEST_DEV"
+run_check $TOP/btrfs-convert "$TEST_DEV"
+run_check $TOP/btrfs-debug-tree "$TEST_DEV"
+run_check_mount_test_dev
+run_check $SUDO_HELPER $TOP/btrfs subvolume delete -c "$TEST_MNT/ext2_saved"
+run_check_umount_test_dev
+run_check $TOP/btrfs-debug-tree "$TEST_DEV"
+run_check_stdout $TOP/btrfs-convert --rollback "$TEST_DEV" |
+ grep -q 'is it deleted' || _fail "unexpected rollback"
+
+exit 0
diff --git a/tests/misc-tests/011-delete-missing-device/test.sh b/tests/misc-tests/011-delete-missing-device/test.sh
new file mode 100755
index 00000000..26645f10
--- /dev/null
+++ b/tests/misc-tests/011-delete-missing-device/test.sh
@@ -0,0 +1,83 @@
+#!/bin/bash
+# make sure that 'missing' is accepted for device deletion
+
+source $TOP/tests/common
+
+check_prereq btrfs-show-super
+check_prereq mkfs.btrfs
+check_prereq btrfs
+
+ndevs=4
+declare -a devs
+dev1=
+devtodel=
+
+setup_root_helper
+
+prepare_devices()
+{
+ for i in `seq $ndevs`; do
+ touch img$i
+ chmod a+rw img$i
+ truncate -s0 img$i
+ truncate -s2g img$i
+ devs[$i]=`run_check_stdout $SUDO_HELPER losetup --find --show img$i`
+ done
+}
+
+cleanup_devices()
+{
+ for dev in ${devs[@]}; do
+ run_mayfail $SUDO_HELPER losetup -d $dev
+ done
+ for i in `seq $ndevs`; do
+ truncate -s0 img$i
+ done
+ run_check $SUDO_HELPER losetup --list
+}
+
+test_do_mkfs()
+{
+ run_check $SUDO_HELPER $TOP/mkfs.btrfs -f $@ ${devs[@]}
+ run_check $TOP/btrfs-show-super $dev1
+ run_check $SUDO_HELPER $TOP/btrfs check $dev1
+ run_check $TOP/btrfs filesystem show
+}
+
+test_wipefs()
+{
+ run_check wipefs -a $devtodel
+ run_check $SUDO_HELPER losetup -d $devtodel
+ run_check losetup -a
+ run_check $TOP/btrfs filesystem show
+}
+test_delete_missing()
+{
+ run_check_mount_test_dev -o degraded
+ run_check $SUDO_HELPER $TOP/btrfs filesystem show $TEST_MNT
+ run_check $SUDO_HELPER $TOP/btrfs device delete missing $TEST_MNT
+ run_check $SUDO_HELPER $TOP/btrfs filesystem show $TEST_MNT
+ run_check_umount_test_dev
+
+ run_check_mount_test_dev
+ local out
+ out="$(run_check_stdout $SUDO_HELPER $TOP/btrfs filesystem show $TEST_MNT)"
+ if echo "$out" | grep -q -- "$devtodel"; then
+ _fail "device $devtodel not deleted"
+ fi
+ if echo "$out" | grep -q missing; then
+ _fail "missing device still present"
+ fi
+ run_check_umount_test_dev
+}
+
+prepare_devices
+dev1=${devs[1]}
+devtodel=${devs[3]}
+TEST_DEV=$dev1
+
+test_do_mkfs
+test_wipefs
+test_delete_missing
+
+cleanup_devices
diff --git a/tests/misc-tests/012-find-root-no-result/first_meta_chunk.btrfs-image b/tests/misc-tests/012-find-root-no-result/first_meta_chunk.btrfs-image
new file mode 100644
index 00000000..7bf6c509
--- /dev/null
+++ b/tests/misc-tests/012-find-root-no-result/first_meta_chunk.btrfs-image
Binary files differ
diff --git a/tests/misc-tests/012-find-root-no-result/test.sh b/tests/misc-tests/012-find-root-no-result/test.sh
new file mode 100755
index 00000000..983a8a1e
--- /dev/null
+++ b/tests/misc-tests/012-find-root-no-result/test.sh
@@ -0,0 +1,24 @@
+#!/bin/bash
+# Regression test for case btrfs-find-root may print no result on a
+# recent fs or balanced fs, whose metadata chunk is the first chunk
+# and the only metadata chunk
+
+source $TOP/tests/common
+
+check_prereq btrfs-find-root
+check_prereq btrfs-image
+
+run_check $TOP/btrfs-image -r first_meta_chunk.btrfs-image test.img || \
+ _fail "failed to extract first_meta_chunk.btrfs-image"
+
+result=$(run_check_stdout $TOP/btrfs-find-root test.img | sed '/^Superblock/d')
+
+if [ -z "$result" ]; then
+ _fail "btrfs-find-root failed to find tree root"
+fi
+
+if ! echo "$result" | grep -q 'Found tree root at'; then
+ _fail "btrfs-find-root failed to find tree root, unexpected output"
+fi
+
+rm test.img
diff --git a/tests/mkfs-tests.sh b/tests/mkfs-tests.sh
new file mode 100755
index 00000000..c0635ad1
--- /dev/null
+++ b/tests/mkfs-tests.sh
@@ -0,0 +1,44 @@
+#!/bin/bash
+#
+# mkfs.btrfs tests
+
+unset TOP
+unset LANG
+LANG=C
+SCRIPT_DIR=$(dirname $(readlink -f $0))
+TOP=$(readlink -f $SCRIPT_DIR/../)
+TEST_DEV=${TEST_DEV:-}
+RESULTS="$TOP/tests/mkfs-tests-results.txt"
+IMAGE="$TOP/tests/test.img"
+
+source $TOP/tests/common
+
+# Allow child test to use $TOP and $RESULTS
+export TOP
+export RESULTS
+# For custom script needs to verfiy recovery
+export LANG
+# For tests that only use a loop device
+export IMAGE
+
+rm -f $RESULTS
+
+check_prereq mkfs.btrfs
+check_prereq btrfs
+
+# The tests are driven by their custom script called 'test.sh'
+
+for i in $(find $TOP/tests/mkfs-tests -maxdepth 1 -mindepth 1 -type d \
+ ${TEST:+-name "$TEST"} | sort)
+do
+ echo " [TEST/mkfs] $(basename $i)"
+ cd $i
+ echo "=== Entering $i" >> $RESULTS
+ if [ -x test.sh ]; then
+ ./test.sh
+ if [ $? -ne 0 ]; then
+ _fail "test failed for case $(basename $i)"
+ fi
+ fi
+ cd $TOP
+done
diff --git a/tests/mkfs-tests/001-basic-profiles/test.sh b/tests/mkfs-tests/001-basic-profiles/test.sh
new file mode 100755
index 00000000..2747d429
--- /dev/null
+++ b/tests/mkfs-tests/001-basic-profiles/test.sh
@@ -0,0 +1,91 @@
+#!/bin/bash
+# test various blockgroup profile combinations, use loop devices as block
+# devices
+
+source $TOP/tests/common
+
+check_prereq btrfs-show-super
+check_prereq mkfs.btrfs
+check_prereq btrfs
+
+ndevs=4
+declare -a devs
+dev1=
+
+setup_root_helper
+
+prepare_devices()
+{
+ for i in `seq $ndevs`; do
+ touch img$i
+ chmod a+rw img$i
+ truncate -s0 img$i
+ truncate -s2g img$i
+ devs[$i]=`run_check_stdout $SUDO_HELPER losetup --find --show img$i`
+ done
+}
+
+cleanup_devices()
+{
+ for dev in ${devs[@]}; do
+ run_check $SUDO_HELPER losetup -d $dev
+ done
+ for i in `seq $ndevs`; do
+ truncate -s0 img$i
+ done
+ run_check $SUDO_HELPER losetup --list
+}
+
+test_get_info()
+{
+ run_check $TOP/btrfs-show-super $dev1
+ run_check $SUDO_HELPER $TOP/btrfs check $dev1
+ run_check $SUDO_HELPER mount $dev1 $TEST_MNT
+ run_check $TOP/btrfs filesystem df $TEST_MNT
+ run_check $SUDO_HELPER $TOP/btrfs filesystem usage $TEST_MNT
+ run_check $SUDO_HELPER $TOP/btrfs device usage $TEST_MNT
+ run_check $SUDO_HELPER umount "$TEST_MNT"
+}
+test_do_mkfs()
+{
+ run_check $SUDO_HELPER $TOP/mkfs.btrfs -f \
+ $@
+}
+
+test_mkfs_single()
+{
+ test_do_mkfs $@ $dev1
+ test_get_info
+}
+test_mkfs_multi()
+{
+ test_do_mkfs $@ ${devs[@]}
+ test_get_info
+}
+
+prepare_devices
+dev1=${devs[1]}
+
+test_mkfs_single
+test_mkfs_single -d single -m single
+test_mkfs_single -d single -m single --mixed
+test_mkfs_single -d single -m dup
+test_mkfs_single -d dup -m single
+test_mkfs_single -d dup -m dup
+test_mkfs_single -d dup -m dup --mixed
+
+test_mkfs_multi
+test_mkfs_multi -d single -m single
+test_mkfs_multi -d single -m single --mixed
+test_mkfs_multi -d raid0 -m raid0
+test_mkfs_multi -d raid0 -m raid0 --mixed
+test_mkfs_multi -d raid1 -m raid1
+test_mkfs_multi -d raid1 -m raid1 --mixed
+test_mkfs_multi -d raid10 -m raid10
+test_mkfs_multi -d raid10 -m raid10 --mixed
+test_mkfs_multi -d raid5 -m raid5
+test_mkfs_multi -d raid5 -m raid5 --mixed
+test_mkfs_multi -d raid6 -m raid6
+test_mkfs_multi -d raid6 -m raid6 --mixed
+
+cleanup_devices
diff --git a/tests/mkfs-tests/002-no-force-mixed-on-small-volume/test.sh b/tests/mkfs-tests/002-no-force-mixed-on-small-volume/test.sh
new file mode 100755
index 00000000..855fbd18
--- /dev/null
+++ b/tests/mkfs-tests/002-no-force-mixed-on-small-volume/test.sh
@@ -0,0 +1,13 @@
+#!/bin/bash
+#
+# Verify that we do not force mixed block groups on small volumes anymore
+
+source $TOP/tests/common
+
+check_prereq mkfs.btrfs
+
+setup_root_helper
+
+run_check truncate -s 512M $IMAGE
+mixed=$(run_check_stdout $TOP/mkfs.btrfs -n 64k -f $IMAGE | egrep 'Data|Metadata')
+echo "$mixed" | grep -q -v 'Data+Metadata:' || _fail "unexpected: created a mixed-bg filesystem"
diff --git a/tests/mkfs-tests/003-mixed-with-wrong-nodesize/test.sh b/tests/mkfs-tests/003-mixed-with-wrong-nodesize/test.sh
new file mode 100755
index 00000000..289d5ff0
--- /dev/null
+++ b/tests/mkfs-tests/003-mixed-with-wrong-nodesize/test.sh
@@ -0,0 +1,12 @@
+#!/bin/bash
+#
+# Mixed mode needs equal sectorsize and nodesize
+
+source $TOP/tests/common
+
+check_prereq mkfs.btrfs
+
+run_check truncate -s 512M $IMAGE
+run_mayfail $TOP/mkfs.btrfs -f -M -s 4096 -n 16384 "$IMAGE" && _fail
+
+exit 0
diff --git a/tests/mkfs-tests/004-rootdir-keeps-size/test.sh b/tests/mkfs-tests/004-rootdir-keeps-size/test.sh
new file mode 100755
index 00000000..7038c8ea
--- /dev/null
+++ b/tests/mkfs-tests/004-rootdir-keeps-size/test.sh
@@ -0,0 +1,31 @@
+#!/bin/bash
+# make sure that mkfs.btrfs --rootsize does not change size of the image
+
+source $TOP/tests/common
+
+check_prereq mkfs.btrfs
+
+prepare_test_dev
+
+test_mkfs_with_size() {
+ local size
+ local imgsize
+ local tmp
+
+ size="$1"
+ run_check truncate -s$size $TEST_DEV
+ imgsize=$(run_check_stdout stat --format=%s $TEST_DEV)
+ run_check $SUDO_HELPER $TOP/mkfs.btrfs -f \
+ --rootdir $TOP/Documentation \
+ $TEST_DEV
+ tmp=$(run_check_stdout stat --format=%s $TEST_DEV)
+ if ! [ "$imgsize" = "$tmp" ]; then
+ _fail "image size changed from $imgsize to $tmp"
+ fi
+}
+
+test_mkfs_with_size 128M
+test_mkfs_with_size 256M
+test_mkfs_with_size 512M
+test_mkfs_with_size 1G
+test_mkfs_with_size 2G
diff --git a/tests/mkfs-tests/005-long-device-name-for-ssd/test.sh b/tests/mkfs-tests/005-long-device-name-for-ssd/test.sh
new file mode 100755
index 00000000..c89ee0e1
--- /dev/null
+++ b/tests/mkfs-tests/005-long-device-name-for-ssd/test.sh
@@ -0,0 +1,40 @@
+#!/bin/bash
+# a long device name must pass the SSD test
+
+source $TOP/tests/common
+
+check_prereq mkfs.btrfs
+check_prereq btrfs-show-super
+
+setup_root_helper
+prepare_test_dev
+
+# prep device
+dmname=\
+btrfs-test-with-very-long-name-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+dmdev=/dev/mapper/$dmname
+
+run_check truncate -s0 img
+chmod a+w img
+run_check truncate -s2g img
+
+loopdev=`run_check_stdout $SUDO_HELPER losetup --find --show img`
+run_check $SUDO_HELPER dmsetup create $dmname --table "0 1048576 linear $loopdev 0"
+
+base=`basename "$loopdev"`
+rot=/sys/class/block/$base/queue/rotational
+
+# switch rotational
+run_check cat $rot
+echo 0 | run_check $SUDO_HELPER tee $rot
+run_check cat $rot
+
+# test
+run_check_stdout $SUDO_HELPER $TOP/mkfs.btrfs -f $@ $dmdev |
+ grep -q 'SSD detected:.*yes' || _fail 'SSD not detected'
+run_check $TOP/btrfs-show-super $dmdev
+
+# cleanup
+run_check $SUDO_HELPER dmsetup remove $dmname
+run_mayfail $SUDO_HELPER losetup -d $loopdev
+run_check truncate -s0 img
diff --git a/tests/mkfs-tests/006-partitioned-loopdev/partition-1g-1g b/tests/mkfs-tests/006-partitioned-loopdev/partition-1g-1g
new file mode 100644
index 00000000..eb057769
--- /dev/null
+++ b/tests/mkfs-tests/006-partitioned-loopdev/partition-1g-1g
Binary files differ
diff --git a/tests/mkfs-tests/006-partitioned-loopdev/test.sh b/tests/mkfs-tests/006-partitioned-loopdev/test.sh
new file mode 100755
index 00000000..7c9fb829
--- /dev/null
+++ b/tests/mkfs-tests/006-partitioned-loopdev/test.sh
@@ -0,0 +1,27 @@
+#!/bin/bash
+# recognize partitioned loop devices
+
+source $TOP/tests/common
+
+check_prereq mkfs.btrfs
+check_prereq btrfs-show-super
+
+setup_root_helper
+
+run_check truncate -s0 img
+chmod a+w img
+cp partition-1g-1g img
+run_check truncate -s2g img
+
+loopdev=$(run_check_stdout $SUDO_HELPER losetup --partscan --find --show img)
+base=$(basename $loopdev)
+
+# expect partitions named like loop0p1 etc
+for looppart in $(ls /dev/$base?*); do
+ run_check $SUDO_HELPER $TOP/mkfs.btrfs -f $looppart
+ run_check $TOP/btrfs-show-super $looppart
+done
+
+# cleanup
+run_check $SUDO_HELPER losetup -d $loopdev
+run_check truncate -s0 img
diff --git a/tests/mkfs-tests/007-mix-nodesize-sectorsize/test.sh b/tests/mkfs-tests/007-mix-nodesize-sectorsize/test.sh
new file mode 100755
index 00000000..d5374cbd
--- /dev/null
+++ b/tests/mkfs-tests/007-mix-nodesize-sectorsize/test.sh
@@ -0,0 +1,36 @@
+#!/bin/bash
+# iterate over nodesize and sectorsize combinations
+
+source $TOP/tests/common
+
+check_prereq btrfs-show-super
+check_prereq mkfs.btrfs
+check_prereq btrfs
+
+setup_root_helper
+prepare_test_dev
+
+test_mkfs_single()
+{
+ run_check $SUDO_HELPER $TOP/mkfs.btrfs -f "$@" $TEST_DEV
+ run_check $TOP/btrfs-show-super $TEST_DEV
+ run_check $SUDO_HELPER $TOP/btrfs check $TEST_DEV
+}
+
+# default
+test_mkfs_single
+
+# nodesize >= sectorsize
+for nodesize in 4096 8192 16384 32768 65536; do
+ for sectorsize in 4096 8192 16384 32768 65536; do
+ [ $nodesize -lt $sectorsize ] && continue
+ test_mkfs_single -n $nodesize -s $sectorsize -d single -m single
+ test_mkfs_single -n $nodesize -s $sectorsize -d single -m dup
+ done
+done
+
+# nodesize, mixed mode
+for nodesize in 4k 8k 16k 32k 64k; do
+ test_mkfs_single -n $nodesize -s $nodesize -d single -m single --mixed
+ test_mkfs_single -n $nodesize -s $nodesize -d dup -m dup --mixed
+done
diff --git a/tests/mkfs-tests/008-secorsize-nodesize-combination/test.sh b/tests/mkfs-tests/008-secorsize-nodesize-combination/test.sh
new file mode 100755
index 00000000..79cc2b22
--- /dev/null
+++ b/tests/mkfs-tests/008-secorsize-nodesize-combination/test.sh
@@ -0,0 +1,50 @@
+#!/bin/bash
+# test various sectorsize and node size combinations
+# including valid and invalid ones
+# only do mkfs and fsck check, no mounting as
+# sub/multi-pagesize is not supported yet
+
+source $TOP/tests/common
+
+check_prereq mkfs.btrfs
+check_prereq btrfs
+
+prepare_test_dev
+
+# disable mixed bg to avoid sectorsize == nodesize check
+features="^mixed-bg"
+
+# caller need to check whether the combination is valid
+do_test()
+{
+ sectorsize=$1
+ nodesize=$2
+ run_mayfail $TOP/mkfs.btrfs -O $features -n $nodesize -s $sectorsize \
+ $TEST_DEV
+ ret=$?
+ if [ $ret == 0 ]; then
+ run_check $TOP/btrfs check $TEST_DEV
+ fi
+ return $ret
+}
+
+# Invalid: Unaligned sectorsize and nodesize
+do_test 8191 8191 && _fail
+
+# Invalid: Aligned sectorsize with unaligned nodesize
+do_test 4k 16385 && _fail
+
+# Invalid: Ungliend sectorsize with aligned nodesize
+do_test 8191 16k && _fail
+
+# Valid: Aligned sectorsize and nodesize
+do_test 4k 16k || _fail
+
+# Invalid: Sectorsize larger than nodesize
+do_test 8k 4k && _fail
+
+# Invalid: too large nodesize
+do_test 16k 128k && _fail
+
+# Valid: large sectorsize
+do_test 64k 64k || _fail