Revision 9b80ddf3
b/block-qcow2.c | ||
---|---|---|
45 | 45 |
|
46 | 46 |
//#define DEBUG_ALLOC |
47 | 47 |
//#define DEBUG_ALLOC2 |
48 |
//#define DEBUG_EXT |
|
48 | 49 |
|
49 | 50 |
#define QCOW_MAGIC (('Q' << 24) | ('F' << 16) | ('I' << 8) | 0xfb) |
50 | 51 |
#define QCOW_VERSION 2 |
... | ... | |
77 | 78 |
uint64_t snapshots_offset; |
78 | 79 |
} QCowHeader; |
79 | 80 |
|
81 |
|
|
82 |
typedef struct { |
|
83 |
uint32_t magic; |
|
84 |
uint32_t len; |
|
85 |
} QCowExtension; |
|
86 |
#define QCOW_EXT_MAGIC_END 0 |
|
87 |
|
|
88 |
|
|
80 | 89 |
typedef struct __attribute__((packed)) QCowSnapshotHeader { |
81 | 90 |
/* header is 8 byte aligned */ |
82 | 91 |
uint64_t l1_table_offset; |
... | ... | |
183 | 192 |
return 0; |
184 | 193 |
} |
185 | 194 |
|
195 |
|
|
196 |
/* |
|
197 |
* read qcow2 extension and fill bs |
|
198 |
* start reading from start_offset |
|
199 |
* finish reading upon magic of value 0 or when end_offset reached |
|
200 |
* unknown magic is skipped (future extension this version knows nothing about) |
|
201 |
* return 0 upon success, non-0 otherwise |
|
202 |
*/ |
|
203 |
static int qcow_read_extensions(BlockDriverState *bs, uint64_t start_offset, |
|
204 |
uint64_t end_offset) |
|
205 |
{ |
|
206 |
BDRVQcowState *s = bs->opaque; |
|
207 |
QCowExtension ext; |
|
208 |
uint64_t offset; |
|
209 |
|
|
210 |
#ifdef DEBUG_EXT |
|
211 |
printf("qcow_read_extensions: start=%ld end=%ld\n", start_offset, end_offset); |
|
212 |
#endif |
|
213 |
offset = start_offset; |
|
214 |
while (offset < end_offset) { |
|
215 |
|
|
216 |
#ifdef DEBUG_EXT |
|
217 |
/* Sanity check */ |
|
218 |
if (offset > s->cluster_size) |
|
219 |
printf("qcow_handle_extension: suspicious offset %lu\n", offset); |
|
220 |
|
|
221 |
printf("attemting to read extended header in offset %lu\n", offset); |
|
222 |
#endif |
|
223 |
|
|
224 |
if (bdrv_pread(s->hd, offset, &ext, sizeof(ext)) != sizeof(ext)) { |
|
225 |
fprintf(stderr, "qcow_handle_extension: ERROR: pread fail from offset %lu\n", |
|
226 |
offset); |
|
227 |
return 1; |
|
228 |
} |
|
229 |
be32_to_cpus(&ext.magic); |
|
230 |
be32_to_cpus(&ext.len); |
|
231 |
offset += sizeof(ext); |
|
232 |
#ifdef DEBUG_EXT |
|
233 |
printf("ext.magic = 0x%x\n", ext.magic); |
|
234 |
#endif |
|
235 |
switch (ext.magic) { |
|
236 |
case QCOW_EXT_MAGIC_END: |
|
237 |
return 0; |
|
238 |
default: |
|
239 |
/* unknown magic -- just skip it */ |
|
240 |
offset += ((ext.len + 7) & ~7); |
|
241 |
break; |
|
242 |
} |
|
243 |
} |
|
244 |
|
|
245 |
return 0; |
|
246 |
} |
|
247 |
|
|
248 |
|
|
186 | 249 |
static int qcow_open(BlockDriverState *bs, const char *filename, int flags) |
187 | 250 |
{ |
188 | 251 |
BDRVQcowState *s = bs->opaque; |
189 | 252 |
int len, i, shift, ret; |
190 | 253 |
QCowHeader header; |
254 |
uint64_t ext_end; |
|
191 | 255 |
|
192 | 256 |
/* Performance is terrible right now with cache=writethrough due mainly |
193 | 257 |
* to reference count updates. If the user does not explicitly specify |
... | ... | |
270 | 334 |
if (refcount_init(bs) < 0) |
271 | 335 |
goto fail; |
272 | 336 |
|
337 |
/* read qcow2 extensions */ |
|
338 |
if (header.backing_file_offset) |
|
339 |
ext_end = header.backing_file_offset; |
|
340 |
else |
|
341 |
ext_end = s->cluster_size; |
|
342 |
if (qcow_read_extensions(bs, sizeof(header), ext_end)) |
|
343 |
goto fail; |
|
344 |
|
|
273 | 345 |
/* read the backing file name */ |
274 | 346 |
if (header.backing_file_offset != 0) { |
275 | 347 |
len = header.backing_file_size; |
Also available in: Unified diff