btrfs: regression test for btrfs extent merge
[xfstests-dev.git] / tests / btrfs / 079
1 #! /bin/bash
2 # FS QA Test No. btrfs/079
3 #
4 # Do write along with fiemap ioctl.
5 # Regression test for the kernel comit:
6 # 51f395ad btrfs: Use right extent length when inserting overlap extent map.
7 #
8 # When calling fiemap(without SYNC flag) and btrfs fs is commiting,
9 # it will cause race condition and cause btrfs to generate a wrong extent
10 # whose len is overflow and fail to insert into the extent map tree,
11 # returning -EEXIST.
12 #
13 # Fixed by the following patches (not merged in mainline yet):
14 # btrfs: Fix and enhance merge_extent_mapping() to insert best fitted extent map
15 # btrfs: Fix the wrong condition judgment about subset extent map
16 #
17 #-----------------------------------------------------------------------
18 # Copyright (C) 2014 Fujitsu All Rights Reserved.
19 # Author: Qu Wenruo <quwenruo@cn.fujitsu.com>
20 #
21 # This program is free software; you can redistribute it and/or
22 # modify it under the terms of the GNU General Public License as
23 # published by the Free Software Foundation.
24 #
25 # This program is distributed in the hope that it would be useful,
26 # but WITHOUT ANY WARRANTY; without even the implied warranty of
27 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
28 # GNU General Public License for more details.
29 #
30 # You should have received a copy of the GNU General Public License
31 # along with this program; if not, write the Free Software Foundation,
32 # Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
33 #-----------------------------------------------------------------------
34 #
35
36 seq=`basename $0`
37 seqres=$RESULT_DIR/$seq
38 echo "QA output created by $seq"
39
40 tmp=/tmp/$$
41 status=1        # failure is the default!
42 trap "_cleanup; exit \$status" 0 1 2 3 15
43
44 _cleanup()
45 {
46         kill $dd_pid &> /dev/null
47         kill $fiemap_pid &> /dev/null
48         wait
49         rm -fr $testfile
50         rm -fr $tmp.* $tmp
51 }
52
53 # get standard environment, filters and checks
54 . ./common/rc
55 . ./common/filter
56
57 # real QA test starts here
58 _supported_fs btrfs
59 _supported_os Linux
60 _require_scratch
61 _need_to_be_root
62 # Since xfs_io's fiemap always use SYNC flag and can't be unset,
63 # we must use filefrag to call fiemap without SYNC flag.
64 _require_command "/usr/sbin/filefrag"
65 _require_xfs_io_command "falloc"
66
67 filesize=$((10 * 1024 * 1024 * 1024)) #10G size
68 buffersize=$((1024 * 1024)) # 1M bs for dd
69 count=$(($filesize / $buffersize))
70 testfile=$SCRATCH_MNT/testfile
71
72 rm -f $seqres.full
73
74 _scratch_mkfs >>$seqres.full 2>&1
75 _scratch_mount
76 _require_fs_space $SCRATCH_MNT $(($filesize / 1024 / 1024 / 1024))
77 $XFS_IO_PROG -f -c "falloc 0 $filesize" $testfile
78
79 dd_work() {
80         out=$1
81         dd if=/dev/zero of=$out bs=$buffersize count=$count \
82            conv=notrunc &> /dev/null
83 }
84
85 # There is a bug for e2fsprogs, at least in version 1.42.9, filefrag will
86 # leak the return value, so we can't judge return value only,
87 # but also to filter the output
88 _filter_error() {
89         # when filefrag fails FIEMAP ioctl, it will fall back to FIBMAP,
90         # which is not supported by btrfs and will report "FIBMAP: strerr()"
91         # However old e2fsprogs will use wrong errno EINVAL other than ENOTTY
92         # so only grep for "FIBMAP" for max compatibility.
93         grep "FIBMAP"
94 }
95
96 fiemap_work() {
97         filename=$1
98         while true; do
99                 filefrag $filename 2> $tmp.output 1> /dev/null
100                 ret=$?
101                 err=`cat $tmp.output | _filter_error`
102                 if [ $ret -ne 0 -o -n "$err" ]; then
103                         kill $dd_pid
104                         return 1
105                 fi
106         done
107 }
108
109 dd_work $testfile &
110 dd_pid=$!
111 fiemap_work $testfile &
112 fiemap_pid=$!
113 wait $dd_pid
114 ddret=$?
115 kill $fiemap_pid &> /dev/null
116 wait $fiemap_pid
117
118 if [ $ddret -ne 0 ]; then
119         echo "Extent merge bug detected"
120         status=1
121         exit
122 else
123         echo "Silence is golden"
124         status=0
125         exit
126 fi