fsx/fsstress: round blocksize properly
[xfstests-dev.git] / tests / btrfs / 103
1 #! /bin/bash
2 # SPDX-License-Identifier: GPL-2.0
3 # Copyright (C) 2015 SUSE Linux Products GmbH. All Rights Reserved.
4 #
5 # FSQA Test No. 103
6 #
7 # Regression test for file read corruption when using compressed extents that
8 # are shared by multiple consecutive ranges of the same file.
9 #
10 seq=`basename $0`
11 seqres=$RESULT_DIR/$seq
12 echo "QA output created by $seq"
13 tmp=/tmp/$$
14 status=1        # failure is the default!
15 trap "_cleanup; exit \$status" 0 1 2 3 15
16
17 _cleanup()
18 {
19         rm -f $tmp.*
20 }
21
22 # get standard environment, filters and checks
23 . ./common/rc
24 . ./common/filter
25
26 # real QA test starts here
27 _supported_fs btrfs
28 _require_scratch
29 _require_cloner
30
31 rm -f $seqres.full
32
33 test_clone_and_read_compressed_extent()
34 {
35         local mount_opts=$1
36
37         _scratch_mkfs >>$seqres.full 2>&1
38         _scratch_mount $mount_opts
39
40         BLOCK_SIZE=$(_get_block_size $SCRATCH_MNT)
41
42         # Create a test file with a single extent that is compressed (the
43         # data we write into it is highly compressible no matter which
44         # compression algorithm is used, zlib or lzo).
45         $XFS_IO_PROG -f -c "pwrite -S 0xaa 0K $((1 * $BLOCK_SIZE))" \
46                 -c "pwrite -S 0xbb $((1 * $BLOCK_SIZE)) $((2 * $BLOCK_SIZE))" \
47                 -c "pwrite -S 0xcc $((3 * $BLOCK_SIZE)) $((1 * $BLOCK_SIZE))" \
48                 $SCRATCH_MNT/foo | _filter_xfs_io_blocks_modified
49
50
51         # Now clone our extent into an adjacent offset.
52         $CLONER_PROG -s $((1 * $BLOCK_SIZE)) -d $((4 * $BLOCK_SIZE)) \
53                      -l $((2 * $BLOCK_SIZE)) $SCRATCH_MNT/foo $SCRATCH_MNT/foo
54
55         # Same as before but for this file we clone the extent into a lower
56         # file offset.
57         $XFS_IO_PROG -f \
58                 -c "pwrite -S 0xaa $((2 * $BLOCK_SIZE)) $((1 * $BLOCK_SIZE))" \
59                 -c "pwrite -S 0xbb $((3 * $BLOCK_SIZE)) $((2 * $BLOCK_SIZE))" \
60                 -c "pwrite -S 0xcc $((5 * $BLOCK_SIZE)) $((1 * $BLOCK_SIZE))" \
61                 $SCRATCH_MNT/bar | _filter_xfs_io_blocks_modified
62
63         $CLONER_PROG -s $((3 * $BLOCK_SIZE)) -d 0 -l $((2 * $BLOCK_SIZE)) \
64                 $SCRATCH_MNT/bar $SCRATCH_MNT/bar
65
66         echo "File contents before unmounting filesystem:"
67         echo "foo:"
68         od -t x1 $SCRATCH_MNT/foo | _filter_od
69         echo "bar:"
70         od -t x1 $SCRATCH_MNT/bar | _filter_od
71
72         # Evicting the inode or clearing the page cache before reading again
73         # the file would also trigger the bug - reads were returning all bytes
74         # in the range corresponding to the second reference to the extent with
75         # a value of 0, but the correct data was persisted (it was a bug
76         # exclusively in the read path). The issue happened only if the same
77         # readpages() call targeted pages belonging to the first and second
78         # ranges that point to the same compressed extent.
79         _scratch_cycle_mount
80
81         echo "File contents after mounting filesystem again:"
82         # Must match the same contents we got before.
83         echo "foo:"
84         od -t x1 $SCRATCH_MNT/foo | _filter_od
85         echo "bar:"
86         od -t x1 $SCRATCH_MNT/bar | _filter_od
87 }
88
89 echo -e "\nTesting with zlib compression..."
90 test_clone_and_read_compressed_extent "-o compress=zlib"
91
92 _scratch_unmount
93
94 echo -e "\nTesting with lzo compression..."
95 test_clone_and_read_compressed_extent "-o compress=lzo"
96
97 status=0
98 exit