]>
Commit | Line | Data |
---|---|---|
0b1eb0ce HR |
1 | #!/usr/bin/env bash |
2 | # | |
3 | # Test qemu-img convert --salvage | |
4 | # | |
5 | # Copyright (C) 2019 Red Hat, Inc. | |
6 | # | |
7 | # This program is free software; you can redistribute it and/or modify | |
8 | # it under the terms of the GNU General Public License as published by | |
9 | # the Free Software Foundation; either version 2 of the License, or | |
10 | # (at your option) any later version. | |
11 | # | |
12 | # This program is distributed in the hope that it will be useful, | |
13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | # GNU General Public License for more details. | |
16 | # | |
17 | # You should have received a copy of the GNU General Public License | |
18 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
19 | # | |
20 | ||
21 | # creator | |
22 | owner=mreitz@redhat.com | |
23 | ||
24 | seq=$(basename $0) | |
25 | echo "QA output created by $seq" | |
26 | ||
27 | status=1 # failure is the default! | |
28 | ||
29 | _cleanup() | |
30 | { | |
31 | _cleanup_test_img | |
32 | } | |
33 | trap "_cleanup; exit \$status" 0 1 2 3 15 | |
34 | ||
35 | # get standard environment, filters and checks | |
36 | . ./common.rc | |
37 | . ./common.filter | |
38 | . ./common.qemu | |
39 | ||
40 | _supported_fmt generic | |
41 | _supported_proto file | |
42 | _supported_os Linux | |
325dd915 | 43 | _unsupported_imgopts "subformat=streamOptimized" |
0b1eb0ce HR |
44 | |
45 | if [ "$IMGOPTSSYNTAX" = "true" ]; then | |
46 | # We use json:{} filenames here, so we cannot work with additional options. | |
47 | _unsupported_fmt $IMGFMT | |
48 | else | |
49 | # With VDI, the output is ordered differently. Just disable it. | |
50 | _unsupported_fmt vdi | |
51 | fi | |
52 | ||
53 | ||
54 | TEST_IMG="$TEST_IMG.orig" _make_test_img 64M | |
55 | ||
56 | $QEMU_IO -c 'write -P 42 0 64M' "$TEST_IMG.orig" | _filter_qemu_io | |
57 | ||
58 | ||
59 | sector_size=512 | |
60 | ||
61 | # Offsets on which to fail block-status. Keep in ascending order so | |
62 | # the indexing done by _filter_offsets will appear in ascending order | |
63 | # in the output as well. | |
64 | status_fail_offsets="$((16 * 1024 * 1024 + 8192)) | |
65 | $((33 * 1024 * 1024 + 512))" | |
66 | ||
67 | # Offsets on which to fail reads. Keep in ascending order for the | |
68 | # same reason. | |
69 | # The second element is shared with $status_fail_offsets on purpose. | |
70 | # Starting with the third element, we test what happens when a | |
71 | # continuous range of sectors is inaccessible. | |
72 | read_fail_offsets="$((32 * 1024 * 1024 - 65536)) | |
73 | $((33 * 1024 * 1024 + 512)) | |
74 | $(seq $((34 * 1024 * 1024)) $sector_size \ | |
75 | $((34 * 1024 * 1024 + 4096 - $sector_size)))" | |
76 | ||
77 | ||
78 | # blkdebug must be above the format layer so it can intercept all | |
79 | # block-status events | |
80 | source_img="json:{'driver': 'blkdebug', | |
81 | 'image': { | |
82 | 'driver': '$IMGFMT', | |
83 | 'file': { | |
84 | 'driver': 'file', | |
85 | 'filename': '$TEST_IMG.orig' | |
86 | } | |
87 | }, | |
88 | 'inject-error': [" | |
89 | ||
90 | for ofs in $status_fail_offsets | |
91 | do | |
92 | source_img+="{ 'event': 'none', | |
93 | 'iotype': 'block-status', | |
94 | 'errno': 5, | |
95 | 'sector': $((ofs / sector_size)) }," | |
96 | done | |
97 | ||
98 | for ofs in $read_fail_offsets | |
99 | do | |
100 | source_img+="{ 'event': 'none', | |
101 | 'iotype': 'read', | |
102 | 'errno': 5, | |
103 | 'sector': $((ofs / sector_size)) }," | |
104 | done | |
105 | ||
106 | # Remove the trailing comma and terminate @inject-error and json:{} | |
107 | source_img="${source_img%,} ] }" | |
108 | ||
109 | ||
110 | echo | |
111 | ||
112 | ||
113 | _filter_offsets() { | |
114 | filters= | |
115 | ||
116 | index=0 | |
117 | for ofs in $1 | |
118 | do | |
119 | filters+=" -e s/$ofs/status_fail_offset_$index/" | |
120 | index=$((index + 1)) | |
121 | done | |
122 | ||
123 | index=0 | |
124 | for ofs in $2 | |
125 | do | |
126 | filters+=" -e s/$ofs/read_fail_offset_$index/" | |
127 | index=$((index + 1)) | |
128 | done | |
129 | ||
130 | sed $filters | |
131 | } | |
132 | ||
133 | # While determining the number of allocated sectors in the input | |
134 | # image, we should see one block status warning per element of | |
135 | # $status_fail_offsets. | |
136 | # | |
137 | # Then, the image is read. Since the block status is queried in | |
138 | # basically the same way, the same warnings as in the previous step | |
139 | # should reappear. Interleaved with those we should see a read | |
140 | # warning per element of $read_fail_offsets. | |
141 | # Note that $read_fail_offsets and $status_fail_offsets share an | |
142 | # element (read_fail_offset_1 == status_fail_offset_1), so | |
143 | # "status_fail_offset_1" in the output is the same as | |
144 | # "read_fail_offset_1". | |
145 | $QEMU_IMG convert --salvage "$source_img" "$TEST_IMG" 2>&1 \ | |
146 | | _filter_offsets "$status_fail_offsets" "$read_fail_offsets" | |
147 | ||
148 | echo | |
149 | ||
150 | # The offsets where the block status could not be determined should | |
151 | # have been treated as containing data and thus should be correct in | |
152 | # the output image. | |
153 | # The offsets where reading failed altogether should be 0. Make them | |
154 | # 0 in the input image, too, so we can compare both images. | |
155 | for ofs in $read_fail_offsets | |
156 | do | |
157 | $QEMU_IO -c "write -z $ofs $sector_size" "$TEST_IMG.orig" \ | |
158 | | _filter_qemu_io \ | |
159 | | _filter_offsets '' "$read_fail_offsets" | |
160 | done | |
161 | ||
162 | echo | |
163 | ||
164 | # These should be equal now. | |
165 | $QEMU_IMG compare "$TEST_IMG.orig" "$TEST_IMG" | |
166 | ||
167 | ||
168 | # success, all done | |
169 | echo "*** done" | |
170 | rm -f $seq.full | |
171 | status=0 |