VirtualBox

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

Last change on this file since 79967 was 79965, checked in by vboxsync, 5 years ago

Storage: Added a desired format parameter to VDGetFormat() so Main can pass along the device type. Bumped the RAW backend down after the CUE and VISO to prevent (impossible) mixups of tiny files. Extended rawProbe() to look for a valid ISO-9660/UDF descriptor sequence on the image if the caller doesn't say it should be a floppy or hdd, only if that fail go by the extension. Note! the pfnProbe callback should probably get a score return parameter to indicate how confient the backend is about the probe result, as this would prevent the RAW backend from accidentally grabbing images which belongs to a plug-in. bugref:9151

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