btrfs: Check false ENOSPC bug caused by incorrect metadata reserve
authorQu Wenruo <quwenruo@cn.fujitsu.com>
Thu, 10 Nov 2016 03:18:48 +0000 (11:18 +0800)
committerEryu Guan <eguan@redhat.com>
Sun, 13 Nov 2016 06:01:06 +0000 (14:01 +0800)
Due to the fact that btrfs uses different max extent size for
compressed and non-compressed write, it calculates metadata
reservation incorrectly.

This can leads to false ENOSPC alert for compressed write.

This test case will check it by using small fs and do parallel write
to trigger it.

It's highly recommened to use MOUNT_OPTIONS="-o compress" and
MKFS_OPTIONS="-n 64k" to trigger it. Without compression, it won't
be triggered.

The fix is not merged and may change in the future, but the function
is good enough:

btrfs: improve inode's outstanding_extents computation
btrfs: fix false enospc for compression

Signed-off-by: Qu Wenruo <quwenruo@cn.fujitsu.com>
Reviewed-by: Eryu Guan <eguan@redhat.com>
Signed-off-by: Eryu Guan <eguan@redhat.com>
tests/btrfs/132 [new file with mode: 0755]
tests/btrfs/132.out [new file with mode: 0644]
tests/btrfs/group

diff --git a/tests/btrfs/132 b/tests/btrfs/132
new file mode 100755 (executable)
index 0000000..0516177
--- /dev/null
@@ -0,0 +1,103 @@
+#! /bin/bash
+# FS QA Test 132
+#
+# Check if false ENOSPC will happen when parallel buffer write happens
+# The problem is caused by incorrect metadata reservation for any buffered
+# write whose max extent size is not 128M (including compression and in-band
+# dedupe).
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2016 Fujitsu.  All Rights Reserved.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it would be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write the Free Software Foundation,
+# Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+#-----------------------------------------------------------------------
+#
+
+seq=`basename $0`
+seqres=$RESULT_DIR/$seq
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=1       # failure is the default!
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+_cleanup()
+{
+       cd /
+       rm -f $tmp.*
+       kill $pids &> /dev/null
+       wait
+}
+
+# get standard environment, filters and checks
+. ./common/rc
+. ./common/filter
+
+# remove previous $seqres.full before test
+rm -f $seqres.full
+
+# real QA test starts here
+
+# Modify as appropriate.
+_supported_fs btrfs
+_supported_os Linux
+_require_scratch
+
+# Use small filesystem to trigger the bug more easily
+# It's highly recommened to run this test case with MKFS_OPTIONS="-n 64k"
+# to further increase the possibility
+# Since the false ENOSPC happens due to incorrect metadata reservation,
+# larger nodesize and small fs will make it much easier to reproduce
+_scratch_mkfs_sized $((512 * 1024 * 1024)) >> $seqres.full 2>&1
+
+# Recommended to use MOUNT_OPTIONS="-o compress" to trigger the bug
+_scratch_mount
+
+sleep_time=$(($TIME_FACTOR * 30))
+loop_writer()
+{
+       offset=$1
+       len=$2
+       file=$3
+
+       while true; do
+               # Only need stderr, and we need to specify small block size
+               # but still large enough trigger compression
+               $XFS_IO_PROG -c "pwrite -b 8K $offset $len" $file > /dev/null
+       done
+}
+
+touch $SCRATCH_MNT/testfile
+
+# Start 2 writter writting into the same file
+# The file is 142M, which is smaller than 1/2 of the filesystem,
+# so no other cause can lead to ENOSPC.
+loop_writer 0 128M $SCRATCH_MNT/testfile &
+pids=$!
+loop_writer 128M 16M $SCRATCH_MNT/testfile &
+pids="$pids $!"
+
+sleep $sleep_time
+
+kill $pids
+wait
+
+# Sync the fs to avoid EBUSY while umount, which is quite common for btrfs
+# compression
+sync
+
+echo "Silence is golden"
+status=0
+exit
diff --git a/tests/btrfs/132.out b/tests/btrfs/132.out
new file mode 100644 (file)
index 0000000..b096312
--- /dev/null
@@ -0,0 +1,2 @@
+QA output created by 132
+Silence is golden
index c09060494021fec98424621abee80f27f950710d..b4e4ff2947ef0921e765f40cb20e950e01deb8f9 100644 (file)
 129 auto quick send
 130 auto clone send
 131 auto quick
+132 auto enospc