btrfs: add test for data corruption when using compression
[xfstests-dev.git] / tests / btrfs / 037
1 #! /bin/bash
2 # FS QA Test No. btrfs/037
3 #
4 # Test for a btrfs data corruption when using compressed files/extents.
5 # Under certain cases, it was possible for reads to return random data
6 # (content from a previously used page) instead of zeroes. This also
7 # caused partial updates to those regions that were supposed to be filled
8 # with zeroes to save random (and invalid) data into the file extents.
9 #
10 # This is fixed by the commit for the linux kernel titled:
11 #
12 #   Btrfs: fix data corruption when reading/updating compressed extents
13 #
14 #-----------------------------------------------------------------------
15 # Copyright (c) 2014 Filipe Manana.  All Rights Reserved.
16 #
17 # This program is free software; you can redistribute it and/or
18 # modify it under the terms of the GNU General Public License as
19 # published by the Free Software Foundation.
20 #
21 # This program is distributed in the hope that it would be useful,
22 # but WITHOUT ANY WARRANTY; without even the implied warranty of
23 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24 # GNU General Public License for more details.
25 #
26 # You should have received a copy of the GNU General Public License
27 # along with this program; if not, write the Free Software Foundation,
28 # Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
29 #-----------------------------------------------------------------------
30 #
31
32 seq=`basename $0`
33 seqres=$RESULT_DIR/$seq
34 echo "QA output created by $seq"
35
36 tmp=`mktemp -d`
37
38 status=1        # failure is the default!
39 trap "_cleanup; exit \$status" 0 1 2 3 15
40
41 _cleanup()
42 {
43     rm -fr $tmp
44 }
45
46 # get standard environment, filters and checks
47 . ./common/rc
48 . ./common/filter
49
50 # real QA test starts here
51 _supported_fs btrfs
52 _supported_os Linux
53 _require_scratch
54 _need_to_be_root
55
56 rm -f $seqres.full
57
58 _scratch_mkfs >/dev/null 2>&1
59 _scratch_mount "-o compress-force=lzo"
60
61 $XFS_IO_PROG -f -c "pwrite -S 0x06 -b 18670 266978 18670" \
62     $SCRATCH_MNT/foobar | _filter_xfs_io
63 $XFS_IO_PROG -c "falloc 26450 665194" $SCRATCH_MNT/foobar | _filter_xfs_io
64 $XFS_IO_PROG -c "truncate 542872" $SCRATCH_MNT/foobar | _filter_xfs_io
65 $XFS_IO_PROG -c "fsync" $SCRATCH_MNT/foobar | _filter_xfs_io
66
67 # Expected file items in the fs tree are (from btrfs-debug-tree):
68 #
69 #   item 4 key (257 INODE_ITEM 0) itemoff 15879 itemsize 160
70 #       inode generation 6 transid 6 size 542872 block group 0 mode 100600
71 #   item 5 key (257 INODE_REF 256) itemoff 15863 itemsize 16
72 #       inode ref index 2 namelen 6 name: foobar
73 #   item 6 key (257 EXTENT_DATA 0) itemoff 15810 itemsize 53
74 #       extent data disk byte 0 nr 0 gen 6
75 #       extent data offset 0 nr 24576 ram 266240
76 #       extent compression 0
77 #   item 7 key (257 EXTENT_DATA 24576) itemoff 15757 itemsize 53
78 #       prealloc data disk byte 12849152 nr 241664 gen 6
79 #       prealloc data offset 0 nr 241664
80 #   item 8 key (257 EXTENT_DATA 266240) itemoff 15704 itemsize 53
81 #       extent data disk byte 12845056 nr 4096 gen 6
82 #       extent data offset 0 nr 20480 ram 20480
83 #       extent compression 2
84 #   item 9 key (257 EXTENT_DATA 286720) itemoff 15651 itemsize 53
85 #       prealloc data disk byte 13090816 nr 405504 gen 6
86 #       prealloc data offset 0 nr 258048
87 #
88 # The on disk extent at 266240, contains 5 compressed chunks of file data.
89 # Each of the first 4 chunks compress 4096 bytes of file data, while the last
90 # one compresses only 3024 bytes of file data. Because this extent item is not
91 # the last one in the file, as it followed by a prealloc extent, reads into
92 # the region [285648 ; 286720[ (length = 4096 - 3024) should return zeroes.
93
94 _scratch_unmount
95 _check_btrfs_filesystem $SCRATCH_DEV
96
97 EXPECTED_MD5="b8b0dbb8e02f94123c741c23659a1c0a"
98
99 for i in `seq 1 27`
100 do
101     _scratch_mount "-o ro"
102     MD5=`md5sum $SCRATCH_MNT/foobar | cut -f 1 -d ' '`
103     _scratch_unmount
104     if [ "${MD5}x" != "${EXPECTED_MD5}x" ]
105     then
106         echo "Unexpected file digest (wanted $EXPECTED_MD5, got $MD5)"
107     fi
108 done
109
110 status=0
111 exit