VirtualBox

source: vbox/trunk/src/VBox/Storage/QCOW.cpp@ 66486

Last change on this file since 66486 was 66486, checked in by vboxsync, 8 years ago

Storage/VD: Convert all backends to use the region list callbacks, remove the pfnGetSize and pfnGetSectorSize callbacks because they are covered by the region lists

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 92.1 KB
Line 
1/* $Id: QCOW.cpp 66486 2017-04-10 07:23:59Z vboxsync $ */
2/** @file
3 * QCOW - QCOW Disk image.
4 */
5
6/*
7 * Copyright (C) 2011-2016 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*********************************************************************************************************************************
20* Header Files *
21*********************************************************************************************************************************/
22#define LOG_GROUP LOG_GROUP_VD_QCOW
23#include <VBox/vd-plugin.h>
24#include <VBox/err.h>
25
26#include <VBox/log.h>
27#include <iprt/asm.h>
28#include <iprt/assert.h>
29#include <iprt/string.h>
30#include <iprt/alloc.h>
31#include <iprt/path.h>
32#include <iprt/list.h>
33
34#include "VDBackends.h"
35
36/** @page pg_storage_qcow QCOW Storage Backend
37 * The QCOW backend implements support for the qemu copy on write format (short QCOW).
38 * There is no official specification available but the format is described
39 * at http://people.gnome.org/~markmc/qcow-image-format.html for version 2
40 * and http://people.gnome.org/~markmc/qcow-image-format-version-1.html for version 1.
41 *
42 * Missing things to implement:
43 * - v2 image creation and handling of the reference count table. (Blocker to enable support for V2 images)
44 * - cluster encryption
45 * - cluster compression
46 * - compaction
47 * - resizing
48 */
49
50
51/*********************************************************************************************************************************
52* Structures in a QCOW image, big endian *
53*********************************************************************************************************************************/
54
55#pragma pack(1) /* Completely unnecessary. */
56typedef struct QCowHeader
57{
58 /** Magic value. */
59 uint32_t u32Magic;
60 /** Version of the image. */
61 uint32_t u32Version;
62 /** Version dependent data. */
63 union
64 {
65 /** Version 1. */
66 struct
67 {
68 /** Backing file offset. */
69 uint64_t u64BackingFileOffset;
70 /** Size of the backing file. */
71 uint32_t u32BackingFileSize;
72 /** mtime (Modification time?) - can be ignored. */
73 uint32_t u32MTime;
74 /** Logical size of the image in bytes. */
75 uint64_t u64Size;
76 /** Number of bits in the virtual offset used as a cluster offset. */
77 uint8_t u8ClusterBits;
78 /** Number of bits in the virtual offset used for the L2 index. */
79 uint8_t u8L2Bits;
80 /** Padding because the header is not packed in the original source. */
81 uint16_t u16Padding;
82 /** Used cryptographic method. */
83 uint32_t u32CryptMethod;
84 /** Offset of the L1 table in the image in bytes. */
85 uint64_t u64L1TableOffset;
86 } v1;
87 /** Version 2. */
88 struct
89 {
90 /** Backing file offset. */
91 uint64_t u64BackingFileOffset;
92 /** Size of the backing file. */
93 uint32_t u32BackingFileSize;
94 /** Number of bits in the virtual offset used as a cluster offset. */
95 uint32_t u32ClusterBits;
96 /** Logical size of the image. */
97 uint64_t u64Size;
98 /** Used cryptographic method. */
99 uint32_t u32CryptMethod;
100 /** Size of the L1 table in entries (each 8bytes big). */
101 uint32_t u32L1Size;
102 /** Offset of the L1 table in the image in bytes. */
103 uint64_t u64L1TableOffset;
104 /** Start of the refcount table in the image. */
105 uint64_t u64RefcountTableOffset;
106 /** Size of the refcount table in clusters. */
107 uint32_t u32RefcountTableClusters;
108 /** Number of snapshots in the image. */
109 uint32_t u32NbSnapshots;
110 /** Offset of the first snapshot header in the image. */
111 uint64_t u64SnapshotsOffset;
112 } v2;
113 } Version;
114} QCowHeader;
115#pragma pack()
116/** Pointer to a on disk QCOW header. */
117typedef QCowHeader *PQCowHeader;
118
119/** QCOW magic value. */
120#define QCOW_MAGIC UINT32_C(0x514649fb) /* QFI\0xfb */
121/** Size of the V1 header. */
122#define QCOW_V1_HDR_SIZE (48)
123/** Size of the V2 header. */
124#define QCOW_V2_HDR_SIZE (72)
125
126/** Cluster is compressed flag for QCOW images. */
127#define QCOW_V1_COMPRESSED_FLAG RT_BIT_64(63)
128
129/** Copied flag for QCOW2 images. */
130#define QCOW_V2_COPIED_FLAG RT_BIT_64(63)
131/** Cluster is compressed flag for QCOW2 images. */
132#define QCOW_V2_COMPRESSED_FLAG RT_BIT_64(62)
133
134
135/*********************************************************************************************************************************
136* Constants And Macros, Structures and Typedefs *
137*********************************************************************************************************************************/
138
139/**
140 * QCOW L2 cache entry.
141 */
142typedef struct QCOWL2CACHEENTRY
143{
144 /** List node for the search list. */
145 RTLISTNODE NodeSearch;
146 /** List node for the LRU list. */
147 RTLISTNODE NodeLru;
148 /** Reference counter. */
149 uint32_t cRefs;
150 /** The offset of the L2 table, used as search key. */
151 uint64_t offL2Tbl;
152 /** Pointer to the cached L2 table. */
153 uint64_t *paL2Tbl;
154} QCOWL2CACHEENTRY, *PQCOWL2CACHEENTRY;
155
156/** Maximum amount of memory the cache is allowed to use. */
157#define QCOW_L2_CACHE_MEMORY_MAX (2*_1M)
158
159/** QCOW default cluster size for image version 2. */
160#define QCOW2_CLUSTER_SIZE_DEFAULT (64*_1K)
161/** QCOW default cluster size for image version 1. */
162#define QCOW_CLUSTER_SIZE_DEFAULT (4*_1K)
163/** QCOW default L2 table size in clusters. */
164#define QCOW_L2_CLUSTERS_DEFAULT (1)
165
166/**
167 * QCOW image data structure.
168 */
169typedef struct QCOWIMAGE
170{
171 /** Image name. */
172 const char *pszFilename;
173 /** Storage handle. */
174 PVDIOSTORAGE pStorage;
175
176 /** Pointer to the per-disk VD interface list. */
177 PVDINTERFACE pVDIfsDisk;
178 /** Pointer to the per-image VD interface list. */
179 PVDINTERFACE pVDIfsImage;
180 /** Error interface. */
181 PVDINTERFACEERROR pIfError;
182 /** I/O interface. */
183 PVDINTERFACEIOINT pIfIo;
184
185 /** Open flags passed by VBoxHD layer. */
186 unsigned uOpenFlags;
187 /** Image flags defined during creation or determined during open. */
188 unsigned uImageFlags;
189 /** Total size of the image. */
190 uint64_t cbSize;
191 /** Physical geometry of this image. */
192 VDGEOMETRY PCHSGeometry;
193 /** Logical geometry of this image. */
194 VDGEOMETRY LCHSGeometry;
195
196 /** Image version. */
197 unsigned uVersion;
198 /** MTime field - used only to preserve value in opened images, unmodified otherwise. */
199 uint32_t MTime;
200
201 /** Filename of the backing file if any. */
202 char *pszBackingFilename;
203 /** Offset of the filename in the image. */
204 uint64_t offBackingFilename;
205 /** Size of the backing filename excluding \0. */
206 uint32_t cbBackingFilename;
207
208 /** Next offset of a new cluster, aligned to sector size. */
209 uint64_t offNextCluster;
210 /** Cluster size in bytes. */
211 uint32_t cbCluster;
212 /** Number of entries in the L1 table. */
213 uint32_t cL1TableEntries;
214 /** Size of an L1 rounded to the next cluster size. */
215 uint32_t cbL1Table;
216 /** Pointer to the L1 table. */
217 uint64_t *paL1Table;
218 /** Offset of the L1 table. */
219 uint64_t offL1Table;
220
221 /** Size of the L2 table in bytes. */
222 uint32_t cbL2Table;
223 /** Number of entries in the L2 table. */
224 uint32_t cL2TableEntries;
225 /** Memory occupied by the L2 table cache. */
226 size_t cbL2Cache;
227 /** The sorted L2 entry list used for searching. */
228 RTLISTNODE ListSearch;
229 /** The LRU L2 entry list used for eviction. */
230 RTLISTNODE ListLru;
231
232 /** Offset of the refcount table. */
233 uint64_t offRefcountTable;
234 /** Size of the refcount table in bytes. */
235 uint32_t cbRefcountTable;
236 /** Number of entries in the refcount table. */
237 uint32_t cRefcountTableEntries;
238 /** Pointer to the refcount table. */
239 uint64_t *paRefcountTable;
240
241 /** Offset mask for a cluster. */
242 uint64_t fOffsetMask;
243 /** Number of bits to shift to get the L1 index. */
244 uint32_t cL1Shift;
245 /** L2 table mask to get the L2 index. */
246 uint64_t fL2Mask;
247 /** Number of bits to shift to get the L2 index. */
248 uint32_t cL2Shift;
249
250 /** Pointer to the L2 table we are currently allocating
251 * (can be only one at a time). */
252 PQCOWL2CACHEENTRY pL2TblAlloc;
253 /** The static region list. */
254 VDREGIONLIST RegionList;
255} QCOWIMAGE, *PQCOWIMAGE;
256
257/**
258 * State of the async cluster allocation.
259 */
260typedef enum QCOWCLUSTERASYNCALLOCSTATE
261{
262 /** Invalid. */
263 QCOWCLUSTERASYNCALLOCSTATE_INVALID = 0,
264 /** L2 table allocation. */
265 QCOWCLUSTERASYNCALLOCSTATE_L2_ALLOC,
266 /** Link L2 table into L1. */
267 QCOWCLUSTERASYNCALLOCSTATE_L2_LINK,
268 /** Allocate user data cluster. */
269 QCOWCLUSTERASYNCALLOCSTATE_USER_ALLOC,
270 /** Link user data cluster. */
271 QCOWCLUSTERASYNCALLOCSTATE_USER_LINK,
272 /** 32bit blowup. */
273 QCOWCLUSTERASYNCALLOCSTATE_32BIT_HACK = 0x7fffffff
274} QCOWCLUSTERASYNCALLOCSTATE, *PQCOWCLUSTERASYNCALLOCSTATE;
275
276/**
277 * Data needed to track async cluster allocation.
278 */
279typedef struct QCOWCLUSTERASYNCALLOC
280{
281 /** The state of the cluster allocation. */
282 QCOWCLUSTERASYNCALLOCSTATE enmAllocState;
283 /** Old image size to rollback in case of an error. */
284 uint64_t offNextClusterOld;
285 /** L1 index to link if any. */
286 uint32_t idxL1;
287 /** L2 index to link, required in any case. */
288 uint32_t idxL2;
289 /** Start offset of the allocated cluster. */
290 uint64_t offClusterNew;
291 /** L2 cache entry if a L2 table is allocated. */
292 PQCOWL2CACHEENTRY pL2Entry;
293 /** Number of bytes to write. */
294 size_t cbToWrite;
295} QCOWCLUSTERASYNCALLOC, *PQCOWCLUSTERASYNCALLOC;
296
297
298/*********************************************************************************************************************************
299* Static Variables *
300*********************************************************************************************************************************/
301
302/** NULL-terminated array of supported file extensions. */
303static const VDFILEEXTENSION s_aQCowFileExtensions[] =
304{
305 {"qcow", VDTYPE_HDD},
306 {"qcow2", VDTYPE_HDD},
307 {NULL, VDTYPE_INVALID}
308};
309
310
311/*********************************************************************************************************************************
312* Internal Functions *
313*********************************************************************************************************************************/
314
315/**
316 * Return power of 2 or 0 if num error.
317 *
318 * @returns The power of 2 or 0 if the given number is not a power of 2.
319 * @param u32 The number.
320 */
321static uint32_t qcowGetPowerOfTwo(uint32_t u32)
322{
323 if (u32 == 0)
324 return 0;
325 uint32_t uPower2 = 0;
326 while ((u32 & 1) == 0)
327 {
328 u32 >>= 1;
329 uPower2++;
330 }
331 return u32 == 1 ? uPower2 : 0;
332}
333
334
335/**
336 * Converts the image header to the host endianess and performs basic checks.
337 *
338 * @returns Whether the given header is valid or not.
339 * @param pHeader Pointer to the header to convert.
340 */
341static bool qcowHdrConvertToHostEndianess(PQCowHeader pHeader)
342{
343 pHeader->u32Magic = RT_BE2H_U32(pHeader->u32Magic);
344 pHeader->u32Version = RT_BE2H_U32(pHeader->u32Version);
345
346 if (pHeader->u32Magic != QCOW_MAGIC)
347 return false;
348
349 if (pHeader->u32Version == 1)
350 {
351 pHeader->Version.v1.u64BackingFileOffset = RT_BE2H_U64(pHeader->Version.v1.u64BackingFileOffset);
352 pHeader->Version.v1.u32BackingFileSize = RT_BE2H_U32(pHeader->Version.v1.u32BackingFileSize);
353 pHeader->Version.v1.u32MTime = RT_BE2H_U32(pHeader->Version.v1.u32MTime);
354 pHeader->Version.v1.u64Size = RT_BE2H_U64(pHeader->Version.v1.u64Size);
355 pHeader->Version.v1.u32CryptMethod = RT_BE2H_U32(pHeader->Version.v1.u32CryptMethod);
356 pHeader->Version.v1.u64L1TableOffset = RT_BE2H_U64(pHeader->Version.v1.u64L1TableOffset);
357 }
358 else if (pHeader->u32Version == 2)
359 {
360 pHeader->Version.v2.u64BackingFileOffset = RT_BE2H_U64(pHeader->Version.v2.u64BackingFileOffset);
361 pHeader->Version.v2.u32BackingFileSize = RT_BE2H_U32(pHeader->Version.v2.u32BackingFileSize);
362 pHeader->Version.v2.u32ClusterBits = RT_BE2H_U32(pHeader->Version.v2.u32ClusterBits);
363 pHeader->Version.v2.u64Size = RT_BE2H_U64(pHeader->Version.v2.u64Size);
364 pHeader->Version.v2.u32CryptMethod = RT_BE2H_U32(pHeader->Version.v2.u32CryptMethod);
365 pHeader->Version.v2.u32L1Size = RT_BE2H_U32(pHeader->Version.v2.u32L1Size);
366 pHeader->Version.v2.u64L1TableOffset = RT_BE2H_U64(pHeader->Version.v2.u64L1TableOffset);
367 pHeader->Version.v2.u64RefcountTableOffset = RT_BE2H_U64(pHeader->Version.v2.u64RefcountTableOffset);
368 pHeader->Version.v2.u32RefcountTableClusters = RT_BE2H_U32(pHeader->Version.v2.u32RefcountTableClusters);
369 pHeader->Version.v2.u32NbSnapshots = RT_BE2H_U32(pHeader->Version.v2.u32NbSnapshots);
370 pHeader->Version.v2.u64SnapshotsOffset = RT_BE2H_U64(pHeader->Version.v2.u64SnapshotsOffset);
371 }
372 else
373 return false;
374
375 return true;
376}
377
378/**
379 * Creates a QCOW header from the given image state.
380 *
381 * @returns nothing.
382 * @param pImage Image instance data.
383 * @param pHeader Pointer to the header to convert.
384 * @param pcbHeader Where to store the size of the header to write.
385 */
386static void qcowHdrConvertFromHostEndianess(PQCOWIMAGE pImage, PQCowHeader pHeader,
387 size_t *pcbHeader)
388{
389 memset(pHeader, 0, sizeof(QCowHeader));
390
391 pHeader->u32Magic = RT_H2BE_U32(QCOW_MAGIC);
392 pHeader->u32Version = RT_H2BE_U32(pImage->uVersion);
393 if (pImage->uVersion == 1)
394 {
395 pHeader->Version.v1.u64BackingFileOffset = RT_H2BE_U64(pImage->offBackingFilename);
396 pHeader->Version.v1.u32BackingFileSize = RT_H2BE_U32(pImage->cbBackingFilename);
397 pHeader->Version.v1.u32MTime = RT_H2BE_U32(pImage->MTime);
398 pHeader->Version.v1.u64Size = RT_H2BE_U64(pImage->cbSize);
399 pHeader->Version.v1.u8ClusterBits = (uint8_t)qcowGetPowerOfTwo(pImage->cbCluster);
400 pHeader->Version.v1.u8L2Bits = (uint8_t)qcowGetPowerOfTwo(pImage->cL2TableEntries);
401 pHeader->Version.v1.u32CryptMethod = RT_H2BE_U32(0);
402 pHeader->Version.v1.u64L1TableOffset = RT_H2BE_U64(pImage->offL1Table);
403 *pcbHeader = QCOW_V1_HDR_SIZE;
404 }
405 else if (pImage->uVersion == 2)
406 {
407 pHeader->Version.v2.u64BackingFileOffset = RT_H2BE_U64(pImage->offBackingFilename);
408 pHeader->Version.v2.u32BackingFileSize = RT_H2BE_U32(pImage->cbBackingFilename);
409 pHeader->Version.v2.u32ClusterBits = RT_H2BE_U32(qcowGetPowerOfTwo(pImage->cbCluster));
410 pHeader->Version.v2.u64Size = RT_H2BE_U64(pImage->cbSize);
411 pHeader->Version.v2.u32CryptMethod = RT_H2BE_U32(0);
412 pHeader->Version.v2.u32L1Size = RT_H2BE_U32(pImage->cL1TableEntries);
413 pHeader->Version.v2.u64L1TableOffset = RT_H2BE_U64(pImage->offL1Table);
414 pHeader->Version.v2.u64RefcountTableOffset = RT_H2BE_U64(pImage->offRefcountTable);
415 pHeader->Version.v2.u32RefcountTableClusters = RT_H2BE_U32(pImage->cbRefcountTable / pImage->cbCluster);
416 pHeader->Version.v2.u32NbSnapshots = RT_H2BE_U32(0);
417 pHeader->Version.v2.u64SnapshotsOffset = RT_H2BE_U64((uint64_t)0);
418 *pcbHeader = QCOW_V2_HDR_SIZE;
419 }
420 else
421 AssertMsgFailed(("Invalid version of the QCOW image format %d\n", pImage->uVersion));
422}
423
424/**
425 * Convert table entries from little endian to host endianess.
426 *
427 * @returns nothing.
428 * @param paTbl Pointer to the table.
429 * @param cEntries Number of entries in the table.
430 */
431static void qcowTableConvertToHostEndianess(uint64_t *paTbl, uint32_t cEntries)
432{
433 while(cEntries-- > 0)
434 {
435 *paTbl = RT_BE2H_U64(*paTbl);
436 paTbl++;
437 }
438}
439
440/**
441 * Convert table entries from host to little endian format.
442 *
443 * @returns nothing.
444 * @param paTblImg Pointer to the table which will store the little endian table.
445 * @param paTbl The source table to convert.
446 * @param cEntries Number of entries in the table.
447 */
448static void qcowTableConvertFromHostEndianess(uint64_t *paTblImg, uint64_t *paTbl,
449 uint32_t cEntries)
450{
451 while(cEntries-- > 0)
452 {
453 *paTblImg = RT_H2BE_U64(*paTbl);
454 paTbl++;
455 paTblImg++;
456 }
457}
458
459/**
460 * Creates the L2 table cache.
461 *
462 * @returns VBox status code.
463 * @param pImage The image instance data.
464 */
465static int qcowL2TblCacheCreate(PQCOWIMAGE pImage)
466{
467 pImage->cbL2Cache = 0;
468 RTListInit(&pImage->ListSearch);
469 RTListInit(&pImage->ListLru);
470
471 return VINF_SUCCESS;
472}
473
474/**
475 * Destroys the L2 table cache.
476 *
477 * @returns nothing.
478 * @param pImage The image instance data.
479 */
480static void qcowL2TblCacheDestroy(PQCOWIMAGE pImage)
481{
482 PQCOWL2CACHEENTRY pL2Entry;
483 PQCOWL2CACHEENTRY pL2Next;
484 RTListForEachSafe(&pImage->ListSearch, pL2Entry, pL2Next, QCOWL2CACHEENTRY, NodeSearch)
485 {
486 Assert(!pL2Entry->cRefs);
487
488 RTListNodeRemove(&pL2Entry->NodeSearch);
489 RTMemPageFree(pL2Entry->paL2Tbl, pImage->cbL2Table);
490 RTMemFree(pL2Entry);
491 }
492
493 pImage->cbL2Cache = 0;
494 RTListInit(&pImage->ListSearch);
495 RTListInit(&pImage->ListLru);
496}
497
498/**
499 * Returns the L2 table matching the given offset or NULL if none could be found.
500 *
501 * @returns Pointer to the L2 table cache entry or NULL.
502 * @param pImage The image instance data.
503 * @param offL2Tbl Offset of the L2 table to search for.
504 */
505static PQCOWL2CACHEENTRY qcowL2TblCacheRetain(PQCOWIMAGE pImage, uint64_t offL2Tbl)
506{
507 if ( pImage->pL2TblAlloc
508 && pImage->pL2TblAlloc->offL2Tbl == offL2Tbl)
509 {
510 pImage->pL2TblAlloc->cRefs++;
511 return pImage->pL2TblAlloc;
512 }
513
514 PQCOWL2CACHEENTRY pL2Entry;
515 RTListForEach(&pImage->ListSearch, pL2Entry, QCOWL2CACHEENTRY, NodeSearch)
516 {
517 if (pL2Entry->offL2Tbl == offL2Tbl)
518 break;
519 }
520
521 if (!RTListNodeIsDummy(&pImage->ListSearch, pL2Entry, QCOWL2CACHEENTRY, NodeSearch))
522 {
523 /* Update LRU list. */
524 RTListNodeRemove(&pL2Entry->NodeLru);
525 RTListPrepend(&pImage->ListLru, &pL2Entry->NodeLru);
526 pL2Entry->cRefs++;
527 return pL2Entry;
528 }
529
530 return NULL;
531}
532
533/**
534 * Releases a L2 table cache entry.
535 *
536 * @returns nothing.
537 * @param pL2Entry The L2 cache entry.
538 */
539static void qcowL2TblCacheEntryRelease(PQCOWL2CACHEENTRY pL2Entry)
540{
541 Assert(pL2Entry->cRefs > 0);
542 pL2Entry->cRefs--;
543}
544
545/**
546 * Allocates a new L2 table from the cache evicting old entries if required.
547 *
548 * @returns Pointer to the L2 cache entry or NULL.
549 * @param pImage The image instance data.
550 */
551static PQCOWL2CACHEENTRY qcowL2TblCacheEntryAlloc(PQCOWIMAGE pImage)
552{
553 PQCOWL2CACHEENTRY pL2Entry = NULL;
554
555 if (pImage->cbL2Cache + pImage->cbL2Table <= QCOW_L2_CACHE_MEMORY_MAX)
556 {
557 /* Add a new entry. */
558 pL2Entry = (PQCOWL2CACHEENTRY)RTMemAllocZ(sizeof(QCOWL2CACHEENTRY));
559 if (pL2Entry)
560 {
561 pL2Entry->paL2Tbl = (uint64_t *)RTMemPageAllocZ(pImage->cbL2Table);
562 if (RT_UNLIKELY(!pL2Entry->paL2Tbl))
563 {
564 RTMemFree(pL2Entry);
565 pL2Entry = NULL;
566 }
567 else
568 {
569 pL2Entry->cRefs = 1;
570 pImage->cbL2Cache += pImage->cbL2Table;
571 }
572 }
573 }
574 else
575 {
576 /* Evict the last not in use entry and use it */
577 Assert(!RTListIsEmpty(&pImage->ListLru));
578
579 RTListForEachReverse(&pImage->ListLru, pL2Entry, QCOWL2CACHEENTRY, NodeLru)
580 {
581 if (!pL2Entry->cRefs)
582 break;
583 }
584
585 if (!RTListNodeIsDummy(&pImage->ListSearch, pL2Entry, QCOWL2CACHEENTRY, NodeSearch))
586 {
587 RTListNodeRemove(&pL2Entry->NodeSearch);
588 RTListNodeRemove(&pL2Entry->NodeLru);
589 pL2Entry->offL2Tbl = 0;
590 pL2Entry->cRefs = 1;
591 }
592 else
593 pL2Entry = NULL;
594 }
595
596 return pL2Entry;
597}
598
599/**
600 * Frees a L2 table cache entry.
601 *
602 * @returns nothing.
603 * @param pImage The image instance data.
604 * @param pL2Entry The L2 cache entry to free.
605 */
606static void qcowL2TblCacheEntryFree(PQCOWIMAGE pImage, PQCOWL2CACHEENTRY pL2Entry)
607{
608 Assert(!pL2Entry->cRefs);
609 RTMemPageFree(pL2Entry->paL2Tbl, pImage->cbL2Table);
610 RTMemFree(pL2Entry);
611
612 pImage->cbL2Cache -= pImage->cbL2Table;
613}
614
615/**
616 * Inserts an entry in the L2 table cache.
617 *
618 * @returns nothing.
619 * @param pImage The image instance data.
620 * @param pL2Entry The L2 cache entry to insert.
621 */
622static void qcowL2TblCacheEntryInsert(PQCOWIMAGE pImage, PQCOWL2CACHEENTRY pL2Entry)
623{
624 Assert(pL2Entry->offL2Tbl > 0);
625
626 /* Insert at the top of the LRU list. */
627 RTListPrepend(&pImage->ListLru, &pL2Entry->NodeLru);
628
629 if (RTListIsEmpty(&pImage->ListSearch))
630 {
631 RTListAppend(&pImage->ListSearch, &pL2Entry->NodeSearch);
632 }
633 else
634 {
635 /* Insert into search list. */
636 PQCOWL2CACHEENTRY pIt;
637 pIt = RTListGetFirst(&pImage->ListSearch, QCOWL2CACHEENTRY, NodeSearch);
638 if (pIt->offL2Tbl > pL2Entry->offL2Tbl)
639 RTListPrepend(&pImage->ListSearch, &pL2Entry->NodeSearch);
640 else
641 {
642 bool fInserted = false;
643
644 RTListForEach(&pImage->ListSearch, pIt, QCOWL2CACHEENTRY, NodeSearch)
645 {
646 Assert(pIt->offL2Tbl != pL2Entry->offL2Tbl);
647 if (pIt->offL2Tbl < pL2Entry->offL2Tbl)
648 {
649 RTListNodeInsertAfter(&pIt->NodeSearch, &pL2Entry->NodeSearch);
650 fInserted = true;
651 break;
652 }
653 }
654 Assert(fInserted);
655 }
656 }
657}
658
659/**
660 * Fetches the L2 from the given offset trying the LRU cache first and
661 * reading it from the image after a cache miss.
662 *
663 * @returns VBox status code.
664 * @param pImage Image instance data.
665 * @param pIoCtx The I/O context.
666 * @param offL2Tbl The offset of the L2 table in the image.
667 * @param ppL2Entry Where to store the L2 table on success.
668 */
669static int qcowL2TblCacheFetch(PQCOWIMAGE pImage, PVDIOCTX pIoCtx, uint64_t offL2Tbl,
670 PQCOWL2CACHEENTRY *ppL2Entry)
671{
672 int rc = VINF_SUCCESS;
673
674 /* Try to fetch the L2 table from the cache first. */
675 PQCOWL2CACHEENTRY pL2Entry = qcowL2TblCacheRetain(pImage, offL2Tbl);
676 if (!pL2Entry)
677 {
678 pL2Entry = qcowL2TblCacheEntryAlloc(pImage);
679
680 if (pL2Entry)
681 {
682 /* Read from the image. */
683 PVDMETAXFER pMetaXfer;
684
685 pL2Entry->offL2Tbl = offL2Tbl;
686 rc = vdIfIoIntFileReadMeta(pImage->pIfIo, pImage->pStorage,
687 offL2Tbl, pL2Entry->paL2Tbl,
688 pImage->cbL2Table, pIoCtx,
689 &pMetaXfer, NULL, NULL);
690 if (RT_SUCCESS(rc))
691 {
692 vdIfIoIntMetaXferRelease(pImage->pIfIo, pMetaXfer);
693#if defined(RT_LITTLE_ENDIAN)
694 qcowTableConvertToHostEndianess(pL2Entry->paL2Tbl, pImage->cL2TableEntries);
695#endif
696 qcowL2TblCacheEntryInsert(pImage, pL2Entry);
697 }
698 else
699 {
700 qcowL2TblCacheEntryRelease(pL2Entry);
701 qcowL2TblCacheEntryFree(pImage, pL2Entry);
702 }
703 }
704 else
705 rc = VERR_NO_MEMORY;
706 }
707
708 if (RT_SUCCESS(rc))
709 *ppL2Entry = pL2Entry;
710
711 return rc;
712}
713
714/**
715 * Sets the L1, L2 and offset bitmasks and L1 and L2 bit shift members.
716 *
717 * @returns nothing.
718 * @param pImage The image instance data.
719 */
720static void qcowTableMasksInit(PQCOWIMAGE pImage)
721{
722 uint32_t cClusterBits, cL2TableBits;
723
724 cClusterBits = qcowGetPowerOfTwo(pImage->cbCluster);
725 cL2TableBits = qcowGetPowerOfTwo(pImage->cL2TableEntries);
726
727 Assert(cClusterBits + cL2TableBits < 64);
728
729 pImage->fOffsetMask = ((uint64_t)pImage->cbCluster - 1);
730 pImage->fL2Mask = ((uint64_t)pImage->cL2TableEntries - 1) << cClusterBits;
731 pImage->cL2Shift = cClusterBits;
732 pImage->cL1Shift = cClusterBits + cL2TableBits;
733}
734
735/**
736 * Converts a given logical offset into the
737 *
738 * @returns nothing.
739 * @param pImage The image instance data.
740 * @param off The logical offset to convert.
741 * @param pidxL1 Where to store the index in the L1 table on success.
742 * @param pidxL2 Where to store the index in the L2 table on success.
743 * @param poffCluster Where to store the offset in the cluster on success.
744 */
745DECLINLINE(void) qcowConvertLogicalOffset(PQCOWIMAGE pImage, uint64_t off, uint32_t *pidxL1,
746 uint32_t *pidxL2, uint32_t *poffCluster)
747{
748 AssertPtr(pidxL1);
749 AssertPtr(pidxL2);
750 AssertPtr(poffCluster);
751
752 *poffCluster = off & pImage->fOffsetMask;
753 *pidxL1 = off >> pImage->cL1Shift;
754 *pidxL2 = (off & pImage->fL2Mask) >> pImage->cL2Shift;
755}
756
757/**
758 * Converts Cluster size to a byte size.
759 *
760 * @returns Number of bytes derived from the given number of clusters.
761 * @param pImage The image instance data.
762 * @param cClusters The clusters to convert.
763 */
764DECLINLINE(uint64_t) qcowCluster2Byte(PQCOWIMAGE pImage, uint64_t cClusters)
765{
766 return cClusters * pImage->cbCluster;
767}
768
769/**
770 * Converts number of bytes to cluster size rounding to the next cluster.
771 *
772 * @returns Number of bytes derived from the given number of clusters.
773 * @param pImage The image instance data.
774 * @param cb Number of bytes to convert.
775 */
776DECLINLINE(uint64_t) qcowByte2Cluster(PQCOWIMAGE pImage, uint64_t cb)
777{
778 return cb / pImage->cbCluster + (cb % pImage->cbCluster ? 1 : 0);
779}
780
781/**
782 * Allocates a new cluster in the image.
783 *
784 * @returns The start offset of the new cluster in the image.
785 * @param pImage The image instance data.
786 * @param cClusters Number of clusters to allocate.
787 */
788DECLINLINE(uint64_t) qcowClusterAllocate(PQCOWIMAGE pImage, uint32_t cClusters)
789{
790 uint64_t offCluster;
791
792 offCluster = pImage->offNextCluster;
793 pImage->offNextCluster += cClusters*pImage->cbCluster;
794
795 return offCluster;
796}
797
798/**
799 * Returns the real image offset for a given cluster or an error if the cluster is not
800 * yet allocated.
801 *
802 * @returns VBox status code.
803 * VERR_VD_BLOCK_FREE if the cluster is not yet allocated.
804 * @param pImage The image instance data.
805 * @param pIoCtx The I/O context.
806 * @param idxL1 The L1 index.
807 * @param idxL2 The L2 index.
808 * @param offCluster Offset inside the cluster.
809 * @param poffImage Where to store the image offset on success;
810 */
811static int qcowConvertToImageOffset(PQCOWIMAGE pImage, PVDIOCTX pIoCtx,
812 uint32_t idxL1, uint32_t idxL2,
813 uint32_t offCluster, uint64_t *poffImage)
814{
815 int rc = VERR_VD_BLOCK_FREE;
816
817 AssertReturn(idxL1 < pImage->cL1TableEntries, VERR_INVALID_PARAMETER);
818 AssertReturn(idxL2 < pImage->cL2TableEntries, VERR_INVALID_PARAMETER);
819
820 if (pImage->paL1Table[idxL1])
821 {
822 PQCOWL2CACHEENTRY pL2Entry;
823
824 rc = qcowL2TblCacheFetch(pImage, pIoCtx, pImage->paL1Table[idxL1], &pL2Entry);
825 if (RT_SUCCESS(rc))
826 {
827 /* Get real file offset. */
828 if (pL2Entry->paL2Tbl[idxL2])
829 {
830 uint64_t off = pL2Entry->paL2Tbl[idxL2];
831
832 /* Strip flags */
833 if (pImage->uVersion == 2)
834 {
835 if (RT_UNLIKELY(off & QCOW_V2_COMPRESSED_FLAG))
836 rc = VERR_NOT_SUPPORTED;
837 else
838 off &= ~(QCOW_V2_COMPRESSED_FLAG | QCOW_V2_COPIED_FLAG);
839 }
840 else
841 {
842 if (RT_UNLIKELY(off & QCOW_V1_COMPRESSED_FLAG))
843 rc = VERR_NOT_SUPPORTED;
844 else
845 off &= ~QCOW_V1_COMPRESSED_FLAG;
846 }
847
848 *poffImage = off + offCluster;
849 }
850 else
851 rc = VERR_VD_BLOCK_FREE;
852
853 qcowL2TblCacheEntryRelease(pL2Entry);
854 }
855 }
856
857 return rc;
858}
859
860/**
861 * Write the given table to image converting to the image endianess if required.
862 *
863 * @returns VBox status code.
864 * @param pImage The image instance data.
865 * @param pIoCtx The I/O context.
866 * @param offTbl The offset the table should be written to.
867 * @param paTbl The table to write.
868 * @param cbTbl Size of the table in bytes.
869 * @param cTblEntries Number entries in the table.
870 * @param pfnComplete Callback called when the write completes.
871 * @param pvUser Opaque user data to pass in the completion callback.
872 */
873static int qcowTblWrite(PQCOWIMAGE pImage, PVDIOCTX pIoCtx, uint64_t offTbl, uint64_t *paTbl,
874 size_t cbTbl, unsigned cTblEntries,
875 PFNVDXFERCOMPLETED pfnComplete, void *pvUser)
876{
877 int rc = VINF_SUCCESS;
878
879#if defined(RT_LITTLE_ENDIAN)
880 uint64_t *paTblImg = (uint64_t *)RTMemAllocZ(cbTbl);
881 if (paTblImg)
882 {
883 qcowTableConvertFromHostEndianess(paTblImg, paTbl, cTblEntries);
884 rc = vdIfIoIntFileWriteMeta(pImage->pIfIo, pImage->pStorage,
885 offTbl, paTblImg, cbTbl,
886 pIoCtx, pfnComplete, pvUser);
887 RTMemFree(paTblImg);
888 }
889 else
890 rc = VERR_NO_MEMORY;
891#else
892 /* Write table directly. */
893 RT_NOREF(cTblEntries);
894 rc = vdIfIoIntFileWriteMeta(pImage->pIfIo, pImage->pStorage,
895 offTbl, paTbl, cbTbl, pIoCtx,
896 pfnComplete, pvUser);
897#endif
898
899 return rc;
900}
901
902/**
903 * Internal. Flush image data to disk.
904 */
905static int qcowFlushImage(PQCOWIMAGE pImage)
906{
907 int rc = VINF_SUCCESS;
908
909 if ( pImage->pStorage
910 && !(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
911 && pImage->cbL1Table)
912 {
913 QCowHeader Header;
914
915#if defined(RT_LITTLE_ENDIAN)
916 uint64_t *paL1TblImg = (uint64_t *)RTMemAllocZ(pImage->cbL1Table);
917 if (paL1TblImg)
918 {
919 qcowTableConvertFromHostEndianess(paL1TblImg, pImage->paL1Table,
920 pImage->cL1TableEntries);
921 rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage,
922 pImage->offL1Table, paL1TblImg,
923 pImage->cbL1Table);
924 RTMemFree(paL1TblImg);
925 }
926 else
927 rc = VERR_NO_MEMORY;
928#else
929 /* Write L1 table directly. */
930 rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage, pImage->offL1Table,
931 pImage->paL1Table, pImage->cbL1Table);
932#endif
933 if (RT_SUCCESS(rc))
934 {
935 /* Write header. */
936 size_t cbHeader = 0;
937 qcowHdrConvertFromHostEndianess(pImage, &Header, &cbHeader);
938 rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage, 0, &Header,
939 cbHeader);
940 if (RT_SUCCESS(rc))
941 rc = vdIfIoIntFileFlushSync(pImage->pIfIo, pImage->pStorage);
942 }
943 }
944
945 return rc;
946}
947
948/**
949 * Internal. Free all allocated space for representing an image except pImage,
950 * and optionally delete the image from disk.
951 */
952static int qcowFreeImage(PQCOWIMAGE pImage, bool fDelete)
953{
954 int rc = VINF_SUCCESS;
955
956 /* Freeing a never allocated image (e.g. because the open failed) is
957 * not signalled as an error. After all nothing bad happens. */
958 if (pImage)
959 {
960 if (pImage->pStorage)
961 {
962 /* No point updating the file that is deleted anyway. */
963 if (!fDelete)
964 qcowFlushImage(pImage);
965
966 rc = vdIfIoIntFileClose(pImage->pIfIo, pImage->pStorage);
967 pImage->pStorage = NULL;
968 }
969
970 if (pImage->paL1Table)
971 RTMemFree(pImage->paL1Table);
972
973 if (pImage->pszBackingFilename)
974 {
975 RTMemFree(pImage->pszBackingFilename);
976 pImage->pszBackingFilename = NULL;
977 }
978
979 qcowL2TblCacheDestroy(pImage);
980
981 if (fDelete && pImage->pszFilename)
982 vdIfIoIntFileDelete(pImage->pIfIo, pImage->pszFilename);
983 }
984
985 LogFlowFunc(("returns %Rrc\n", rc));
986 return rc;
987}
988
989/**
990 * Validates the header.
991 *
992 * @returns VBox status code.
993 * @param pImage Image backend instance data.
994 * @param pHdr The header to validate.
995 * @param cbFile The image file size in bytes.
996 */
997static int qcowHdrValidate(PQCOWIMAGE pImage, PQCowHeader pHdr, uint64_t cbFile)
998{
999 if (pHdr->u32Version == 1)
1000 {
1001 /* Check that the backing filename is contained in the file. */
1002 if (pHdr->Version.v1.u64BackingFileOffset + pHdr->Version.v1.u32BackingFileSize > cbFile)
1003 return vdIfError(pImage->pIfError, VERR_INVALID_STATE, RT_SRC_POS,
1004 N_("QCOW: Backing file offset and size exceed size of image '%s' (%u vs %u)"),
1005 pImage->pszFilename, pHdr->Version.v1.u64BackingFileOffset + pHdr->Version.v1.u32BackingFileSize,
1006 cbFile);
1007
1008 /* Check that the cluster bits indicate at least a 512byte sector size. */
1009 if (RT_BIT_32(pHdr->Version.v1.u8ClusterBits) < 512)
1010 return vdIfError(pImage->pIfError, VERR_INVALID_STATE, RT_SRC_POS,
1011 N_("QCOW: Cluster size is too small for image '%s' (%u vs %u)"),
1012 pImage->pszFilename, RT_BIT_32(pHdr->Version.v1.u8ClusterBits), 512);
1013
1014 /*
1015 * Check for possible overflow when multiplying cluster size and L2 entry count because it is used
1016 * to calculate the number of L1 table entries later on.
1017 */
1018 if (RT_BIT_32(pHdr->Version.v1.u8L2Bits) * RT_BIT_32(pHdr->Version.v1.u8ClusterBits) == 0)
1019 return vdIfError(pImage->pIfError, VERR_INVALID_STATE, RT_SRC_POS,
1020 N_("QCOW: Overflow during L1 table size calculation for image '%s'"),
1021 pImage->pszFilename);
1022 }
1023 else if (pHdr->u32Version == 2)
1024 {
1025 /* Check that the backing filename is contained in the file. */
1026 if (pHdr->Version.v2.u64BackingFileOffset + pHdr->Version.v2.u32BackingFileSize > cbFile)
1027 return vdIfError(pImage->pIfError, VERR_INVALID_STATE, RT_SRC_POS,
1028 N_("QCOW: Backing file offset and size exceed size of image '%s' (%u vs %u)"),
1029 pImage->pszFilename, pHdr->Version.v2.u64BackingFileOffset + pHdr->Version.v2.u32BackingFileSize,
1030 cbFile);
1031
1032 /* Check that the cluster bits indicate at least a 512byte sector size. */
1033 if (RT_BIT_32(pHdr->Version.v2.u32ClusterBits) < 512)
1034 return vdIfError(pImage->pIfError, VERR_INVALID_STATE, RT_SRC_POS,
1035 N_("QCOW: Cluster size is too small for image '%s' (%u vs %u)"),
1036 pImage->pszFilename, RT_BIT_32(pHdr->Version.v2.u32ClusterBits), 512);
1037 }
1038 else
1039 return vdIfError(pImage->pIfError, VERR_NOT_SUPPORTED, RT_SRC_POS,
1040 N_("QCOW: Version %u in image '%s' is not supported"),
1041 pHdr->u32Version, pImage->pszFilename);
1042
1043 return VINF_SUCCESS;
1044}
1045
1046/**
1047 * Internal: Open an image, constructing all necessary data structures.
1048 */
1049static int qcowOpenImage(PQCOWIMAGE pImage, unsigned uOpenFlags)
1050{
1051 pImage->uOpenFlags = uOpenFlags;
1052
1053 pImage->pIfError = VDIfErrorGet(pImage->pVDIfsDisk);
1054 pImage->pIfIo = VDIfIoIntGet(pImage->pVDIfsImage);
1055 AssertPtrReturn(pImage->pIfIo, VERR_INVALID_PARAMETER);
1056
1057 int rc = qcowL2TblCacheCreate(pImage);
1058 if (RT_SUCCESS(rc))
1059 {
1060 /* Open the image. */
1061 rc = vdIfIoIntFileOpen(pImage->pIfIo, pImage->pszFilename,
1062 VDOpenFlagsToFileOpenFlags(uOpenFlags,
1063 false /* fCreate */),
1064 &pImage->pStorage);
1065 if (RT_SUCCESS(rc))
1066 {
1067 uint64_t cbFile;
1068 rc = vdIfIoIntFileGetSize(pImage->pIfIo, pImage->pStorage, &cbFile);
1069 if ( RT_SUCCESS(rc)
1070 && cbFile > sizeof(QCowHeader))
1071 {
1072 QCowHeader Header;
1073
1074 rc = vdIfIoIntFileReadSync(pImage->pIfIo, pImage->pStorage, 0, &Header, sizeof(Header));
1075 if ( RT_SUCCESS(rc)
1076 && qcowHdrConvertToHostEndianess(&Header))
1077 {
1078 pImage->offNextCluster = RT_ALIGN_64(cbFile, 512); /* Align image to sector boundary. */
1079 Assert(pImage->offNextCluster >= cbFile);
1080
1081 rc = qcowHdrValidate(pImage, &Header, cbFile);
1082 if (RT_SUCCESS(rc))
1083 {
1084 if (Header.u32Version == 1)
1085 {
1086 if (!Header.Version.v1.u32CryptMethod)
1087 {
1088 pImage->uVersion = 1;
1089 pImage->offBackingFilename = Header.Version.v1.u64BackingFileOffset;
1090 pImage->cbBackingFilename = Header.Version.v1.u32BackingFileSize;
1091 pImage->MTime = Header.Version.v1.u32MTime;
1092 pImage->cbSize = Header.Version.v1.u64Size;
1093 pImage->cbCluster = RT_BIT_32(Header.Version.v1.u8ClusterBits);
1094 pImage->cL2TableEntries = RT_BIT_32(Header.Version.v1.u8L2Bits);
1095 pImage->cbL2Table = RT_ALIGN_64(pImage->cL2TableEntries * sizeof(uint64_t), pImage->cbCluster);
1096 pImage->offL1Table = Header.Version.v1.u64L1TableOffset;
1097 pImage->cL1TableEntries = pImage->cbSize / (pImage->cbCluster * pImage->cL2TableEntries);
1098 if (pImage->cbSize % (pImage->cbCluster * pImage->cL2TableEntries))
1099 pImage->cL1TableEntries++;
1100 }
1101 else
1102 rc = vdIfError(pImage->pIfError, VERR_NOT_SUPPORTED, RT_SRC_POS,
1103 N_("QCow: Encrypted image '%s' is not supported"),
1104 pImage->pszFilename);
1105 }
1106 else if (Header.u32Version == 2)
1107 {
1108 if (Header.Version.v2.u32CryptMethod)
1109 rc = vdIfError(pImage->pIfError, VERR_NOT_SUPPORTED, RT_SRC_POS,
1110 N_("QCow: Encrypted image '%s' is not supported"),
1111 pImage->pszFilename);
1112 else if (Header.Version.v2.u32NbSnapshots)
1113 rc = vdIfError(pImage->pIfError, VERR_NOT_SUPPORTED, RT_SRC_POS,
1114 N_("QCow: Image '%s' contains snapshots which is not supported"),
1115 pImage->pszFilename);
1116 else
1117 {
1118 pImage->uVersion = 2;
1119 pImage->offBackingFilename = Header.Version.v2.u64BackingFileOffset;
1120 pImage->cbBackingFilename = Header.Version.v2.u32BackingFileSize;
1121 pImage->cbSize = Header.Version.v2.u64Size;
1122 pImage->cbCluster = RT_BIT_32(Header.Version.v2.u32ClusterBits);
1123 pImage->cL2TableEntries = pImage->cbCluster / sizeof(uint64_t);
1124 pImage->cbL2Table = pImage->cbCluster;
1125 pImage->offL1Table = Header.Version.v2.u64L1TableOffset;
1126 pImage->cL1TableEntries = Header.Version.v2.u32L1Size;
1127 pImage->offRefcountTable = Header.Version.v2.u64RefcountTableOffset;
1128 pImage->cbRefcountTable = qcowCluster2Byte(pImage, Header.Version.v2.u32RefcountTableClusters);
1129 pImage->cRefcountTableEntries = pImage->cbRefcountTable / sizeof(uint64_t);
1130 }
1131 }
1132 else
1133 rc = vdIfError(pImage->pIfError, VERR_NOT_SUPPORTED, RT_SRC_POS,
1134 N_("QCow: Image '%s' uses version %u which is not supported"),
1135 pImage->pszFilename, Header.u32Version);
1136
1137 pImage->cbL1Table = RT_ALIGN_64(pImage->cL1TableEntries * sizeof(uint64_t), pImage->cbCluster);
1138 if ((uint64_t)pImage->cbL1Table != RT_ALIGN_64(pImage->cL1TableEntries * sizeof(uint64_t), pImage->cbCluster))
1139 rc = vdIfError(pImage->pIfError, VERR_INVALID_STATE, RT_SRC_POS,
1140 N_("QCOW: L1 table size overflow in image '%s'"),
1141 pImage->pszFilename);
1142 }
1143
1144 /** @todo Check that there are no compressed clusters in the image
1145 * (by traversing the L2 tables and checking each offset).
1146 * Refuse to open such images.
1147 */
1148
1149 if ( RT_SUCCESS(rc)
1150 && pImage->cbBackingFilename
1151 && pImage->offBackingFilename)
1152 {
1153 /* Load backing filename from image. */
1154 pImage->pszBackingFilename = (char *)RTMemAllocZ(pImage->cbBackingFilename + 1); /* +1 for \0 terminator. */
1155 if (pImage->pszBackingFilename)
1156 {
1157 rc = vdIfIoIntFileReadSync(pImage->pIfIo, pImage->pStorage,
1158 pImage->offBackingFilename, pImage->pszBackingFilename,
1159 pImage->cbBackingFilename);
1160 }
1161 else
1162 rc = VERR_NO_MEMORY;
1163 }
1164
1165 if ( RT_SUCCESS(rc)
1166 && pImage->cbRefcountTable
1167 && pImage->offRefcountTable)
1168 {
1169 /* Load refcount table. */
1170 Assert(pImage->cRefcountTableEntries);
1171 pImage->paRefcountTable = (uint64_t *)RTMemAllocZ(pImage->cbRefcountTable);
1172 if (RT_LIKELY(pImage->paRefcountTable))
1173 {
1174 rc = vdIfIoIntFileReadSync(pImage->pIfIo, pImage->pStorage,
1175 pImage->offRefcountTable, pImage->paRefcountTable,
1176 pImage->cbRefcountTable);
1177 if (RT_SUCCESS(rc))
1178 qcowTableConvertToHostEndianess(pImage->paRefcountTable,
1179 pImage->cRefcountTableEntries);
1180 else
1181 rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS,
1182 N_("QCow: Reading refcount table of image '%s' failed"),
1183 pImage->pszFilename);
1184 }
1185 else
1186 rc = vdIfError(pImage->pIfError, VERR_NO_MEMORY, RT_SRC_POS,
1187 N_("QCow: Allocating memory for refcount table of image '%s' failed"),
1188 pImage->pszFilename);
1189 }
1190
1191 if (RT_SUCCESS(rc))
1192 {
1193 qcowTableMasksInit(pImage);
1194
1195 /* Allocate L1 table. */
1196 pImage->paL1Table = (uint64_t *)RTMemAllocZ(pImage->cbL1Table);
1197 if (pImage->paL1Table)
1198 {
1199 /* Read from the image. */
1200 rc = vdIfIoIntFileReadSync(pImage->pIfIo, pImage->pStorage,
1201 pImage->offL1Table, pImage->paL1Table,
1202 pImage->cbL1Table);
1203 if (RT_SUCCESS(rc))
1204 qcowTableConvertToHostEndianess(pImage->paL1Table, pImage->cL1TableEntries);
1205 else
1206 rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS,
1207 N_("QCow: Reading the L1 table for image '%s' failed"),
1208 pImage->pszFilename);
1209 }
1210 else
1211 rc = vdIfError(pImage->pIfError, VERR_NO_MEMORY, RT_SRC_POS,
1212 N_("QCow: Out of memory allocating L1 table for image '%s'"),
1213 pImage->pszFilename);
1214 }
1215 }
1216 else if (RT_SUCCESS(rc))
1217 rc = VERR_VD_GEN_INVALID_HEADER;
1218 }
1219 else if (RT_SUCCESS(rc))
1220 rc = VERR_VD_GEN_INVALID_HEADER;
1221 }
1222 /* else: Do NOT signal an appropriate error here, as the VD layer has the
1223 * choice of retrying the open if it failed. */
1224 }
1225 else
1226 rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS,
1227 N_("Qcow: Creating the L2 table cache for image '%s' failed"),
1228 pImage->pszFilename);
1229
1230 if (RT_SUCCESS(rc))
1231 {
1232 PVDREGIONDESC pRegion = &pImage->RegionList.aRegions[0];
1233 pImage->RegionList.fFlags = 0;
1234 pImage->RegionList.cRegions = 1;
1235
1236 pRegion->offRegion = 0; /* Disk start. */
1237 pRegion->cbBlock = 512;
1238 pRegion->enmDataForm = VDREGIONDATAFORM_RAW;
1239 pRegion->enmMetadataForm = VDREGIONMETADATAFORM_NONE;
1240 pRegion->cbData = 512;
1241 pRegion->cbMetadata = 0;
1242 pRegion->cRegionBlocksOrBytes = pImage->cbSize;
1243 }
1244 else
1245 qcowFreeImage(pImage, false);
1246 return rc;
1247}
1248
1249/**
1250 * Internal: Create a qcow image.
1251 */
1252static int qcowCreateImage(PQCOWIMAGE pImage, uint64_t cbSize,
1253 unsigned uImageFlags, const char *pszComment,
1254 PCVDGEOMETRY pPCHSGeometry,
1255 PCVDGEOMETRY pLCHSGeometry, unsigned uOpenFlags,
1256 PVDINTERFACEPROGRESS pIfProgress,
1257 unsigned uPercentStart, unsigned uPercentSpan)
1258{
1259 RT_NOREF1(pszComment);
1260 int rc;
1261 int32_t fOpen;
1262
1263 if (!(uImageFlags & VD_IMAGE_FLAGS_FIXED))
1264 {
1265 rc = qcowL2TblCacheCreate(pImage);
1266 if (RT_SUCCESS(rc))
1267 {
1268 pImage->uOpenFlags = uOpenFlags & ~VD_OPEN_FLAGS_READONLY;
1269 pImage->uImageFlags = uImageFlags;
1270 pImage->PCHSGeometry = *pPCHSGeometry;
1271 pImage->LCHSGeometry = *pLCHSGeometry;
1272 pImage->pIfError = VDIfErrorGet(pImage->pVDIfsDisk);
1273 pImage->pIfIo = VDIfIoIntGet(pImage->pVDIfsImage);
1274 AssertPtrReturn(pImage->pIfIo, VERR_INVALID_PARAMETER);
1275
1276 /* Create image file. */
1277 fOpen = VDOpenFlagsToFileOpenFlags(pImage->uOpenFlags, true /* fCreate */);
1278 rc = vdIfIoIntFileOpen(pImage->pIfIo, pImage->pszFilename, fOpen, &pImage->pStorage);
1279 if (RT_SUCCESS(rc))
1280 {
1281 /* Init image state. */
1282 pImage->uVersion = 1; /* We create only version 1 images at the moment. */
1283 pImage->cbSize = cbSize;
1284 pImage->cbCluster = QCOW_CLUSTER_SIZE_DEFAULT;
1285 pImage->cbL2Table = qcowCluster2Byte(pImage, QCOW_L2_CLUSTERS_DEFAULT);
1286 pImage->cL2TableEntries = pImage->cbL2Table / sizeof(uint64_t);
1287 pImage->cL1TableEntries = cbSize / (pImage->cbCluster * pImage->cL2TableEntries);
1288 if (cbSize % (pImage->cbCluster * pImage->cL2TableEntries))
1289 pImage->cL1TableEntries++;
1290 pImage->cbL1Table = pImage->cL1TableEntries * sizeof(uint64_t);
1291 pImage->offL1Table = QCOW_V1_HDR_SIZE;
1292 pImage->cbBackingFilename = 0;
1293 pImage->offBackingFilename = 0;
1294 pImage->offNextCluster = RT_ALIGN_64(QCOW_V1_HDR_SIZE + pImage->cbL1Table, pImage->cbCluster);
1295 qcowTableMasksInit(pImage);
1296
1297 /* Init L1 table. */
1298 pImage->paL1Table = (uint64_t *)RTMemAllocZ(pImage->cbL1Table);
1299 if (RT_LIKELY(pImage->paL1Table))
1300 {
1301 if (RT_SUCCESS(rc))
1302 vdIfProgress(pIfProgress, uPercentStart + uPercentSpan * 98 / 100);
1303
1304 rc = qcowFlushImage(pImage);
1305 if (RT_SUCCESS(rc))
1306 rc = vdIfIoIntFileSetSize(pImage->pIfIo, pImage->pStorage, pImage->offNextCluster);
1307 }
1308 else
1309 rc = vdIfError(pImage->pIfError, VERR_NO_MEMORY, RT_SRC_POS, N_("QCow: cannot allocate memory for L1 table of image '%s'"),
1310 pImage->pszFilename);
1311 }
1312 else
1313 rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("QCow: cannot create image '%s'"), pImage->pszFilename);
1314 }
1315 else
1316 rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("QCow: Failed to create L2 cache for image '%s'"),
1317 pImage->pszFilename);
1318 }
1319 else
1320 rc = vdIfError(pImage->pIfError, VERR_VD_INVALID_TYPE, RT_SRC_POS, N_("QCow: cannot create fixed image '%s'"), pImage->pszFilename);
1321
1322 if (RT_SUCCESS(rc))
1323 vdIfProgress(pIfProgress, uPercentStart + uPercentSpan);
1324
1325 if (RT_SUCCESS(rc))
1326 {
1327 PVDREGIONDESC pRegion = &pImage->RegionList.aRegions[0];
1328 pImage->RegionList.fFlags = 0;
1329 pImage->RegionList.cRegions = 1;
1330
1331 pRegion->offRegion = 0; /* Disk start. */
1332 pRegion->cbBlock = 512;
1333 pRegion->enmDataForm = VDREGIONDATAFORM_RAW;
1334 pRegion->enmMetadataForm = VDREGIONMETADATAFORM_NONE;
1335 pRegion->cbData = 512;
1336 pRegion->cbMetadata = 0;
1337 pRegion->cRegionBlocksOrBytes = pImage->cbSize;
1338 }
1339 else
1340 qcowFreeImage(pImage, rc != VERR_ALREADY_EXISTS);
1341 return rc;
1342}
1343
1344/**
1345 * Rollback anything done during async cluster allocation.
1346 *
1347 * @returns VBox status code.
1348 * @param pImage The image instance data.
1349 * @param pIoCtx The I/O context.
1350 * @param pClusterAlloc The cluster allocation to rollback.
1351 */
1352static int qcowAsyncClusterAllocRollback(PQCOWIMAGE pImage, PVDIOCTX pIoCtx, PQCOWCLUSTERASYNCALLOC pClusterAlloc)
1353{
1354 RT_NOREF1(pIoCtx);
1355 int rc = VINF_SUCCESS;
1356
1357 switch (pClusterAlloc->enmAllocState)
1358 {
1359 case QCOWCLUSTERASYNCALLOCSTATE_L2_ALLOC:
1360 case QCOWCLUSTERASYNCALLOCSTATE_L2_LINK:
1361 {
1362 /* Revert the L1 table entry */
1363 pImage->paL1Table[pClusterAlloc->idxL1] = 0;
1364 pImage->pL2TblAlloc = NULL;
1365
1366 /* Assumption right now is that the L1 table is not modified on storage if the link fails. */
1367 rc = vdIfIoIntFileSetSize(pImage->pIfIo, pImage->pStorage, pClusterAlloc->offNextClusterOld);
1368 qcowL2TblCacheEntryRelease(pClusterAlloc->pL2Entry); /* Release L2 cache entry. */
1369 Assert(!pClusterAlloc->pL2Entry->cRefs);
1370 qcowL2TblCacheEntryFree(pImage, pClusterAlloc->pL2Entry); /* Free it, it is not in the cache yet. */
1371 break;
1372 }
1373 case QCOWCLUSTERASYNCALLOCSTATE_USER_ALLOC:
1374 case QCOWCLUSTERASYNCALLOCSTATE_USER_LINK:
1375 {
1376 /* Assumption right now is that the L2 table is not modified if the link fails. */
1377 pClusterAlloc->pL2Entry->paL2Tbl[pClusterAlloc->idxL2] = 0;
1378 rc = vdIfIoIntFileSetSize(pImage->pIfIo, pImage->pStorage, pClusterAlloc->offNextClusterOld);
1379 qcowL2TblCacheEntryRelease(pClusterAlloc->pL2Entry); /* Release L2 cache entry. */
1380 break;
1381 }
1382 default:
1383 AssertMsgFailed(("Invalid cluster allocation state %d\n", pClusterAlloc->enmAllocState));
1384 rc = VERR_INVALID_STATE;
1385 }
1386
1387 RTMemFree(pClusterAlloc);
1388 return rc;
1389}
1390
1391/**
1392 * Updates the state of the async cluster allocation.
1393 *
1394 * @returns VBox status code.
1395 * @param pBackendData The opaque backend data.
1396 * @param pIoCtx I/O context associated with this request.
1397 * @param pvUser Opaque user data passed during a read/write request.
1398 * @param rcReq Status code for the completed request.
1399 */
1400static DECLCALLBACK(int) qcowAsyncClusterAllocUpdate(void *pBackendData, PVDIOCTX pIoCtx, void *pvUser, int rcReq)
1401{
1402 int rc = VINF_SUCCESS;
1403 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData;
1404 PQCOWCLUSTERASYNCALLOC pClusterAlloc = (PQCOWCLUSTERASYNCALLOC)pvUser;
1405
1406 if (RT_FAILURE(rcReq))
1407 return qcowAsyncClusterAllocRollback(pImage, pIoCtx, pClusterAlloc);
1408
1409 AssertPtr(pClusterAlloc->pL2Entry);
1410
1411 switch (pClusterAlloc->enmAllocState)
1412 {
1413 case QCOWCLUSTERASYNCALLOCSTATE_L2_ALLOC:
1414 {
1415 /* Update the link in the in memory L1 table now. */
1416 pImage->paL1Table[pClusterAlloc->idxL1] = pClusterAlloc->pL2Entry->offL2Tbl;
1417
1418 /* Update the link in the on disk L1 table now. */
1419 pClusterAlloc->enmAllocState = QCOWCLUSTERASYNCALLOCSTATE_L2_LINK;
1420 rc = qcowTblWrite(pImage, pIoCtx, pImage->offL1Table, pImage->paL1Table,
1421 pImage->cbL1Table, pImage->cL1TableEntries,
1422 qcowAsyncClusterAllocUpdate, pClusterAlloc);
1423 if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS)
1424 break;
1425 else if (RT_FAILURE(rc))
1426 {
1427 /* Rollback. */
1428 qcowAsyncClusterAllocRollback(pImage, pIoCtx, pClusterAlloc);
1429 break;
1430 }
1431 /* Success, fall through. */
1432 }
1433 /* fall thru */
1434 case QCOWCLUSTERASYNCALLOCSTATE_L2_LINK:
1435 {
1436 /* L2 link updated in L1 , save L2 entry in cache and allocate new user data cluster. */
1437 uint64_t offData = qcowClusterAllocate(pImage, 1);
1438
1439 pImage->pL2TblAlloc = NULL;
1440 qcowL2TblCacheEntryInsert(pImage, pClusterAlloc->pL2Entry);
1441
1442 pClusterAlloc->enmAllocState = QCOWCLUSTERASYNCALLOCSTATE_USER_ALLOC;
1443 pClusterAlloc->offNextClusterOld = offData;
1444 pClusterAlloc->offClusterNew = offData;
1445
1446 /* Write data. */
1447 rc = vdIfIoIntFileWriteUser(pImage->pIfIo, pImage->pStorage,
1448 offData, pIoCtx, pClusterAlloc->cbToWrite,
1449 qcowAsyncClusterAllocUpdate, pClusterAlloc);
1450 if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS)
1451 break;
1452 else if (RT_FAILURE(rc))
1453 {
1454 qcowAsyncClusterAllocRollback(pImage, pIoCtx, pClusterAlloc);
1455 RTMemFree(pClusterAlloc);
1456 break;
1457 }
1458 }
1459 /* fall thru */
1460 case QCOWCLUSTERASYNCALLOCSTATE_USER_ALLOC:
1461 {
1462 pClusterAlloc->enmAllocState = QCOWCLUSTERASYNCALLOCSTATE_USER_LINK;
1463 pClusterAlloc->pL2Entry->paL2Tbl[pClusterAlloc->idxL2] = pClusterAlloc->offClusterNew;
1464
1465 /* Link L2 table and update it. */
1466 rc = qcowTblWrite(pImage, pIoCtx, pImage->paL1Table[pClusterAlloc->idxL1],
1467 pClusterAlloc->pL2Entry->paL2Tbl,
1468 pImage->cbL2Table, pImage->cL2TableEntries,
1469 qcowAsyncClusterAllocUpdate, pClusterAlloc);
1470 if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS)
1471 break;
1472 else if (RT_FAILURE(rc))
1473 {
1474 qcowAsyncClusterAllocRollback(pImage, pIoCtx, pClusterAlloc);
1475 RTMemFree(pClusterAlloc);
1476 break;
1477 }
1478 }
1479 /* fall thru */
1480 case QCOWCLUSTERASYNCALLOCSTATE_USER_LINK:
1481 {
1482 /* Everything done without errors, signal completion. */
1483 qcowL2TblCacheEntryRelease(pClusterAlloc->pL2Entry);
1484 RTMemFree(pClusterAlloc);
1485 rc = VINF_SUCCESS;
1486 break;
1487 }
1488 default:
1489 AssertMsgFailed(("Invalid async cluster allocation state %d\n",
1490 pClusterAlloc->enmAllocState));
1491 }
1492
1493 return rc;
1494}
1495
1496/** @copydoc VDIMAGEBACKEND::pfnProbe */
1497static DECLCALLBACK(int) qcowProbe(const char *pszFilename, PVDINTERFACE pVDIfsDisk,
1498 PVDINTERFACE pVDIfsImage, VDTYPE *penmType)
1499{
1500 RT_NOREF1(pVDIfsDisk);
1501 LogFlowFunc(("pszFilename=\"%s\" pVDIfsDisk=%#p pVDIfsImage=%#p\n", pszFilename, pVDIfsDisk, pVDIfsImage));
1502 PVDIOSTORAGE pStorage = NULL;
1503 uint64_t cbFile;
1504 int rc = VINF_SUCCESS;
1505
1506 /* Get I/O interface. */
1507 PVDINTERFACEIOINT pIfIo = VDIfIoIntGet(pVDIfsImage);
1508 AssertPtrReturn(pIfIo, VERR_INVALID_PARAMETER);
1509 AssertReturn((VALID_PTR(pszFilename) && *pszFilename), VERR_INVALID_PARAMETER);
1510
1511 /*
1512 * Open the file and read the footer.
1513 */
1514 rc = vdIfIoIntFileOpen(pIfIo, pszFilename,
1515 VDOpenFlagsToFileOpenFlags(VD_OPEN_FLAGS_READONLY,
1516 false /* fCreate */),
1517 &pStorage);
1518 if (RT_SUCCESS(rc))
1519 {
1520 rc = vdIfIoIntFileGetSize(pIfIo, pStorage, &cbFile);
1521 if ( RT_SUCCESS(rc)
1522 && cbFile > sizeof(QCowHeader))
1523 {
1524 QCowHeader Header;
1525
1526 rc = vdIfIoIntFileReadSync(pIfIo, pStorage, 0, &Header, sizeof(Header));
1527 if ( RT_SUCCESS(rc)
1528 && qcowHdrConvertToHostEndianess(&Header))
1529 *penmType = VDTYPE_HDD;
1530 else
1531 rc = VERR_VD_GEN_INVALID_HEADER;
1532 }
1533 else
1534 rc = VERR_VD_GEN_INVALID_HEADER;
1535 }
1536
1537 if (pStorage)
1538 vdIfIoIntFileClose(pIfIo, pStorage);
1539
1540 LogFlowFunc(("returns %Rrc\n", rc));
1541 return rc;
1542}
1543
1544/** @copydoc VDIMAGEBACKEND::pfnOpen */
1545static DECLCALLBACK(int) qcowOpen(const char *pszFilename, unsigned uOpenFlags,
1546 PVDINTERFACE pVDIfsDisk, PVDINTERFACE pVDIfsImage,
1547 VDTYPE enmType, void **ppBackendData)
1548{
1549 RT_NOREF1(enmType); /**< @todo r=klaus make use of the type info. */
1550
1551 LogFlowFunc(("pszFilename=\"%s\" uOpenFlags=%#x pVDIfsDisk=%#p pVDIfsImage=%#p enmType=%u ppBackendData=%#p\n",
1552 pszFilename, uOpenFlags, pVDIfsDisk, pVDIfsImage, enmType, ppBackendData));
1553 int rc;
1554
1555 /* Check open flags. All valid flags are supported. */
1556 AssertReturn(!(uOpenFlags & ~VD_OPEN_FLAGS_MASK), VERR_INVALID_PARAMETER);
1557 AssertReturn((VALID_PTR(pszFilename) && *pszFilename), VERR_INVALID_PARAMETER);
1558
1559 PQCOWIMAGE pImage = (PQCOWIMAGE)RTMemAllocZ(RT_UOFFSETOF(QCOWIMAGE, RegionList.aRegions[1]));
1560 if (RT_LIKELY(pImage))
1561 {
1562 pImage->pszFilename = pszFilename;
1563 pImage->pStorage = NULL;
1564 pImage->pVDIfsDisk = pVDIfsDisk;
1565 pImage->pVDIfsImage = pVDIfsImage;
1566
1567 rc = qcowOpenImage(pImage, uOpenFlags);
1568 if (RT_SUCCESS(rc))
1569 *ppBackendData = pImage;
1570 else
1571 RTMemFree(pImage);
1572 }
1573 else
1574 rc = VERR_NO_MEMORY;
1575
1576 LogFlowFunc(("returns %Rrc (pBackendData=%#p)\n", rc, *ppBackendData));
1577 return rc;
1578}
1579
1580/** @copydoc VDIMAGEBACKEND::pfnCreate */
1581static DECLCALLBACK(int) qcowCreate(const char *pszFilename, uint64_t cbSize,
1582 unsigned uImageFlags, const char *pszComment,
1583 PCVDGEOMETRY pPCHSGeometry, PCVDGEOMETRY pLCHSGeometry,
1584 PCRTUUID pUuid, unsigned uOpenFlags,
1585 unsigned uPercentStart, unsigned uPercentSpan,
1586 PVDINTERFACE pVDIfsDisk, PVDINTERFACE pVDIfsImage,
1587 PVDINTERFACE pVDIfsOperation, VDTYPE enmType,
1588 void **ppBackendData)
1589{
1590 RT_NOREF1(pUuid);
1591 LogFlowFunc(("pszFilename=\"%s\" cbSize=%llu uImageFlags=%#x pszComment=\"%s\" pPCHSGeometry=%#p pLCHSGeometry=%#p Uuid=%RTuuid uOpenFlags=%#x uPercentStart=%u uPercentSpan=%u pVDIfsDisk=%#p pVDIfsImage=%#p pVDIfsOperation=%#p enmType=%u ppBackendData=%#p",
1592 pszFilename, cbSize, uImageFlags, pszComment, pPCHSGeometry, pLCHSGeometry, pUuid, uOpenFlags, uPercentStart, uPercentSpan, pVDIfsDisk, pVDIfsImage, pVDIfsOperation, enmType, ppBackendData));
1593 int rc;
1594
1595 /* Check the VD container type. */
1596 if (enmType != VDTYPE_HDD)
1597 return VERR_VD_INVALID_TYPE;
1598
1599 /* Check open flags. All valid flags are supported. */
1600 AssertReturn(!(uOpenFlags & ~VD_OPEN_FLAGS_MASK), VERR_INVALID_PARAMETER);
1601 AssertReturn( VALID_PTR(pszFilename)
1602 && *pszFilename
1603 && VALID_PTR(pPCHSGeometry)
1604 && VALID_PTR(pLCHSGeometry), VERR_INVALID_PARAMETER);
1605
1606 PQCOWIMAGE pImage = (PQCOWIMAGE)RTMemAllocZ(RT_UOFFSETOF(QCOWIMAGE, RegionList.aRegions[1]));
1607 if (RT_LIKELY(pImage))
1608 {
1609 PVDINTERFACEPROGRESS pIfProgress = VDIfProgressGet(pVDIfsOperation);
1610
1611 pImage->pszFilename = pszFilename;
1612 pImage->pStorage = NULL;
1613 pImage->pVDIfsDisk = pVDIfsDisk;
1614 pImage->pVDIfsImage = pVDIfsImage;
1615
1616 rc = qcowCreateImage(pImage, cbSize, uImageFlags, pszComment,
1617 pPCHSGeometry, pLCHSGeometry, uOpenFlags,
1618 pIfProgress, uPercentStart, uPercentSpan);
1619 if (RT_SUCCESS(rc))
1620 {
1621 /* So far the image is opened in read/write mode. Make sure the
1622 * image is opened in read-only mode if the caller requested that. */
1623 if (uOpenFlags & VD_OPEN_FLAGS_READONLY)
1624 {
1625 qcowFreeImage(pImage, false);
1626 rc = qcowOpenImage(pImage, uOpenFlags);
1627 }
1628
1629 if (RT_SUCCESS(rc))
1630 *ppBackendData = pImage;
1631 }
1632
1633 if (RT_FAILURE(rc))
1634 RTMemFree(pImage);
1635 }
1636 else
1637 rc = VERR_NO_MEMORY;
1638
1639 LogFlowFunc(("returns %Rrc (pBackendData=%#p)\n", rc, *ppBackendData));
1640 return rc;
1641}
1642
1643/** @copydoc VDIMAGEBACKEND::pfnRename */
1644static DECLCALLBACK(int) qcowRename(void *pBackendData, const char *pszFilename)
1645{
1646 LogFlowFunc(("pBackendData=%#p pszFilename=%#p\n", pBackendData, pszFilename));
1647 int rc = VINF_SUCCESS;
1648 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData;
1649
1650 /* Check arguments. */
1651 AssertReturn((pImage && pszFilename && *pszFilename), VERR_INVALID_PARAMETER);
1652
1653 /* Close the image. */
1654 rc = qcowFreeImage(pImage, false);
1655 if (RT_SUCCESS(rc))
1656 {
1657 /* Rename the file. */
1658 rc = vdIfIoIntFileMove(pImage->pIfIo, pImage->pszFilename, pszFilename, 0);
1659 if (RT_SUCCESS(rc))
1660 {
1661 /* Update pImage with the new information. */
1662 pImage->pszFilename = pszFilename;
1663
1664 /* Open the old image with new name. */
1665 rc = qcowOpenImage(pImage, pImage->uOpenFlags);
1666 }
1667 else
1668 {
1669 /* The move failed, try to reopen the original image. */
1670 int rc2 = qcowOpenImage(pImage, pImage->uOpenFlags);
1671 if (RT_FAILURE(rc2))
1672 rc = rc2;
1673 }
1674 }
1675
1676 LogFlowFunc(("returns %Rrc\n", rc));
1677 return rc;
1678}
1679
1680/** @copydoc VDIMAGEBACKEND::pfnClose */
1681static DECLCALLBACK(int) qcowClose(void *pBackendData, bool fDelete)
1682{
1683 LogFlowFunc(("pBackendData=%#p fDelete=%d\n", pBackendData, fDelete));
1684 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData;
1685
1686 int rc = qcowFreeImage(pImage, fDelete);
1687 RTMemFree(pImage);
1688
1689 LogFlowFunc(("returns %Rrc\n", rc));
1690 return rc;
1691}
1692
1693static DECLCALLBACK(int) qcowRead(void *pBackendData, uint64_t uOffset, size_t cbToRead,
1694 PVDIOCTX pIoCtx, size_t *pcbActuallyRead)
1695{
1696 LogFlowFunc(("pBackendData=%#p uOffset=%llu pIoCtx=%#p cbToRead=%zu pcbActuallyRead=%#p\n",
1697 pBackendData, uOffset, pIoCtx, cbToRead, pcbActuallyRead));
1698 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData;
1699 uint32_t offCluster = 0;
1700 uint32_t idxL1 = 0;
1701 uint32_t idxL2 = 0;
1702 uint64_t offFile = 0;
1703 int rc;
1704
1705 AssertPtr(pImage);
1706 Assert(uOffset % 512 == 0);
1707 Assert(cbToRead % 512 == 0);
1708 AssertReturn((VALID_PTR(pIoCtx) && cbToRead), VERR_INVALID_PARAMETER);
1709 AssertReturn(uOffset + cbToRead <= pImage->cbSize, VERR_INVALID_PARAMETER);
1710
1711 qcowConvertLogicalOffset(pImage, uOffset, &idxL1, &idxL2, &offCluster);
1712
1713 /* Clip read size to remain in the cluster. */
1714 cbToRead = RT_MIN(cbToRead, pImage->cbCluster - offCluster);
1715
1716 /* Get offset in image. */
1717 rc = qcowConvertToImageOffset(pImage, pIoCtx, idxL1, idxL2, offCluster, &offFile);
1718 if (RT_SUCCESS(rc))
1719 rc = vdIfIoIntFileReadUser(pImage->pIfIo, pImage->pStorage, offFile,
1720 pIoCtx, cbToRead);
1721
1722 if ( ( RT_SUCCESS(rc)
1723 || rc == VERR_VD_BLOCK_FREE
1724 || rc == VERR_VD_ASYNC_IO_IN_PROGRESS)
1725 && pcbActuallyRead)
1726 *pcbActuallyRead = cbToRead;
1727
1728 LogFlowFunc(("returns %Rrc\n", rc));
1729 return rc;
1730}
1731
1732static DECLCALLBACK(int) qcowWrite(void *pBackendData, uint64_t uOffset, size_t cbToWrite,
1733 PVDIOCTX pIoCtx, size_t *pcbWriteProcess, size_t *pcbPreRead,
1734 size_t *pcbPostRead, unsigned fWrite)
1735{
1736 LogFlowFunc(("pBackendData=%#p uOffset=%llu pIoCtx=%#p cbToWrite=%zu pcbWriteProcess=%#p pcbPreRead=%#p pcbPostRead=%#p\n",
1737 pBackendData, uOffset, pIoCtx, cbToWrite, pcbWriteProcess, pcbPreRead, pcbPostRead));
1738 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData;
1739 uint32_t offCluster = 0;
1740 uint32_t idxL1 = 0;
1741 uint32_t idxL2 = 0;
1742 uint64_t offImage = 0;
1743 int rc = VINF_SUCCESS;
1744
1745 AssertPtr(pImage);
1746 Assert(!(uOffset % 512));
1747 Assert(!(cbToWrite % 512));
1748 AssertReturn((VALID_PTR(pIoCtx) && cbToWrite), VERR_INVALID_PARAMETER);
1749 AssertReturn(uOffset + cbToWrite <= pImage->cbSize, VERR_INVALID_PARAMETER);
1750
1751 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
1752 {
1753 /* Convert offset to L1, L2 index and cluster offset. */
1754 qcowConvertLogicalOffset(pImage, uOffset, &idxL1, &idxL2, &offCluster);
1755
1756 /* Clip write size to remain in the cluster. */
1757 cbToWrite = RT_MIN(cbToWrite, pImage->cbCluster - offCluster);
1758 Assert(!(cbToWrite % 512));
1759
1760 /* Get offset in image. */
1761 rc = qcowConvertToImageOffset(pImage, pIoCtx, idxL1, idxL2, offCluster, &offImage);
1762 if (RT_SUCCESS(rc))
1763 rc = vdIfIoIntFileWriteUser(pImage->pIfIo, pImage->pStorage,
1764 offImage, pIoCtx, cbToWrite, NULL, NULL);
1765 else if (rc == VERR_VD_BLOCK_FREE)
1766 {
1767 if ( cbToWrite == pImage->cbCluster
1768 && !(fWrite & VD_WRITE_NO_ALLOC))
1769 {
1770 PQCOWL2CACHEENTRY pL2Entry = NULL;
1771
1772 /* Full cluster write to previously unallocated cluster.
1773 * Allocate cluster and write data. */
1774 Assert(!offCluster);
1775
1776 do
1777 {
1778 /* Check if we have to allocate a new cluster for L2 tables. */
1779 if (!pImage->paL1Table[idxL1])
1780 {
1781 uint64_t offL2Tbl;
1782 PQCOWCLUSTERASYNCALLOC pL2ClusterAlloc = NULL;
1783
1784 /* Allocate new async cluster allocation state. */
1785 pL2ClusterAlloc = (PQCOWCLUSTERASYNCALLOC)RTMemAllocZ(sizeof(QCOWCLUSTERASYNCALLOC));
1786 if (RT_UNLIKELY(!pL2ClusterAlloc))
1787 {
1788 rc = VERR_NO_MEMORY;
1789 break;
1790 }
1791
1792 pL2Entry = qcowL2TblCacheEntryAlloc(pImage);
1793 if (!pL2Entry)
1794 {
1795 rc = VERR_NO_MEMORY;
1796 RTMemFree(pL2ClusterAlloc);
1797 break;
1798 }
1799
1800 offL2Tbl = qcowClusterAllocate(pImage, qcowByte2Cluster(pImage, pImage->cbL2Table));
1801 pL2Entry->offL2Tbl = offL2Tbl;
1802 memset(pL2Entry->paL2Tbl, 0, pImage->cbL2Table);
1803
1804 pL2ClusterAlloc->enmAllocState = QCOWCLUSTERASYNCALLOCSTATE_L2_ALLOC;
1805 pL2ClusterAlloc->offNextClusterOld = offL2Tbl;
1806 pL2ClusterAlloc->offClusterNew = offL2Tbl;
1807 pL2ClusterAlloc->idxL1 = idxL1;
1808 pL2ClusterAlloc->idxL2 = idxL2;
1809 pL2ClusterAlloc->cbToWrite = cbToWrite;
1810 pL2ClusterAlloc->pL2Entry = pL2Entry;
1811
1812 pImage->pL2TblAlloc = pL2Entry;
1813
1814 LogFlowFunc(("Allocating new L2 table at cluster offset %llu\n", offL2Tbl));
1815
1816 /*
1817 * Write the L2 table first and link to the L1 table afterwards.
1818 * If something unexpected happens the worst case which can happen
1819 * is a leak of some clusters.
1820 */
1821 rc = vdIfIoIntFileWriteMeta(pImage->pIfIo, pImage->pStorage,
1822 offL2Tbl, pL2Entry->paL2Tbl, pImage->cbL2Table, pIoCtx,
1823 qcowAsyncClusterAllocUpdate, pL2ClusterAlloc);
1824 if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS)
1825 break;
1826 else if (RT_FAILURE(rc))
1827 {
1828 RTMemFree(pL2ClusterAlloc);
1829 qcowL2TblCacheEntryFree(pImage, pL2Entry);
1830 break;
1831 }
1832
1833 rc = qcowAsyncClusterAllocUpdate(pImage, pIoCtx, pL2ClusterAlloc, rc);
1834 }
1835 else
1836 {
1837 LogFlowFunc(("Fetching L2 table at cluster offset %llu\n", pImage->paL1Table[idxL1]));
1838
1839 rc = qcowL2TblCacheFetch(pImage, pIoCtx, pImage->paL1Table[idxL1],
1840 &pL2Entry);
1841 if (RT_SUCCESS(rc))
1842 {
1843 PQCOWCLUSTERASYNCALLOC pDataClusterAlloc = NULL;
1844
1845 /* Allocate new async cluster allocation state. */
1846 pDataClusterAlloc = (PQCOWCLUSTERASYNCALLOC)RTMemAllocZ(sizeof(QCOWCLUSTERASYNCALLOC));
1847 if (RT_UNLIKELY(!pDataClusterAlloc))
1848 {
1849 rc = VERR_NO_MEMORY;
1850 break;
1851 }
1852
1853 /* Allocate new cluster for the data. */
1854 uint64_t offData = qcowClusterAllocate(pImage, 1);
1855
1856 pDataClusterAlloc->enmAllocState = QCOWCLUSTERASYNCALLOCSTATE_USER_ALLOC;
1857 pDataClusterAlloc->offNextClusterOld = offData;
1858 pDataClusterAlloc->offClusterNew = offData;
1859 pDataClusterAlloc->idxL1 = idxL1;
1860 pDataClusterAlloc->idxL2 = idxL2;
1861 pDataClusterAlloc->cbToWrite = cbToWrite;
1862 pDataClusterAlloc->pL2Entry = pL2Entry;
1863
1864 /* Write data. */
1865 rc = vdIfIoIntFileWriteUser(pImage->pIfIo, pImage->pStorage,
1866 offData, pIoCtx, cbToWrite,
1867 qcowAsyncClusterAllocUpdate, pDataClusterAlloc);
1868 if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS)
1869 break;
1870 else if (RT_FAILURE(rc))
1871 {
1872 RTMemFree(pDataClusterAlloc);
1873 break;
1874 }
1875
1876 rc = qcowAsyncClusterAllocUpdate(pImage, pIoCtx, pDataClusterAlloc, rc);
1877 }
1878 }
1879
1880 } while (0);
1881
1882 *pcbPreRead = 0;
1883 *pcbPostRead = 0;
1884 }
1885 else
1886 {
1887 /* Trying to do a partial write to an unallocated cluster. Don't do
1888 * anything except letting the upper layer know what to do. */
1889 *pcbPreRead = offCluster;
1890 *pcbPostRead = pImage->cbCluster - cbToWrite - *pcbPreRead;
1891 }
1892 }
1893
1894 if (pcbWriteProcess)
1895 *pcbWriteProcess = cbToWrite;
1896 }
1897 else
1898 rc = VERR_VD_IMAGE_READ_ONLY;
1899
1900 LogFlowFunc(("returns %Rrc\n", rc));
1901 return rc;
1902}
1903
1904static DECLCALLBACK(int) qcowFlush(void *pBackendData, PVDIOCTX pIoCtx)
1905{
1906 LogFlowFunc(("pBackendData=%#p\n", pBackendData));
1907 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData;
1908 int rc = VINF_SUCCESS;
1909
1910 AssertPtr(pImage);
1911 AssertPtrReturn(pIoCtx, VERR_INVALID_PARAMETER);
1912
1913 if ( pImage->pStorage
1914 && !(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
1915 {
1916 QCowHeader Header;
1917
1918 rc = qcowTblWrite(pImage, pIoCtx, pImage->offL1Table, pImage->paL1Table,
1919 pImage->cbL1Table, pImage->cL1TableEntries, NULL, NULL);
1920 if (RT_SUCCESS(rc) || rc == VERR_VD_ASYNC_IO_IN_PROGRESS)
1921 {
1922 /* Write header. */
1923 size_t cbHeader = 0;
1924 qcowHdrConvertFromHostEndianess(pImage, &Header, &cbHeader);
1925 rc = vdIfIoIntFileWriteMeta(pImage->pIfIo, pImage->pStorage,
1926 0, &Header, cbHeader,
1927 pIoCtx, NULL, NULL);
1928 if (RT_SUCCESS(rc) || rc == VERR_VD_ASYNC_IO_IN_PROGRESS)
1929 rc = vdIfIoIntFileFlush(pImage->pIfIo, pImage->pStorage,
1930 pIoCtx, NULL, NULL);
1931 }
1932 }
1933
1934 LogFlowFunc(("returns %Rrc\n", rc));
1935 return rc;
1936}
1937
1938/** @copydoc VDIMAGEBACKEND::pfnGetVersion */
1939static DECLCALLBACK(unsigned) qcowGetVersion(void *pBackendData)
1940{
1941 LogFlowFunc(("pBackendData=%#p\n", pBackendData));
1942 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData;
1943
1944 AssertPtrReturn(pImage, 0);
1945
1946 return pImage->uVersion;
1947}
1948
1949/** @copydoc VDIMAGEBACKEND::pfnGetFileSize */
1950static DECLCALLBACK(uint64_t) qcowGetFileSize(void *pBackendData)
1951{
1952 LogFlowFunc(("pBackendData=%#p\n", pBackendData));
1953 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData;
1954 uint64_t cb = 0;
1955
1956 AssertPtrReturn(pImage, 0);
1957
1958 uint64_t cbFile;
1959 if (pImage->pStorage)
1960 {
1961 int rc = vdIfIoIntFileGetSize(pImage->pIfIo, pImage->pStorage, &cbFile);
1962 if (RT_SUCCESS(rc))
1963 cb += cbFile;
1964 }
1965
1966 LogFlowFunc(("returns %lld\n", cb));
1967 return cb;
1968}
1969
1970/** @copydoc VDIMAGEBACKEND::pfnGetPCHSGeometry */
1971static DECLCALLBACK(int) qcowGetPCHSGeometry(void *pBackendData, PVDGEOMETRY pPCHSGeometry)
1972{
1973 LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p\n", pBackendData, pPCHSGeometry));
1974 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData;
1975 int rc = VINF_SUCCESS;
1976
1977 AssertPtrReturn(pImage, VERR_VD_NOT_OPENED);
1978
1979 if (pImage->PCHSGeometry.cCylinders)
1980 *pPCHSGeometry = pImage->PCHSGeometry;
1981 else
1982 rc = VERR_VD_GEOMETRY_NOT_SET;
1983
1984 LogFlowFunc(("returns %Rrc (PCHS=%u/%u/%u)\n", rc, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors));
1985 return rc;
1986}
1987
1988/** @copydoc VDIMAGEBACKEND::pfnSetPCHSGeometry */
1989static DECLCALLBACK(int) qcowSetPCHSGeometry(void *pBackendData, PCVDGEOMETRY pPCHSGeometry)
1990{
1991 LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p PCHS=%u/%u/%u\n",
1992 pBackendData, pPCHSGeometry, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors));
1993 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData;
1994 int rc = VINF_SUCCESS;
1995
1996 AssertPtrReturn(pImage, VERR_VD_NOT_OPENED);
1997
1998 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
1999 rc = VERR_VD_IMAGE_READ_ONLY;
2000 else
2001 pImage->PCHSGeometry = *pPCHSGeometry;
2002
2003 LogFlowFunc(("returns %Rrc\n", rc));
2004 return rc;
2005}
2006
2007/** @copydoc VDIMAGEBACKEND::pfnGetLCHSGeometry */
2008static DECLCALLBACK(int) qcowGetLCHSGeometry(void *pBackendData, PVDGEOMETRY pLCHSGeometry)
2009{
2010 LogFlowFunc(("pBackendData=%#p pLCHSGeometry=%#p\n", pBackendData, pLCHSGeometry));
2011 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData;
2012 int rc = VINF_SUCCESS;
2013
2014 AssertPtrReturn(pImage, VERR_VD_NOT_OPENED);
2015
2016 if (pImage->LCHSGeometry.cCylinders)
2017 *pLCHSGeometry = pImage->LCHSGeometry;
2018 else
2019 rc = VERR_VD_GEOMETRY_NOT_SET;
2020
2021 LogFlowFunc(("returns %Rrc (LCHS=%u/%u/%u)\n", rc, pLCHSGeometry->cCylinders,
2022 pLCHSGeometry->cHeads, pLCHSGeometry->cSectors));
2023 return rc;
2024}
2025
2026/** @copydoc VDIMAGEBACKEND::pfnSetLCHSGeometry */
2027static DECLCALLBACK(int) qcowSetLCHSGeometry(void *pBackendData, PCVDGEOMETRY pLCHSGeometry)
2028{
2029 LogFlowFunc(("pBackendData=%#p pLCHSGeometry=%#p LCHS=%u/%u/%u\n", pBackendData,
2030 pLCHSGeometry, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors));
2031 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData;
2032 int rc = VINF_SUCCESS;
2033
2034 AssertPtrReturn(pImage, VERR_VD_NOT_OPENED);
2035
2036 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
2037 rc = VERR_VD_IMAGE_READ_ONLY;
2038 else
2039 pImage->LCHSGeometry = *pLCHSGeometry;
2040
2041 LogFlowFunc(("returns %Rrc\n", rc));
2042 return rc;
2043}
2044
2045/** @copydoc VDIMAGEBACKEND::pfnQueryRegions */
2046static DECLCALLBACK(int) qcowQueryRegions(void *pBackendData, PCVDREGIONLIST *ppRegionList)
2047{
2048 LogFlowFunc(("pBackendData=%#p ppRegionList=%#p\n", pBackendData, ppRegionList));
2049 PQCOWIMAGE pThis = (PQCOWIMAGE)pBackendData;
2050
2051 AssertPtrReturn(pThis, VERR_VD_NOT_OPENED);
2052
2053 *ppRegionList = &pThis->RegionList;
2054 LogFlowFunc(("returns %Rrc\n", VINF_SUCCESS));
2055 return VINF_SUCCESS;
2056}
2057
2058/** @copydoc VDIMAGEBACKEND::pfnRegionListRelease */
2059static DECLCALLBACK(void) qcowRegionListRelease(void *pBackendData, PCVDREGIONLIST pRegionList)
2060{
2061 RT_NOREF1(pRegionList);
2062 LogFlowFunc(("pBackendData=%#p pRegionList=%#p\n", pBackendData, pRegionList));
2063 PQCOWIMAGE pThis = (PQCOWIMAGE)pBackendData;
2064 AssertPtr(pThis); RT_NOREF(pThis);
2065
2066 /* Nothing to do here. */
2067}
2068
2069/** @copydoc VDIMAGEBACKEND::pfnGetImageFlags */
2070static DECLCALLBACK(unsigned) qcowGetImageFlags(void *pBackendData)
2071{
2072 LogFlowFunc(("pBackendData=%#p\n", pBackendData));
2073 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData;
2074
2075 AssertPtrReturn(pImage, 0);
2076
2077 LogFlowFunc(("returns %#x\n", pImage->uImageFlags));
2078 return pImage->uImageFlags;
2079}
2080
2081/** @copydoc VDIMAGEBACKEND::pfnGetOpenFlags */
2082static DECLCALLBACK(unsigned) qcowGetOpenFlags(void *pBackendData)
2083{
2084 LogFlowFunc(("pBackendData=%#p\n", pBackendData));
2085 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData;
2086
2087 AssertPtrReturn(pImage, 0);
2088
2089 LogFlowFunc(("returns %#x\n", pImage->uOpenFlags));
2090 return pImage->uOpenFlags;
2091}
2092
2093/** @copydoc VDIMAGEBACKEND::pfnSetOpenFlags */
2094static DECLCALLBACK(int) qcowSetOpenFlags(void *pBackendData, unsigned uOpenFlags)
2095{
2096 LogFlowFunc(("pBackendData=%#p\n uOpenFlags=%#x", pBackendData, uOpenFlags));
2097 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData;
2098 int rc = VINF_SUCCESS;
2099
2100 /* Image must be opened and the new flags must be valid. */
2101 if (!pImage || (uOpenFlags & ~( VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO
2102 | VD_OPEN_FLAGS_ASYNC_IO | VD_OPEN_FLAGS_SHAREABLE
2103 | VD_OPEN_FLAGS_SEQUENTIAL | VD_OPEN_FLAGS_SKIP_CONSISTENCY_CHECKS)))
2104 rc = VERR_INVALID_PARAMETER;
2105 else
2106 {
2107 /* Implement this operation via reopening the image. */
2108 rc = qcowFreeImage(pImage, false);
2109 if (RT_SUCCESS(rc))
2110 rc = qcowOpenImage(pImage, uOpenFlags);
2111 }
2112
2113 LogFlowFunc(("returns %Rrc\n", rc));
2114 return rc;
2115}
2116
2117/** @copydoc VDIMAGEBACKEND::pfnGetComment */
2118static DECLCALLBACK(int) qcowGetComment(void *pBackendData, char *pszComment, size_t cbComment)
2119{
2120 RT_NOREF2(pszComment, cbComment);
2121 LogFlowFunc(("pBackendData=%#p pszComment=%#p cbComment=%zu\n", pBackendData, pszComment, cbComment));
2122 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData;
2123
2124 AssertPtrReturn(pImage, VERR_VD_NOT_OPENED);
2125
2126 LogFlowFunc(("returns %Rrc comment='%s'\n", VERR_NOT_SUPPORTED, pszComment));
2127 return VERR_NOT_SUPPORTED;
2128}
2129
2130/** @copydoc VDIMAGEBACKEND::pfnSetComment */
2131static DECLCALLBACK(int) qcowSetComment(void *pBackendData, const char *pszComment)
2132{
2133 RT_NOREF1(pszComment);
2134 LogFlowFunc(("pBackendData=%#p pszComment=\"%s\"\n", pBackendData, pszComment));
2135 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData;
2136
2137 AssertPtrReturn(pImage, VERR_VD_NOT_OPENED);
2138
2139 int rc;
2140 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
2141 rc = VERR_VD_IMAGE_READ_ONLY;
2142 else
2143 rc = VERR_NOT_SUPPORTED;
2144
2145 LogFlowFunc(("returns %Rrc\n", rc));
2146 return rc;
2147}
2148
2149/** @copydoc VDIMAGEBACKEND::pfnGetUuid */
2150static DECLCALLBACK(int) qcowGetUuid(void *pBackendData, PRTUUID pUuid)
2151{
2152 RT_NOREF1(pUuid);
2153 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
2154 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData;
2155
2156 AssertPtrReturn(pImage, VERR_VD_NOT_OPENED);
2157
2158 LogFlowFunc(("returns %Rrc (%RTuuid)\n", VERR_NOT_SUPPORTED, pUuid));
2159 return VERR_NOT_SUPPORTED;
2160}
2161
2162/** @copydoc VDIMAGEBACKEND::pfnSetUuid */
2163static DECLCALLBACK(int) qcowSetUuid(void *pBackendData, PCRTUUID pUuid)
2164{
2165 RT_NOREF1(pUuid);
2166 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid));
2167 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData;
2168
2169 AssertPtrReturn(pImage, VERR_VD_NOT_OPENED);
2170
2171 int rc;
2172 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
2173 rc = VERR_VD_IMAGE_READ_ONLY;
2174 else
2175 rc = VERR_NOT_SUPPORTED;
2176
2177 LogFlowFunc(("returns %Rrc\n", rc));
2178 return rc;
2179}
2180
2181/** @copydoc VDIMAGEBACKEND::pfnGetModificationUuid */
2182static DECLCALLBACK(int) qcowGetModificationUuid(void *pBackendData, PRTUUID pUuid)
2183{
2184 RT_NOREF1(pUuid);
2185 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
2186 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData;
2187
2188 AssertPtrReturn(pImage, VERR_VD_NOT_OPENED);
2189
2190 LogFlowFunc(("returns %Rrc (%RTuuid)\n", VERR_NOT_SUPPORTED, pUuid));
2191 return VERR_NOT_SUPPORTED;
2192}
2193
2194/** @copydoc VDIMAGEBACKEND::pfnSetModificationUuid */
2195static DECLCALLBACK(int) qcowSetModificationUuid(void *pBackendData, PCRTUUID pUuid)
2196{
2197 RT_NOREF1(pUuid);
2198 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid));
2199 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData;
2200
2201 AssertPtrReturn(pImage, VERR_VD_NOT_OPENED);
2202
2203 int rc;
2204 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
2205 rc = VERR_VD_IMAGE_READ_ONLY;
2206 else
2207 rc = VERR_NOT_SUPPORTED;
2208
2209 LogFlowFunc(("returns %Rrc\n", rc));
2210 return rc;
2211}
2212
2213/** @copydoc VDIMAGEBACKEND::pfnGetParentUuid */
2214static DECLCALLBACK(int) qcowGetParentUuid(void *pBackendData, PRTUUID pUuid)
2215{
2216 RT_NOREF1(pUuid);
2217 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
2218 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData;
2219
2220 AssertPtrReturn(pImage, VERR_VD_NOT_OPENED);
2221
2222 LogFlowFunc(("returns %Rrc (%RTuuid)\n", VERR_NOT_SUPPORTED, pUuid));
2223 return VERR_NOT_SUPPORTED;
2224}
2225
2226/** @copydoc VDIMAGEBACKEND::pfnSetParentUuid */
2227static DECLCALLBACK(int) qcowSetParentUuid(void *pBackendData, PCRTUUID pUuid)
2228{
2229 RT_NOREF1(pUuid);
2230 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid));
2231 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData;
2232
2233 AssertPtrReturn(pImage, VERR_VD_NOT_OPENED);
2234
2235 int rc;
2236 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
2237 rc = VERR_VD_IMAGE_READ_ONLY;
2238 else
2239 rc = VERR_NOT_SUPPORTED;
2240
2241 LogFlowFunc(("returns %Rrc\n", rc));
2242 return rc;
2243}
2244
2245/** @copydoc VDIMAGEBACKEND::pfnGetParentModificationUuid */
2246static DECLCALLBACK(int) qcowGetParentModificationUuid(void *pBackendData, PRTUUID pUuid)
2247{
2248 RT_NOREF1(pUuid);
2249 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
2250 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData;
2251
2252 AssertPtrReturn(pImage, VERR_VD_NOT_OPENED);
2253
2254 LogFlowFunc(("returns %Rrc (%RTuuid)\n", VERR_NOT_SUPPORTED, pUuid));
2255 return VERR_NOT_SUPPORTED;
2256}
2257
2258/** @copydoc VDIMAGEBACKEND::pfnSetParentModificationUuid */
2259static DECLCALLBACK(int) qcowSetParentModificationUuid(void *pBackendData, PCRTUUID pUuid)
2260{
2261 RT_NOREF1(pUuid);
2262 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid));
2263 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData;
2264
2265 AssertPtrReturn(pImage, VERR_VD_NOT_OPENED);
2266
2267 int rc;
2268 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
2269 rc = VERR_VD_IMAGE_READ_ONLY;
2270 else
2271 rc = VERR_NOT_SUPPORTED;
2272
2273 LogFlowFunc(("returns %Rrc\n", rc));
2274 return rc;
2275}
2276
2277/** @copydoc VDIMAGEBACKEND::pfnDump */
2278static DECLCALLBACK(void) qcowDump(void *pBackendData)
2279{
2280 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData;
2281
2282 AssertPtrReturnVoid(pImage);
2283 vdIfErrorMessage(pImage->pIfError, "Header: Geometry PCHS=%u/%u/%u LCHS=%u/%u/%u cbSector=%llu\n",
2284 pImage->PCHSGeometry.cCylinders, pImage->PCHSGeometry.cHeads, pImage->PCHSGeometry.cSectors,
2285 pImage->LCHSGeometry.cCylinders, pImage->LCHSGeometry.cHeads, pImage->LCHSGeometry.cSectors,
2286 pImage->cbSize / 512);
2287}
2288
2289/** @copydoc VDIMAGEBACKEND::pfnGetParentFilename */
2290static DECLCALLBACK(int) qcowGetParentFilename(void *pBackendData, char **ppszParentFilename)
2291{
2292 int rc = VINF_SUCCESS;
2293 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData;
2294
2295 AssertPtr(pImage);
2296 if (pImage)
2297 if (pImage->pszBackingFilename)
2298 *ppszParentFilename = RTStrDup(pImage->pszBackingFilename);
2299 else
2300 rc = VERR_NOT_SUPPORTED;
2301 else
2302 rc = VERR_VD_NOT_OPENED;
2303
2304 LogFlowFunc(("returns %Rrc\n", rc));
2305 return rc;
2306}
2307
2308/** @copydoc VDIMAGEBACKEND::pfnSetParentFilename */
2309static DECLCALLBACK(int) qcowSetParentFilename(void *pBackendData, const char *pszParentFilename)
2310{
2311 int rc = VINF_SUCCESS;
2312 PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData;
2313
2314 AssertPtr(pImage);
2315 if (pImage)
2316 {
2317 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
2318 rc = VERR_VD_IMAGE_READ_ONLY;
2319 else if ( pImage->pszBackingFilename
2320 && (strlen(pszParentFilename) > pImage->cbBackingFilename))
2321 rc = VERR_NOT_SUPPORTED; /* The new filename is longer than the old one. */
2322 else
2323 {
2324 if (pImage->pszBackingFilename)
2325 RTStrFree(pImage->pszBackingFilename);
2326 pImage->pszBackingFilename = RTStrDup(pszParentFilename);
2327 if (!pImage->pszBackingFilename)
2328 rc = VERR_NO_MEMORY;
2329 else
2330 {
2331 if (!pImage->offBackingFilename)
2332 {
2333 /* Allocate new cluster. */
2334 uint64_t offData = qcowClusterAllocate(pImage, 1);
2335
2336 Assert((offData & UINT32_MAX) == offData);
2337 pImage->offBackingFilename = (uint32_t)offData;
2338 pImage->cbBackingFilename = (uint32_t)strlen(pszParentFilename);
2339 rc = vdIfIoIntFileSetSize(pImage->pIfIo, pImage->pStorage,
2340 offData + pImage->cbCluster);
2341 }
2342
2343 if (RT_SUCCESS(rc))
2344 rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage,
2345 pImage->offBackingFilename,
2346 pImage->pszBackingFilename,
2347 strlen(pImage->pszBackingFilename));
2348 }
2349 }
2350 }
2351 else
2352 rc = VERR_VD_NOT_OPENED;
2353
2354 LogFlowFunc(("returns %Rrc\n", rc));
2355 return rc;
2356}
2357
2358
2359
2360const VDIMAGEBACKEND g_QCowBackend =
2361{
2362 /* u32Version */
2363 VD_IMGBACKEND_VERSION,
2364 /* pszBackendName */
2365 "QCOW",
2366 /* uBackendCaps */
2367 VD_CAP_FILE | VD_CAP_VFS | VD_CAP_CREATE_DYNAMIC | VD_CAP_DIFF | VD_CAP_ASYNC,
2368 /* paFileExtensions */
2369 s_aQCowFileExtensions,
2370 /* paConfigInfo */
2371 NULL,
2372 /* pfnProbe */
2373 qcowProbe,
2374 /* pfnOpen */
2375 qcowOpen,
2376 /* pfnCreate */
2377 qcowCreate,
2378 /* pfnRename */
2379 qcowRename,
2380 /* pfnClose */
2381 qcowClose,
2382 /* pfnRead */
2383 qcowRead,
2384 /* pfnWrite */
2385 qcowWrite,
2386 /* pfnFlush */
2387 qcowFlush,
2388 /* pfnDiscard */
2389 NULL,
2390 /* pfnGetVersion */
2391 qcowGetVersion,
2392 /* pfnGetFileSize */
2393 qcowGetFileSize,
2394 /* pfnGetPCHSGeometry */
2395 qcowGetPCHSGeometry,
2396 /* pfnSetPCHSGeometry */
2397 qcowSetPCHSGeometry,
2398 /* pfnGetLCHSGeometry */
2399 qcowGetLCHSGeometry,
2400 /* pfnSetLCHSGeometry */
2401 qcowSetLCHSGeometry,
2402 /* pfnQueryRegions */
2403 qcowQueryRegions,
2404 /* pfnRegionListRelease */
2405 qcowRegionListRelease,
2406 /* pfnGetImageFlags */
2407 qcowGetImageFlags,
2408 /* pfnGetOpenFlags */
2409 qcowGetOpenFlags,
2410 /* pfnSetOpenFlags */
2411 qcowSetOpenFlags,
2412 /* pfnGetComment */
2413 qcowGetComment,
2414 /* pfnSetComment */
2415 qcowSetComment,
2416 /* pfnGetUuid */
2417 qcowGetUuid,
2418 /* pfnSetUuid */
2419 qcowSetUuid,
2420 /* pfnGetModificationUuid */
2421 qcowGetModificationUuid,
2422 /* pfnSetModificationUuid */
2423 qcowSetModificationUuid,
2424 /* pfnGetParentUuid */
2425 qcowGetParentUuid,
2426 /* pfnSetParentUuid */
2427 qcowSetParentUuid,
2428 /* pfnGetParentModificationUuid */
2429 qcowGetParentModificationUuid,
2430 /* pfnSetParentModificationUuid */
2431 qcowSetParentModificationUuid,
2432 /* pfnDump */
2433 qcowDump,
2434 /* pfnGetTimestamp */
2435 NULL,
2436 /* pfnGetParentTimestamp */
2437 NULL,
2438 /* pfnSetParentTimestamp */
2439 NULL,
2440 /* pfnGetParentFilename */
2441 qcowGetParentFilename,
2442 /* pfnSetParentFilename */
2443 qcowSetParentFilename,
2444 /* pfnComposeLocation */
2445 genericFileComposeLocation,
2446 /* pfnComposeName */
2447 genericFileComposeName,
2448 /* pfnCompact */
2449 NULL,
2450 /* pfnResize */
2451 NULL,
2452 /* pfnRepair */
2453 NULL,
2454 /* pfnTraverseMetadata */
2455 NULL,
2456 /* u32VersionEnd */
2457 VD_IMGBACKEND_VERSION
2458};
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette