btrfs/012: check free size of scratch device before copying files
[xfstests-dev.git] / tests / generic / 574
1 #! /bin/bash
2 # SPDX-License-Identifier: GPL-2.0
3 # Copyright 2018 Google LLC
4 #
5 # FS QA Test generic/574
6 #
7 # Test corrupting verity files.  This test corrupts various parts of the
8 # contents of a verity file, or parts of its Merkle tree, by writing directly to
9 # the block device.  It verifies that this causes I/O errors when the relevant
10 # part of the contents is later read by any means.
11 #
12 seq=`basename $0`
13 seqres=$RESULT_DIR/$seq
14 echo "QA output created by $seq"
15
16 here=`pwd`
17 tmp=/tmp/$$
18 status=1        # failure is the default!
19 trap "_cleanup; exit \$status" 0 1 2 3 15
20
21 _cleanup()
22 {
23         cd /
24         _restore_fsverity_signatures
25         rm -f $tmp.*
26 }
27
28 # get standard environment, filters and checks
29 . ./common/rc
30 . ./common/filter
31 . ./common/verity
32
33 # remove previous $seqres.full before test
34 rm -f $seqres.full
35
36 # real QA test starts here
37 _supported_fs generic
38 _require_scratch_verity
39 _disable_fsverity_signatures
40
41 _scratch_mkfs_verity &>> $seqres.full
42 _scratch_mount
43 fsv_orig_file=$SCRATCH_MNT/file
44 fsv_file=$SCRATCH_MNT/file.fsv
45
46 setup_zeroed_file()
47 {
48         local len=$1
49         local sparse=$2
50
51         if $sparse; then
52                 dd if=/dev/zero of=$fsv_orig_file bs=1 count=0 seek=$len \
53                         status=none
54         else
55                 head -c $len /dev/zero > $fsv_orig_file
56         fi
57         cp $fsv_orig_file $fsv_file
58         _fsv_enable $fsv_file
59         md5sum $fsv_file |& _filter_scratch
60 }
61
62 filter_sigbus()
63 {
64         sed -e 's/.*Bus error.*/Bus error/'
65 }
66
67 round_up_to_page_boundary()
68 {
69         local n=$1
70         local page_size=$(get_page_size)
71
72         echo $(( (n + page_size - 1) & ~(page_size - 1) ))
73 }
74
75 corruption_test()
76 {
77         local file_len=$1
78         local zap_offset=$2
79         local zap_len=$3
80         local is_merkle_tree=${4:-false} # if true, zap tree instead of data
81         local use_sparse_file=${5:-false}
82         local page_aligned_eof=$(round_up_to_page_boundary $file_len)
83         local measurement
84
85         if $is_merkle_tree; then
86                 local corrupt_func=_fsv_scratch_corrupt_merkle_tree
87         else
88                 local corrupt_func=_fsv_scratch_corrupt_bytes
89         fi
90
91         local msg="Corruption test:"
92         msg+=" file_len=$file_len"
93         if $use_sparse_file; then
94                 msg+=" (sparse)"
95         fi
96         msg+=" zap_offset=$zap_offset"
97         if $is_merkle_tree; then
98                 msg+=" (in Merkle tree)"
99         fi
100         msg+=" zap_len=$zap_len"
101
102         _fsv_scratch_begin_subtest "$msg"
103         setup_zeroed_file $file_len $use_sparse_file
104         cmp $fsv_file $fsv_orig_file
105         echo "Corrupting bytes..."
106         head -c $zap_len /dev/zero | tr '\0' X \
107                 | $corrupt_func $fsv_file $zap_offset
108
109         echo "Validating corruption (reading full file)..."
110         _scratch_cycle_mount
111         md5sum $fsv_file |& _filter_scratch
112
113         echo "Validating corruption (direct I/O)..."
114         _scratch_cycle_mount
115         dd if=$fsv_file bs=$FSV_BLOCK_SIZE iflag=direct status=none \
116                 of=/dev/null |& _filter_scratch
117
118         if ! $is_merkle_tree; then
119                 echo "Validating corruption (reading just corrupted part)..."
120                 dd if=$fsv_file bs=1 skip=$zap_offset count=$zap_len \
121                         of=/dev/null status=none |& _filter_scratch
122         fi
123
124         echo "Validating corruption (reading full file via mmap)..."
125         bash -c "trap '' SIGBUS; $XFS_IO_PROG -r $fsv_file \
126                 -c 'mmap -r 0 $page_aligned_eof' \
127                 -c 'mread 0 $file_len'" |& filter_sigbus
128
129         if ! $is_merkle_tree; then
130                 echo "Validating corruption (reading just corrupted part via mmap)..."
131                 bash -c "trap '' SIGBUS; $XFS_IO_PROG -r $fsv_file \
132                         -c 'mmap -r 0 $page_aligned_eof' \
133                         -c 'mread $zap_offset $zap_len'" |& filter_sigbus
134         fi
135 }
136
137 # Note: these tests just overwrite some bytes without checking their original
138 # values.  Therefore, make sure to overwrite at least 5 or so bytes, to make it
139 # nearly guaranteed that there will be a change -- even when the test file is
140 # encrypted due to the test_dummy_encryption mount option being specified.
141
142 corruption_test 131072 0 5
143 corruption_test 131072 4091 5
144 corruption_test 131072 65536 65536
145 corruption_test 131072 131067 5
146
147 # Non-zeroed bytes in the final partial block beyond EOF should cause reads to
148 # fail too.  Such bytes would be visible via mmap().
149 corruption_test 130999 131000 72
150
151 # Merkle tree corruption.
152 corruption_test 200000 100 10 true
153
154 # Sparse file.  Corrupting the Merkle tree should still cause reads to fail,
155 # i.e. the filesystem must verify holes.
156 corruption_test 200000 100 10 true true
157
158 # success, all done
159 status=0
160 exit