VirtualBox

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

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

Storage/QCOW: Remember an L2 table if it was just created so it can be accessed when another read or write happens in the same area at the same time. Fixes assertion in VD layer

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