VirtualBox

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

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

Storage/VD: Add proper versioning of the backend structures instead of just relying on the structure size to make changing callback signatures possible in the future and still being able to reject incompatible plugins

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