root / block / qcow2-cluster.c @ dc7588c1
History | View | Annotate | Download (43.2 kB)
1 | 45aba42f | Kevin Wolf | /*
|
---|---|---|---|
2 | 45aba42f | Kevin Wolf | * Block driver for the QCOW version 2 format
|
3 | 45aba42f | Kevin Wolf | *
|
4 | 45aba42f | Kevin Wolf | * Copyright (c) 2004-2006 Fabrice Bellard
|
5 | 45aba42f | Kevin Wolf | *
|
6 | 45aba42f | Kevin Wolf | * Permission is hereby granted, free of charge, to any person obtaining a copy
|
7 | 45aba42f | Kevin Wolf | * of this software and associated documentation files (the "Software"), to deal
|
8 | 45aba42f | Kevin Wolf | * in the Software without restriction, including without limitation the rights
|
9 | 45aba42f | Kevin Wolf | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
10 | 45aba42f | Kevin Wolf | * copies of the Software, and to permit persons to whom the Software is
|
11 | 45aba42f | Kevin Wolf | * furnished to do so, subject to the following conditions:
|
12 | 45aba42f | Kevin Wolf | *
|
13 | 45aba42f | Kevin Wolf | * The above copyright notice and this permission notice shall be included in
|
14 | 45aba42f | Kevin Wolf | * all copies or substantial portions of the Software.
|
15 | 45aba42f | Kevin Wolf | *
|
16 | 45aba42f | Kevin Wolf | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
17 | 45aba42f | Kevin Wolf | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
18 | 45aba42f | Kevin Wolf | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
19 | 45aba42f | Kevin Wolf | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
20 | 45aba42f | Kevin Wolf | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
21 | 45aba42f | Kevin Wolf | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
22 | 45aba42f | Kevin Wolf | * THE SOFTWARE.
|
23 | 45aba42f | Kevin Wolf | */
|
24 | 45aba42f | Kevin Wolf | |
25 | 45aba42f | Kevin Wolf | #include <zlib.h> |
26 | 45aba42f | Kevin Wolf | |
27 | 45aba42f | Kevin Wolf | #include "qemu-common.h" |
28 | 737e150e | Paolo Bonzini | #include "block/block_int.h" |
29 | 45aba42f | Kevin Wolf | #include "block/qcow2.h" |
30 | 3cce16f4 | Kevin Wolf | #include "trace.h" |
31 | 45aba42f | Kevin Wolf | |
32 | 72893756 | Stefan Hajnoczi | int qcow2_grow_l1_table(BlockDriverState *bs, int min_size, bool exact_size) |
33 | 45aba42f | Kevin Wolf | { |
34 | 45aba42f | Kevin Wolf | BDRVQcowState *s = bs->opaque; |
35 | 45aba42f | Kevin Wolf | int new_l1_size, new_l1_size2, ret, i;
|
36 | 45aba42f | Kevin Wolf | uint64_t *new_l1_table; |
37 | 5d757b56 | Kevin Wolf | int64_t new_l1_table_offset; |
38 | 45aba42f | Kevin Wolf | uint8_t data[12];
|
39 | 45aba42f | Kevin Wolf | |
40 | 72893756 | Stefan Hajnoczi | if (min_size <= s->l1_size)
|
41 | 45aba42f | Kevin Wolf | return 0; |
42 | 72893756 | Stefan Hajnoczi | |
43 | 72893756 | Stefan Hajnoczi | if (exact_size) {
|
44 | 72893756 | Stefan Hajnoczi | new_l1_size = min_size; |
45 | 72893756 | Stefan Hajnoczi | } else {
|
46 | 72893756 | Stefan Hajnoczi | /* Bump size up to reduce the number of times we have to grow */
|
47 | 72893756 | Stefan Hajnoczi | new_l1_size = s->l1_size; |
48 | 72893756 | Stefan Hajnoczi | if (new_l1_size == 0) { |
49 | 72893756 | Stefan Hajnoczi | new_l1_size = 1;
|
50 | 72893756 | Stefan Hajnoczi | } |
51 | 72893756 | Stefan Hajnoczi | while (min_size > new_l1_size) {
|
52 | 72893756 | Stefan Hajnoczi | new_l1_size = (new_l1_size * 3 + 1) / 2; |
53 | 72893756 | Stefan Hajnoczi | } |
54 | 45aba42f | Kevin Wolf | } |
55 | 72893756 | Stefan Hajnoczi | |
56 | 45aba42f | Kevin Wolf | #ifdef DEBUG_ALLOC2
|
57 | 35ee5e39 | Frediano Ziglio | fprintf(stderr, "grow l1_table from %d to %d\n", s->l1_size, new_l1_size);
|
58 | 45aba42f | Kevin Wolf | #endif
|
59 | 45aba42f | Kevin Wolf | |
60 | 45aba42f | Kevin Wolf | new_l1_size2 = sizeof(uint64_t) * new_l1_size;
|
61 | 7267c094 | Anthony Liguori | new_l1_table = g_malloc0(align_offset(new_l1_size2, 512));
|
62 | 45aba42f | Kevin Wolf | memcpy(new_l1_table, s->l1_table, s->l1_size * sizeof(uint64_t));
|
63 | 45aba42f | Kevin Wolf | |
64 | 45aba42f | Kevin Wolf | /* write new table (align to cluster) */
|
65 | 66f82cee | Kevin Wolf | BLKDBG_EVENT(bs->file, BLKDBG_L1_GROW_ALLOC_TABLE); |
66 | ed6ccf0f | Kevin Wolf | new_l1_table_offset = qcow2_alloc_clusters(bs, new_l1_size2); |
67 | 5d757b56 | Kevin Wolf | if (new_l1_table_offset < 0) { |
68 | 7267c094 | Anthony Liguori | g_free(new_l1_table); |
69 | 5d757b56 | Kevin Wolf | return new_l1_table_offset;
|
70 | 5d757b56 | Kevin Wolf | } |
71 | 29c1a730 | Kevin Wolf | |
72 | 29c1a730 | Kevin Wolf | ret = qcow2_cache_flush(bs, s->refcount_block_cache); |
73 | 29c1a730 | Kevin Wolf | if (ret < 0) { |
74 | 80fa3341 | Kevin Wolf | goto fail;
|
75 | 29c1a730 | Kevin Wolf | } |
76 | 45aba42f | Kevin Wolf | |
77 | 66f82cee | Kevin Wolf | BLKDBG_EVENT(bs->file, BLKDBG_L1_GROW_WRITE_TABLE); |
78 | 45aba42f | Kevin Wolf | for(i = 0; i < s->l1_size; i++) |
79 | 45aba42f | Kevin Wolf | new_l1_table[i] = cpu_to_be64(new_l1_table[i]); |
80 | 8b3b7206 | Kevin Wolf | ret = bdrv_pwrite_sync(bs->file, new_l1_table_offset, new_l1_table, new_l1_size2); |
81 | 8b3b7206 | Kevin Wolf | if (ret < 0) |
82 | 45aba42f | Kevin Wolf | goto fail;
|
83 | 45aba42f | Kevin Wolf | for(i = 0; i < s->l1_size; i++) |
84 | 45aba42f | Kevin Wolf | new_l1_table[i] = be64_to_cpu(new_l1_table[i]); |
85 | 45aba42f | Kevin Wolf | |
86 | 45aba42f | Kevin Wolf | /* set new table */
|
87 | 66f82cee | Kevin Wolf | BLKDBG_EVENT(bs->file, BLKDBG_L1_GROW_ACTIVATE_TABLE); |
88 | 45aba42f | Kevin Wolf | cpu_to_be32w((uint32_t*)data, new_l1_size); |
89 | 653df36b | Aurelien Jarno | cpu_to_be64wu((uint64_t*)(data + 4), new_l1_table_offset);
|
90 | 8b3b7206 | Kevin Wolf | ret = bdrv_pwrite_sync(bs->file, offsetof(QCowHeader, l1_size), data,sizeof(data));
|
91 | 8b3b7206 | Kevin Wolf | if (ret < 0) { |
92 | 45aba42f | Kevin Wolf | goto fail;
|
93 | fb8fa77c | Kevin Wolf | } |
94 | 7267c094 | Anthony Liguori | g_free(s->l1_table); |
95 | ed6ccf0f | Kevin Wolf | qcow2_free_clusters(bs, s->l1_table_offset, s->l1_size * sizeof(uint64_t));
|
96 | 45aba42f | Kevin Wolf | s->l1_table_offset = new_l1_table_offset; |
97 | 45aba42f | Kevin Wolf | s->l1_table = new_l1_table; |
98 | 45aba42f | Kevin Wolf | s->l1_size = new_l1_size; |
99 | 45aba42f | Kevin Wolf | return 0; |
100 | 45aba42f | Kevin Wolf | fail:
|
101 | 7267c094 | Anthony Liguori | g_free(new_l1_table); |
102 | fb8fa77c | Kevin Wolf | qcow2_free_clusters(bs, new_l1_table_offset, new_l1_size2); |
103 | 8b3b7206 | Kevin Wolf | return ret;
|
104 | 45aba42f | Kevin Wolf | } |
105 | 45aba42f | Kevin Wolf | |
106 | 45aba42f | Kevin Wolf | /*
|
107 | 45aba42f | Kevin Wolf | * l2_load
|
108 | 45aba42f | Kevin Wolf | *
|
109 | 45aba42f | Kevin Wolf | * Loads a L2 table into memory. If the table is in the cache, the cache
|
110 | 45aba42f | Kevin Wolf | * is used; otherwise the L2 table is loaded from the image file.
|
111 | 45aba42f | Kevin Wolf | *
|
112 | 45aba42f | Kevin Wolf | * Returns a pointer to the L2 table on success, or NULL if the read from
|
113 | 45aba42f | Kevin Wolf | * the image file failed.
|
114 | 45aba42f | Kevin Wolf | */
|
115 | 45aba42f | Kevin Wolf | |
116 | 55c17e98 | Kevin Wolf | static int l2_load(BlockDriverState *bs, uint64_t l2_offset, |
117 | 55c17e98 | Kevin Wolf | uint64_t **l2_table) |
118 | 45aba42f | Kevin Wolf | { |
119 | 45aba42f | Kevin Wolf | BDRVQcowState *s = bs->opaque; |
120 | 55c17e98 | Kevin Wolf | int ret;
|
121 | 45aba42f | Kevin Wolf | |
122 | 29c1a730 | Kevin Wolf | ret = qcow2_cache_get(bs, s->l2_table_cache, l2_offset, (void**) l2_table);
|
123 | 45aba42f | Kevin Wolf | |
124 | 29c1a730 | Kevin Wolf | return ret;
|
125 | 45aba42f | Kevin Wolf | } |
126 | 45aba42f | Kevin Wolf | |
127 | 45aba42f | Kevin Wolf | /*
|
128 | 6583e3c7 | Kevin Wolf | * Writes one sector of the L1 table to the disk (can't update single entries
|
129 | 6583e3c7 | Kevin Wolf | * and we really don't want bdrv_pread to perform a read-modify-write)
|
130 | 6583e3c7 | Kevin Wolf | */
|
131 | 6583e3c7 | Kevin Wolf | #define L1_ENTRIES_PER_SECTOR (512 / 8) |
132 | 66f82cee | Kevin Wolf | static int write_l1_entry(BlockDriverState *bs, int l1_index) |
133 | 6583e3c7 | Kevin Wolf | { |
134 | 66f82cee | Kevin Wolf | BDRVQcowState *s = bs->opaque; |
135 | 6583e3c7 | Kevin Wolf | uint64_t buf[L1_ENTRIES_PER_SECTOR]; |
136 | 6583e3c7 | Kevin Wolf | int l1_start_index;
|
137 | f7defcb6 | Kevin Wolf | int i, ret;
|
138 | 6583e3c7 | Kevin Wolf | |
139 | 6583e3c7 | Kevin Wolf | l1_start_index = l1_index & ~(L1_ENTRIES_PER_SECTOR - 1);
|
140 | 6583e3c7 | Kevin Wolf | for (i = 0; i < L1_ENTRIES_PER_SECTOR; i++) { |
141 | 6583e3c7 | Kevin Wolf | buf[i] = cpu_to_be64(s->l1_table[l1_start_index + i]); |
142 | 6583e3c7 | Kevin Wolf | } |
143 | 6583e3c7 | Kevin Wolf | |
144 | 66f82cee | Kevin Wolf | BLKDBG_EVENT(bs->file, BLKDBG_L1_UPDATE); |
145 | 8b3b7206 | Kevin Wolf | ret = bdrv_pwrite_sync(bs->file, s->l1_table_offset + 8 * l1_start_index,
|
146 | f7defcb6 | Kevin Wolf | buf, sizeof(buf));
|
147 | f7defcb6 | Kevin Wolf | if (ret < 0) { |
148 | f7defcb6 | Kevin Wolf | return ret;
|
149 | 6583e3c7 | Kevin Wolf | } |
150 | 6583e3c7 | Kevin Wolf | |
151 | 6583e3c7 | Kevin Wolf | return 0; |
152 | 6583e3c7 | Kevin Wolf | } |
153 | 6583e3c7 | Kevin Wolf | |
154 | 6583e3c7 | Kevin Wolf | /*
|
155 | 45aba42f | Kevin Wolf | * l2_allocate
|
156 | 45aba42f | Kevin Wolf | *
|
157 | 45aba42f | Kevin Wolf | * Allocate a new l2 entry in the file. If l1_index points to an already
|
158 | 45aba42f | Kevin Wolf | * used entry in the L2 table (i.e. we are doing a copy on write for the L2
|
159 | 45aba42f | Kevin Wolf | * table) copy the contents of the old L2 table into the newly allocated one.
|
160 | 45aba42f | Kevin Wolf | * Otherwise the new table is initialized with zeros.
|
161 | 45aba42f | Kevin Wolf | *
|
162 | 45aba42f | Kevin Wolf | */
|
163 | 45aba42f | Kevin Wolf | |
164 | c46e1167 | Kevin Wolf | static int l2_allocate(BlockDriverState *bs, int l1_index, uint64_t **table) |
165 | 45aba42f | Kevin Wolf | { |
166 | 45aba42f | Kevin Wolf | BDRVQcowState *s = bs->opaque; |
167 | 6583e3c7 | Kevin Wolf | uint64_t old_l2_offset; |
168 | f4f0d391 | Kevin Wolf | uint64_t *l2_table; |
169 | f4f0d391 | Kevin Wolf | int64_t l2_offset; |
170 | c46e1167 | Kevin Wolf | int ret;
|
171 | 45aba42f | Kevin Wolf | |
172 | 45aba42f | Kevin Wolf | old_l2_offset = s->l1_table[l1_index]; |
173 | 45aba42f | Kevin Wolf | |
174 | 3cce16f4 | Kevin Wolf | trace_qcow2_l2_allocate(bs, l1_index); |
175 | 3cce16f4 | Kevin Wolf | |
176 | 45aba42f | Kevin Wolf | /* allocate a new l2 entry */
|
177 | 45aba42f | Kevin Wolf | |
178 | ed6ccf0f | Kevin Wolf | l2_offset = qcow2_alloc_clusters(bs, s->l2_size * sizeof(uint64_t));
|
179 | 5d757b56 | Kevin Wolf | if (l2_offset < 0) { |
180 | c46e1167 | Kevin Wolf | return l2_offset;
|
181 | 5d757b56 | Kevin Wolf | } |
182 | 29c1a730 | Kevin Wolf | |
183 | 29c1a730 | Kevin Wolf | ret = qcow2_cache_flush(bs, s->refcount_block_cache); |
184 | 29c1a730 | Kevin Wolf | if (ret < 0) { |
185 | 29c1a730 | Kevin Wolf | goto fail;
|
186 | 29c1a730 | Kevin Wolf | } |
187 | 45aba42f | Kevin Wolf | |
188 | 45aba42f | Kevin Wolf | /* allocate a new entry in the l2 cache */
|
189 | 45aba42f | Kevin Wolf | |
190 | 3cce16f4 | Kevin Wolf | trace_qcow2_l2_allocate_get_empty(bs, l1_index); |
191 | 29c1a730 | Kevin Wolf | ret = qcow2_cache_get_empty(bs, s->l2_table_cache, l2_offset, (void**) table);
|
192 | 29c1a730 | Kevin Wolf | if (ret < 0) { |
193 | 29c1a730 | Kevin Wolf | return ret;
|
194 | 29c1a730 | Kevin Wolf | } |
195 | 29c1a730 | Kevin Wolf | |
196 | 29c1a730 | Kevin Wolf | l2_table = *table; |
197 | 45aba42f | Kevin Wolf | |
198 | 8e37f681 | Kevin Wolf | if ((old_l2_offset & L1E_OFFSET_MASK) == 0) { |
199 | 45aba42f | Kevin Wolf | /* if there was no old l2 table, clear the new table */
|
200 | 45aba42f | Kevin Wolf | memset(l2_table, 0, s->l2_size * sizeof(uint64_t)); |
201 | 45aba42f | Kevin Wolf | } else {
|
202 | 29c1a730 | Kevin Wolf | uint64_t* old_table; |
203 | 29c1a730 | Kevin Wolf | |
204 | 45aba42f | Kevin Wolf | /* if there was an old l2 table, read it from the disk */
|
205 | 66f82cee | Kevin Wolf | BLKDBG_EVENT(bs->file, BLKDBG_L2_ALLOC_COW_READ); |
206 | 8e37f681 | Kevin Wolf | ret = qcow2_cache_get(bs, s->l2_table_cache, |
207 | 8e37f681 | Kevin Wolf | old_l2_offset & L1E_OFFSET_MASK, |
208 | 29c1a730 | Kevin Wolf | (void**) &old_table);
|
209 | 29c1a730 | Kevin Wolf | if (ret < 0) { |
210 | 29c1a730 | Kevin Wolf | goto fail;
|
211 | 29c1a730 | Kevin Wolf | } |
212 | 29c1a730 | Kevin Wolf | |
213 | 29c1a730 | Kevin Wolf | memcpy(l2_table, old_table, s->cluster_size); |
214 | 29c1a730 | Kevin Wolf | |
215 | 29c1a730 | Kevin Wolf | ret = qcow2_cache_put(bs, s->l2_table_cache, (void**) &old_table);
|
216 | c46e1167 | Kevin Wolf | if (ret < 0) { |
217 | 175e1152 | Kevin Wolf | goto fail;
|
218 | c46e1167 | Kevin Wolf | } |
219 | 45aba42f | Kevin Wolf | } |
220 | 29c1a730 | Kevin Wolf | |
221 | 45aba42f | Kevin Wolf | /* write the l2 table to the file */
|
222 | 66f82cee | Kevin Wolf | BLKDBG_EVENT(bs->file, BLKDBG_L2_ALLOC_WRITE); |
223 | 29c1a730 | Kevin Wolf | |
224 | 3cce16f4 | Kevin Wolf | trace_qcow2_l2_allocate_write_l2(bs, l1_index); |
225 | 29c1a730 | Kevin Wolf | qcow2_cache_entry_mark_dirty(s->l2_table_cache, l2_table); |
226 | 29c1a730 | Kevin Wolf | ret = qcow2_cache_flush(bs, s->l2_table_cache); |
227 | c46e1167 | Kevin Wolf | if (ret < 0) { |
228 | 175e1152 | Kevin Wolf | goto fail;
|
229 | 175e1152 | Kevin Wolf | } |
230 | 175e1152 | Kevin Wolf | |
231 | 175e1152 | Kevin Wolf | /* update the L1 entry */
|
232 | 3cce16f4 | Kevin Wolf | trace_qcow2_l2_allocate_write_l1(bs, l1_index); |
233 | 175e1152 | Kevin Wolf | s->l1_table[l1_index] = l2_offset | QCOW_OFLAG_COPIED; |
234 | 175e1152 | Kevin Wolf | ret = write_l1_entry(bs, l1_index); |
235 | 175e1152 | Kevin Wolf | if (ret < 0) { |
236 | 175e1152 | Kevin Wolf | goto fail;
|
237 | c46e1167 | Kevin Wolf | } |
238 | 45aba42f | Kevin Wolf | |
239 | c46e1167 | Kevin Wolf | *table = l2_table; |
240 | 3cce16f4 | Kevin Wolf | trace_qcow2_l2_allocate_done(bs, l1_index, 0);
|
241 | c46e1167 | Kevin Wolf | return 0; |
242 | 175e1152 | Kevin Wolf | |
243 | 175e1152 | Kevin Wolf | fail:
|
244 | 3cce16f4 | Kevin Wolf | trace_qcow2_l2_allocate_done(bs, l1_index, ret); |
245 | 29c1a730 | Kevin Wolf | qcow2_cache_put(bs, s->l2_table_cache, (void**) table);
|
246 | 68dba0bf | Kevin Wolf | s->l1_table[l1_index] = old_l2_offset; |
247 | 175e1152 | Kevin Wolf | return ret;
|
248 | 45aba42f | Kevin Wolf | } |
249 | 45aba42f | Kevin Wolf | |
250 | 2bfcc4a0 | Kevin Wolf | /*
|
251 | 2bfcc4a0 | Kevin Wolf | * Checks how many clusters in a given L2 table are contiguous in the image
|
252 | 2bfcc4a0 | Kevin Wolf | * file. As soon as one of the flags in the bitmask stop_flags changes compared
|
253 | 2bfcc4a0 | Kevin Wolf | * to the first cluster, the search is stopped and the cluster is not counted
|
254 | 2bfcc4a0 | Kevin Wolf | * as contiguous. (This allows it, for example, to stop at the first compressed
|
255 | 2bfcc4a0 | Kevin Wolf | * cluster which may require a different handling)
|
256 | 2bfcc4a0 | Kevin Wolf | */
|
257 | 45aba42f | Kevin Wolf | static int count_contiguous_clusters(uint64_t nb_clusters, int cluster_size, |
258 | 2bfcc4a0 | Kevin Wolf | uint64_t *l2_table, uint64_t start, uint64_t stop_flags) |
259 | 45aba42f | Kevin Wolf | { |
260 | 45aba42f | Kevin Wolf | int i;
|
261 | 2bfcc4a0 | Kevin Wolf | uint64_t mask = stop_flags | L2E_OFFSET_MASK; |
262 | 2bfcc4a0 | Kevin Wolf | uint64_t offset = be64_to_cpu(l2_table[0]) & mask;
|
263 | 45aba42f | Kevin Wolf | |
264 | 45aba42f | Kevin Wolf | if (!offset)
|
265 | 45aba42f | Kevin Wolf | return 0; |
266 | 45aba42f | Kevin Wolf | |
267 | 2bfcc4a0 | Kevin Wolf | for (i = start; i < start + nb_clusters; i++) {
|
268 | 2bfcc4a0 | Kevin Wolf | uint64_t l2_entry = be64_to_cpu(l2_table[i]) & mask; |
269 | 2bfcc4a0 | Kevin Wolf | if (offset + (uint64_t) i * cluster_size != l2_entry) {
|
270 | 45aba42f | Kevin Wolf | break;
|
271 | 2bfcc4a0 | Kevin Wolf | } |
272 | 2bfcc4a0 | Kevin Wolf | } |
273 | 45aba42f | Kevin Wolf | |
274 | 45aba42f | Kevin Wolf | return (i - start);
|
275 | 45aba42f | Kevin Wolf | } |
276 | 45aba42f | Kevin Wolf | |
277 | 45aba42f | Kevin Wolf | static int count_contiguous_free_clusters(uint64_t nb_clusters, uint64_t *l2_table) |
278 | 45aba42f | Kevin Wolf | { |
279 | 2bfcc4a0 | Kevin Wolf | int i;
|
280 | 2bfcc4a0 | Kevin Wolf | |
281 | 2bfcc4a0 | Kevin Wolf | for (i = 0; i < nb_clusters; i++) { |
282 | 2bfcc4a0 | Kevin Wolf | int type = qcow2_get_cluster_type(be64_to_cpu(l2_table[i]));
|
283 | 45aba42f | Kevin Wolf | |
284 | 2bfcc4a0 | Kevin Wolf | if (type != QCOW2_CLUSTER_UNALLOCATED) {
|
285 | 2bfcc4a0 | Kevin Wolf | break;
|
286 | 2bfcc4a0 | Kevin Wolf | } |
287 | 2bfcc4a0 | Kevin Wolf | } |
288 | 45aba42f | Kevin Wolf | |
289 | 45aba42f | Kevin Wolf | return i;
|
290 | 45aba42f | Kevin Wolf | } |
291 | 45aba42f | Kevin Wolf | |
292 | 45aba42f | Kevin Wolf | /* The crypt function is compatible with the linux cryptoloop
|
293 | 45aba42f | Kevin Wolf | algorithm for < 4 GB images. NOTE: out_buf == in_buf is
|
294 | 45aba42f | Kevin Wolf | supported */
|
295 | ed6ccf0f | Kevin Wolf | void qcow2_encrypt_sectors(BDRVQcowState *s, int64_t sector_num,
|
296 | ed6ccf0f | Kevin Wolf | uint8_t *out_buf, const uint8_t *in_buf,
|
297 | ed6ccf0f | Kevin Wolf | int nb_sectors, int enc, |
298 | ed6ccf0f | Kevin Wolf | const AES_KEY *key)
|
299 | 45aba42f | Kevin Wolf | { |
300 | 45aba42f | Kevin Wolf | union {
|
301 | 45aba42f | Kevin Wolf | uint64_t ll[2];
|
302 | 45aba42f | Kevin Wolf | uint8_t b[16];
|
303 | 45aba42f | Kevin Wolf | } ivec; |
304 | 45aba42f | Kevin Wolf | int i;
|
305 | 45aba42f | Kevin Wolf | |
306 | 45aba42f | Kevin Wolf | for(i = 0; i < nb_sectors; i++) { |
307 | 45aba42f | Kevin Wolf | ivec.ll[0] = cpu_to_le64(sector_num);
|
308 | 45aba42f | Kevin Wolf | ivec.ll[1] = 0; |
309 | 45aba42f | Kevin Wolf | AES_cbc_encrypt(in_buf, out_buf, 512, key,
|
310 | 45aba42f | Kevin Wolf | ivec.b, enc); |
311 | 45aba42f | Kevin Wolf | sector_num++; |
312 | 45aba42f | Kevin Wolf | in_buf += 512;
|
313 | 45aba42f | Kevin Wolf | out_buf += 512;
|
314 | 45aba42f | Kevin Wolf | } |
315 | 45aba42f | Kevin Wolf | } |
316 | 45aba42f | Kevin Wolf | |
317 | aef4acb6 | Stefan Hajnoczi | static int coroutine_fn copy_sectors(BlockDriverState *bs, |
318 | aef4acb6 | Stefan Hajnoczi | uint64_t start_sect, |
319 | aef4acb6 | Stefan Hajnoczi | uint64_t cluster_offset, |
320 | aef4acb6 | Stefan Hajnoczi | int n_start, int n_end) |
321 | 45aba42f | Kevin Wolf | { |
322 | 45aba42f | Kevin Wolf | BDRVQcowState *s = bs->opaque; |
323 | aef4acb6 | Stefan Hajnoczi | QEMUIOVector qiov; |
324 | aef4acb6 | Stefan Hajnoczi | struct iovec iov;
|
325 | 45aba42f | Kevin Wolf | int n, ret;
|
326 | 1b9f1491 | Kevin Wolf | |
327 | 1b9f1491 | Kevin Wolf | /*
|
328 | 1b9f1491 | Kevin Wolf | * If this is the last cluster and it is only partially used, we must only
|
329 | 1b9f1491 | Kevin Wolf | * copy until the end of the image, or bdrv_check_request will fail for the
|
330 | 1b9f1491 | Kevin Wolf | * bdrv_read/write calls below.
|
331 | 1b9f1491 | Kevin Wolf | */
|
332 | 1b9f1491 | Kevin Wolf | if (start_sect + n_end > bs->total_sectors) {
|
333 | 1b9f1491 | Kevin Wolf | n_end = bs->total_sectors - start_sect; |
334 | 1b9f1491 | Kevin Wolf | } |
335 | 45aba42f | Kevin Wolf | |
336 | 45aba42f | Kevin Wolf | n = n_end - n_start; |
337 | 1b9f1491 | Kevin Wolf | if (n <= 0) { |
338 | 45aba42f | Kevin Wolf | return 0; |
339 | 1b9f1491 | Kevin Wolf | } |
340 | 1b9f1491 | Kevin Wolf | |
341 | aef4acb6 | Stefan Hajnoczi | iov.iov_len = n * BDRV_SECTOR_SIZE; |
342 | aef4acb6 | Stefan Hajnoczi | iov.iov_base = qemu_blockalign(bs, iov.iov_len); |
343 | aef4acb6 | Stefan Hajnoczi | |
344 | aef4acb6 | Stefan Hajnoczi | qemu_iovec_init_external(&qiov, &iov, 1);
|
345 | 1b9f1491 | Kevin Wolf | |
346 | 66f82cee | Kevin Wolf | BLKDBG_EVENT(bs->file, BLKDBG_COW_READ); |
347 | aef4acb6 | Stefan Hajnoczi | |
348 | aef4acb6 | Stefan Hajnoczi | /* Call .bdrv_co_readv() directly instead of using the public block-layer
|
349 | aef4acb6 | Stefan Hajnoczi | * interface. This avoids double I/O throttling and request tracking,
|
350 | aef4acb6 | Stefan Hajnoczi | * which can lead to deadlock when block layer copy-on-read is enabled.
|
351 | aef4acb6 | Stefan Hajnoczi | */
|
352 | aef4acb6 | Stefan Hajnoczi | ret = bs->drv->bdrv_co_readv(bs, start_sect + n_start, n, &qiov); |
353 | 1b9f1491 | Kevin Wolf | if (ret < 0) { |
354 | 1b9f1491 | Kevin Wolf | goto out;
|
355 | 1b9f1491 | Kevin Wolf | } |
356 | 1b9f1491 | Kevin Wolf | |
357 | 45aba42f | Kevin Wolf | if (s->crypt_method) {
|
358 | ed6ccf0f | Kevin Wolf | qcow2_encrypt_sectors(s, start_sect + n_start, |
359 | aef4acb6 | Stefan Hajnoczi | iov.iov_base, iov.iov_base, n, 1,
|
360 | 45aba42f | Kevin Wolf | &s->aes_encrypt_key); |
361 | 45aba42f | Kevin Wolf | } |
362 | 1b9f1491 | Kevin Wolf | |
363 | 66f82cee | Kevin Wolf | BLKDBG_EVENT(bs->file, BLKDBG_COW_WRITE); |
364 | aef4acb6 | Stefan Hajnoczi | ret = bdrv_co_writev(bs->file, (cluster_offset >> 9) + n_start, n, &qiov);
|
365 | 1b9f1491 | Kevin Wolf | if (ret < 0) { |
366 | 1b9f1491 | Kevin Wolf | goto out;
|
367 | 1b9f1491 | Kevin Wolf | } |
368 | 1b9f1491 | Kevin Wolf | |
369 | 1b9f1491 | Kevin Wolf | ret = 0;
|
370 | 1b9f1491 | Kevin Wolf | out:
|
371 | aef4acb6 | Stefan Hajnoczi | qemu_vfree(iov.iov_base); |
372 | 1b9f1491 | Kevin Wolf | return ret;
|
373 | 45aba42f | Kevin Wolf | } |
374 | 45aba42f | Kevin Wolf | |
375 | 45aba42f | Kevin Wolf | |
376 | 45aba42f | Kevin Wolf | /*
|
377 | 45aba42f | Kevin Wolf | * get_cluster_offset
|
378 | 45aba42f | Kevin Wolf | *
|
379 | 1c46efaa | Kevin Wolf | * For a given offset of the disk image, find the cluster offset in
|
380 | 1c46efaa | Kevin Wolf | * qcow2 file. The offset is stored in *cluster_offset.
|
381 | 45aba42f | Kevin Wolf | *
|
382 | d57237f2 | Devin Nakamura | * on entry, *num is the number of contiguous sectors we'd like to
|
383 | 45aba42f | Kevin Wolf | * access following offset.
|
384 | 45aba42f | Kevin Wolf | *
|
385 | d57237f2 | Devin Nakamura | * on exit, *num is the number of contiguous sectors we can read.
|
386 | 45aba42f | Kevin Wolf | *
|
387 | 68d000a3 | Kevin Wolf | * Returns the cluster type (QCOW2_CLUSTER_*) on success, -errno in error
|
388 | 68d000a3 | Kevin Wolf | * cases.
|
389 | 45aba42f | Kevin Wolf | */
|
390 | 1c46efaa | Kevin Wolf | int qcow2_get_cluster_offset(BlockDriverState *bs, uint64_t offset,
|
391 | 1c46efaa | Kevin Wolf | int *num, uint64_t *cluster_offset)
|
392 | 45aba42f | Kevin Wolf | { |
393 | 45aba42f | Kevin Wolf | BDRVQcowState *s = bs->opaque; |
394 | 80ee15a6 | Kevin Wolf | unsigned int l1_index, l2_index; |
395 | 1c46efaa | Kevin Wolf | uint64_t l2_offset, *l2_table; |
396 | 45aba42f | Kevin Wolf | int l1_bits, c;
|
397 | 80ee15a6 | Kevin Wolf | unsigned int index_in_cluster, nb_clusters; |
398 | 80ee15a6 | Kevin Wolf | uint64_t nb_available, nb_needed; |
399 | 55c17e98 | Kevin Wolf | int ret;
|
400 | 45aba42f | Kevin Wolf | |
401 | 45aba42f | Kevin Wolf | index_in_cluster = (offset >> 9) & (s->cluster_sectors - 1); |
402 | 45aba42f | Kevin Wolf | nb_needed = *num + index_in_cluster; |
403 | 45aba42f | Kevin Wolf | |
404 | 45aba42f | Kevin Wolf | l1_bits = s->l2_bits + s->cluster_bits; |
405 | 45aba42f | Kevin Wolf | |
406 | 45aba42f | Kevin Wolf | /* compute how many bytes there are between the offset and
|
407 | 45aba42f | Kevin Wolf | * the end of the l1 entry
|
408 | 45aba42f | Kevin Wolf | */
|
409 | 45aba42f | Kevin Wolf | |
410 | 80ee15a6 | Kevin Wolf | nb_available = (1ULL << l1_bits) - (offset & ((1ULL << l1_bits) - 1)); |
411 | 45aba42f | Kevin Wolf | |
412 | 45aba42f | Kevin Wolf | /* compute the number of available sectors */
|
413 | 45aba42f | Kevin Wolf | |
414 | 45aba42f | Kevin Wolf | nb_available = (nb_available >> 9) + index_in_cluster;
|
415 | 45aba42f | Kevin Wolf | |
416 | 45aba42f | Kevin Wolf | if (nb_needed > nb_available) {
|
417 | 45aba42f | Kevin Wolf | nb_needed = nb_available; |
418 | 45aba42f | Kevin Wolf | } |
419 | 45aba42f | Kevin Wolf | |
420 | 1c46efaa | Kevin Wolf | *cluster_offset = 0;
|
421 | 45aba42f | Kevin Wolf | |
422 | 45aba42f | Kevin Wolf | /* seek the the l2 offset in the l1 table */
|
423 | 45aba42f | Kevin Wolf | |
424 | 45aba42f | Kevin Wolf | l1_index = offset >> l1_bits; |
425 | 68d000a3 | Kevin Wolf | if (l1_index >= s->l1_size) {
|
426 | 68d000a3 | Kevin Wolf | ret = QCOW2_CLUSTER_UNALLOCATED; |
427 | 45aba42f | Kevin Wolf | goto out;
|
428 | 68d000a3 | Kevin Wolf | } |
429 | 45aba42f | Kevin Wolf | |
430 | 68d000a3 | Kevin Wolf | l2_offset = s->l1_table[l1_index] & L1E_OFFSET_MASK; |
431 | 68d000a3 | Kevin Wolf | if (!l2_offset) {
|
432 | 68d000a3 | Kevin Wolf | ret = QCOW2_CLUSTER_UNALLOCATED; |
433 | 45aba42f | Kevin Wolf | goto out;
|
434 | 68d000a3 | Kevin Wolf | } |
435 | 45aba42f | Kevin Wolf | |
436 | 45aba42f | Kevin Wolf | /* load the l2 table in memory */
|
437 | 45aba42f | Kevin Wolf | |
438 | 55c17e98 | Kevin Wolf | ret = l2_load(bs, l2_offset, &l2_table); |
439 | 55c17e98 | Kevin Wolf | if (ret < 0) { |
440 | 55c17e98 | Kevin Wolf | return ret;
|
441 | 1c46efaa | Kevin Wolf | } |
442 | 45aba42f | Kevin Wolf | |
443 | 45aba42f | Kevin Wolf | /* find the cluster offset for the given disk offset */
|
444 | 45aba42f | Kevin Wolf | |
445 | 45aba42f | Kevin Wolf | l2_index = (offset >> s->cluster_bits) & (s->l2_size - 1);
|
446 | 1c46efaa | Kevin Wolf | *cluster_offset = be64_to_cpu(l2_table[l2_index]); |
447 | 45aba42f | Kevin Wolf | nb_clusters = size_to_clusters(s, nb_needed << 9);
|
448 | 45aba42f | Kevin Wolf | |
449 | 68d000a3 | Kevin Wolf | ret = qcow2_get_cluster_type(*cluster_offset); |
450 | 68d000a3 | Kevin Wolf | switch (ret) {
|
451 | 68d000a3 | Kevin Wolf | case QCOW2_CLUSTER_COMPRESSED:
|
452 | 68d000a3 | Kevin Wolf | /* Compressed clusters can only be processed one by one */
|
453 | 68d000a3 | Kevin Wolf | c = 1;
|
454 | 68d000a3 | Kevin Wolf | *cluster_offset &= L2E_COMPRESSED_OFFSET_SIZE_MASK; |
455 | 68d000a3 | Kevin Wolf | break;
|
456 | 6377af48 | Kevin Wolf | case QCOW2_CLUSTER_ZERO:
|
457 | 381b487d | Paolo Bonzini | if (s->qcow_version < 3) { |
458 | 381b487d | Paolo Bonzini | return -EIO;
|
459 | 381b487d | Paolo Bonzini | } |
460 | 6377af48 | Kevin Wolf | c = count_contiguous_clusters(nb_clusters, s->cluster_size, |
461 | 6377af48 | Kevin Wolf | &l2_table[l2_index], 0,
|
462 | 6377af48 | Kevin Wolf | QCOW_OFLAG_COMPRESSED | QCOW_OFLAG_ZERO); |
463 | 6377af48 | Kevin Wolf | *cluster_offset = 0;
|
464 | 6377af48 | Kevin Wolf | break;
|
465 | 68d000a3 | Kevin Wolf | case QCOW2_CLUSTER_UNALLOCATED:
|
466 | 45aba42f | Kevin Wolf | /* how many empty clusters ? */
|
467 | 45aba42f | Kevin Wolf | c = count_contiguous_free_clusters(nb_clusters, &l2_table[l2_index]); |
468 | 68d000a3 | Kevin Wolf | *cluster_offset = 0;
|
469 | 68d000a3 | Kevin Wolf | break;
|
470 | 68d000a3 | Kevin Wolf | case QCOW2_CLUSTER_NORMAL:
|
471 | 45aba42f | Kevin Wolf | /* how many allocated clusters ? */
|
472 | 45aba42f | Kevin Wolf | c = count_contiguous_clusters(nb_clusters, s->cluster_size, |
473 | 6377af48 | Kevin Wolf | &l2_table[l2_index], 0,
|
474 | 6377af48 | Kevin Wolf | QCOW_OFLAG_COMPRESSED | QCOW_OFLAG_ZERO); |
475 | 68d000a3 | Kevin Wolf | *cluster_offset &= L2E_OFFSET_MASK; |
476 | 68d000a3 | Kevin Wolf | break;
|
477 | 1417d7e4 | Kevin Wolf | default:
|
478 | 1417d7e4 | Kevin Wolf | abort(); |
479 | 45aba42f | Kevin Wolf | } |
480 | 45aba42f | Kevin Wolf | |
481 | 29c1a730 | Kevin Wolf | qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table);
|
482 | 29c1a730 | Kevin Wolf | |
483 | 68d000a3 | Kevin Wolf | nb_available = (c * s->cluster_sectors); |
484 | 68d000a3 | Kevin Wolf | |
485 | 45aba42f | Kevin Wolf | out:
|
486 | 45aba42f | Kevin Wolf | if (nb_available > nb_needed)
|
487 | 45aba42f | Kevin Wolf | nb_available = nb_needed; |
488 | 45aba42f | Kevin Wolf | |
489 | 45aba42f | Kevin Wolf | *num = nb_available - index_in_cluster; |
490 | 45aba42f | Kevin Wolf | |
491 | 68d000a3 | Kevin Wolf | return ret;
|
492 | 45aba42f | Kevin Wolf | } |
493 | 45aba42f | Kevin Wolf | |
494 | 45aba42f | Kevin Wolf | /*
|
495 | 45aba42f | Kevin Wolf | * get_cluster_table
|
496 | 45aba42f | Kevin Wolf | *
|
497 | 45aba42f | Kevin Wolf | * for a given disk offset, load (and allocate if needed)
|
498 | 45aba42f | Kevin Wolf | * the l2 table.
|
499 | 45aba42f | Kevin Wolf | *
|
500 | 45aba42f | Kevin Wolf | * the l2 table offset in the qcow2 file and the cluster index
|
501 | 45aba42f | Kevin Wolf | * in the l2 table are given to the caller.
|
502 | 45aba42f | Kevin Wolf | *
|
503 | 1e3e8f1a | Kevin Wolf | * Returns 0 on success, -errno in failure case
|
504 | 45aba42f | Kevin Wolf | */
|
505 | 45aba42f | Kevin Wolf | static int get_cluster_table(BlockDriverState *bs, uint64_t offset, |
506 | 45aba42f | Kevin Wolf | uint64_t **new_l2_table, |
507 | 45aba42f | Kevin Wolf | int *new_l2_index)
|
508 | 45aba42f | Kevin Wolf | { |
509 | 45aba42f | Kevin Wolf | BDRVQcowState *s = bs->opaque; |
510 | 80ee15a6 | Kevin Wolf | unsigned int l1_index, l2_index; |
511 | c46e1167 | Kevin Wolf | uint64_t l2_offset; |
512 | c46e1167 | Kevin Wolf | uint64_t *l2_table = NULL;
|
513 | 80ee15a6 | Kevin Wolf | int ret;
|
514 | 45aba42f | Kevin Wolf | |
515 | 45aba42f | Kevin Wolf | /* seek the the l2 offset in the l1 table */
|
516 | 45aba42f | Kevin Wolf | |
517 | 45aba42f | Kevin Wolf | l1_index = offset >> (s->l2_bits + s->cluster_bits); |
518 | 45aba42f | Kevin Wolf | if (l1_index >= s->l1_size) {
|
519 | 72893756 | Stefan Hajnoczi | ret = qcow2_grow_l1_table(bs, l1_index + 1, false); |
520 | 1e3e8f1a | Kevin Wolf | if (ret < 0) { |
521 | 1e3e8f1a | Kevin Wolf | return ret;
|
522 | 1e3e8f1a | Kevin Wolf | } |
523 | 45aba42f | Kevin Wolf | } |
524 | 8e37f681 | Kevin Wolf | |
525 | 8e37f681 | Kevin Wolf | l2_offset = s->l1_table[l1_index] & L1E_OFFSET_MASK; |
526 | 45aba42f | Kevin Wolf | |
527 | 45aba42f | Kevin Wolf | /* seek the l2 table of the given l2 offset */
|
528 | 45aba42f | Kevin Wolf | |
529 | 8e37f681 | Kevin Wolf | if (s->l1_table[l1_index] & QCOW_OFLAG_COPIED) {
|
530 | 45aba42f | Kevin Wolf | /* load the l2 table in memory */
|
531 | 55c17e98 | Kevin Wolf | ret = l2_load(bs, l2_offset, &l2_table); |
532 | 55c17e98 | Kevin Wolf | if (ret < 0) { |
533 | 55c17e98 | Kevin Wolf | return ret;
|
534 | 1e3e8f1a | Kevin Wolf | } |
535 | 45aba42f | Kevin Wolf | } else {
|
536 | 16fde5f2 | Kevin Wolf | /* First allocate a new L2 table (and do COW if needed) */
|
537 | c46e1167 | Kevin Wolf | ret = l2_allocate(bs, l1_index, &l2_table); |
538 | c46e1167 | Kevin Wolf | if (ret < 0) { |
539 | c46e1167 | Kevin Wolf | return ret;
|
540 | 1e3e8f1a | Kevin Wolf | } |
541 | 16fde5f2 | Kevin Wolf | |
542 | 16fde5f2 | Kevin Wolf | /* Then decrease the refcount of the old table */
|
543 | 16fde5f2 | Kevin Wolf | if (l2_offset) {
|
544 | 16fde5f2 | Kevin Wolf | qcow2_free_clusters(bs, l2_offset, s->l2_size * sizeof(uint64_t));
|
545 | 16fde5f2 | Kevin Wolf | } |
546 | 45aba42f | Kevin Wolf | } |
547 | 45aba42f | Kevin Wolf | |
548 | 45aba42f | Kevin Wolf | /* find the cluster offset for the given disk offset */
|
549 | 45aba42f | Kevin Wolf | |
550 | 45aba42f | Kevin Wolf | l2_index = (offset >> s->cluster_bits) & (s->l2_size - 1);
|
551 | 45aba42f | Kevin Wolf | |
552 | 45aba42f | Kevin Wolf | *new_l2_table = l2_table; |
553 | 45aba42f | Kevin Wolf | *new_l2_index = l2_index; |
554 | 45aba42f | Kevin Wolf | |
555 | 1e3e8f1a | Kevin Wolf | return 0; |
556 | 45aba42f | Kevin Wolf | } |
557 | 45aba42f | Kevin Wolf | |
558 | 45aba42f | Kevin Wolf | /*
|
559 | 45aba42f | Kevin Wolf | * alloc_compressed_cluster_offset
|
560 | 45aba42f | Kevin Wolf | *
|
561 | 45aba42f | Kevin Wolf | * For a given offset of the disk image, return cluster offset in
|
562 | 45aba42f | Kevin Wolf | * qcow2 file.
|
563 | 45aba42f | Kevin Wolf | *
|
564 | 45aba42f | Kevin Wolf | * If the offset is not found, allocate a new compressed cluster.
|
565 | 45aba42f | Kevin Wolf | *
|
566 | 45aba42f | Kevin Wolf | * Return the cluster offset if successful,
|
567 | 45aba42f | Kevin Wolf | * Return 0, otherwise.
|
568 | 45aba42f | Kevin Wolf | *
|
569 | 45aba42f | Kevin Wolf | */
|
570 | 45aba42f | Kevin Wolf | |
571 | ed6ccf0f | Kevin Wolf | uint64_t qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs, |
572 | ed6ccf0f | Kevin Wolf | uint64_t offset, |
573 | ed6ccf0f | Kevin Wolf | int compressed_size)
|
574 | 45aba42f | Kevin Wolf | { |
575 | 45aba42f | Kevin Wolf | BDRVQcowState *s = bs->opaque; |
576 | 45aba42f | Kevin Wolf | int l2_index, ret;
|
577 | 3948d1d4 | Kevin Wolf | uint64_t *l2_table; |
578 | f4f0d391 | Kevin Wolf | int64_t cluster_offset; |
579 | 45aba42f | Kevin Wolf | int nb_csectors;
|
580 | 45aba42f | Kevin Wolf | |
581 | 3948d1d4 | Kevin Wolf | ret = get_cluster_table(bs, offset, &l2_table, &l2_index); |
582 | 1e3e8f1a | Kevin Wolf | if (ret < 0) { |
583 | 45aba42f | Kevin Wolf | return 0; |
584 | 1e3e8f1a | Kevin Wolf | } |
585 | 45aba42f | Kevin Wolf | |
586 | b0b6862e | Kevin Wolf | /* Compression can't overwrite anything. Fail if the cluster was already
|
587 | b0b6862e | Kevin Wolf | * allocated. */
|
588 | 45aba42f | Kevin Wolf | cluster_offset = be64_to_cpu(l2_table[l2_index]); |
589 | b0b6862e | Kevin Wolf | if (cluster_offset & L2E_OFFSET_MASK) {
|
590 | 8f1efd00 | Kevin Wolf | qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table);
|
591 | 8f1efd00 | Kevin Wolf | return 0; |
592 | 8f1efd00 | Kevin Wolf | } |
593 | 45aba42f | Kevin Wolf | |
594 | ed6ccf0f | Kevin Wolf | cluster_offset = qcow2_alloc_bytes(bs, compressed_size); |
595 | 5d757b56 | Kevin Wolf | if (cluster_offset < 0) { |
596 | 29c1a730 | Kevin Wolf | qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table);
|
597 | 5d757b56 | Kevin Wolf | return 0; |
598 | 5d757b56 | Kevin Wolf | } |
599 | 5d757b56 | Kevin Wolf | |
600 | 45aba42f | Kevin Wolf | nb_csectors = ((cluster_offset + compressed_size - 1) >> 9) - |
601 | 45aba42f | Kevin Wolf | (cluster_offset >> 9);
|
602 | 45aba42f | Kevin Wolf | |
603 | 45aba42f | Kevin Wolf | cluster_offset |= QCOW_OFLAG_COMPRESSED | |
604 | 45aba42f | Kevin Wolf | ((uint64_t)nb_csectors << s->csize_shift); |
605 | 45aba42f | Kevin Wolf | |
606 | 45aba42f | Kevin Wolf | /* update L2 table */
|
607 | 45aba42f | Kevin Wolf | |
608 | 45aba42f | Kevin Wolf | /* compressed clusters never have the copied flag */
|
609 | 45aba42f | Kevin Wolf | |
610 | 66f82cee | Kevin Wolf | BLKDBG_EVENT(bs->file, BLKDBG_L2_UPDATE_COMPRESSED); |
611 | 29c1a730 | Kevin Wolf | qcow2_cache_entry_mark_dirty(s->l2_table_cache, l2_table); |
612 | 45aba42f | Kevin Wolf | l2_table[l2_index] = cpu_to_be64(cluster_offset); |
613 | 29c1a730 | Kevin Wolf | ret = qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table);
|
614 | 79a31189 | Kevin Wolf | if (ret < 0) { |
615 | 29c1a730 | Kevin Wolf | return 0; |
616 | 4c1612d9 | Kevin Wolf | } |
617 | 4c1612d9 | Kevin Wolf | |
618 | 29c1a730 | Kevin Wolf | return cluster_offset;
|
619 | 4c1612d9 | Kevin Wolf | } |
620 | 4c1612d9 | Kevin Wolf | |
621 | 593fb83c | Kevin Wolf | static int perform_cow(BlockDriverState *bs, QCowL2Meta *m, Qcow2COWRegion *r) |
622 | 593fb83c | Kevin Wolf | { |
623 | 593fb83c | Kevin Wolf | BDRVQcowState *s = bs->opaque; |
624 | 593fb83c | Kevin Wolf | int ret;
|
625 | 593fb83c | Kevin Wolf | |
626 | 593fb83c | Kevin Wolf | if (r->nb_sectors == 0) { |
627 | 593fb83c | Kevin Wolf | return 0; |
628 | 593fb83c | Kevin Wolf | } |
629 | 593fb83c | Kevin Wolf | |
630 | 593fb83c | Kevin Wolf | qemu_co_mutex_unlock(&s->lock); |
631 | 593fb83c | Kevin Wolf | ret = copy_sectors(bs, m->offset / BDRV_SECTOR_SIZE, m->alloc_offset, |
632 | 593fb83c | Kevin Wolf | r->offset / BDRV_SECTOR_SIZE, |
633 | 593fb83c | Kevin Wolf | r->offset / BDRV_SECTOR_SIZE + r->nb_sectors); |
634 | 593fb83c | Kevin Wolf | qemu_co_mutex_lock(&s->lock); |
635 | 593fb83c | Kevin Wolf | |
636 | 593fb83c | Kevin Wolf | if (ret < 0) { |
637 | 593fb83c | Kevin Wolf | return ret;
|
638 | 593fb83c | Kevin Wolf | } |
639 | 593fb83c | Kevin Wolf | |
640 | 593fb83c | Kevin Wolf | /*
|
641 | 593fb83c | Kevin Wolf | * Before we update the L2 table to actually point to the new cluster, we
|
642 | 593fb83c | Kevin Wolf | * need to be sure that the refcounts have been increased and COW was
|
643 | 593fb83c | Kevin Wolf | * handled.
|
644 | 593fb83c | Kevin Wolf | */
|
645 | 593fb83c | Kevin Wolf | qcow2_cache_depends_on_flush(s->l2_table_cache); |
646 | 593fb83c | Kevin Wolf | |
647 | 593fb83c | Kevin Wolf | return 0; |
648 | 593fb83c | Kevin Wolf | } |
649 | 593fb83c | Kevin Wolf | |
650 | 148da7ea | Kevin Wolf | int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m)
|
651 | 45aba42f | Kevin Wolf | { |
652 | 45aba42f | Kevin Wolf | BDRVQcowState *s = bs->opaque; |
653 | 45aba42f | Kevin Wolf | int i, j = 0, l2_index, ret; |
654 | 593fb83c | Kevin Wolf | uint64_t *old_cluster, *l2_table; |
655 | 250196f1 | Kevin Wolf | uint64_t cluster_offset = m->alloc_offset; |
656 | 45aba42f | Kevin Wolf | |
657 | 3cce16f4 | Kevin Wolf | trace_qcow2_cluster_link_l2(qemu_coroutine_self(), m->nb_clusters); |
658 | f50f88b9 | Kevin Wolf | assert(m->nb_clusters > 0);
|
659 | 45aba42f | Kevin Wolf | |
660 | 7267c094 | Anthony Liguori | old_cluster = g_malloc(m->nb_clusters * sizeof(uint64_t));
|
661 | 45aba42f | Kevin Wolf | |
662 | 45aba42f | Kevin Wolf | /* copy content of unmodified sectors */
|
663 | 593fb83c | Kevin Wolf | ret = perform_cow(bs, m, &m->cow_start); |
664 | 593fb83c | Kevin Wolf | if (ret < 0) { |
665 | 593fb83c | Kevin Wolf | goto err;
|
666 | 45aba42f | Kevin Wolf | } |
667 | 45aba42f | Kevin Wolf | |
668 | 593fb83c | Kevin Wolf | ret = perform_cow(bs, m, &m->cow_end); |
669 | 593fb83c | Kevin Wolf | if (ret < 0) { |
670 | 593fb83c | Kevin Wolf | goto err;
|
671 | 29c1a730 | Kevin Wolf | } |
672 | 29c1a730 | Kevin Wolf | |
673 | 593fb83c | Kevin Wolf | /* Update L2 table. */
|
674 | 74c4510a | Kevin Wolf | if (s->use_lazy_refcounts) {
|
675 | 280d3735 | Kevin Wolf | qcow2_mark_dirty(bs); |
676 | 280d3735 | Kevin Wolf | } |
677 | bfe8043e | Stefan Hajnoczi | if (qcow2_need_accurate_refcounts(s)) {
|
678 | bfe8043e | Stefan Hajnoczi | qcow2_cache_set_dependency(bs, s->l2_table_cache, |
679 | bfe8043e | Stefan Hajnoczi | s->refcount_block_cache); |
680 | bfe8043e | Stefan Hajnoczi | } |
681 | 280d3735 | Kevin Wolf | |
682 | 3948d1d4 | Kevin Wolf | ret = get_cluster_table(bs, m->offset, &l2_table, &l2_index); |
683 | 1e3e8f1a | Kevin Wolf | if (ret < 0) { |
684 | 45aba42f | Kevin Wolf | goto err;
|
685 | 1e3e8f1a | Kevin Wolf | } |
686 | 29c1a730 | Kevin Wolf | qcow2_cache_entry_mark_dirty(s->l2_table_cache, l2_table); |
687 | 45aba42f | Kevin Wolf | |
688 | 45aba42f | Kevin Wolf | for (i = 0; i < m->nb_clusters; i++) { |
689 | 45aba42f | Kevin Wolf | /* if two concurrent writes happen to the same unallocated cluster
|
690 | 45aba42f | Kevin Wolf | * each write allocates separate cluster and writes data concurrently.
|
691 | 45aba42f | Kevin Wolf | * The first one to complete updates l2 table with pointer to its
|
692 | 45aba42f | Kevin Wolf | * cluster the second one has to do RMW (which is done above by
|
693 | 45aba42f | Kevin Wolf | * copy_sectors()), update l2 table with its cluster pointer and free
|
694 | 45aba42f | Kevin Wolf | * old cluster. This is what this loop does */
|
695 | 45aba42f | Kevin Wolf | if(l2_table[l2_index + i] != 0) |
696 | 45aba42f | Kevin Wolf | old_cluster[j++] = l2_table[l2_index + i]; |
697 | 45aba42f | Kevin Wolf | |
698 | 45aba42f | Kevin Wolf | l2_table[l2_index + i] = cpu_to_be64((cluster_offset + |
699 | 45aba42f | Kevin Wolf | (i << s->cluster_bits)) | QCOW_OFLAG_COPIED); |
700 | 45aba42f | Kevin Wolf | } |
701 | 45aba42f | Kevin Wolf | |
702 | 9f8e668e | Kevin Wolf | |
703 | 29c1a730 | Kevin Wolf | ret = qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table);
|
704 | c835d00f | Kevin Wolf | if (ret < 0) { |
705 | 45aba42f | Kevin Wolf | goto err;
|
706 | 4c1612d9 | Kevin Wolf | } |
707 | 45aba42f | Kevin Wolf | |
708 | 7ec5e6a4 | Kevin Wolf | /*
|
709 | 7ec5e6a4 | Kevin Wolf | * If this was a COW, we need to decrease the refcount of the old cluster.
|
710 | 7ec5e6a4 | Kevin Wolf | * Also flush bs->file to get the right order for L2 and refcount update.
|
711 | 7ec5e6a4 | Kevin Wolf | */
|
712 | 7ec5e6a4 | Kevin Wolf | if (j != 0) { |
713 | 7ec5e6a4 | Kevin Wolf | for (i = 0; i < j; i++) { |
714 | 8e37f681 | Kevin Wolf | qcow2_free_any_clusters(bs, be64_to_cpu(old_cluster[i]), 1);
|
715 | 7ec5e6a4 | Kevin Wolf | } |
716 | 7ec5e6a4 | Kevin Wolf | } |
717 | 45aba42f | Kevin Wolf | |
718 | 45aba42f | Kevin Wolf | ret = 0;
|
719 | 45aba42f | Kevin Wolf | err:
|
720 | 7267c094 | Anthony Liguori | g_free(old_cluster); |
721 | 45aba42f | Kevin Wolf | return ret;
|
722 | 45aba42f | Kevin Wolf | } |
723 | 45aba42f | Kevin Wolf | |
724 | 45aba42f | Kevin Wolf | /*
|
725 | bf319ece | Kevin Wolf | * Returns the number of contiguous clusters that can be used for an allocating
|
726 | bf319ece | Kevin Wolf | * write, but require COW to be performed (this includes yet unallocated space,
|
727 | bf319ece | Kevin Wolf | * which must copy from the backing file)
|
728 | bf319ece | Kevin Wolf | */
|
729 | bf319ece | Kevin Wolf | static int count_cow_clusters(BDRVQcowState *s, int nb_clusters, |
730 | bf319ece | Kevin Wolf | uint64_t *l2_table, int l2_index)
|
731 | bf319ece | Kevin Wolf | { |
732 | 143550a8 | Kevin Wolf | int i;
|
733 | bf319ece | Kevin Wolf | |
734 | 143550a8 | Kevin Wolf | for (i = 0; i < nb_clusters; i++) { |
735 | 143550a8 | Kevin Wolf | uint64_t l2_entry = be64_to_cpu(l2_table[l2_index + i]); |
736 | 143550a8 | Kevin Wolf | int cluster_type = qcow2_get_cluster_type(l2_entry);
|
737 | 143550a8 | Kevin Wolf | |
738 | 143550a8 | Kevin Wolf | switch(cluster_type) {
|
739 | 143550a8 | Kevin Wolf | case QCOW2_CLUSTER_NORMAL:
|
740 | 143550a8 | Kevin Wolf | if (l2_entry & QCOW_OFLAG_COPIED) {
|
741 | 143550a8 | Kevin Wolf | goto out;
|
742 | 143550a8 | Kevin Wolf | } |
743 | bf319ece | Kevin Wolf | break;
|
744 | 143550a8 | Kevin Wolf | case QCOW2_CLUSTER_UNALLOCATED:
|
745 | 143550a8 | Kevin Wolf | case QCOW2_CLUSTER_COMPRESSED:
|
746 | 6377af48 | Kevin Wolf | case QCOW2_CLUSTER_ZERO:
|
747 | bf319ece | Kevin Wolf | break;
|
748 | 143550a8 | Kevin Wolf | default:
|
749 | 143550a8 | Kevin Wolf | abort(); |
750 | 143550a8 | Kevin Wolf | } |
751 | bf319ece | Kevin Wolf | } |
752 | bf319ece | Kevin Wolf | |
753 | 143550a8 | Kevin Wolf | out:
|
754 | bf319ece | Kevin Wolf | assert(i <= nb_clusters); |
755 | bf319ece | Kevin Wolf | return i;
|
756 | bf319ece | Kevin Wolf | } |
757 | bf319ece | Kevin Wolf | |
758 | bf319ece | Kevin Wolf | /*
|
759 | 226c3c26 | Kevin Wolf | * Check if there already is an AIO write request in flight which allocates
|
760 | 226c3c26 | Kevin Wolf | * the same cluster. In this case we need to wait until the previous
|
761 | 226c3c26 | Kevin Wolf | * request has completed and updated the L2 table accordingly.
|
762 | 65eb2e35 | Kevin Wolf | *
|
763 | 65eb2e35 | Kevin Wolf | * Returns:
|
764 | 65eb2e35 | Kevin Wolf | * 0 if there was no dependency. *cur_bytes indicates the number of
|
765 | 65eb2e35 | Kevin Wolf | * bytes from guest_offset that can be read before the next
|
766 | 65eb2e35 | Kevin Wolf | * dependency must be processed (or the request is complete)
|
767 | 65eb2e35 | Kevin Wolf | *
|
768 | 65eb2e35 | Kevin Wolf | * -EAGAIN if we had to wait for another request, previously gathered
|
769 | 65eb2e35 | Kevin Wolf | * information on cluster allocation may be invalid now. The caller
|
770 | 65eb2e35 | Kevin Wolf | * must start over anyway, so consider *cur_bytes undefined.
|
771 | 250196f1 | Kevin Wolf | */
|
772 | 226c3c26 | Kevin Wolf | static int handle_dependencies(BlockDriverState *bs, uint64_t guest_offset, |
773 | ecdd5333 | Kevin Wolf | uint64_t *cur_bytes, QCowL2Meta **m) |
774 | 250196f1 | Kevin Wolf | { |
775 | 250196f1 | Kevin Wolf | BDRVQcowState *s = bs->opaque; |
776 | 250196f1 | Kevin Wolf | QCowL2Meta *old_alloc; |
777 | 65eb2e35 | Kevin Wolf | uint64_t bytes = *cur_bytes; |
778 | 250196f1 | Kevin Wolf | |
779 | 250196f1 | Kevin Wolf | QLIST_FOREACH(old_alloc, &s->cluster_allocs, next_in_flight) { |
780 | 250196f1 | Kevin Wolf | |
781 | 65eb2e35 | Kevin Wolf | uint64_t start = guest_offset; |
782 | 65eb2e35 | Kevin Wolf | uint64_t end = start + bytes; |
783 | 65eb2e35 | Kevin Wolf | uint64_t old_start = l2meta_cow_start(old_alloc); |
784 | 65eb2e35 | Kevin Wolf | uint64_t old_end = l2meta_cow_end(old_alloc); |
785 | 250196f1 | Kevin Wolf | |
786 | d9d74f41 | Kevin Wolf | if (end <= old_start || start >= old_end) {
|
787 | 250196f1 | Kevin Wolf | /* No intersection */
|
788 | 250196f1 | Kevin Wolf | } else {
|
789 | 250196f1 | Kevin Wolf | if (start < old_start) {
|
790 | 250196f1 | Kevin Wolf | /* Stop at the start of a running allocation */
|
791 | 65eb2e35 | Kevin Wolf | bytes = old_start - start; |
792 | 250196f1 | Kevin Wolf | } else {
|
793 | 65eb2e35 | Kevin Wolf | bytes = 0;
|
794 | 250196f1 | Kevin Wolf | } |
795 | 250196f1 | Kevin Wolf | |
796 | ecdd5333 | Kevin Wolf | /* Stop if already an l2meta exists. After yielding, it wouldn't
|
797 | ecdd5333 | Kevin Wolf | * be valid any more, so we'd have to clean up the old L2Metas
|
798 | ecdd5333 | Kevin Wolf | * and deal with requests depending on them before starting to
|
799 | ecdd5333 | Kevin Wolf | * gather new ones. Not worth the trouble. */
|
800 | ecdd5333 | Kevin Wolf | if (bytes == 0 && *m) { |
801 | ecdd5333 | Kevin Wolf | *cur_bytes = 0;
|
802 | ecdd5333 | Kevin Wolf | return 0; |
803 | ecdd5333 | Kevin Wolf | } |
804 | ecdd5333 | Kevin Wolf | |
805 | 65eb2e35 | Kevin Wolf | if (bytes == 0) { |
806 | 250196f1 | Kevin Wolf | /* Wait for the dependency to complete. We need to recheck
|
807 | 250196f1 | Kevin Wolf | * the free/allocated clusters when we continue. */
|
808 | 250196f1 | Kevin Wolf | qemu_co_mutex_unlock(&s->lock); |
809 | 250196f1 | Kevin Wolf | qemu_co_queue_wait(&old_alloc->dependent_requests); |
810 | 250196f1 | Kevin Wolf | qemu_co_mutex_lock(&s->lock); |
811 | 250196f1 | Kevin Wolf | return -EAGAIN;
|
812 | 250196f1 | Kevin Wolf | } |
813 | 250196f1 | Kevin Wolf | } |
814 | 250196f1 | Kevin Wolf | } |
815 | 250196f1 | Kevin Wolf | |
816 | 65eb2e35 | Kevin Wolf | /* Make sure that existing clusters and new allocations are only used up to
|
817 | 65eb2e35 | Kevin Wolf | * the next dependency if we shortened the request above */
|
818 | 65eb2e35 | Kevin Wolf | *cur_bytes = bytes; |
819 | 250196f1 | Kevin Wolf | |
820 | 226c3c26 | Kevin Wolf | return 0; |
821 | 226c3c26 | Kevin Wolf | } |
822 | 226c3c26 | Kevin Wolf | |
823 | 226c3c26 | Kevin Wolf | /*
|
824 | 0af729ec | Kevin Wolf | * Checks how many already allocated clusters that don't require a copy on
|
825 | 0af729ec | Kevin Wolf | * write there are at the given guest_offset (up to *bytes). If
|
826 | 0af729ec | Kevin Wolf | * *host_offset is not zero, only physically contiguous clusters beginning at
|
827 | 0af729ec | Kevin Wolf | * this host offset are counted.
|
828 | 0af729ec | Kevin Wolf | *
|
829 | 411d62b0 | Kevin Wolf | * Note that guest_offset may not be cluster aligned. In this case, the
|
830 | 411d62b0 | Kevin Wolf | * returned *host_offset points to exact byte referenced by guest_offset and
|
831 | 411d62b0 | Kevin Wolf | * therefore isn't cluster aligned as well.
|
832 | 0af729ec | Kevin Wolf | *
|
833 | 0af729ec | Kevin Wolf | * Returns:
|
834 | 0af729ec | Kevin Wolf | * 0: if no allocated clusters are available at the given offset.
|
835 | 0af729ec | Kevin Wolf | * *bytes is normally unchanged. It is set to 0 if the cluster
|
836 | 0af729ec | Kevin Wolf | * is allocated and doesn't need COW, but doesn't have the right
|
837 | 0af729ec | Kevin Wolf | * physical offset.
|
838 | 0af729ec | Kevin Wolf | *
|
839 | 0af729ec | Kevin Wolf | * 1: if allocated clusters that don't require a COW are available at
|
840 | 0af729ec | Kevin Wolf | * the requested offset. *bytes may have decreased and describes
|
841 | 0af729ec | Kevin Wolf | * the length of the area that can be written to.
|
842 | 0af729ec | Kevin Wolf | *
|
843 | 0af729ec | Kevin Wolf | * -errno: in error cases
|
844 | 0af729ec | Kevin Wolf | */
|
845 | 0af729ec | Kevin Wolf | static int handle_copied(BlockDriverState *bs, uint64_t guest_offset, |
846 | c53ede9f | Kevin Wolf | uint64_t *host_offset, uint64_t *bytes, QCowL2Meta **m) |
847 | 0af729ec | Kevin Wolf | { |
848 | 0af729ec | Kevin Wolf | BDRVQcowState *s = bs->opaque; |
849 | 0af729ec | Kevin Wolf | int l2_index;
|
850 | 0af729ec | Kevin Wolf | uint64_t cluster_offset; |
851 | 0af729ec | Kevin Wolf | uint64_t *l2_table; |
852 | acb0467f | Kevin Wolf | unsigned int nb_clusters; |
853 | c53ede9f | Kevin Wolf | unsigned int keep_clusters; |
854 | 0af729ec | Kevin Wolf | int ret, pret;
|
855 | 0af729ec | Kevin Wolf | |
856 | 0af729ec | Kevin Wolf | trace_qcow2_handle_copied(qemu_coroutine_self(), guest_offset, *host_offset, |
857 | 0af729ec | Kevin Wolf | *bytes); |
858 | 0af729ec | Kevin Wolf | |
859 | 411d62b0 | Kevin Wolf | assert(*host_offset == 0 || offset_into_cluster(s, guest_offset)
|
860 | 411d62b0 | Kevin Wolf | == offset_into_cluster(s, *host_offset)); |
861 | 411d62b0 | Kevin Wolf | |
862 | acb0467f | Kevin Wolf | /*
|
863 | acb0467f | Kevin Wolf | * Calculate the number of clusters to look for. We stop at L2 table
|
864 | acb0467f | Kevin Wolf | * boundaries to keep things simple.
|
865 | acb0467f | Kevin Wolf | */
|
866 | acb0467f | Kevin Wolf | nb_clusters = |
867 | acb0467f | Kevin Wolf | size_to_clusters(s, offset_into_cluster(s, guest_offset) + *bytes); |
868 | acb0467f | Kevin Wolf | |
869 | acb0467f | Kevin Wolf | l2_index = offset_to_l2_index(s, guest_offset); |
870 | acb0467f | Kevin Wolf | nb_clusters = MIN(nb_clusters, s->l2_size - l2_index); |
871 | acb0467f | Kevin Wolf | |
872 | 0af729ec | Kevin Wolf | /* Find L2 entry for the first involved cluster */
|
873 | 0af729ec | Kevin Wolf | ret = get_cluster_table(bs, guest_offset, &l2_table, &l2_index); |
874 | 0af729ec | Kevin Wolf | if (ret < 0) { |
875 | 0af729ec | Kevin Wolf | return ret;
|
876 | 0af729ec | Kevin Wolf | } |
877 | 0af729ec | Kevin Wolf | |
878 | 0af729ec | Kevin Wolf | cluster_offset = be64_to_cpu(l2_table[l2_index]); |
879 | 0af729ec | Kevin Wolf | |
880 | 0af729ec | Kevin Wolf | /* Check how many clusters are already allocated and don't need COW */
|
881 | 0af729ec | Kevin Wolf | if (qcow2_get_cluster_type(cluster_offset) == QCOW2_CLUSTER_NORMAL
|
882 | 0af729ec | Kevin Wolf | && (cluster_offset & QCOW_OFLAG_COPIED)) |
883 | 0af729ec | Kevin Wolf | { |
884 | e62daaf6 | Kevin Wolf | /* If a specific host_offset is required, check it */
|
885 | e62daaf6 | Kevin Wolf | bool offset_matches =
|
886 | e62daaf6 | Kevin Wolf | (cluster_offset & L2E_OFFSET_MASK) == *host_offset; |
887 | e62daaf6 | Kevin Wolf | |
888 | e62daaf6 | Kevin Wolf | if (*host_offset != 0 && !offset_matches) { |
889 | e62daaf6 | Kevin Wolf | *bytes = 0;
|
890 | e62daaf6 | Kevin Wolf | ret = 0;
|
891 | e62daaf6 | Kevin Wolf | goto out;
|
892 | e62daaf6 | Kevin Wolf | } |
893 | e62daaf6 | Kevin Wolf | |
894 | 0af729ec | Kevin Wolf | /* We keep all QCOW_OFLAG_COPIED clusters */
|
895 | c53ede9f | Kevin Wolf | keep_clusters = |
896 | acb0467f | Kevin Wolf | count_contiguous_clusters(nb_clusters, s->cluster_size, |
897 | 0af729ec | Kevin Wolf | &l2_table[l2_index], 0,
|
898 | 0af729ec | Kevin Wolf | QCOW_OFLAG_COPIED | QCOW_OFLAG_ZERO); |
899 | c53ede9f | Kevin Wolf | assert(keep_clusters <= nb_clusters); |
900 | c53ede9f | Kevin Wolf | |
901 | c53ede9f | Kevin Wolf | *bytes = MIN(*bytes, |
902 | c53ede9f | Kevin Wolf | keep_clusters * s->cluster_size |
903 | c53ede9f | Kevin Wolf | - offset_into_cluster(s, guest_offset)); |
904 | 0af729ec | Kevin Wolf | |
905 | 0af729ec | Kevin Wolf | ret = 1;
|
906 | 0af729ec | Kevin Wolf | } else {
|
907 | 0af729ec | Kevin Wolf | ret = 0;
|
908 | 0af729ec | Kevin Wolf | } |
909 | 0af729ec | Kevin Wolf | |
910 | 0af729ec | Kevin Wolf | /* Cleanup */
|
911 | e62daaf6 | Kevin Wolf | out:
|
912 | 0af729ec | Kevin Wolf | pret = qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table);
|
913 | 0af729ec | Kevin Wolf | if (pret < 0) { |
914 | 0af729ec | Kevin Wolf | return pret;
|
915 | 0af729ec | Kevin Wolf | } |
916 | 0af729ec | Kevin Wolf | |
917 | e62daaf6 | Kevin Wolf | /* Only return a host offset if we actually made progress. Otherwise we
|
918 | e62daaf6 | Kevin Wolf | * would make requirements for handle_alloc() that it can't fulfill */
|
919 | e62daaf6 | Kevin Wolf | if (ret) {
|
920 | 411d62b0 | Kevin Wolf | *host_offset = (cluster_offset & L2E_OFFSET_MASK) |
921 | 411d62b0 | Kevin Wolf | + offset_into_cluster(s, guest_offset); |
922 | e62daaf6 | Kevin Wolf | } |
923 | e62daaf6 | Kevin Wolf | |
924 | 0af729ec | Kevin Wolf | return ret;
|
925 | 0af729ec | Kevin Wolf | } |
926 | 0af729ec | Kevin Wolf | |
927 | 0af729ec | Kevin Wolf | /*
|
928 | 226c3c26 | Kevin Wolf | * Allocates new clusters for the given guest_offset.
|
929 | 226c3c26 | Kevin Wolf | *
|
930 | 226c3c26 | Kevin Wolf | * At most *nb_clusters are allocated, and on return *nb_clusters is updated to
|
931 | 226c3c26 | Kevin Wolf | * contain the number of clusters that have been allocated and are contiguous
|
932 | 226c3c26 | Kevin Wolf | * in the image file.
|
933 | 226c3c26 | Kevin Wolf | *
|
934 | 226c3c26 | Kevin Wolf | * If *host_offset is non-zero, it specifies the offset in the image file at
|
935 | 226c3c26 | Kevin Wolf | * which the new clusters must start. *nb_clusters can be 0 on return in this
|
936 | 226c3c26 | Kevin Wolf | * case if the cluster at host_offset is already in use. If *host_offset is
|
937 | 226c3c26 | Kevin Wolf | * zero, the clusters can be allocated anywhere in the image file.
|
938 | 226c3c26 | Kevin Wolf | *
|
939 | 226c3c26 | Kevin Wolf | * *host_offset is updated to contain the offset into the image file at which
|
940 | 226c3c26 | Kevin Wolf | * the first allocated cluster starts.
|
941 | 226c3c26 | Kevin Wolf | *
|
942 | 226c3c26 | Kevin Wolf | * Return 0 on success and -errno in error cases. -EAGAIN means that the
|
943 | 226c3c26 | Kevin Wolf | * function has been waiting for another request and the allocation must be
|
944 | 226c3c26 | Kevin Wolf | * restarted, but the whole request should not be failed.
|
945 | 226c3c26 | Kevin Wolf | */
|
946 | 226c3c26 | Kevin Wolf | static int do_alloc_cluster_offset(BlockDriverState *bs, uint64_t guest_offset, |
947 | 226c3c26 | Kevin Wolf | uint64_t *host_offset, unsigned int *nb_clusters) |
948 | 226c3c26 | Kevin Wolf | { |
949 | 226c3c26 | Kevin Wolf | BDRVQcowState *s = bs->opaque; |
950 | 226c3c26 | Kevin Wolf | |
951 | 226c3c26 | Kevin Wolf | trace_qcow2_do_alloc_clusters_offset(qemu_coroutine_self(), guest_offset, |
952 | 226c3c26 | Kevin Wolf | *host_offset, *nb_clusters); |
953 | 226c3c26 | Kevin Wolf | |
954 | 250196f1 | Kevin Wolf | /* Allocate new clusters */
|
955 | 250196f1 | Kevin Wolf | trace_qcow2_cluster_alloc_phys(qemu_coroutine_self()); |
956 | 250196f1 | Kevin Wolf | if (*host_offset == 0) { |
957 | df021791 | Kevin Wolf | int64_t cluster_offset = |
958 | df021791 | Kevin Wolf | qcow2_alloc_clusters(bs, *nb_clusters * s->cluster_size); |
959 | df021791 | Kevin Wolf | if (cluster_offset < 0) { |
960 | df021791 | Kevin Wolf | return cluster_offset;
|
961 | df021791 | Kevin Wolf | } |
962 | df021791 | Kevin Wolf | *host_offset = cluster_offset; |
963 | df021791 | Kevin Wolf | return 0; |
964 | 250196f1 | Kevin Wolf | } else {
|
965 | 17a71e58 | Kevin Wolf | int ret = qcow2_alloc_clusters_at(bs, *host_offset, *nb_clusters);
|
966 | df021791 | Kevin Wolf | if (ret < 0) { |
967 | df021791 | Kevin Wolf | return ret;
|
968 | df021791 | Kevin Wolf | } |
969 | df021791 | Kevin Wolf | *nb_clusters = ret; |
970 | df021791 | Kevin Wolf | return 0; |
971 | 250196f1 | Kevin Wolf | } |
972 | 250196f1 | Kevin Wolf | } |
973 | 250196f1 | Kevin Wolf | |
974 | 250196f1 | Kevin Wolf | /*
|
975 | 10f0ed8b | Kevin Wolf | * Allocates new clusters for an area that either is yet unallocated or needs a
|
976 | 10f0ed8b | Kevin Wolf | * copy on write. If *host_offset is non-zero, clusters are only allocated if
|
977 | 10f0ed8b | Kevin Wolf | * the new allocation can match the specified host offset.
|
978 | 10f0ed8b | Kevin Wolf | *
|
979 | 411d62b0 | Kevin Wolf | * Note that guest_offset may not be cluster aligned. In this case, the
|
980 | 411d62b0 | Kevin Wolf | * returned *host_offset points to exact byte referenced by guest_offset and
|
981 | 411d62b0 | Kevin Wolf | * therefore isn't cluster aligned as well.
|
982 | 10f0ed8b | Kevin Wolf | *
|
983 | 10f0ed8b | Kevin Wolf | * Returns:
|
984 | 10f0ed8b | Kevin Wolf | * 0: if no clusters could be allocated. *bytes is set to 0,
|
985 | 10f0ed8b | Kevin Wolf | * *host_offset is left unchanged.
|
986 | 10f0ed8b | Kevin Wolf | *
|
987 | 10f0ed8b | Kevin Wolf | * 1: if new clusters were allocated. *bytes may be decreased if the
|
988 | 10f0ed8b | Kevin Wolf | * new allocation doesn't cover all of the requested area.
|
989 | 10f0ed8b | Kevin Wolf | * *host_offset is updated to contain the host offset of the first
|
990 | 10f0ed8b | Kevin Wolf | * newly allocated cluster.
|
991 | 10f0ed8b | Kevin Wolf | *
|
992 | 10f0ed8b | Kevin Wolf | * -errno: in error cases
|
993 | 10f0ed8b | Kevin Wolf | */
|
994 | 10f0ed8b | Kevin Wolf | static int handle_alloc(BlockDriverState *bs, uint64_t guest_offset, |
995 | c37f4cd7 | Kevin Wolf | uint64_t *host_offset, uint64_t *bytes, QCowL2Meta **m) |
996 | 10f0ed8b | Kevin Wolf | { |
997 | 10f0ed8b | Kevin Wolf | BDRVQcowState *s = bs->opaque; |
998 | 10f0ed8b | Kevin Wolf | int l2_index;
|
999 | 10f0ed8b | Kevin Wolf | uint64_t *l2_table; |
1000 | 10f0ed8b | Kevin Wolf | uint64_t entry; |
1001 | f5bc6350 | Kevin Wolf | unsigned int nb_clusters; |
1002 | 10f0ed8b | Kevin Wolf | int ret;
|
1003 | 10f0ed8b | Kevin Wolf | |
1004 | 10f0ed8b | Kevin Wolf | uint64_t alloc_cluster_offset; |
1005 | 10f0ed8b | Kevin Wolf | |
1006 | 10f0ed8b | Kevin Wolf | trace_qcow2_handle_alloc(qemu_coroutine_self(), guest_offset, *host_offset, |
1007 | 10f0ed8b | Kevin Wolf | *bytes); |
1008 | 10f0ed8b | Kevin Wolf | assert(*bytes > 0);
|
1009 | 10f0ed8b | Kevin Wolf | |
1010 | f5bc6350 | Kevin Wolf | /*
|
1011 | f5bc6350 | Kevin Wolf | * Calculate the number of clusters to look for. We stop at L2 table
|
1012 | f5bc6350 | Kevin Wolf | * boundaries to keep things simple.
|
1013 | f5bc6350 | Kevin Wolf | */
|
1014 | c37f4cd7 | Kevin Wolf | nb_clusters = |
1015 | c37f4cd7 | Kevin Wolf | size_to_clusters(s, offset_into_cluster(s, guest_offset) + *bytes); |
1016 | c37f4cd7 | Kevin Wolf | |
1017 | f5bc6350 | Kevin Wolf | l2_index = offset_to_l2_index(s, guest_offset); |
1018 | c37f4cd7 | Kevin Wolf | nb_clusters = MIN(nb_clusters, s->l2_size - l2_index); |
1019 | f5bc6350 | Kevin Wolf | |
1020 | 10f0ed8b | Kevin Wolf | /* Find L2 entry for the first involved cluster */
|
1021 | 10f0ed8b | Kevin Wolf | ret = get_cluster_table(bs, guest_offset, &l2_table, &l2_index); |
1022 | 10f0ed8b | Kevin Wolf | if (ret < 0) { |
1023 | 10f0ed8b | Kevin Wolf | return ret;
|
1024 | 10f0ed8b | Kevin Wolf | } |
1025 | 10f0ed8b | Kevin Wolf | |
1026 | 3b8e2e26 | Kevin Wolf | entry = be64_to_cpu(l2_table[l2_index]); |
1027 | 10f0ed8b | Kevin Wolf | |
1028 | 10f0ed8b | Kevin Wolf | /* For the moment, overwrite compressed clusters one by one */
|
1029 | 10f0ed8b | Kevin Wolf | if (entry & QCOW_OFLAG_COMPRESSED) {
|
1030 | 10f0ed8b | Kevin Wolf | nb_clusters = 1;
|
1031 | 10f0ed8b | Kevin Wolf | } else {
|
1032 | 3b8e2e26 | Kevin Wolf | nb_clusters = count_cow_clusters(s, nb_clusters, l2_table, l2_index); |
1033 | 10f0ed8b | Kevin Wolf | } |
1034 | 10f0ed8b | Kevin Wolf | |
1035 | ecdd5333 | Kevin Wolf | /* This function is only called when there were no non-COW clusters, so if
|
1036 | ecdd5333 | Kevin Wolf | * we can't find any unallocated or COW clusters either, something is
|
1037 | ecdd5333 | Kevin Wolf | * wrong with our code. */
|
1038 | ecdd5333 | Kevin Wolf | assert(nb_clusters > 0);
|
1039 | ecdd5333 | Kevin Wolf | |
1040 | 10f0ed8b | Kevin Wolf | ret = qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table);
|
1041 | 10f0ed8b | Kevin Wolf | if (ret < 0) { |
1042 | 10f0ed8b | Kevin Wolf | return ret;
|
1043 | 10f0ed8b | Kevin Wolf | } |
1044 | 10f0ed8b | Kevin Wolf | |
1045 | 10f0ed8b | Kevin Wolf | /* Allocate, if necessary at a given offset in the image file */
|
1046 | 411d62b0 | Kevin Wolf | alloc_cluster_offset = start_of_cluster(s, *host_offset); |
1047 | 83baa9a4 | Kevin Wolf | ret = do_alloc_cluster_offset(bs, guest_offset, &alloc_cluster_offset, |
1048 | 10f0ed8b | Kevin Wolf | &nb_clusters); |
1049 | 10f0ed8b | Kevin Wolf | if (ret < 0) { |
1050 | 10f0ed8b | Kevin Wolf | goto fail;
|
1051 | 10f0ed8b | Kevin Wolf | } |
1052 | 10f0ed8b | Kevin Wolf | |
1053 | 83baa9a4 | Kevin Wolf | /* Can't extend contiguous allocation */
|
1054 | 83baa9a4 | Kevin Wolf | if (nb_clusters == 0) { |
1055 | 10f0ed8b | Kevin Wolf | *bytes = 0;
|
1056 | 10f0ed8b | Kevin Wolf | return 0; |
1057 | 10f0ed8b | Kevin Wolf | } |
1058 | 10f0ed8b | Kevin Wolf | |
1059 | 83baa9a4 | Kevin Wolf | /*
|
1060 | 83baa9a4 | Kevin Wolf | * Save info needed for meta data update.
|
1061 | 83baa9a4 | Kevin Wolf | *
|
1062 | 83baa9a4 | Kevin Wolf | * requested_sectors: Number of sectors from the start of the first
|
1063 | 83baa9a4 | Kevin Wolf | * newly allocated cluster to the end of the (possibly shortened
|
1064 | 83baa9a4 | Kevin Wolf | * before) write request.
|
1065 | 83baa9a4 | Kevin Wolf | *
|
1066 | 83baa9a4 | Kevin Wolf | * avail_sectors: Number of sectors from the start of the first
|
1067 | 83baa9a4 | Kevin Wolf | * newly allocated to the end of the last newly allocated cluster.
|
1068 | 83baa9a4 | Kevin Wolf | *
|
1069 | 83baa9a4 | Kevin Wolf | * nb_sectors: The number of sectors from the start of the first
|
1070 | 83baa9a4 | Kevin Wolf | * newly allocated cluster to the end of the area that the write
|
1071 | 83baa9a4 | Kevin Wolf | * request actually writes to (excluding COW at the end)
|
1072 | 83baa9a4 | Kevin Wolf | */
|
1073 | 83baa9a4 | Kevin Wolf | int requested_sectors =
|
1074 | 83baa9a4 | Kevin Wolf | (*bytes + offset_into_cluster(s, guest_offset)) |
1075 | 83baa9a4 | Kevin Wolf | >> BDRV_SECTOR_BITS; |
1076 | 83baa9a4 | Kevin Wolf | int avail_sectors = nb_clusters
|
1077 | 83baa9a4 | Kevin Wolf | << (s->cluster_bits - BDRV_SECTOR_BITS); |
1078 | 83baa9a4 | Kevin Wolf | int alloc_n_start = offset_into_cluster(s, guest_offset)
|
1079 | 83baa9a4 | Kevin Wolf | >> BDRV_SECTOR_BITS; |
1080 | 83baa9a4 | Kevin Wolf | int nb_sectors = MIN(requested_sectors, avail_sectors);
|
1081 | 88c6588c | Kevin Wolf | QCowL2Meta *old_m = *m; |
1082 | 83baa9a4 | Kevin Wolf | |
1083 | 83baa9a4 | Kevin Wolf | *m = g_malloc0(sizeof(**m));
|
1084 | 83baa9a4 | Kevin Wolf | |
1085 | 83baa9a4 | Kevin Wolf | **m = (QCowL2Meta) { |
1086 | 88c6588c | Kevin Wolf | .next = old_m, |
1087 | 88c6588c | Kevin Wolf | |
1088 | 411d62b0 | Kevin Wolf | .alloc_offset = alloc_cluster_offset, |
1089 | 83baa9a4 | Kevin Wolf | .offset = start_of_cluster(s, guest_offset), |
1090 | 83baa9a4 | Kevin Wolf | .nb_clusters = nb_clusters, |
1091 | 83baa9a4 | Kevin Wolf | .nb_available = nb_sectors, |
1092 | 83baa9a4 | Kevin Wolf | |
1093 | 83baa9a4 | Kevin Wolf | .cow_start = { |
1094 | 83baa9a4 | Kevin Wolf | .offset = 0,
|
1095 | 83baa9a4 | Kevin Wolf | .nb_sectors = alloc_n_start, |
1096 | 83baa9a4 | Kevin Wolf | }, |
1097 | 83baa9a4 | Kevin Wolf | .cow_end = { |
1098 | 83baa9a4 | Kevin Wolf | .offset = nb_sectors * BDRV_SECTOR_SIZE, |
1099 | 83baa9a4 | Kevin Wolf | .nb_sectors = avail_sectors - nb_sectors, |
1100 | 83baa9a4 | Kevin Wolf | }, |
1101 | 83baa9a4 | Kevin Wolf | }; |
1102 | 83baa9a4 | Kevin Wolf | qemu_co_queue_init(&(*m)->dependent_requests); |
1103 | 83baa9a4 | Kevin Wolf | QLIST_INSERT_HEAD(&s->cluster_allocs, *m, next_in_flight); |
1104 | 83baa9a4 | Kevin Wolf | |
1105 | 411d62b0 | Kevin Wolf | *host_offset = alloc_cluster_offset + offset_into_cluster(s, guest_offset); |
1106 | 83baa9a4 | Kevin Wolf | *bytes = MIN(*bytes, (nb_sectors * BDRV_SECTOR_SIZE) |
1107 | 83baa9a4 | Kevin Wolf | - offset_into_cluster(s, guest_offset)); |
1108 | 83baa9a4 | Kevin Wolf | assert(*bytes != 0);
|
1109 | 83baa9a4 | Kevin Wolf | |
1110 | 10f0ed8b | Kevin Wolf | return 1; |
1111 | 10f0ed8b | Kevin Wolf | |
1112 | 10f0ed8b | Kevin Wolf | fail:
|
1113 | 10f0ed8b | Kevin Wolf | if (*m && (*m)->nb_clusters > 0) { |
1114 | 10f0ed8b | Kevin Wolf | QLIST_REMOVE(*m, next_in_flight); |
1115 | 10f0ed8b | Kevin Wolf | } |
1116 | 10f0ed8b | Kevin Wolf | return ret;
|
1117 | 10f0ed8b | Kevin Wolf | } |
1118 | 10f0ed8b | Kevin Wolf | |
1119 | 10f0ed8b | Kevin Wolf | /*
|
1120 | 45aba42f | Kevin Wolf | * alloc_cluster_offset
|
1121 | 45aba42f | Kevin Wolf | *
|
1122 | 250196f1 | Kevin Wolf | * For a given offset on the virtual disk, find the cluster offset in qcow2
|
1123 | 250196f1 | Kevin Wolf | * file. If the offset is not found, allocate a new cluster.
|
1124 | 45aba42f | Kevin Wolf | *
|
1125 | 250196f1 | Kevin Wolf | * If the cluster was already allocated, m->nb_clusters is set to 0 and
|
1126 | a7912369 | Frediano Ziglio | * other fields in m are meaningless.
|
1127 | 148da7ea | Kevin Wolf | *
|
1128 | 148da7ea | Kevin Wolf | * If the cluster is newly allocated, m->nb_clusters is set to the number of
|
1129 | 68d100e9 | Kevin Wolf | * contiguous clusters that have been allocated. In this case, the other
|
1130 | 68d100e9 | Kevin Wolf | * fields of m are valid and contain information about the first allocated
|
1131 | 68d100e9 | Kevin Wolf | * cluster.
|
1132 | 45aba42f | Kevin Wolf | *
|
1133 | 68d100e9 | Kevin Wolf | * If the request conflicts with another write request in flight, the coroutine
|
1134 | 68d100e9 | Kevin Wolf | * is queued and will be reentered when the dependency has completed.
|
1135 | 148da7ea | Kevin Wolf | *
|
1136 | 148da7ea | Kevin Wolf | * Return 0 on success and -errno in error cases
|
1137 | 45aba42f | Kevin Wolf | */
|
1138 | f4f0d391 | Kevin Wolf | int qcow2_alloc_cluster_offset(BlockDriverState *bs, uint64_t offset,
|
1139 | f50f88b9 | Kevin Wolf | int n_start, int n_end, int *num, uint64_t *host_offset, QCowL2Meta **m) |
1140 | 45aba42f | Kevin Wolf | { |
1141 | 45aba42f | Kevin Wolf | BDRVQcowState *s = bs->opaque; |
1142 | 710c2496 | Kevin Wolf | uint64_t start, remaining; |
1143 | 250196f1 | Kevin Wolf | uint64_t cluster_offset; |
1144 | 65eb2e35 | Kevin Wolf | uint64_t cur_bytes; |
1145 | 710c2496 | Kevin Wolf | int ret;
|
1146 | 45aba42f | Kevin Wolf | |
1147 | 3cce16f4 | Kevin Wolf | trace_qcow2_alloc_clusters_offset(qemu_coroutine_self(), offset, |
1148 | 3cce16f4 | Kevin Wolf | n_start, n_end); |
1149 | 3cce16f4 | Kevin Wolf | |
1150 | 710c2496 | Kevin Wolf | assert(n_start * BDRV_SECTOR_SIZE == offset_into_cluster(s, offset)); |
1151 | 710c2496 | Kevin Wolf | offset = start_of_cluster(s, offset); |
1152 | 710c2496 | Kevin Wolf | |
1153 | 72424114 | Kevin Wolf | again:
|
1154 | 710c2496 | Kevin Wolf | start = offset + (n_start << BDRV_SECTOR_BITS); |
1155 | 710c2496 | Kevin Wolf | remaining = (n_end - n_start) << BDRV_SECTOR_BITS; |
1156 | 0af729ec | Kevin Wolf | cluster_offset = 0;
|
1157 | 0af729ec | Kevin Wolf | *host_offset = 0;
|
1158 | ecdd5333 | Kevin Wolf | cur_bytes = 0;
|
1159 | ecdd5333 | Kevin Wolf | *m = NULL;
|
1160 | 0af729ec | Kevin Wolf | |
1161 | 2c3b32d2 | Kevin Wolf | while (true) { |
1162 | ecdd5333 | Kevin Wolf | |
1163 | ecdd5333 | Kevin Wolf | if (!*host_offset) {
|
1164 | ecdd5333 | Kevin Wolf | *host_offset = start_of_cluster(s, cluster_offset); |
1165 | ecdd5333 | Kevin Wolf | } |
1166 | ecdd5333 | Kevin Wolf | |
1167 | ecdd5333 | Kevin Wolf | assert(remaining >= cur_bytes); |
1168 | ecdd5333 | Kevin Wolf | |
1169 | ecdd5333 | Kevin Wolf | start += cur_bytes; |
1170 | ecdd5333 | Kevin Wolf | remaining -= cur_bytes; |
1171 | ecdd5333 | Kevin Wolf | cluster_offset += cur_bytes; |
1172 | ecdd5333 | Kevin Wolf | |
1173 | ecdd5333 | Kevin Wolf | if (remaining == 0) { |
1174 | ecdd5333 | Kevin Wolf | break;
|
1175 | ecdd5333 | Kevin Wolf | } |
1176 | ecdd5333 | Kevin Wolf | |
1177 | ecdd5333 | Kevin Wolf | cur_bytes = remaining; |
1178 | ecdd5333 | Kevin Wolf | |
1179 | 2c3b32d2 | Kevin Wolf | /*
|
1180 | 2c3b32d2 | Kevin Wolf | * Now start gathering as many contiguous clusters as possible:
|
1181 | 2c3b32d2 | Kevin Wolf | *
|
1182 | 2c3b32d2 | Kevin Wolf | * 1. Check for overlaps with in-flight allocations
|
1183 | 2c3b32d2 | Kevin Wolf | *
|
1184 | 2c3b32d2 | Kevin Wolf | * a) Overlap not in the first cluster -> shorten this request and
|
1185 | 2c3b32d2 | Kevin Wolf | * let the caller handle the rest in its next loop iteration.
|
1186 | 2c3b32d2 | Kevin Wolf | *
|
1187 | 2c3b32d2 | Kevin Wolf | * b) Real overlaps of two requests. Yield and restart the search
|
1188 | 2c3b32d2 | Kevin Wolf | * for contiguous clusters (the situation could have changed
|
1189 | 2c3b32d2 | Kevin Wolf | * while we were sleeping)
|
1190 | 2c3b32d2 | Kevin Wolf | *
|
1191 | 2c3b32d2 | Kevin Wolf | * c) TODO: Request starts in the same cluster as the in-flight
|
1192 | 2c3b32d2 | Kevin Wolf | * allocation ends. Shorten the COW of the in-fight allocation,
|
1193 | 2c3b32d2 | Kevin Wolf | * set cluster_offset to write to the same cluster and set up
|
1194 | 2c3b32d2 | Kevin Wolf | * the right synchronisation between the in-flight request and
|
1195 | 2c3b32d2 | Kevin Wolf | * the new one.
|
1196 | 2c3b32d2 | Kevin Wolf | */
|
1197 | ecdd5333 | Kevin Wolf | ret = handle_dependencies(bs, start, &cur_bytes, m); |
1198 | 2c3b32d2 | Kevin Wolf | if (ret == -EAGAIN) {
|
1199 | ecdd5333 | Kevin Wolf | /* Currently handle_dependencies() doesn't yield if we already had
|
1200 | ecdd5333 | Kevin Wolf | * an allocation. If it did, we would have to clean up the L2Meta
|
1201 | ecdd5333 | Kevin Wolf | * structs before starting over. */
|
1202 | ecdd5333 | Kevin Wolf | assert(*m == NULL);
|
1203 | 2c3b32d2 | Kevin Wolf | goto again;
|
1204 | 2c3b32d2 | Kevin Wolf | } else if (ret < 0) { |
1205 | 2c3b32d2 | Kevin Wolf | return ret;
|
1206 | ecdd5333 | Kevin Wolf | } else if (cur_bytes == 0) { |
1207 | ecdd5333 | Kevin Wolf | break;
|
1208 | 2c3b32d2 | Kevin Wolf | } else {
|
1209 | 2c3b32d2 | Kevin Wolf | /* handle_dependencies() may have decreased cur_bytes (shortened
|
1210 | 2c3b32d2 | Kevin Wolf | * the allocations below) so that the next dependency is processed
|
1211 | 2c3b32d2 | Kevin Wolf | * correctly during the next loop iteration. */
|
1212 | 0af729ec | Kevin Wolf | } |
1213 | 710c2496 | Kevin Wolf | |
1214 | 2c3b32d2 | Kevin Wolf | /*
|
1215 | 2c3b32d2 | Kevin Wolf | * 2. Count contiguous COPIED clusters.
|
1216 | 2c3b32d2 | Kevin Wolf | */
|
1217 | 2c3b32d2 | Kevin Wolf | ret = handle_copied(bs, start, &cluster_offset, &cur_bytes, m); |
1218 | 2c3b32d2 | Kevin Wolf | if (ret < 0) { |
1219 | 2c3b32d2 | Kevin Wolf | return ret;
|
1220 | 2c3b32d2 | Kevin Wolf | } else if (ret) { |
1221 | ecdd5333 | Kevin Wolf | continue;
|
1222 | 2c3b32d2 | Kevin Wolf | } else if (cur_bytes == 0) { |
1223 | 2c3b32d2 | Kevin Wolf | break;
|
1224 | 2c3b32d2 | Kevin Wolf | } |
1225 | 060bee89 | Kevin Wolf | |
1226 | 2c3b32d2 | Kevin Wolf | /*
|
1227 | 2c3b32d2 | Kevin Wolf | * 3. If the request still hasn't completed, allocate new clusters,
|
1228 | 2c3b32d2 | Kevin Wolf | * considering any cluster_offset of steps 1c or 2.
|
1229 | 2c3b32d2 | Kevin Wolf | */
|
1230 | 2c3b32d2 | Kevin Wolf | ret = handle_alloc(bs, start, &cluster_offset, &cur_bytes, m); |
1231 | 2c3b32d2 | Kevin Wolf | if (ret < 0) { |
1232 | 2c3b32d2 | Kevin Wolf | return ret;
|
1233 | 2c3b32d2 | Kevin Wolf | } else if (ret) { |
1234 | ecdd5333 | Kevin Wolf | continue;
|
1235 | 2c3b32d2 | Kevin Wolf | } else {
|
1236 | 2c3b32d2 | Kevin Wolf | assert(cur_bytes == 0);
|
1237 | 2c3b32d2 | Kevin Wolf | break;
|
1238 | 2c3b32d2 | Kevin Wolf | } |
1239 | f5bc6350 | Kevin Wolf | } |
1240 | 10f0ed8b | Kevin Wolf | |
1241 | 710c2496 | Kevin Wolf | *num = (n_end - n_start) - (remaining >> BDRV_SECTOR_BITS); |
1242 | 710c2496 | Kevin Wolf | assert(*num > 0);
|
1243 | 710c2496 | Kevin Wolf | assert(*host_offset != 0);
|
1244 | 45aba42f | Kevin Wolf | |
1245 | 148da7ea | Kevin Wolf | return 0; |
1246 | 45aba42f | Kevin Wolf | } |
1247 | 45aba42f | Kevin Wolf | |
1248 | 45aba42f | Kevin Wolf | static int decompress_buffer(uint8_t *out_buf, int out_buf_size, |
1249 | 45aba42f | Kevin Wolf | const uint8_t *buf, int buf_size) |
1250 | 45aba42f | Kevin Wolf | { |
1251 | 45aba42f | Kevin Wolf | z_stream strm1, *strm = &strm1; |
1252 | 45aba42f | Kevin Wolf | int ret, out_len;
|
1253 | 45aba42f | Kevin Wolf | |
1254 | 45aba42f | Kevin Wolf | memset(strm, 0, sizeof(*strm)); |
1255 | 45aba42f | Kevin Wolf | |
1256 | 45aba42f | Kevin Wolf | strm->next_in = (uint8_t *)buf; |
1257 | 45aba42f | Kevin Wolf | strm->avail_in = buf_size; |
1258 | 45aba42f | Kevin Wolf | strm->next_out = out_buf; |
1259 | 45aba42f | Kevin Wolf | strm->avail_out = out_buf_size; |
1260 | 45aba42f | Kevin Wolf | |
1261 | 45aba42f | Kevin Wolf | ret = inflateInit2(strm, -12);
|
1262 | 45aba42f | Kevin Wolf | if (ret != Z_OK)
|
1263 | 45aba42f | Kevin Wolf | return -1; |
1264 | 45aba42f | Kevin Wolf | ret = inflate(strm, Z_FINISH); |
1265 | 45aba42f | Kevin Wolf | out_len = strm->next_out - out_buf; |
1266 | 45aba42f | Kevin Wolf | if ((ret != Z_STREAM_END && ret != Z_BUF_ERROR) ||
|
1267 | 45aba42f | Kevin Wolf | out_len != out_buf_size) { |
1268 | 45aba42f | Kevin Wolf | inflateEnd(strm); |
1269 | 45aba42f | Kevin Wolf | return -1; |
1270 | 45aba42f | Kevin Wolf | } |
1271 | 45aba42f | Kevin Wolf | inflateEnd(strm); |
1272 | 45aba42f | Kevin Wolf | return 0; |
1273 | 45aba42f | Kevin Wolf | } |
1274 | 45aba42f | Kevin Wolf | |
1275 | 66f82cee | Kevin Wolf | int qcow2_decompress_cluster(BlockDriverState *bs, uint64_t cluster_offset)
|
1276 | 45aba42f | Kevin Wolf | { |
1277 | 66f82cee | Kevin Wolf | BDRVQcowState *s = bs->opaque; |
1278 | 45aba42f | Kevin Wolf | int ret, csize, nb_csectors, sector_offset;
|
1279 | 45aba42f | Kevin Wolf | uint64_t coffset; |
1280 | 45aba42f | Kevin Wolf | |
1281 | 45aba42f | Kevin Wolf | coffset = cluster_offset & s->cluster_offset_mask; |
1282 | 45aba42f | Kevin Wolf | if (s->cluster_cache_offset != coffset) {
|
1283 | 45aba42f | Kevin Wolf | nb_csectors = ((cluster_offset >> s->csize_shift) & s->csize_mask) + 1;
|
1284 | 45aba42f | Kevin Wolf | sector_offset = coffset & 511;
|
1285 | 45aba42f | Kevin Wolf | csize = nb_csectors * 512 - sector_offset;
|
1286 | 66f82cee | Kevin Wolf | BLKDBG_EVENT(bs->file, BLKDBG_READ_COMPRESSED); |
1287 | 66f82cee | Kevin Wolf | ret = bdrv_read(bs->file, coffset >> 9, s->cluster_data, nb_csectors);
|
1288 | 45aba42f | Kevin Wolf | if (ret < 0) { |
1289 | 8af36488 | Kevin Wolf | return ret;
|
1290 | 45aba42f | Kevin Wolf | } |
1291 | 45aba42f | Kevin Wolf | if (decompress_buffer(s->cluster_cache, s->cluster_size,
|
1292 | 45aba42f | Kevin Wolf | s->cluster_data + sector_offset, csize) < 0) {
|
1293 | 8af36488 | Kevin Wolf | return -EIO;
|
1294 | 45aba42f | Kevin Wolf | } |
1295 | 45aba42f | Kevin Wolf | s->cluster_cache_offset = coffset; |
1296 | 45aba42f | Kevin Wolf | } |
1297 | 45aba42f | Kevin Wolf | return 0; |
1298 | 45aba42f | Kevin Wolf | } |
1299 | 5ea929e3 | Kevin Wolf | |
1300 | 5ea929e3 | Kevin Wolf | /*
|
1301 | 5ea929e3 | Kevin Wolf | * This discards as many clusters of nb_clusters as possible at once (i.e.
|
1302 | 5ea929e3 | Kevin Wolf | * all clusters in the same L2 table) and returns the number of discarded
|
1303 | 5ea929e3 | Kevin Wolf | * clusters.
|
1304 | 5ea929e3 | Kevin Wolf | */
|
1305 | 5ea929e3 | Kevin Wolf | static int discard_single_l2(BlockDriverState *bs, uint64_t offset, |
1306 | 5ea929e3 | Kevin Wolf | unsigned int nb_clusters) |
1307 | 5ea929e3 | Kevin Wolf | { |
1308 | 5ea929e3 | Kevin Wolf | BDRVQcowState *s = bs->opaque; |
1309 | 3948d1d4 | Kevin Wolf | uint64_t *l2_table; |
1310 | 5ea929e3 | Kevin Wolf | int l2_index;
|
1311 | 5ea929e3 | Kevin Wolf | int ret;
|
1312 | 5ea929e3 | Kevin Wolf | int i;
|
1313 | 5ea929e3 | Kevin Wolf | |
1314 | 3948d1d4 | Kevin Wolf | ret = get_cluster_table(bs, offset, &l2_table, &l2_index); |
1315 | 5ea929e3 | Kevin Wolf | if (ret < 0) { |
1316 | 5ea929e3 | Kevin Wolf | return ret;
|
1317 | 5ea929e3 | Kevin Wolf | } |
1318 | 5ea929e3 | Kevin Wolf | |
1319 | 5ea929e3 | Kevin Wolf | /* Limit nb_clusters to one L2 table */
|
1320 | 5ea929e3 | Kevin Wolf | nb_clusters = MIN(nb_clusters, s->l2_size - l2_index); |
1321 | 5ea929e3 | Kevin Wolf | |
1322 | 5ea929e3 | Kevin Wolf | for (i = 0; i < nb_clusters; i++) { |
1323 | 5ea929e3 | Kevin Wolf | uint64_t old_offset; |
1324 | 5ea929e3 | Kevin Wolf | |
1325 | 5ea929e3 | Kevin Wolf | old_offset = be64_to_cpu(l2_table[l2_index + i]); |
1326 | 8e37f681 | Kevin Wolf | if ((old_offset & L2E_OFFSET_MASK) == 0) { |
1327 | 5ea929e3 | Kevin Wolf | continue;
|
1328 | 5ea929e3 | Kevin Wolf | } |
1329 | 5ea929e3 | Kevin Wolf | |
1330 | 5ea929e3 | Kevin Wolf | /* First remove L2 entries */
|
1331 | 5ea929e3 | Kevin Wolf | qcow2_cache_entry_mark_dirty(s->l2_table_cache, l2_table); |
1332 | 5ea929e3 | Kevin Wolf | l2_table[l2_index + i] = cpu_to_be64(0);
|
1333 | 5ea929e3 | Kevin Wolf | |
1334 | 5ea929e3 | Kevin Wolf | /* Then decrease the refcount */
|
1335 | 5ea929e3 | Kevin Wolf | qcow2_free_any_clusters(bs, old_offset, 1);
|
1336 | 5ea929e3 | Kevin Wolf | } |
1337 | 5ea929e3 | Kevin Wolf | |
1338 | 5ea929e3 | Kevin Wolf | ret = qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table);
|
1339 | 5ea929e3 | Kevin Wolf | if (ret < 0) { |
1340 | 5ea929e3 | Kevin Wolf | return ret;
|
1341 | 5ea929e3 | Kevin Wolf | } |
1342 | 5ea929e3 | Kevin Wolf | |
1343 | 5ea929e3 | Kevin Wolf | return nb_clusters;
|
1344 | 5ea929e3 | Kevin Wolf | } |
1345 | 5ea929e3 | Kevin Wolf | |
1346 | 5ea929e3 | Kevin Wolf | int qcow2_discard_clusters(BlockDriverState *bs, uint64_t offset,
|
1347 | 5ea929e3 | Kevin Wolf | int nb_sectors)
|
1348 | 5ea929e3 | Kevin Wolf | { |
1349 | 5ea929e3 | Kevin Wolf | BDRVQcowState *s = bs->opaque; |
1350 | 5ea929e3 | Kevin Wolf | uint64_t end_offset; |
1351 | 5ea929e3 | Kevin Wolf | unsigned int nb_clusters; |
1352 | 5ea929e3 | Kevin Wolf | int ret;
|
1353 | 5ea929e3 | Kevin Wolf | |
1354 | 5ea929e3 | Kevin Wolf | end_offset = offset + (nb_sectors << BDRV_SECTOR_BITS); |
1355 | 5ea929e3 | Kevin Wolf | |
1356 | 5ea929e3 | Kevin Wolf | /* Round start up and end down */
|
1357 | 5ea929e3 | Kevin Wolf | offset = align_offset(offset, s->cluster_size); |
1358 | 5ea929e3 | Kevin Wolf | end_offset &= ~(s->cluster_size - 1);
|
1359 | 5ea929e3 | Kevin Wolf | |
1360 | 5ea929e3 | Kevin Wolf | if (offset > end_offset) {
|
1361 | 5ea929e3 | Kevin Wolf | return 0; |
1362 | 5ea929e3 | Kevin Wolf | } |
1363 | 5ea929e3 | Kevin Wolf | |
1364 | 5ea929e3 | Kevin Wolf | nb_clusters = size_to_clusters(s, end_offset - offset); |
1365 | 5ea929e3 | Kevin Wolf | |
1366 | 5ea929e3 | Kevin Wolf | /* Each L2 table is handled by its own loop iteration */
|
1367 | 5ea929e3 | Kevin Wolf | while (nb_clusters > 0) { |
1368 | 5ea929e3 | Kevin Wolf | ret = discard_single_l2(bs, offset, nb_clusters); |
1369 | 5ea929e3 | Kevin Wolf | if (ret < 0) { |
1370 | 5ea929e3 | Kevin Wolf | return ret;
|
1371 | 5ea929e3 | Kevin Wolf | } |
1372 | 5ea929e3 | Kevin Wolf | |
1373 | 5ea929e3 | Kevin Wolf | nb_clusters -= ret; |
1374 | 5ea929e3 | Kevin Wolf | offset += (ret * s->cluster_size); |
1375 | 5ea929e3 | Kevin Wolf | } |
1376 | 5ea929e3 | Kevin Wolf | |
1377 | 5ea929e3 | Kevin Wolf | return 0; |
1378 | 5ea929e3 | Kevin Wolf | } |
1379 | 621f0589 | Kevin Wolf | |
1380 | 621f0589 | Kevin Wolf | /*
|
1381 | 621f0589 | Kevin Wolf | * This zeroes as many clusters of nb_clusters as possible at once (i.e.
|
1382 | 621f0589 | Kevin Wolf | * all clusters in the same L2 table) and returns the number of zeroed
|
1383 | 621f0589 | Kevin Wolf | * clusters.
|
1384 | 621f0589 | Kevin Wolf | */
|
1385 | 621f0589 | Kevin Wolf | static int zero_single_l2(BlockDriverState *bs, uint64_t offset, |
1386 | 621f0589 | Kevin Wolf | unsigned int nb_clusters) |
1387 | 621f0589 | Kevin Wolf | { |
1388 | 621f0589 | Kevin Wolf | BDRVQcowState *s = bs->opaque; |
1389 | 621f0589 | Kevin Wolf | uint64_t *l2_table; |
1390 | 621f0589 | Kevin Wolf | int l2_index;
|
1391 | 621f0589 | Kevin Wolf | int ret;
|
1392 | 621f0589 | Kevin Wolf | int i;
|
1393 | 621f0589 | Kevin Wolf | |
1394 | 621f0589 | Kevin Wolf | ret = get_cluster_table(bs, offset, &l2_table, &l2_index); |
1395 | 621f0589 | Kevin Wolf | if (ret < 0) { |
1396 | 621f0589 | Kevin Wolf | return ret;
|
1397 | 621f0589 | Kevin Wolf | } |
1398 | 621f0589 | Kevin Wolf | |
1399 | 621f0589 | Kevin Wolf | /* Limit nb_clusters to one L2 table */
|
1400 | 621f0589 | Kevin Wolf | nb_clusters = MIN(nb_clusters, s->l2_size - l2_index); |
1401 | 621f0589 | Kevin Wolf | |
1402 | 621f0589 | Kevin Wolf | for (i = 0; i < nb_clusters; i++) { |
1403 | 621f0589 | Kevin Wolf | uint64_t old_offset; |
1404 | 621f0589 | Kevin Wolf | |
1405 | 621f0589 | Kevin Wolf | old_offset = be64_to_cpu(l2_table[l2_index + i]); |
1406 | 621f0589 | Kevin Wolf | |
1407 | 621f0589 | Kevin Wolf | /* Update L2 entries */
|
1408 | 621f0589 | Kevin Wolf | qcow2_cache_entry_mark_dirty(s->l2_table_cache, l2_table); |
1409 | 621f0589 | Kevin Wolf | if (old_offset & QCOW_OFLAG_COMPRESSED) {
|
1410 | 621f0589 | Kevin Wolf | l2_table[l2_index + i] = cpu_to_be64(QCOW_OFLAG_ZERO); |
1411 | 621f0589 | Kevin Wolf | qcow2_free_any_clusters(bs, old_offset, 1);
|
1412 | 621f0589 | Kevin Wolf | } else {
|
1413 | 621f0589 | Kevin Wolf | l2_table[l2_index + i] |= cpu_to_be64(QCOW_OFLAG_ZERO); |
1414 | 621f0589 | Kevin Wolf | } |
1415 | 621f0589 | Kevin Wolf | } |
1416 | 621f0589 | Kevin Wolf | |
1417 | 621f0589 | Kevin Wolf | ret = qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table);
|
1418 | 621f0589 | Kevin Wolf | if (ret < 0) { |
1419 | 621f0589 | Kevin Wolf | return ret;
|
1420 | 621f0589 | Kevin Wolf | } |
1421 | 621f0589 | Kevin Wolf | |
1422 | 621f0589 | Kevin Wolf | return nb_clusters;
|
1423 | 621f0589 | Kevin Wolf | } |
1424 | 621f0589 | Kevin Wolf | |
1425 | 621f0589 | Kevin Wolf | int qcow2_zero_clusters(BlockDriverState *bs, uint64_t offset, int nb_sectors) |
1426 | 621f0589 | Kevin Wolf | { |
1427 | 621f0589 | Kevin Wolf | BDRVQcowState *s = bs->opaque; |
1428 | 621f0589 | Kevin Wolf | unsigned int nb_clusters; |
1429 | 621f0589 | Kevin Wolf | int ret;
|
1430 | 621f0589 | Kevin Wolf | |
1431 | 621f0589 | Kevin Wolf | /* The zero flag is only supported by version 3 and newer */
|
1432 | 621f0589 | Kevin Wolf | if (s->qcow_version < 3) { |
1433 | 621f0589 | Kevin Wolf | return -ENOTSUP;
|
1434 | 621f0589 | Kevin Wolf | } |
1435 | 621f0589 | Kevin Wolf | |
1436 | 621f0589 | Kevin Wolf | /* Each L2 table is handled by its own loop iteration */
|
1437 | 621f0589 | Kevin Wolf | nb_clusters = size_to_clusters(s, nb_sectors << BDRV_SECTOR_BITS); |
1438 | 621f0589 | Kevin Wolf | |
1439 | 621f0589 | Kevin Wolf | while (nb_clusters > 0) { |
1440 | 621f0589 | Kevin Wolf | ret = zero_single_l2(bs, offset, nb_clusters); |
1441 | 621f0589 | Kevin Wolf | if (ret < 0) { |
1442 | 621f0589 | Kevin Wolf | return ret;
|
1443 | 621f0589 | Kevin Wolf | } |
1444 | 621f0589 | Kevin Wolf | |
1445 | 621f0589 | Kevin Wolf | nb_clusters -= ret; |
1446 | 621f0589 | Kevin Wolf | offset += (ret * s->cluster_size); |
1447 | 621f0589 | Kevin Wolf | } |
1448 | 621f0589 | Kevin Wolf | |
1449 | 621f0589 | Kevin Wolf | return 0; |
1450 | 621f0589 | Kevin Wolf | } |