VirtualBox

source: vbox/trunk/include/VBox/VBoxHDD.h@ 27933

Last change on this file since 27933 was 27808, checked in by vboxsync, 15 years ago

VBoxHDD: First part of the async I/O support

  • The async I/O interface is not presented to the backend directly anymore but goes through a new interface in VBoxHDD doing the request management
  • Implemented everything to make the old coe work again
  • Async I/O completely disabled for now because it is not working atm (the old code for VMDK was removed)
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 87.1 KB
Line 
1/** @file
2 * VBox HDD Container API.
3 */
4
5/*
6 * Copyright (C) 2006-2010 Sun Microsystems, Inc.
7 *
8 * This file is part of VirtualBox Open Source Edition (OSE), as
9 * available from http://www.virtualbox.org. This file is free software;
10 * you can redistribute it and/or modify it under the terms of the GNU
11 * General Public License (GPL) as published by the Free Software
12 * Foundation, in version 2 as it comes in the "COPYING" file of the
13 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
14 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
15 *
16 * The contents of this file may alternatively be used under the terms
17 * of the Common Development and Distribution License Version 1.0
18 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
19 * VirtualBox OSE distribution, in which case the provisions of the
20 * CDDL are applicable instead of those of the GPL.
21 *
22 * You may elect to license modified versions of this file under the
23 * terms and conditions of either the GPL or the CDDL or both.
24 *
25 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
26 * Clara, CA 95054 USA or visit http://www.sun.com if you need
27 * additional information or have any questions.
28 */
29
30#ifndef ___VBox_VD_h
31#define ___VBox_VD_h
32
33#include <iprt/assert.h>
34#include <iprt/string.h>
35#include <iprt/mem.h>
36#include <iprt/net.h>
37#include <VBox/cdefs.h>
38#include <VBox/types.h>
39#include <VBox/err.h>
40#include <VBox/pdmifs.h>
41
42RT_C_DECLS_BEGIN
43
44#ifdef IN_RING0
45# error "There are no VBox HDD Container APIs available in Ring-0 Host Context!"
46#endif
47
48/** @defgroup grp_vd VBox HDD Container
49 * @{
50 */
51
52/** Current VMDK image version. */
53#define VMDK_IMAGE_VERSION (0x0001)
54
55/** Current VDI image major version. */
56#define VDI_IMAGE_VERSION_MAJOR (0x0001)
57/** Current VDI image minor version. */
58#define VDI_IMAGE_VERSION_MINOR (0x0001)
59/** Current VDI image version. */
60#define VDI_IMAGE_VERSION ((VDI_IMAGE_VERSION_MAJOR << 16) | VDI_IMAGE_VERSION_MINOR)
61
62/** Get VDI major version from combined version. */
63#define VDI_GET_VERSION_MAJOR(uVer) ((uVer) >> 16)
64/** Get VDI minor version from combined version. */
65#define VDI_GET_VERSION_MINOR(uVer) ((uVer) & 0xffff)
66
67/** Placeholder for specifying the last opened image. */
68#define VD_LAST_IMAGE 0xffffffffU
69
70/** @name VBox HDD container image flags
71 * @{
72 */
73/** No flags. */
74#define VD_IMAGE_FLAGS_NONE (0)
75/** Fixed image. */
76#define VD_IMAGE_FLAGS_FIXED (0x10000)
77/** Diff image. Mutually exclusive with fixed image. */
78#define VD_IMAGE_FLAGS_DIFF (0x20000)
79/** VMDK: Split image into 2GB extents. */
80#define VD_VMDK_IMAGE_FLAGS_SPLIT_2G (0x0001)
81/** VMDK: Raw disk image (giving access to a number of host partitions). */
82#define VD_VMDK_IMAGE_FLAGS_RAWDISK (0x0002)
83/** VMDK: stream optimized image, read only. */
84#define VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED (0x0004)
85/** VMDK: ESX variant, use in addition to other flags. */
86#define VD_VMDK_IMAGE_FLAGS_ESX (0x0008)
87/** VDI: Fill new blocks with zeroes while expanding image file. Only valid
88 * for newly created images, never set for opened existing images. */
89#define VD_VDI_IMAGE_FLAGS_ZERO_EXPAND (0x0100)
90
91/** Mask of valid image flags for VMDK. */
92#define VD_VMDK_IMAGE_FLAGS_MASK ( VD_IMAGE_FLAGS_FIXED | VD_IMAGE_FLAGS_DIFF | VD_IMAGE_FLAGS_NONE \
93 | VD_VMDK_IMAGE_FLAGS_SPLIT_2G | VD_VMDK_IMAGE_FLAGS_RAWDISK \
94 | VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED | VD_VMDK_IMAGE_FLAGS_ESX)
95
96/** Mask of valid image flags for VDI. */
97#define VD_VDI_IMAGE_FLAGS_MASK (VD_IMAGE_FLAGS_FIXED | VD_IMAGE_FLAGS_DIFF | VD_IMAGE_FLAGS_NONE | VD_VDI_IMAGE_FLAGS_ZERO_EXPAND)
98
99/** Mask of all valid image flags for all formats. */
100#define VD_IMAGE_FLAGS_MASK (VD_VMDK_IMAGE_FLAGS_MASK | VD_VDI_IMAGE_FLAGS_MASK)
101
102/** Default image flags. */
103#define VD_IMAGE_FLAGS_DEFAULT (VD_IMAGE_FLAGS_NONE)
104/** @} */
105
106
107/**
108 * Auxiliary type for describing partitions on raw disks.
109 */
110typedef struct VBOXHDDRAWPART
111{
112 /** Device to use for this partition. Can be the disk device if the offset
113 * field is set appropriately. If this is NULL, then this partition will
114 * not be accessible to the guest. The size of the partition must still
115 * be set correctly. */
116 const char *pszRawDevice;
117 /** Offset where the partition data starts in this device. */
118 uint64_t uPartitionStartOffset;
119 /** Offset where the partition data starts in the disk. */
120 uint64_t uPartitionStart;
121 /** Size of the partition. */
122 uint64_t cbPartition;
123 /** Size of the partitioning info to prepend. */
124 uint64_t cbPartitionData;
125 /** Offset where the partitioning info starts in the disk. */
126 uint64_t uPartitionDataStart;
127 /** Pointer to the partitioning info to prepend. */
128 const void *pvPartitionData;
129} VBOXHDDRAWPART, *PVBOXHDDRAWPART;
130
131/**
132 * Auxiliary data structure for creating raw disks.
133 */
134typedef struct VBOXHDDRAW
135{
136 /** Signature for structure. Must be 'R', 'A', 'W', '\\0'. Actually a trick
137 * to make logging of the comment string produce sensible results. */
138 char szSignature[4];
139 /** Flag whether access to full disk should be given (ignoring the
140 * partition information below). */
141 bool fRawDisk;
142 /** Filename for the raw disk. Ignored for partitioned raw disks.
143 * For Linux e.g. /dev/sda, and for Windows e.g. \\\\.\\PhysicalDisk0. */
144 const char *pszRawDisk;
145 /** Number of entries in the partitions array. */
146 unsigned cPartitions;
147 /** Pointer to the partitions array. */
148 PVBOXHDDRAWPART pPartitions;
149} VBOXHDDRAW, *PVBOXHDDRAW;
150
151/** @name VBox HDD container image open mode flags
152 * @{
153 */
154/** Try to open image in read/write exclusive access mode if possible, or in read-only elsewhere. */
155#define VD_OPEN_FLAGS_NORMAL 0
156/** Open image in read-only mode with sharing access with others. */
157#define VD_OPEN_FLAGS_READONLY RT_BIT(0)
158/** Honor zero block writes instead of ignoring them whenever possible.
159 * This is not supported by all formats. It is silently ignored in this case. */
160#define VD_OPEN_FLAGS_HONOR_ZEROES RT_BIT(1)
161/** Honor writes of the same data instead of ignoring whenever possible.
162 * This is handled generically, and is only meaningful for differential image
163 * formats. It is silently ignored otherwise. */
164#define VD_OPEN_FLAGS_HONOR_SAME RT_BIT(2)
165/** Do not perform the base/diff image check on open. This does NOT imply
166 * opening the image as readonly (would break e.g. adding UUIDs to VMDK files
167 * created by other products). Images opened with this flag should only be
168 * used for querying information, and nothing else. */
169#define VD_OPEN_FLAGS_INFO RT_BIT(3)
170/** Open image for asynchronous access.
171 * Only available if VD_CAP_ASYNC_IO is set
172 * Check with VDIsAsynchonousIoSupported wether
173 * asynchronous I/O is really supported for this file.
174 */
175#define VD_OPEN_FLAGS_ASYNC_IO RT_BIT(4)
176/** Mask of valid flags. */
177#define VD_OPEN_FLAGS_MASK (VD_OPEN_FLAGS_NORMAL | VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_HONOR_ZEROES | VD_OPEN_FLAGS_HONOR_SAME | VD_OPEN_FLAGS_INFO | VD_OPEN_FLAGS_ASYNC_IO)
178/** @}*/
179
180
181/** @name VBox HDD container backend capability flags
182 * @{
183 */
184/** Supports UUIDs as expected by VirtualBox code. */
185#define VD_CAP_UUID RT_BIT(0)
186/** Supports creating fixed size images, allocating all space instantly. */
187#define VD_CAP_CREATE_FIXED RT_BIT(1)
188/** Supports creating dynamically growing images, allocating space on demand. */
189#define VD_CAP_CREATE_DYNAMIC RT_BIT(2)
190/** Supports creating images split in chunks of a bit less than 2GBytes. */
191#define VD_CAP_CREATE_SPLIT_2G RT_BIT(3)
192/** Supports being used as differencing image format backend. */
193#define VD_CAP_DIFF RT_BIT(4)
194/** Supports asynchronous I/O operations for at least some configurations. */
195#define VD_CAP_ASYNC RT_BIT(5)
196/** The backend operates on files. The caller needs to know to handle the
197 * location appropriately. */
198#define VD_CAP_FILE RT_BIT(6)
199/** The backend uses the config interface. The caller needs to know how to
200 * provide the mandatory configuration parts this way. */
201#define VD_CAP_CONFIG RT_BIT(7)
202/** The backend uses the network stack interface. The caller has to provide
203 * the appropriate interface. */
204#define VD_CAP_TCPNET RT_BIT(8)
205/** @}*/
206
207/**
208 * Supported interface types.
209 */
210typedef enum VDINTERFACETYPE
211{
212 /** First valid interface. */
213 VDINTERFACETYPE_FIRST = 0,
214 /** Interface to pass error message to upper layers. Per-disk. */
215 VDINTERFACETYPE_ERROR = VDINTERFACETYPE_FIRST,
216 /** Interface for asynchronous I/O operations. Per-disk. */
217 VDINTERFACETYPE_ASYNCIO,
218 /** Interface for progress notification. Per-operation. */
219 VDINTERFACETYPE_PROGRESS,
220 /** Interface for configuration information. Per-image. */
221 VDINTERFACETYPE_CONFIG,
222 /** Interface for TCP network stack. Per-disk. */
223 VDINTERFACETYPE_TCPNET,
224 /** Interface for getting parent image state. Per-operation. */
225 VDINTERFACETYPE_PARENTSTATE,
226 /** Interface for synchronizing accesses from several threads. Per-disk. */
227 VDINTERFACETYPE_THREADSYNC,
228 /** Interface for I/O between the generic VBoxHDD code and the backend. Per-image. */
229 VDINTERFACETYPE_IO,
230 /** invalid interface. */
231 VDINTERFACETYPE_INVALID
232} VDINTERFACETYPE;
233
234/**
235 * Common structure for all interfaces.
236 */
237typedef struct VDINTERFACE
238{
239 /** Human readable interface name. */
240 const char *pszInterfaceName;
241 /** The size of the struct. */
242 uint32_t cbSize;
243 /** Pointer to the next common interface structure. */
244 struct VDINTERFACE *pNext;
245 /** Interface type. */
246 VDINTERFACETYPE enmInterface;
247 /** Opaque user data which is passed on every call. */
248 void *pvUser;
249 /** Pointer to the function call table of the interface.
250 * As this is opaque this must be casted to the right interface
251 * struct defined below based on the interface type in enmInterface. */
252 void *pCallbacks;
253} VDINTERFACE;
254/** Pointer to a VDINTERFACE. */
255typedef VDINTERFACE *PVDINTERFACE;
256/** Pointer to a const VDINTERFACE. */
257typedef const VDINTERFACE *PCVDINTERFACE;
258
259/**
260 * Helper functions to handle interface lists.
261 *
262 * @note These interface lists are used consistently to pass per-disk,
263 * per-image and/or per-operation callbacks. Those three purposes are strictly
264 * separate. See the individual interface declarations for what context they
265 * apply to. The caller is responsible for ensuring that the lifetime of the
266 * interface descriptors is appropriate for the category of interface.
267 */
268
269/**
270 * Get a specific interface from a list of interfaces specified by the type.
271 *
272 * @return Pointer to the matching interface or NULL if none was found.
273 * @param pVDIfs Pointer to the VD interface list.
274 * @param enmInterface Interface to search for.
275 */
276DECLINLINE(PVDINTERFACE) VDInterfaceGet(PVDINTERFACE pVDIfs, VDINTERFACETYPE enmInterface)
277{
278 AssertMsgReturn( (enmInterface >= VDINTERFACETYPE_FIRST)
279 && (enmInterface < VDINTERFACETYPE_INVALID),
280 ("enmInterface=%u", enmInterface), NULL);
281
282 while (pVDIfs)
283 {
284 /* Sanity checks. */
285 AssertMsgBreak(pVDIfs->cbSize == sizeof(VDINTERFACE),
286 ("cbSize=%u\n", pVDIfs->cbSize));
287
288 if (pVDIfs->enmInterface == enmInterface)
289 return pVDIfs;
290 pVDIfs = pVDIfs->pNext;
291 }
292
293 /* No matching interface was found. */
294 return NULL;
295}
296
297/**
298 * Add an interface to a list of interfaces.
299 *
300 * @return VBox status code.
301 * @param pInterface Pointer to an unitialized common interface structure.
302 * @param pszName Name of the interface.
303 * @param enmInterface Type of the interface.
304 * @param pCallbacks The callback table of the interface.
305 * @param pvUser Opaque user data passed on every function call.
306 * @param ppVDIfs Pointer to the VD interface list.
307 */
308DECLINLINE(int) VDInterfaceAdd(PVDINTERFACE pInterface, const char *pszName,
309 VDINTERFACETYPE enmInterface, void *pCallbacks,
310 void *pvUser, PVDINTERFACE *ppVDIfs)
311{
312
313 /** Argument checks. */
314 AssertMsgReturn( (enmInterface >= VDINTERFACETYPE_FIRST)
315 && (enmInterface < VDINTERFACETYPE_INVALID),
316 ("enmInterface=%u", enmInterface), VERR_INVALID_PARAMETER);
317
318 AssertMsgReturn(VALID_PTR(pCallbacks),
319 ("pCallbacks=%#p", pCallbacks),
320 VERR_INVALID_PARAMETER);
321
322 AssertMsgReturn(VALID_PTR(ppVDIfs),
323 ("pInterfaceList=%#p", ppVDIfs),
324 VERR_INVALID_PARAMETER);
325
326 /* Fill out interface descriptor. */
327 pInterface->cbSize = sizeof(VDINTERFACE);
328 pInterface->pszInterfaceName = pszName;
329 pInterface->enmInterface = enmInterface;
330 pInterface->pCallbacks = pCallbacks;
331 pInterface->pvUser = pvUser;
332 pInterface->pNext = *ppVDIfs;
333
334 /* Remember the new start of the list. */
335 *ppVDIfs = pInterface;
336
337 return VINF_SUCCESS;
338}
339
340/**
341 * Removes an interface from a list of interfaces.
342 *
343 * @return VBox status code
344 * @param pInterface Pointer to an initialized common interface structure to remove.
345 * @param ppVDIfs Pointer to the VD interface list to remove from.
346 */
347DECLINLINE(int) VDInterfaceRemove(PVDINTERFACE pInterface, PVDINTERFACE *ppVDIfs)
348{
349 int rc = VERR_NOT_FOUND;
350
351 /** Argument checks. */
352 AssertMsgReturn(VALID_PTR(pInterface),
353 ("pInterface=%#p", pInterface),
354 VERR_INVALID_PARAMETER);
355
356 AssertMsgReturn(VALID_PTR(ppVDIfs),
357 ("pInterfaceList=%#p", ppVDIfs),
358 VERR_INVALID_PARAMETER);
359
360 if (*ppVDIfs)
361 {
362 PVDINTERFACE pPrev = NULL;
363 PVDINTERFACE pCurr = *ppVDIfs;
364
365 while ( pCurr
366 && (pCurr != pInterface))
367 {
368 pPrev = pCurr;
369 pCurr = pCurr->pNext;
370 }
371
372 /* First interface */
373 if (!pPrev)
374 {
375 *ppVDIfs = pCurr->pNext;
376 rc = VINF_SUCCESS;
377 }
378 else if (pCurr)
379 {
380 pPrev = pCurr->pNext;
381 rc = VINF_SUCCESS;
382 }
383 }
384
385 return rc;
386}
387
388/**
389 * Interface to deliver error messages (and also informational messages)
390 * to upper layers.
391 *
392 * Per disk interface. Optional, but think twice if you want to miss the
393 * opportunity of reporting better human-readable error messages.
394 */
395typedef struct VDINTERFACEERROR
396{
397 /**
398 * Size of the error interface.
399 */
400 uint32_t cbSize;
401
402 /**
403 * Interface type.
404 */
405 VDINTERFACETYPE enmInterface;
406
407 /**
408 * Error message callback. Must be able to accept special IPRT format
409 * strings.
410 *
411 * @param pvUser The opaque data passed on container creation.
412 * @param rc The VBox error code.
413 * @param RT_SRC_POS_DECL Use RT_SRC_POS.
414 * @param pszFormat Error message format string.
415 * @param va Error message arguments.
416 */
417 DECLR3CALLBACKMEMBER(void, pfnError, (void *pvUser, int rc, RT_SRC_POS_DECL, const char *pszFormat, va_list va));
418
419 /**
420 * Informational message callback. May be NULL. Used e.g. in
421 * VDDumpImages(). Must be able to accept special IPRT format strings.
422 *
423 * @return VBox status code.
424 * @param pvUser The opaque data passed on container creation.
425 * @param pszFormat Error message format string.
426 * @param ... Error message arguments.
427 */
428 DECLR3CALLBACKMEMBER(int, pfnMessage, (void *pvUser, const char *pszFormat, ...));
429
430} VDINTERFACEERROR, *PVDINTERFACEERROR;
431
432/**
433 * Get error interface from opaque callback table.
434 *
435 * @return Pointer to the callback table.
436 * @param pInterface Pointer to the interface descriptor.
437 */
438DECLINLINE(PVDINTERFACEERROR) VDGetInterfaceError(PVDINTERFACE pInterface)
439{
440 /* Check that the interface descriptor is a error interface. */
441 AssertMsgReturn( (pInterface->enmInterface == VDINTERFACETYPE_ERROR)
442 && (pInterface->cbSize == sizeof(VDINTERFACE)),
443 ("Not an error interface"), NULL);
444
445 PVDINTERFACEERROR pInterfaceError = (PVDINTERFACEERROR)pInterface->pCallbacks;
446
447 /* Do basic checks. */
448 AssertMsgReturn( (pInterfaceError->cbSize == sizeof(VDINTERFACEERROR))
449 && (pInterfaceError->enmInterface == VDINTERFACETYPE_ERROR),
450 ("A non error callback table attached to a error interface descriptor\n"), NULL);
451
452 return pInterfaceError;
453}
454
455/**
456 * Completion callback which is called by the interface owner
457 * to inform the backend that a task finished.
458 *
459 * @return VBox status code.
460 * @param pvUser Opaque user data which is passed on request submission.
461 * @param ppvCaller Where to store the opaque user data the caller of
462 * VDAsyncRead or VDAsyncWrite passed.
463 */
464typedef DECLCALLBACK(int) FNVDCOMPLETED(void *pvUser, void **ppvCaller);
465/** Pointer to FNVDCOMPLETED() */
466typedef FNVDCOMPLETED *PFNVDCOMPLETED;
467
468/** Open the storage readonly. */
469#define VD_INTERFACEASYNCIO_OPEN_FLAGS_READONLY RT_BIT(0)
470/** Create the storage backend if it doesn't exist. */
471#define VD_INTERFACEASYNCIO_OPEN_FLAGS_CREATE RT_BIT(1)
472
473/**
474 * Support interface for asynchronous I/O
475 *
476 * Per-disk. Optional.
477 */
478typedef struct VDINTERFACEASYNCIO
479{
480 /**
481 * Size of the async interface.
482 */
483 uint32_t cbSize;
484
485 /**
486 * Interface type.
487 */
488 VDINTERFACETYPE enmInterface;
489
490 /**
491 * Open callback
492 *
493 * @return VBox status code.
494 * @param pvUser The opaque data passed on container creation.
495 * @param pszLocation Name of the location to open.
496 * @param uOpenFlags Flags for opening the backend.
497 * See VD_INTERFACEASYNCIO_OPEN_FLAGS_* #defines
498 * @param pfnCompleted The callback which is called whenever a task
499 * completed. The backend has to pass the user data
500 * of the request initiator (ie the one who calls
501 * VDAsyncRead or VDAsyncWrite) in pvCompletion
502 * if this is NULL.
503 * @param pVDIfsDisk Pointer to the per-disk VD interface list.
504 * @param ppStorage Where to store the opaque storage handle.
505 */
506 DECLR3CALLBACKMEMBER(int, pfnOpen, (void *pvUser, const char *pszLocation,
507 unsigned uOpenFlags,
508 PFNVDCOMPLETED pfnCompleted,
509 PVDINTERFACE pVDIfsDisk,
510 void **ppStorage));
511
512 /**
513 * Close callback.
514 *
515 * @return VBox status code.
516 * @param pvUser The opaque data passed on container creation.
517 * @param pStorage The opaque storage handle to close.
518 */
519 DECLR3CALLBACKMEMBER(int, pfnClose, (void *pvUser, void *pStorage));
520
521 /**
522 * Returns the size of the opened storage backend.
523 *
524 * @return VBox status code.
525 * @param pvUser The opaque data passed on container creation.
526 * @param pStorage The opaque storage handle to close.
527 * @param pcbSize Where to store the size of the storage backend.
528 */
529 DECLR3CALLBACKMEMBER(int, pfnGetSize, (void *pvUser, void *pStorage, uint64_t *pcbSize));
530
531 /**
532 * Sets the size of the opened storage backend if possible.
533 *
534 * @return VBox status code.
535 * @retval VERR_NOT_SUPPORTED if the backend does not support this operation.
536 * @param pvUser The opaque data passed on container creation.
537 * @param pStorage The opaque storage handle to close.
538 * @param cbSize The new size of the image.
539 */
540 DECLR3CALLBACKMEMBER(int, pfnSetSize, (void *pvUser, void *pStorage, uint64_t cbSize));
541
542 /**
543 * Synchronous write callback.
544 *
545 * @return VBox status code.
546 * @param pvUser The opaque data passed on container creation.
547 * @param pStorage The storage handle to use.
548 * @param uOffset The offset to start from.
549 * @param cbWrite How many bytes to write.
550 * @param pvBuf Pointer to the bits need to be written.
551 * @param pcbWritten Where to store how many bytes where actually written.
552 */
553 DECLR3CALLBACKMEMBER(int, pfnWriteSync, (void *pvUser, void *pStorage, uint64_t uOffset,
554 size_t cbWrite, const void *pvBuf, size_t *pcbWritten));
555
556 /**
557 * Synchronous read callback.
558 *
559 * @return VBox status code.
560 * @param pvUser The opaque data passed on container creation.
561 * @param pStorage The storage handle to use.
562 * @param uOffset The offset to start from.
563 * @param cbRead How many bytes to read.
564 * @param pvBuf Where to store the read bits.
565 * @param pcbRead Where to store how many bytes where actually read.
566 */
567 DECLR3CALLBACKMEMBER(int, pfnReadSync, (void *pvUser, void *pStorage, uint64_t uOffset,
568 size_t cbRead, void *pvBuf, size_t *pcbRead));
569
570 /**
571 * Flush data to the storage backend.
572 *
573 * @return VBox statis code.
574 * @param pvUser The opaque data passed on container creation.
575 * @param pStorage The storage handle to flush.
576 */
577 DECLR3CALLBACKMEMBER(int, pfnFlushSync, (void *pvUser, void *pStorage));
578
579 /**
580 * Initiate a asynchronous read request.
581 *
582 * @return VBox status code.
583 * @param pvUser The opqaue user data passed on container creation.
584 * @param pStorage The storage handle.
585 * @param uOffset The offset to start reading from.
586 * @param paSegments Scatter gather list to store the data in.
587 * @param cSegments Number of segments in the list.
588 * @param cbRead How many bytes to read.
589 * @param pvCompletion The opaque user data which is returned upon completion.
590 * @param ppTask Where to store the opaque task handle.
591 */
592 DECLR3CALLBACKMEMBER(int, pfnReadAsync, (void *pvUser, void *pStorage, uint64_t uOffset,
593 PCPDMDATASEG paSegments, size_t cSegments,
594 size_t cbRead, void *pvCompletion,
595 void **ppTask));
596
597 /**
598 * Initiate a asynchronous write request.
599 *
600 * @return VBox status code.
601 * @param pvUser The opaque user data passed on conatiner creation.
602 * @param pStorage The storage handle.
603 * @param uOffset The offset to start writing to.
604 * @param paSegments Scatter gather list of the data to write
605 * @param cSegments Number of segments in the list.
606 * @param cbWrite How many bytes to write.
607 * @param pvCompletion The opaque user data which is returned upon completion.
608 * @param ppTask Where to store the opaque task handle.
609 */
610 DECLR3CALLBACKMEMBER(int, pfnWriteAsync, (void *pvUser, void *pStorage, uint64_t uOffset,
611 PCPDMDATASEG paSegments, size_t cSegments,
612 size_t cbWrite, void *pvCompletion,
613 void **ppTask));
614
615 /**
616 * Initiates a async flush request.
617 *
618 * @return VBox statis code.
619 * @param pvUser The opaque data passed on container creation.
620 * @param pStorage The storage handle to flush.
621 * @param pvCompletion The opaque user data which is returned upon completion.
622 * @param ppTask Where to store the opaque task handle.
623 */
624 DECLR3CALLBACKMEMBER(int, pfnFlushAsync, (void *pvUser, void *pStorage,
625 void *pvCompletion, void **ppTask));
626
627} VDINTERFACEASYNCIO, *PVDINTERFACEASYNCIO;
628
629/**
630 * Get async I/O interface from opaque callback table.
631 *
632 * @return Pointer to the callback table.
633 * @param pInterface Pointer to the interface descriptor.
634 */
635DECLINLINE(PVDINTERFACEASYNCIO) VDGetInterfaceAsyncIO(PVDINTERFACE pInterface)
636{
637 /* Check that the interface descriptor is a async I/O interface. */
638 AssertMsgReturn( (pInterface->enmInterface == VDINTERFACETYPE_ASYNCIO)
639 && (pInterface->cbSize == sizeof(VDINTERFACE)),
640 ("Not an async I/O interface"), NULL);
641
642 PVDINTERFACEASYNCIO pInterfaceAsyncIO = (PVDINTERFACEASYNCIO)pInterface->pCallbacks;
643
644 /* Do basic checks. */
645 AssertMsgReturn( (pInterfaceAsyncIO->cbSize == sizeof(VDINTERFACEASYNCIO))
646 && (pInterfaceAsyncIO->enmInterface == VDINTERFACETYPE_ASYNCIO),
647 ("A non async I/O callback table attached to a async I/O interface descriptor\n"), NULL);
648
649 return pInterfaceAsyncIO;
650}
651
652/**
653 * Callback which provides progress information about a currently running
654 * lengthy operation.
655 *
656 * @return VBox status code.
657 * @param pvUser The opaque user data associated with this interface.
658 * @param uPercent Completion percentage.
659 */
660typedef DECLCALLBACK(int) FNVDPROGRESS(void *pvUser, unsigned uPercentage);
661/** Pointer to FNVDPROGRESS() */
662typedef FNVDPROGRESS *PFNVDPROGRESS;
663
664/**
665 * Progress notification interface
666 *
667 * Per-operation. Optional.
668 */
669typedef struct VDINTERFACEPROGRESS
670{
671 /**
672 * Size of the progress interface.
673 */
674 uint32_t cbSize;
675
676 /**
677 * Interface type.
678 */
679 VDINTERFACETYPE enmInterface;
680
681 /**
682 * Progress notification callbacks.
683 */
684 PFNVDPROGRESS pfnProgress;
685
686} VDINTERFACEPROGRESS, *PVDINTERFACEPROGRESS;
687
688/**
689 * Get progress interface from opaque callback table.
690 *
691 * @return Pointer to the callback table.
692 * @param pInterface Pointer to the interface descriptor.
693 */
694DECLINLINE(PVDINTERFACEPROGRESS) VDGetInterfaceProgress(PVDINTERFACE pInterface)
695{
696 /* Check that the interface descriptor is a progress interface. */
697 AssertMsgReturn( (pInterface->enmInterface == VDINTERFACETYPE_PROGRESS)
698 && (pInterface->cbSize == sizeof(VDINTERFACE)),
699 ("Not a progress interface"), NULL);
700
701
702 PVDINTERFACEPROGRESS pInterfaceProgress = (PVDINTERFACEPROGRESS)pInterface->pCallbacks;
703
704 /* Do basic checks. */
705 AssertMsgReturn( (pInterfaceProgress->cbSize == sizeof(VDINTERFACEPROGRESS))
706 && (pInterfaceProgress->enmInterface == VDINTERFACETYPE_PROGRESS),
707 ("A non progress callback table attached to a progress interface descriptor\n"), NULL);
708
709 return pInterfaceProgress;
710}
711
712
713/**
714 * Configuration information interface
715 *
716 * Per-image. Optional for most backends, but mandatory for images which do
717 * not operate on files (including standard block or character devices).
718 */
719typedef struct VDINTERFACECONFIG
720{
721 /**
722 * Size of the configuration interface.
723 */
724 uint32_t cbSize;
725
726 /**
727 * Interface type.
728 */
729 VDINTERFACETYPE enmInterface;
730
731 /**
732 * Validates that the keys are within a set of valid names.
733 *
734 * @return true if all key names are found in pszzAllowed.
735 * @return false if not.
736 * @param pvUser The opaque user data associated with this interface.
737 * @param pszzValid List of valid key names separated by '\\0' and ending with
738 * a double '\\0'.
739 */
740 DECLR3CALLBACKMEMBER(bool, pfnAreKeysValid, (void *pvUser, const char *pszzValid));
741
742 /**
743 * Retrieves the length of the string value associated with a key (including
744 * the terminator, for compatibility with CFGMR3QuerySize).
745 *
746 * @return VBox status code.
747 * VERR_CFGM_VALUE_NOT_FOUND means that the key is not known.
748 * @param pvUser The opaque user data associated with this interface.
749 * @param pszName Name of the key to query.
750 * @param pcbValue Where to store the value length. Non-NULL.
751 */
752 DECLR3CALLBACKMEMBER(int, pfnQuerySize, (void *pvUser, const char *pszName, size_t *pcbValue));
753
754 /**
755 * Query the string value associated with a key.
756 *
757 * @return VBox status code.
758 * VERR_CFGM_VALUE_NOT_FOUND means that the key is not known.
759 * VERR_CFGM_NOT_ENOUGH_SPACE means that the buffer is not big enough.
760 * @param pvUser The opaque user data associated with this interface.
761 * @param pszName Name of the key to query.
762 * @param pszValue Pointer to buffer where to store value.
763 * @param cchValue Length of value buffer.
764 */
765 DECLR3CALLBACKMEMBER(int, pfnQuery, (void *pvUser, const char *pszName, char *pszValue, size_t cchValue));
766
767} VDINTERFACECONFIG, *PVDINTERFACECONFIG;
768
769/**
770 * Get configuration information interface from opaque callback table.
771 *
772 * @return Pointer to the callback table.
773 * @param pInterface Pointer to the interface descriptor.
774 */
775DECLINLINE(PVDINTERFACECONFIG) VDGetInterfaceConfig(PVDINTERFACE pInterface)
776{
777 /* Check that the interface descriptor is a config interface. */
778 AssertMsgReturn( (pInterface->enmInterface == VDINTERFACETYPE_CONFIG)
779 && (pInterface->cbSize == sizeof(VDINTERFACE)),
780 ("Not a config interface"), NULL);
781
782 PVDINTERFACECONFIG pInterfaceConfig = (PVDINTERFACECONFIG)pInterface->pCallbacks;
783
784 /* Do basic checks. */
785 AssertMsgReturn( (pInterfaceConfig->cbSize == sizeof(VDINTERFACECONFIG))
786 && (pInterfaceConfig->enmInterface == VDINTERFACETYPE_CONFIG),
787 ("A non config callback table attached to a config interface descriptor\n"), NULL);
788
789 return pInterfaceConfig;
790}
791
792/**
793 * Query configuration, validates that the keys are within a set of valid names.
794 *
795 * @return true if all key names are found in pszzAllowed.
796 * @return false if not.
797 * @param pCfgIf Pointer to configuration callback table.
798 * @param pvUser The opaque user data associated with this interface.
799 * @param pszzValid List of valid names separated by '\\0' and ending with
800 * a double '\\0'.
801 */
802DECLINLINE(bool) VDCFGAreKeysValid(PVDINTERFACECONFIG pCfgIf, void *pvUser,
803 const char *pszzValid)
804{
805 return pCfgIf->pfnAreKeysValid(pvUser, pszzValid);
806}
807
808/**
809 * Query configuration, unsigned 64-bit integer value with default.
810 *
811 * @return VBox status code.
812 * @param pCfgIf Pointer to configuration callback table.
813 * @param pvUser The opaque user data associated with this interface.
814 * @param pszName Name of an integer value
815 * @param pu64 Where to store the value. Set to default on failure.
816 * @param u64Def The default value.
817 */
818DECLINLINE(int) VDCFGQueryU64Def(PVDINTERFACECONFIG pCfgIf, void *pvUser,
819 const char *pszName, uint64_t *pu64,
820 uint64_t u64Def)
821{
822 char aszBuf[32];
823 int rc = pCfgIf->pfnQuery(pvUser, pszName, aszBuf, sizeof(aszBuf));
824 if (RT_SUCCESS(rc))
825 {
826 rc = RTStrToUInt64Full(aszBuf, 0, pu64);
827 }
828 else if (rc == VERR_CFGM_VALUE_NOT_FOUND)
829 {
830 rc = VINF_SUCCESS;
831 *pu64 = u64Def;
832 }
833 return rc;
834}
835
836/**
837 * Query configuration, unsigned 32-bit integer value with default.
838 *
839 * @return VBox status code.
840 * @param pCfgIf Pointer to configuration callback table.
841 * @param pvUser The opaque user data associated with this interface.
842 * @param pszName Name of an integer value
843 * @param pu32 Where to store the value. Set to default on failure.
844 * @param u32Def The default value.
845 */
846DECLINLINE(int) VDCFGQueryU32Def(PVDINTERFACECONFIG pCfgIf, void *pvUser,
847 const char *pszName, uint32_t *pu32,
848 uint32_t u32Def)
849{
850 uint64_t u64;
851 int rc = VDCFGQueryU64Def(pCfgIf, pvUser, pszName, &u64, u32Def);
852 if (RT_SUCCESS(rc))
853 {
854 if (!(u64 & UINT64_C(0xffffffff00000000)))
855 *pu32 = (uint32_t)u64;
856 else
857 rc = VERR_CFGM_INTEGER_TOO_BIG;
858 }
859 return rc;
860}
861
862/**
863 * Query configuration, bool value with default.
864 *
865 * @return VBox status code.
866 * @param pCfgIf Pointer to configuration callback table.
867 * @param pvUser The opaque user data associated with this interface.
868 * @param pszName Name of an integer value
869 * @param pf Where to store the value. Set to default on failure.
870 * @param fDef The default value.
871 */
872DECLINLINE(int) VDCFGQueryBoolDef(PVDINTERFACECONFIG pCfgIf, void *pvUser,
873 const char *pszName, bool *pf,
874 bool fDef)
875{
876 uint64_t u64;
877 int rc = VDCFGQueryU64Def(pCfgIf, pvUser, pszName, &u64, fDef);
878 if (RT_SUCCESS(rc))
879 *pf = u64 ? true : false;
880 return rc;
881}
882
883/**
884 * Query configuration, dynamically allocated (RTMemAlloc) zero terminated
885 * character value.
886 *
887 * @return VBox status code.
888 * @param pCfgIf Pointer to configuration callback table.
889 * @param pvUser The opaque user data associated with this interface.
890 * @param pszName Name of an zero terminated character value
891 * @param ppszString Where to store the string pointer. Not set on failure.
892 * Free this using RTMemFree().
893 */
894DECLINLINE(int) VDCFGQueryStringAlloc(PVDINTERFACECONFIG pCfgIf,
895 void *pvUser, const char *pszName,
896 char **ppszString)
897{
898 size_t cb;
899 int rc = pCfgIf->pfnQuerySize(pvUser, pszName, &cb);
900 if (RT_SUCCESS(rc))
901 {
902 char *pszString = (char *)RTMemAlloc(cb);
903 if (pszString)
904 {
905 rc = pCfgIf->pfnQuery(pvUser, pszName, pszString, cb);
906 if (RT_SUCCESS(rc))
907 *ppszString = pszString;
908 else
909 RTMemFree(pszString);
910 }
911 else
912 rc = VERR_NO_MEMORY;
913 }
914 return rc;
915}
916
917/**
918 * Query configuration, dynamically allocated (RTMemAlloc) zero terminated
919 * character value with default.
920 *
921 * @return VBox status code.
922 * @param pCfgIf Pointer to configuration callback table.
923 * @param pvUser The opaque user data associated with this interface.
924 * @param pszName Name of an zero terminated character value
925 * @param ppszString Where to store the string pointer. Not set on failure.
926 * Free this using RTMemFree().
927 * @param pszDef The default value.
928 */
929DECLINLINE(int) VDCFGQueryStringAllocDef(PVDINTERFACECONFIG pCfgIf,
930 void *pvUser, const char *pszName,
931 char **ppszString,
932 const char *pszDef)
933{
934 size_t cb;
935 int rc = pCfgIf->pfnQuerySize(pvUser, pszName, &cb);
936 if (rc == VERR_CFGM_VALUE_NOT_FOUND || rc == VERR_CFGM_NO_PARENT)
937 {
938 cb = strlen(pszDef) + 1;
939 rc = VINF_SUCCESS;
940 }
941 if (RT_SUCCESS(rc))
942 {
943 char *pszString = (char *)RTMemAlloc(cb);
944 if (pszString)
945 {
946 rc = pCfgIf->pfnQuery(pvUser, pszName, pszString, cb);
947 if (rc == VERR_CFGM_VALUE_NOT_FOUND || rc == VERR_CFGM_NO_PARENT)
948 {
949 memcpy(pszString, pszDef, cb);
950 rc = VINF_SUCCESS;
951 }
952 if (RT_SUCCESS(rc))
953 *ppszString = pszString;
954 else
955 RTMemFree(pszString);
956 }
957 else
958 rc = VERR_NO_MEMORY;
959 }
960 return rc;
961}
962
963/**
964 * Query configuration, dynamically allocated (RTMemAlloc) byte string value.
965 *
966 * @return VBox status code.
967 * @param pCfgIf Pointer to configuration callback table.
968 * @param pvUser The opaque user data associated with this interface.
969 * @param pszName Name of an zero terminated character value
970 * @param ppvData Where to store the byte string pointer. Not set on failure.
971 * Free this using RTMemFree().
972 * @param pcbData Where to store the byte string length.
973 */
974DECLINLINE(int) VDCFGQueryBytesAlloc(PVDINTERFACECONFIG pCfgIf,
975 void *pvUser, const char *pszName,
976 void **ppvData, size_t *pcbData)
977{
978 size_t cb;
979 int rc = pCfgIf->pfnQuerySize(pvUser, pszName, &cb);
980 if (RT_SUCCESS(rc))
981 {
982 char *pvData = (char *)RTMemAlloc(cb);
983 if (pvData)
984 {
985 rc = pCfgIf->pfnQuery(pvUser, pszName, pvData, cb);
986 if (RT_SUCCESS(rc))
987 {
988 *ppvData = pvData;
989 *pcbData = cb;
990 }
991 else
992 RTMemFree(pvData);
993 }
994 else
995 rc = VERR_NO_MEMORY;
996 }
997 return rc;
998}
999
1000
1001/**
1002 * TCP network stack interface
1003 *
1004 * Per-disk. Mandatory for backends which have the VD_CAP_TCPNET bit set.
1005 */
1006typedef struct VDINTERFACETCPNET
1007{
1008 /**
1009 * Size of the configuration interface.
1010 */
1011 uint32_t cbSize;
1012
1013 /**
1014 * Interface type.
1015 */
1016 VDINTERFACETYPE enmInterface;
1017
1018 /**
1019 * Connect as a client to a TCP port.
1020 *
1021 * @return iprt status code.
1022 * @param pszAddress The address to connect to.
1023 * @param uPort The port to connect to.
1024 * @param pSock Where to store the handle to the established connect
1025ion.
1026 */
1027 DECLR3CALLBACKMEMBER(int, pfnClientConnect, (const char *pszAddress, uint32_t uPort, PRTSOCKET pSock));
1028
1029 /**
1030 * Close a TCP connection.
1031 *
1032 * @return iprt status code.
1033 * @param Sock Socket descriptor.
1034ion.
1035 */
1036 DECLR3CALLBACKMEMBER(int, pfnClientClose, (RTSOCKET Sock));
1037
1038 /**
1039 * Socket I/O multiplexing.
1040 * Checks if the socket is ready for reading.
1041 *
1042 * @return iprt status code.
1043 * @param Sock Socket descriptor.
1044 * @param cMillies Number of milliseconds to wait for the socket.
1045 * Use RT_INDEFINITE_WAIT to wait for ever.
1046 */
1047 DECLR3CALLBACKMEMBER(int, pfnSelectOne, (RTSOCKET Sock, RTMSINTERVAL cMillies));
1048
1049 /**
1050 * Receive data from a socket.
1051 *
1052 * @return iprt status code.
1053 * @param Sock Socket descriptor.
1054 * @param pvBuffer Where to put the data we read.
1055 * @param cbBuffer Read buffer size.
1056 * @param pcbRead Number of bytes read.
1057 * If NULL the entire buffer will be filled upon successful return.
1058 * If not NULL a partial read can be done successfully.
1059 */
1060 DECLR3CALLBACKMEMBER(int, pfnRead, (RTSOCKET Sock, void *pvBuffer, size_t cbBuffer, size_t *pcbRead));
1061
1062 /**
1063 * Send data from a socket.
1064 *
1065 * @return iprt status code.
1066 * @param Sock Socket descriptor.
1067 * @param pvBuffer Buffer to write data to socket.
1068 * @param cbBuffer How much to write.
1069 * @param pcbRead Number of bytes read.
1070 */
1071 DECLR3CALLBACKMEMBER(int, pfnWrite, (RTSOCKET Sock, const void *pvBuffer, size_t cbBuffer));
1072
1073 /**
1074 * Flush socket write buffers.
1075 *
1076 * @return iprt status code.
1077 * @param Sock Socket descriptor.
1078 */
1079 DECLR3CALLBACKMEMBER(int, pfnFlush, (RTSOCKET Sock));
1080
1081 /**
1082 * Gets the address of the local side.
1083 *
1084 * @return iprt status code.
1085 * @param Sock Socket descriptor.
1086 * @param pAddr Where to store the local address on success.
1087 */
1088 DECLR3CALLBACKMEMBER(int, pfnGetLocalAddress, (RTSOCKET Sock, PRTNETADDR pAddr));
1089
1090 /**
1091 * Gets the address of the other party.
1092 *
1093 * @return iprt status code.
1094 * @param Sock Socket descriptor.
1095 * @param pAddr Where to store the peer address on success.
1096 */
1097 DECLR3CALLBACKMEMBER(int, pfnGetPeerAddress, (RTSOCKET Sock, PRTNETADDR pAddr));
1098
1099} VDINTERFACETCPNET, *PVDINTERFACETCPNET;
1100
1101/**
1102 * Get TCP network stack interface from opaque callback table.
1103 *
1104 * @return Pointer to the callback table.
1105 * @param pInterface Pointer to the interface descriptor.
1106 */
1107DECLINLINE(PVDINTERFACETCPNET) VDGetInterfaceTcpNet(PVDINTERFACE pInterface)
1108{
1109 /* Check that the interface descriptor is a TCP network stack interface. */
1110 AssertMsgReturn( (pInterface->enmInterface == VDINTERFACETYPE_TCPNET)
1111 && (pInterface->cbSize == sizeof(VDINTERFACE)),
1112 ("Not a TCP network stack interface"), NULL);
1113
1114 PVDINTERFACETCPNET pInterfaceTcpNet = (PVDINTERFACETCPNET)pInterface->pCallbacks;
1115
1116 /* Do basic checks. */
1117 AssertMsgReturn( (pInterfaceTcpNet->cbSize == sizeof(VDINTERFACETCPNET))
1118 && (pInterfaceTcpNet->enmInterface == VDINTERFACETYPE_TCPNET),
1119 ("A non TCP network stack callback table attached to a TCP network stack interface descriptor\n"), NULL);
1120
1121 return pInterfaceTcpNet;
1122}
1123
1124/**
1125 * Interface to get the parent state.
1126 *
1127 * Per operation interface. Optional, present only if there is a parent, and
1128 * used only internally for compacting.
1129 */
1130typedef struct VDINTERFACEPARENTSTATE
1131{
1132 /**
1133 * Size of the parent state interface.
1134 */
1135 uint32_t cbSize;
1136
1137 /**
1138 * Interface type.
1139 */
1140 VDINTERFACETYPE enmInterface;
1141
1142 /**
1143 * Read data callback.
1144 *
1145 * @return VBox status code.
1146 * @return VERR_VD_NOT_OPENED if no image is opened in HDD container.
1147 * @param pvUser The opaque data passed for the operation.
1148 * @param uOffset Offset of first reading byte from start of disk.
1149 * Must be aligned to a sector boundary.
1150 * @param pvBuf Pointer to buffer for reading data.
1151 * @param cbRead Number of bytes to read.
1152 * Must be aligned to a sector boundary.
1153 */
1154 DECLR3CALLBACKMEMBER(int, pfnParentRead, (void *pvUser, uint64_t uOffset, void *pvBuf, size_t cbRead));
1155
1156} VDINTERFACEPARENTSTATE, *PVDINTERFACEPARENTSTATE;
1157
1158
1159/**
1160 * Get parent state interface from opaque callback table.
1161 *
1162 * @return Pointer to the callback table.
1163 * @param pInterface Pointer to the interface descriptor.
1164 */
1165DECLINLINE(PVDINTERFACEPARENTSTATE) VDGetInterfaceParentState(PVDINTERFACE pInterface)
1166{
1167 /* Check that the interface descriptor is a parent state interface. */
1168 AssertMsgReturn( (pInterface->enmInterface == VDINTERFACETYPE_PARENTSTATE)
1169 && (pInterface->cbSize == sizeof(VDINTERFACE)),
1170 ("Not a parent state interface"), NULL);
1171
1172 PVDINTERFACEPARENTSTATE pInterfaceParentState = (PVDINTERFACEPARENTSTATE)pInterface->pCallbacks;
1173
1174 /* Do basic checks. */
1175 AssertMsgReturn( (pInterfaceParentState->cbSize == sizeof(VDINTERFACEPARENTSTATE))
1176 && (pInterfaceParentState->enmInterface == VDINTERFACETYPE_PARENTSTATE),
1177 ("A non parent state callback table attached to a parent state interface descriptor\n"), NULL);
1178
1179 return pInterfaceParentState;
1180}
1181
1182/**
1183 * Interface to synchronize concurrent accesses by several threads.
1184 *
1185 * @note The scope of this interface is to manage concurrent accesses after
1186 * the HDD container has been created, and they must stop before destroying the
1187 * container. Opening or closing images is covered by the synchronization, but
1188 * that does not mean it is safe to close images while a thread executes
1189 * <link to="VDMerge"/> or <link to="VDCopy"/> operating on these images.
1190 * Making them safe would require the lock to be held during the entire
1191 * operation, which prevents other concurrent acitivities.
1192 *
1193 * @note Right now this is kept as simple as possible, and does not even
1194 * attempt to provide enough information to allow e.g. concurrent write
1195 * accesses to different areas of the disk. The reason is that it is very
1196 * difficult to predict which area of a disk is affected by a write,
1197 * especially when different image formats are mixed. Maybe later a more
1198 * sophisticated interface will be provided which has the necessary information
1199 * about worst case affected areas.
1200 *
1201 * Per disk interface. Optional, needed if the disk is accessed concurrently
1202 * by several threads, e.g. when merging diff images while a VM is running.
1203 */
1204typedef struct VDINTERFACETHREADSYNC
1205{
1206 /**
1207 * Size of the thread synchronization interface.
1208 */
1209 uint32_t cbSize;
1210
1211 /**
1212 * Interface type.
1213 */
1214 VDINTERFACETYPE enmInterface;
1215
1216 /**
1217 * Start a read operation.
1218 */
1219 DECLR3CALLBACKMEMBER(int, pfnStartRead, (void *pvUser));
1220
1221 /**
1222 * Finish a read operation.
1223 */
1224 DECLR3CALLBACKMEMBER(int, pfnFinishRead, (void *pvUser));
1225
1226 /**
1227 * Start a write operation.
1228 */
1229 DECLR3CALLBACKMEMBER(int, pfnStartWrite, (void *pvUser));
1230
1231 /**
1232 * Finish a write operation.
1233 */
1234 DECLR3CALLBACKMEMBER(int, pfnFinishWrite, (void *pvUser));
1235
1236} VDINTERFACETHREADSYNC, *PVDINTERFACETHREADSYNC;
1237
1238/**
1239 * Get thread synchronization interface from opaque callback table.
1240 *
1241 * @return Pointer to the callback table.
1242 * @param pInterface Pointer to the interface descriptor.
1243 */
1244DECLINLINE(PVDINTERFACETHREADSYNC) VDGetInterfaceThreadSync(PVDINTERFACE pInterface)
1245{
1246 /* Check that the interface descriptor is a thread synchronization interface. */
1247 AssertMsgReturn( (pInterface->enmInterface == VDINTERFACETYPE_THREADSYNC)
1248 && (pInterface->cbSize == sizeof(VDINTERFACE)),
1249 ("Not a thread synchronization interface"), NULL);
1250
1251 PVDINTERFACETHREADSYNC pInterfaceThreadSync = (PVDINTERFACETHREADSYNC)pInterface->pCallbacks;
1252
1253 /* Do basic checks. */
1254 AssertMsgReturn( (pInterfaceThreadSync->cbSize == sizeof(VDINTERFACETHREADSYNC))
1255 && (pInterfaceThreadSync->enmInterface == VDINTERFACETYPE_THREADSYNC),
1256 ("A non thread synchronization callback table attached to a thread synchronization interface descriptor\n"), NULL);
1257
1258 return pInterfaceThreadSync;
1259}
1260
1261/** @name Configuration interface key handling flags.
1262 * @{
1263 */
1264/** Mandatory config key. Not providing a value for this key will cause
1265 * the backend to fail. */
1266#define VD_CFGKEY_MANDATORY RT_BIT(0)
1267/** Expert config key. Not showing it by default in the GUI is is probably
1268 * a good idea, as the average user won't understand it easily. */
1269#define VD_CFGKEY_EXPERT RT_BIT(1)
1270/** @}*/
1271
1272
1273/**
1274 * Configuration value type for configuration information interface.
1275 */
1276typedef enum VDCFGVALUETYPE
1277{
1278 /** Integer value. */
1279 VDCFGVALUETYPE_INTEGER = 1,
1280 /** String value. */
1281 VDCFGVALUETYPE_STRING,
1282 /** Bytestring value. */
1283 VDCFGVALUETYPE_BYTES
1284} VDCFGVALUETYPE;
1285
1286
1287/**
1288 * Structure describing configuration keys required/supported by a backend
1289 * through the config interface.
1290 */
1291typedef struct VDCONFIGINFO
1292{
1293 /** Key name of the configuration. */
1294 const char *pszKey;
1295 /** Pointer to default value (descriptor). NULL if no useful default value
1296 * can be specified. */
1297 const char *pszDefaultValue;
1298 /** Value type for this key. */
1299 VDCFGVALUETYPE enmValueType;
1300 /** Key handling flags (a combination of VD_CFGKEY_* flags). */
1301 uint64_t uKeyFlags;
1302} VDCONFIGINFO;
1303
1304/** Pointer to structure describing configuration keys. */
1305typedef VDCONFIGINFO *PVDCONFIGINFO;
1306
1307/** Pointer to const structure describing configuration keys. */
1308typedef const VDCONFIGINFO *PCVDCONFIGINFO;
1309
1310/**
1311 * Data structure for returning a list of backend capabilities.
1312 */
1313typedef struct VDBACKENDINFO
1314{
1315 /** Name of the backend. Must be unique even with case insensitive comparison. */
1316 const char *pszBackend;
1317 /** Capabilities of the backend (a combination of the VD_CAP_* flags). */
1318 uint64_t uBackendCaps;
1319 /** Pointer to a NULL-terminated array of strings, containing the supported
1320 * file extensions. Note that some backends do not work on files, so this
1321 * pointer may just contain NULL. */
1322 const char * const *papszFileExtensions;
1323 /** Pointer to an array of structs describing each supported config key.
1324 * Terminated by a NULL config key. Note that some backends do not support
1325 * the configuration interface, so this pointer may just contain NULL.
1326 * Mandatory if the backend sets VD_CAP_CONFIG. */
1327 PCVDCONFIGINFO paConfigInfo;
1328 /** Returns a human readable hard disk location string given a
1329 * set of hard disk configuration keys. The returned string is an
1330 * equivalent of the full file path for image-based hard disks.
1331 * Mandatory for backends with no VD_CAP_FILE and NULL otherwise. */
1332 DECLR3CALLBACKMEMBER(int, pfnComposeLocation, (PVDINTERFACE pConfig, char **pszLocation));
1333 /** Returns a human readable hard disk name string given a
1334 * set of hard disk configuration keys. The returned string is an
1335 * equivalent of the file name part in the full file path for
1336 * image-based hard disks. Mandatory for backends with no
1337 * VD_CAP_FILE and NULL otherwise. */
1338 DECLR3CALLBACKMEMBER(int, pfnComposeName, (PVDINTERFACE pConfig, char **pszName));
1339} VDBACKENDINFO, *PVDBACKENDINFO;
1340
1341/**
1342 * Completion callback for metadata reads or writes.
1343 *
1344 * @return nothing.
1345 * @param pvBackendData The opaque backend data.
1346 * @param pvMetaUser Opaque user data passed during a metadata read/write request.
1347 */
1348typedef DECLCALLBACK(void) FNVDMETACOMPLETED(void *pvBackendData, void *pvMetaUser);
1349/** Pointer to FNVDCOMPLETED() */
1350typedef FNVDMETACOMPLETED *PFNVDMETACOMPLETED;
1351
1352/** Forward declaration. Only visible in the VBoxHDD module. */
1353/** I/O context */
1354typedef struct VDIOCTX *PVDIOCTX;
1355/** Storage backend handle. */
1356typedef struct VDIOSTORAGE *PVDIOSTORAGE;
1357/** Pointer to a storage backend handle. */
1358typedef PVDIOSTORAGE *PPVDIOSTORAGE;
1359
1360/**
1361 * Support interface for I/O
1362 *
1363 * Per-image. Required.
1364 */
1365typedef struct VDINTERFACEIO
1366{
1367 /**
1368 * Size of the I/O interface.
1369 */
1370 uint32_t cbSize;
1371
1372 /**
1373 * Interface type.
1374 */
1375 VDINTERFACETYPE enmInterface;
1376
1377 /**
1378 * Open callback
1379 *
1380 * @return VBox status code.
1381 * @param pvUser The opaque data passed on container creation.
1382 * @param pszLocation Name of the location to open.
1383 * @param uOpenFlags Flags for opening the backend.
1384 * See VD_INTERFACEASYNCIO_OPEN_FLAGS_* #defines
1385 * @param ppStorage Where to store the storage handle.
1386 */
1387 DECLR3CALLBACKMEMBER(int, pfnOpen, (void *pvUser, const char *pszLocation,
1388 unsigned uOpenFlags, PPVDIOSTORAGE ppStorage));
1389
1390 /**
1391 * Close callback.
1392 *
1393 * @return VBox status code.
1394 * @param pvUser The opaque data passed on container creation.
1395 * @param pStorage The storage handle to close.
1396 */
1397 DECLR3CALLBACKMEMBER(int, pfnClose, (void *pvUser, PVDIOSTORAGE pStorage));
1398
1399 /**
1400 * Returns the size of the opened storage backend.
1401 *
1402 * @return VBox status code.
1403 * @param pvUser The opaque data passed on container creation.
1404 * @param pStorage The storage handle to get the size from.
1405 * @param pcbSize Where to store the size of the storage backend.
1406 */
1407 DECLR3CALLBACKMEMBER(int, pfnGetSize, (void *pvUser, PVDIOSTORAGE pStorage,
1408 uint64_t *pcbSize));
1409
1410 /**
1411 * Sets the size of the opened storage backend if possible.
1412 *
1413 * @return VBox status code.
1414 * @retval VERR_NOT_SUPPORTED if the backend does not support this operation.
1415 * @param pvUser The opaque data passed on container creation.
1416 * @param pStorage The storage handle.
1417 * @param cbSize The new size of the image.
1418 */
1419 DECLR3CALLBACKMEMBER(int, pfnSetSize, (void *pvUser, PVDIOSTORAGE pStorage,
1420 uint64_t cbSize));
1421
1422 /**
1423 * Synchronous write callback.
1424 *
1425 * @return VBox status code.
1426 * @param pvUser The opaque data passed on container creation.
1427 * @param pStorage The storage handle to use.
1428 * @param uOffset The offset to start from.
1429 * @param cbWrite How many bytes to write.
1430 * @param pvBuf Pointer to the bits need to be written.
1431 * @param pcbWritten Where to store how many bytes where actually written.
1432 *
1433 * @notes Do not use in code called from the async read/write entry points in the backends.
1434 * This should be only used during open/close of images and for the support functions
1435 * which are not called while a VM is running (pfnCompact).
1436 */
1437 DECLR3CALLBACKMEMBER(int, pfnWriteSync, (void *pvUser, PVDIOSTORAGE pStorage, uint64_t uOffset,
1438 size_t cbWrite, const void *pvBuf, size_t *pcbWritten));
1439
1440 /**
1441 * Synchronous read callback.
1442 *
1443 * @return VBox status code.
1444 * @param pvUser The opaque data passed on container creation.
1445 * @param pStorage The storage handle to use.
1446 * @param uOffset The offset to start from.
1447 * @param cbRead How many bytes to read.
1448 * @param pvBuf Where to store the read bits.
1449 * @param pcbRead Where to store how many bytes where actually read.
1450 *
1451 * @notes See pfnWriteSync()
1452 */
1453 DECLR3CALLBACKMEMBER(int, pfnReadSync, (void *pvUser, PVDIOSTORAGE pStorage, uint64_t uOffset,
1454 size_t cbRead, void *pvBuf, size_t *pcbRead));
1455
1456 /**
1457 * Flush data to the storage backend.
1458 *
1459 * @return VBox statis code.
1460 * @param pvUser The opaque data passed on container creation.
1461 * @param pStorage The storage handle to flush.
1462 *
1463 * @notes See pfnWriteSync()
1464 */
1465 DECLR3CALLBACKMEMBER(int, pfnFlushSync, (void *pvUser, PVDIOSTORAGE pStorage));
1466
1467 /**
1468 * Initiate a asynchronous read request for user data.
1469 *
1470 * @return VBox status code.
1471 * @param pvUser The opqaue user data passed on container creation.
1472 * @param pStorage The storage handle.
1473 * @param uOffset The offset to start reading from.
1474 * @param pIoCtx I/O context passed in VDAsyncRead/Write.
1475 * @param cbRead How many bytes to read.
1476 */
1477 DECLR3CALLBACKMEMBER(int, pfnReadUserAsync, (void *pvUser, PVDIOSTORAGE pStorage,
1478 uint64_t uOffset, PVDIOCTX pIoCtx,
1479 size_t cbRead));
1480
1481 /**
1482 * Initiate a asynchronous write request for user data.
1483 *
1484 * @return VBox status code.
1485 * @param pvUser The opaque user data passed on container creation.
1486 * @param pStorage The storage handle.
1487 * @param uOffset The offset to start writing to.
1488 * @param pIoCtx I/O context passed in VDAsyncRead/Write
1489 * @param cbWrite How many bytes to write.
1490 */
1491 DECLR3CALLBACKMEMBER(int, pfnWriteUserAsync, (void *pvUser, PVDIOSTORAGE pStorage,
1492 uint64_t uOffset, PVDIOCTX pIoCtx,
1493 size_t cbWrite));
1494
1495 /**
1496 * Reads metadata asynchronously from storage.
1497 * The current I/O context will be halted.
1498 *
1499 * @returns VBox status code.
1500 * @param pvUser The opaque user data passed on container creation.
1501 * @param pStorage The storage handle.
1502 * @param uOffset Offsete to start reading from.
1503 * @param pvBuf Where to store the data.
1504 * @param cbRead How many bytes to read.
1505 * @param pIoCtx The I/O context which triggered the read.
1506 * @param pfnMetaCompleted Callback to call when the read completes.
1507 * @param pvMetaUser Opaque user data which is passed in the callback.
1508 */
1509 DECLR3CALLBACKMEMBER(int, pfnReadMetaAsync, (void *pvUser, PVDIOSTORAGE pStorage,
1510 uint64_t uOffset, void *pvBuf,
1511 size_t cbRead, PVDIOCTX pIoCtx,
1512 PFNVDMETACOMPLETED pfnMetaCompleted,
1513 void *pvMetaUser));
1514
1515 /**
1516 * Writes metadata asynchronously to storage.
1517 *
1518 * @returns VBox status code.
1519 * @param pvUser The opaque user data passed on container creation.
1520 * @param pStorage The storage handle.
1521 * @param uOffset Offsete to start writing to.
1522 * @param pvBuf Written data.
1523 * @param cbWrite How many bytes to write.
1524 * @param pIoCtx The I/O context which triggered the write.
1525 * @param pfnMetaCompleted Callback to call when the write completes.
1526 * @param pvMetaUser Opaque user data which is passed in the callback.
1527 */
1528 DECLR3CALLBACKMEMBER(int, pfnWriteMetaAsync, (void *pvUser, PVDIOSTORAGE pStorage,
1529 uint64_t uOffset, void *pvBuf,
1530 size_t cbWrite, PVDIOCTX pIoCtx,
1531 PFNVDMETACOMPLETED pfnMetaCompleted,
1532 void *pvMetaUser));
1533
1534 /**
1535 * Initiates a async flush request.
1536 *
1537 * @return VBox statis code.
1538 * @param pvUser The opaque data passed on container creation.
1539 * @param pStorage The storage handle to flush.
1540 * @param pIoCtx I/O context which triggered the flush.
1541 */
1542 DECLR3CALLBACKMEMBER(int, pfnFlushAsync, (void *pvUser, PVDIOSTORAGE pStorage,
1543 PVDIOCTX pIoCtx));
1544
1545 /**
1546 * Copies a buffer into the I/O context.
1547 *
1548 * @return Number of bytes copied.
1549 * @param pvUser The opaque user data passed on conatiner creation.
1550 * @param pIoCtx I/O context to copy the data to.
1551 * @param pvBuf Buffer to copy.
1552 * @param cbBuf Number of bytes to copy.
1553 */
1554 DECLR3CALLBACKMEMBER(size_t, pfnIoCtxCopyTo, (void *pvUser, PVDIOCTX pIoCtx,
1555 void *pvBuf, size_t cbBuf));
1556
1557 /**
1558 * Copies data from the I/O context into a buffer.
1559 *
1560 * @return Number of bytes copied.
1561 * @param pvUser The opaque user data passed on conatiner creation.
1562 * @param pIoCtx I/O context to copy the data from.
1563 * @param pvBuf Destination buffer.
1564 * @param cbBuf Number of bytes to copy.
1565 */
1566 DECLR3CALLBACKMEMBER(size_t, pfnIoCtxCopyFrom, (void *pvUser, PVDIOCTX pIoCtx,
1567 void *pvBuf, size_t cbBuf));
1568
1569 /**
1570 * Sets the buffer of the given context to a specific byte.
1571 *
1572 * @return Number of bytes set.
1573 * @param pvUser The opaque user data passed on conatiner creation.
1574 * @param pIoCtx I/O context to copy the data from.
1575 * @param ch The byte to set.
1576 * @param cbSet Number of bytes to set.
1577 */
1578 DECLR3CALLBACKMEMBER(size_t, pfnIoCtxSet, (void *pvUser, PVDIOCTX pIoCtx,
1579 int ch, size_t cbSet));
1580
1581} VDINTERFACEIO, *PVDINTERFACEIO;
1582
1583/**
1584 * Get async I/O interface from opaque callback table.
1585 *
1586 * @return Pointer to the callback table.
1587 * @param pInterface Pointer to the interface descriptor.
1588 */
1589DECLINLINE(PVDINTERFACEIO) VDGetInterfaceIO(PVDINTERFACE pInterface)
1590{
1591 /* Check that the interface descriptor is a async I/O interface. */
1592 AssertMsgReturn( (pInterface->enmInterface == VDINTERFACETYPE_IO)
1593 && (pInterface->cbSize == sizeof(VDINTERFACE)),
1594 ("Not an I/O interface"), NULL);
1595
1596 PVDINTERFACEIO pInterfaceIO = (PVDINTERFACEIO)pInterface->pCallbacks;
1597
1598 /* Do basic checks. */
1599 AssertMsgReturn( (pInterfaceIO->cbSize == sizeof(VDINTERFACEIO))
1600 && (pInterfaceIO->enmInterface == VDINTERFACETYPE_IO),
1601 ("A non I/O callback table attached to a I/O interface descriptor\n"), NULL);
1602
1603 return pInterfaceIO;
1604}
1605
1606/**
1607 * VBox HDD Container main structure.
1608 */
1609/* Forward declaration, VBOXHDD structure is visible only inside VBox HDD module. */
1610struct VBOXHDD;
1611typedef struct VBOXHDD VBOXHDD;
1612typedef VBOXHDD *PVBOXHDD;
1613
1614/**
1615 * Request completion callback for the async read/write API.
1616 */
1617typedef void (FNVDASYNCTRANSFERCOMPLETE) (void *pvUser1, void *pvUser2);
1618/** Pointer to a transfer compelte callback. */
1619typedef FNVDASYNCTRANSFERCOMPLETE *PFNVDASYNCTRANSFERCOMPLETE;
1620
1621/**
1622 * Initializes HDD backends.
1623 *
1624 * @returns VBox status code.
1625 */
1626VBOXDDU_DECL(int) VDInit(void);
1627
1628/**
1629 * Destroys loaded HDD backends.
1630 *
1631 * @returns VBox status code.
1632 */
1633VBOXDDU_DECL(int) VDShutdown(void);
1634
1635/**
1636 * Lists all HDD backends and their capabilities in a caller-provided buffer.
1637 *
1638 * @return VBox status code.
1639 * VERR_BUFFER_OVERFLOW if not enough space is passed.
1640 * @param cEntriesAlloc Number of list entries available.
1641 * @param pEntries Pointer to array for the entries.
1642 * @param pcEntriesUsed Number of entries returned.
1643 */
1644VBOXDDU_DECL(int) VDBackendInfo(unsigned cEntriesAlloc, PVDBACKENDINFO pEntries,
1645 unsigned *pcEntriesUsed);
1646
1647/**
1648 * Lists the capablities of a backend indentified by its name.
1649 *
1650 * @return VBox status code.
1651 * @param pszBackend The backend name (case insensitive).
1652 * @param pEntries Pointer to an entry.
1653 */
1654VBOXDDU_DECL(int) VDBackendInfoOne(const char *pszBackend, PVDBACKENDINFO pEntry);
1655
1656/**
1657 * Allocates and initializes an empty HDD container.
1658 * No image files are opened.
1659 *
1660 * @return VBox status code.
1661 * @param pVDIfsDisk Pointer to the per-disk VD interface list.
1662 * @param ppDisk Where to store the reference to HDD container.
1663 */
1664VBOXDDU_DECL(int) VDCreate(PVDINTERFACE pVDIfsDisk, PVBOXHDD *ppDisk);
1665
1666/**
1667 * Destroys HDD container.
1668 * If container has opened image files they will be closed.
1669 *
1670 * @param pDisk Pointer to HDD container.
1671 */
1672VBOXDDU_DECL(void) VDDestroy(PVBOXHDD pDisk);
1673
1674/**
1675 * Try to get the backend name which can use this image.
1676 *
1677 * @return VBox status code.
1678 * @param pVDIfsDisk Pointer to the per-disk VD interface list.
1679 * @param pszFilename Name of the image file for which the backend is queried.
1680 * @param ppszFormat Receives pointer of the UTF-8 string which contains the format name.
1681 * The returned pointer must be freed using RTStrFree().
1682 */
1683VBOXDDU_DECL(int) VDGetFormat(PVDINTERFACE pVDIfsDisk, const char *pszFilename, char **ppszFormat);
1684
1685/**
1686 * Opens an image file.
1687 *
1688 * The first opened image file in HDD container must have a base image type,
1689 * others (next opened images) must be differencing or undo images.
1690 * Linkage is checked for differencing image to be consistent with the previously opened image.
1691 * When another differencing image is opened and the last image was opened in read/write access
1692 * mode, then the last image is reopened in read-only with deny write sharing mode. This allows
1693 * other processes to use images in read-only mode too.
1694 *
1695 * Note that the image is opened in read-only mode if a read/write open is not possible.
1696 * Use VDIsReadOnly to check open mode.
1697 *
1698 * @return VBox status code.
1699 * @param pDisk Pointer to HDD container.
1700 * @param pszBackend Name of the image file backend to use (case insensitive).
1701 * @param pszFilename Name of the image file to open.
1702 * @param uOpenFlags Image file open mode, see VD_OPEN_FLAGS_* constants.
1703 * @param pVDIfsImage Pointer to the per-image VD interface list.
1704 */
1705VBOXDDU_DECL(int) VDOpen(PVBOXHDD pDisk, const char *pszBackend,
1706 const char *pszFilename, unsigned uOpenFlags,
1707 PVDINTERFACE pVDIfsImage);
1708
1709/**
1710 * Creates and opens a new base image file.
1711 *
1712 * @return VBox status code.
1713 * @param pDisk Pointer to HDD container.
1714 * @param pszBackend Name of the image file backend to use (case insensitive).
1715 * @param pszFilename Name of the image file to create.
1716 * @param cbSize Image size in bytes.
1717 * @param uImageFlags Flags specifying special image features.
1718 * @param pszComment Pointer to image comment. NULL is ok.
1719 * @param pPCHSGeometry Pointer to physical disk geometry <= (16383,16,63). Not NULL.
1720 * @param pLCHSGeometry Pointer to logical disk geometry <= (x,255,63). Not NULL.
1721 * @param pUuid New UUID of the image. If NULL, a new UUID is created.
1722 * @param uOpenFlags Image file open mode, see VD_OPEN_FLAGS_* constants.
1723 * @param pVDIfsImage Pointer to the per-image VD interface list.
1724 * @param pVDIfsOperation Pointer to the per-operation VD interface list.
1725 */
1726VBOXDDU_DECL(int) VDCreateBase(PVBOXHDD pDisk, const char *pszBackend,
1727 const char *pszFilename, uint64_t cbSize,
1728 unsigned uImageFlags, const char *pszComment,
1729 PCPDMMEDIAGEOMETRY pPCHSGeometry,
1730 PCPDMMEDIAGEOMETRY pLCHSGeometry,
1731 PCRTUUID pUuid, unsigned uOpenFlags,
1732 PVDINTERFACE pVDIfsImage,
1733 PVDINTERFACE pVDIfsOperation);
1734
1735/**
1736 * Creates and opens a new differencing image file in HDD container.
1737 * See comments for VDOpen function about differencing images.
1738 *
1739 * @return VBox status code.
1740 * @param pDisk Pointer to HDD container.
1741 * @param pszBackend Name of the image file backend to use (case insensitive).
1742 * @param pszFilename Name of the differencing image file to create.
1743 * @param uImageFlags Flags specifying special image features.
1744 * @param pszComment Pointer to image comment. NULL is ok.
1745 * @param pUuid New UUID of the image. If NULL, a new UUID is created.
1746 * @param pParentUuid New parent UUID of the image. If NULL, the UUID is queried automatically.
1747 * @param uOpenFlags Image file open mode, see VD_OPEN_FLAGS_* constants.
1748 * @param pVDIfsImage Pointer to the per-image VD interface list.
1749 * @param pVDIfsOperation Pointer to the per-operation VD interface list.
1750 */
1751VBOXDDU_DECL(int) VDCreateDiff(PVBOXHDD pDisk, const char *pszBackend,
1752 const char *pszFilename, unsigned uImageFlags,
1753 const char *pszComment, PCRTUUID pUuid,
1754 PCRTUUID pParentUuid, unsigned uOpenFlags,
1755 PVDINTERFACE pVDIfsImage,
1756 PVDINTERFACE pVDIfsOperation);
1757
1758/**
1759 * Merges two images (not necessarily with direct parent/child relationship).
1760 * As a side effect the source image and potentially the other images which
1761 * are also merged to the destination are deleted from both the disk and the
1762 * images in the HDD container.
1763 *
1764 * @return VBox status code.
1765 * @return VERR_VD_IMAGE_NOT_FOUND if image with specified number was not opened.
1766 * @param pDisk Pointer to HDD container.
1767 * @param nImageFrom Image number to merge from, counts from 0. 0 is always base image of container.
1768 * @param nImageTo Image number to merge to, counts from 0. 0 is always base image of container.
1769 * @param pVDIfsOperation Pointer to the per-operation VD interface list.
1770 */
1771VBOXDDU_DECL(int) VDMerge(PVBOXHDD pDisk, unsigned nImageFrom,
1772 unsigned nImageTo, PVDINTERFACE pVDIfsOperation);
1773
1774/**
1775 * Copies an image from one HDD container to another.
1776 * The copy is opened in the target HDD container.
1777 * It is possible to convert between different image formats, because the
1778 * backend for the destination may be different from the source.
1779 * If both the source and destination reference the same HDD container,
1780 * then the image is moved (by copying/deleting or renaming) to the new location.
1781 * The source container is unchanged if the move operation fails, otherwise
1782 * the image at the new location is opened in the same way as the old one was.
1783 *
1784 * @note The read/write accesses across disks are not synchronized, just the
1785 * accesses to each disk. Once there is a use case which requires a defined
1786 * read/write behavior in this situation this needs to be extended.
1787 *
1788 * @return VBox status code.
1789 * @return VERR_VD_IMAGE_NOT_FOUND if image with specified number was not opened.
1790 * @param pDiskFrom Pointer to source HDD container.
1791 * @param nImage Image number, counts from 0. 0 is always base image of container.
1792 * @param pDiskTo Pointer to destination HDD container.
1793 * @param pszBackend Name of the image file backend to use (may be NULL to use the same as the source, case insensitive).
1794 * @param pszFilename New name of the image (may be NULL to specify that the
1795 * copy destination is the destination container, or
1796 * if pDiskFrom == pDiskTo, i.e. when moving).
1797 * @param fMoveByRename If true, attempt to perform a move by renaming (if successful the new size is ignored).
1798 * @param cbSize New image size (0 means leave unchanged).
1799 * @param uImageFlags Flags specifying special destination image features.
1800 * @param pDstUuid New UUID of the destination image. If NULL, a new UUID is created.
1801 * This parameter is used if and only if a true copy is created.
1802 * In all rename/move cases or copy to existing image cases the modification UUIDs are copied over.
1803 * @param pVDIfsOperation Pointer to the per-operation VD interface list.
1804 * @param pDstVDIfsImage Pointer to the per-image VD interface list, for the
1805 * destination image.
1806 * @param pDstVDIfsOperation Pointer to the per-operation VD interface list,
1807 * for the destination operation.
1808 */
1809VBOXDDU_DECL(int) VDCopy(PVBOXHDD pDiskFrom, unsigned nImage, PVBOXHDD pDiskTo,
1810 const char *pszBackend, const char *pszFilename,
1811 bool fMoveByRename, uint64_t cbSize,
1812 unsigned uImageFlags, PCRTUUID pDstUuid,
1813 PVDINTERFACE pVDIfsOperation,
1814 PVDINTERFACE pDstVDIfsImage,
1815 PVDINTERFACE pDstVDIfsOperation);
1816
1817/**
1818 * Optimizes the storage consumption of an image. Typically the unused blocks
1819 * have to be wiped with zeroes to achieve a substantial reduced storage use.
1820 * Another optimization done is reordering the image blocks, which can provide
1821 * a significant performance boost, as reads and writes tend to use less random
1822 * file offsets.
1823 *
1824 * @note Compaction is treated as a single operation with regard to thread
1825 * synchronization, which means that it potentially blocks other activities for
1826 * a long time. The complexity of compaction would grow even more if concurrent
1827 * accesses have to be handled.
1828 *
1829 * @return VBox status code.
1830 * @return VERR_VD_IMAGE_NOT_FOUND if image with specified number was not opened.
1831 * @return VERR_VD_IMAGE_READ_ONLY if image is not writable.
1832 * @return VERR_NOT_SUPPORTED if this kind of image can be compacted, but
1833 * this isn't supported yet.
1834 * @param pDisk Pointer to HDD container.
1835 * @param nImage Image number, counts from 0. 0 is always base image of container.
1836 * @param pVDIfsOperation Pointer to the per-operation VD interface list.
1837 */
1838VBOXDDU_DECL(int) VDCompact(PVBOXHDD pDisk, unsigned nImage,
1839 PVDINTERFACE pVDIfsOperation);
1840
1841/**
1842 * Closes the last opened image file in HDD container.
1843 * If previous image file was opened in read-only mode (the normal case) and
1844 * the last opened image is in read-write mode then the previous image will be
1845 * reopened in read/write mode.
1846 *
1847 * @return VBox status code.
1848 * @return VERR_VD_NOT_OPENED if no image is opened in HDD container.
1849 * @param pDisk Pointer to HDD container.
1850 * @param fDelete If true, delete the image from the host disk.
1851 */
1852VBOXDDU_DECL(int) VDClose(PVBOXHDD pDisk, bool fDelete);
1853
1854/**
1855 * Closes all opened image files in HDD container.
1856 *
1857 * @return VBox status code.
1858 * @param pDisk Pointer to HDD container.
1859 */
1860VBOXDDU_DECL(int) VDCloseAll(PVBOXHDD pDisk);
1861
1862/**
1863 * Read data from virtual HDD.
1864 *
1865 * @return VBox status code.
1866 * @return VERR_VD_NOT_OPENED if no image is opened in HDD container.
1867 * @param pDisk Pointer to HDD container.
1868 * @param uOffset Offset of first reading byte from start of disk.
1869 * Must be aligned to a sector boundary.
1870 * @param pvBuf Pointer to buffer for reading data.
1871 * @param cbRead Number of bytes to read.
1872 * Must be aligned to a sector boundary.
1873 */
1874VBOXDDU_DECL(int) VDRead(PVBOXHDD pDisk, uint64_t uOffset, void *pvBuf, size_t cbRead);
1875
1876/**
1877 * Write data to virtual HDD.
1878 *
1879 * @return VBox status code.
1880 * @return VERR_VD_NOT_OPENED if no image is opened in HDD container.
1881 * @param pDisk Pointer to HDD container.
1882 * @param uOffset Offset of first writing byte from start of disk.
1883 * Must be aligned to a sector boundary.
1884 * @param pvBuf Pointer to buffer for writing data.
1885 * @param cbWrite Number of bytes to write.
1886 * Must be aligned to a sector boundary.
1887 */
1888VBOXDDU_DECL(int) VDWrite(PVBOXHDD pDisk, uint64_t uOffset, const void *pvBuf, size_t cbWrite);
1889
1890/**
1891 * Make sure the on disk representation of a virtual HDD is up to date.
1892 *
1893 * @return VBox status code.
1894 * @return VERR_VD_NOT_OPENED if no image is opened in HDD container.
1895 * @param pDisk Pointer to HDD container.
1896 */
1897VBOXDDU_DECL(int) VDFlush(PVBOXHDD pDisk);
1898
1899/**
1900 * Get number of opened images in HDD container.
1901 *
1902 * @return Number of opened images for HDD container. 0 if no images have been opened.
1903 * @param pDisk Pointer to HDD container.
1904 */
1905VBOXDDU_DECL(unsigned) VDGetCount(PVBOXHDD pDisk);
1906
1907/**
1908 * Get read/write mode of HDD container.
1909 *
1910 * @return Virtual disk ReadOnly status.
1911 * @return true if no image is opened in HDD container.
1912 * @param pDisk Pointer to HDD container.
1913 */
1914VBOXDDU_DECL(bool) VDIsReadOnly(PVBOXHDD pDisk);
1915
1916/**
1917 * Get total capacity of an image in HDD container.
1918 *
1919 * @return Virtual disk size in bytes.
1920 * @return 0 if image with specified number was not opened.
1921 * @param pDisk Pointer to HDD container.
1922 * @param nImage Image number, counts from 0. 0 is always base image of container.
1923 */
1924VBOXDDU_DECL(uint64_t) VDGetSize(PVBOXHDD pDisk, unsigned nImage);
1925
1926/**
1927 * Get total file size of an image in HDD container.
1928 *
1929 * @return Virtual disk size in bytes.
1930 * @return 0 if image with specified number was not opened.
1931 * @param pDisk Pointer to HDD container.
1932 * @param nImage Image number, counts from 0. 0 is always base image of container.
1933 */
1934VBOXDDU_DECL(uint64_t) VDGetFileSize(PVBOXHDD pDisk, unsigned nImage);
1935
1936/**
1937 * Get virtual disk PCHS geometry of an image in HDD container.
1938 *
1939 * @return VBox status code.
1940 * @return VERR_VD_IMAGE_NOT_FOUND if image with specified number was not opened.
1941 * @return VERR_VD_GEOMETRY_NOT_SET if no geometry present in the HDD container.
1942 * @param pDisk Pointer to HDD container.
1943 * @param nImage Image number, counts from 0. 0 is always base image of container.
1944 * @param pPCHSGeometry Where to store PCHS geometry. Not NULL.
1945 */
1946VBOXDDU_DECL(int) VDGetPCHSGeometry(PVBOXHDD pDisk, unsigned nImage,
1947 PPDMMEDIAGEOMETRY pPCHSGeometry);
1948
1949/**
1950 * Store virtual disk PCHS geometry of an image in HDD container.
1951 *
1952 * @return VBox status code.
1953 * @return VERR_VD_IMAGE_NOT_FOUND if image with specified number was not opened.
1954 * @param pDisk Pointer to HDD container.
1955 * @param nImage Image number, counts from 0. 0 is always base image of container.
1956 * @param pPCHSGeometry Where to load PCHS geometry from. Not NULL.
1957 */
1958VBOXDDU_DECL(int) VDSetPCHSGeometry(PVBOXHDD pDisk, unsigned nImage,
1959 PCPDMMEDIAGEOMETRY pPCHSGeometry);
1960
1961/**
1962 * Get virtual disk LCHS geometry of an image in HDD container.
1963 *
1964 * @return VBox status code.
1965 * @return VERR_VD_IMAGE_NOT_FOUND if image with specified number was not opened.
1966 * @return VERR_VD_GEOMETRY_NOT_SET if no geometry present in the HDD container.
1967 * @param pDisk Pointer to HDD container.
1968 * @param nImage Image number, counts from 0. 0 is always base image of container.
1969 * @param pLCHSGeometry Where to store LCHS geometry. Not NULL.
1970 */
1971VBOXDDU_DECL(int) VDGetLCHSGeometry(PVBOXHDD pDisk, unsigned nImage,
1972 PPDMMEDIAGEOMETRY pLCHSGeometry);
1973
1974/**
1975 * Store virtual disk LCHS geometry of an image in HDD container.
1976 *
1977 * @return VBox status code.
1978 * @return VERR_VD_IMAGE_NOT_FOUND if image with specified number was not opened.
1979 * @param pDisk Pointer to HDD container.
1980 * @param nImage Image number, counts from 0. 0 is always base image of container.
1981 * @param pLCHSGeometry Where to load LCHS geometry from. Not NULL.
1982 */
1983VBOXDDU_DECL(int) VDSetLCHSGeometry(PVBOXHDD pDisk, unsigned nImage,
1984 PCPDMMEDIAGEOMETRY pLCHSGeometry);
1985
1986/**
1987 * Get version of image in HDD container.
1988 *
1989 * @return VBox status code.
1990 * @return VERR_VD_IMAGE_NOT_FOUND if image with specified number was not opened.
1991 * @param pDisk Pointer to HDD container.
1992 * @param nImage Image number, counts from 0. 0 is always base image of container.
1993 * @param puVersion Where to store the image version.
1994 */
1995VBOXDDU_DECL(int) VDGetVersion(PVBOXHDD pDisk, unsigned nImage,
1996 unsigned *puVersion);
1997
1998/**
1999 * List the capabilities of image backend in HDD container.
2000 *
2001 * @return VBox status code.
2002 * @return VERR_VD_IMAGE_NOT_FOUND if image with specified number was not opened.
2003 * @param pDisk Pointer to the HDD container.
2004 * @param nImage Image number, counts from 0. 0 is always base image of container.
2005 * @param pbackendInfo Where to store the backend information.
2006 */
2007VBOXDDU_DECL(int) VDBackendInfoSingle(PVBOXHDD pDisk, unsigned nImage,
2008 PVDBACKENDINFO pBackendInfo);
2009
2010/**
2011 * Get flags of image in HDD container.
2012 *
2013 * @return VBox status code.
2014 * @return VERR_VD_IMAGE_NOT_FOUND if image with specified number was not opened.
2015 * @param pDisk Pointer to HDD container.
2016 * @param nImage Image number, counts from 0. 0 is always base image of container.
2017 * @param puImageFlags Where to store the image flags.
2018 */
2019VBOXDDU_DECL(int) VDGetImageFlags(PVBOXHDD pDisk, unsigned nImage, unsigned *puImageFlags);
2020
2021/**
2022 * Get open flags of image in HDD container.
2023 *
2024 * @return VBox status code.
2025 * @return VERR_VD_IMAGE_NOT_FOUND if image with specified number was not opened.
2026 * @param pDisk Pointer to HDD container.
2027 * @param nImage Image number, counts from 0. 0 is always base image of container.
2028 * @param puOpenFlags Where to store the image open flags.
2029 */
2030VBOXDDU_DECL(int) VDGetOpenFlags(PVBOXHDD pDisk, unsigned nImage,
2031 unsigned *puOpenFlags);
2032
2033/**
2034 * Set open flags of image in HDD container.
2035 * This operation may cause file locking changes and/or files being reopened.
2036 * Note that in case of unrecoverable error all images in HDD container will be closed.
2037 *
2038 * @return VBox status code.
2039 * @return VERR_VD_IMAGE_NOT_FOUND if image with specified number was not opened.
2040 * @param pDisk Pointer to HDD container.
2041 * @param nImage Image number, counts from 0. 0 is always base image of container.
2042 * @param uOpenFlags Image file open mode, see VD_OPEN_FLAGS_* constants.
2043 */
2044VBOXDDU_DECL(int) VDSetOpenFlags(PVBOXHDD pDisk, unsigned nImage,
2045 unsigned uOpenFlags);
2046
2047/**
2048 * Get base filename of image in HDD container. Some image formats use
2049 * other filenames as well, so don't use this for anything but informational
2050 * purposes.
2051 *
2052 * @return VBox status code.
2053 * @return VERR_VD_IMAGE_NOT_FOUND if image with specified number was not opened.
2054 * @return VERR_BUFFER_OVERFLOW if pszFilename buffer too small to hold filename.
2055 * @param pDisk Pointer to HDD container.
2056 * @param nImage Image number, counts from 0. 0 is always base image of container.
2057 * @param pszFilename Where to store the image file name.
2058 * @param cbFilename Size of buffer pszFilename points to.
2059 */
2060VBOXDDU_DECL(int) VDGetFilename(PVBOXHDD pDisk, unsigned nImage,
2061 char *pszFilename, unsigned cbFilename);
2062
2063/**
2064 * Get the comment line of image in HDD container.
2065 *
2066 * @return VBox status code.
2067 * @return VERR_VD_IMAGE_NOT_FOUND if image with specified number was not opened.
2068 * @return VERR_BUFFER_OVERFLOW if pszComment buffer too small to hold comment text.
2069 * @param pDisk Pointer to HDD container.
2070 * @param nImage Image number, counts from 0. 0 is always base image of container.
2071 * @param pszComment Where to store the comment string of image. NULL is ok.
2072 * @param cbComment The size of pszComment buffer. 0 is ok.
2073 */
2074VBOXDDU_DECL(int) VDGetComment(PVBOXHDD pDisk, unsigned nImage,
2075 char *pszComment, unsigned cbComment);
2076
2077/**
2078 * Changes the comment line of image in HDD container.
2079 *
2080 * @return VBox status code.
2081 * @return VERR_VD_IMAGE_NOT_FOUND if image with specified number was not opened.
2082 * @param pDisk Pointer to HDD container.
2083 * @param nImage Image number, counts from 0. 0 is always base image of container.
2084 * @param pszComment New comment string (UTF-8). NULL is allowed to reset the comment.
2085 */
2086VBOXDDU_DECL(int) VDSetComment(PVBOXHDD pDisk, unsigned nImage,
2087 const char *pszComment);
2088
2089/**
2090 * Get UUID of image in HDD container.
2091 *
2092 * @return VBox status code.
2093 * @return VERR_VD_IMAGE_NOT_FOUND if image with specified number was not opened.
2094 * @param pDisk Pointer to HDD container.
2095 * @param nImage Image number, counts from 0. 0 is always base image of container.
2096 * @param pUuid Where to store the image UUID.
2097 */
2098VBOXDDU_DECL(int) VDGetUuid(PVBOXHDD pDisk, unsigned nImage, PRTUUID pUuid);
2099
2100/**
2101 * Set the image's UUID. Should not be used by normal applications.
2102 *
2103 * @return VBox status code.
2104 * @return VERR_VD_IMAGE_NOT_FOUND if image with specified number was not opened.
2105 * @param pDisk Pointer to HDD container.
2106 * @param nImage Image number, counts from 0. 0 is always base image of container.
2107 * @param pUuid New UUID of the image. If NULL, a new UUID is created.
2108 */
2109VBOXDDU_DECL(int) VDSetUuid(PVBOXHDD pDisk, unsigned nImage, PCRTUUID pUuid);
2110
2111/**
2112 * Get last modification UUID of image in HDD container.
2113 *
2114 * @return VBox status code.
2115 * @return VERR_VD_IMAGE_NOT_FOUND if image with specified number was not opened.
2116 * @param pDisk Pointer to HDD container.
2117 * @param nImage Image number, counts from 0. 0 is always base image of container.
2118 * @param pUuid Where to store the image modification UUID.
2119 */
2120VBOXDDU_DECL(int) VDGetModificationUuid(PVBOXHDD pDisk, unsigned nImage,
2121 PRTUUID pUuid);
2122
2123/**
2124 * Set the image's last modification UUID. Should not be used by normal applications.
2125 *
2126 * @return VBox status code.
2127 * @return VERR_VD_IMAGE_NOT_FOUND if image with specified number was not opened.
2128 * @param pDisk Pointer to HDD container.
2129 * @param nImage Image number, counts from 0. 0 is always base image of container.
2130 * @param pUuid New modification UUID of the image. If NULL, a new UUID is created.
2131 */
2132VBOXDDU_DECL(int) VDSetModificationUuid(PVBOXHDD pDisk, unsigned nImage,
2133 PCRTUUID pUuid);
2134
2135/**
2136 * Get parent UUID of image in HDD container.
2137 *
2138 * @return VBox status code.
2139 * @return VERR_VD_IMAGE_NOT_FOUND if image with specified number was not opened.
2140 * @param pDisk Pointer to HDD container.
2141 * @param nImage Image number, counts from 0. 0 is always base image of the container.
2142 * @param pUuid Where to store the parent image UUID.
2143 */
2144VBOXDDU_DECL(int) VDGetParentUuid(PVBOXHDD pDisk, unsigned nImage,
2145 PRTUUID pUuid);
2146
2147/**
2148 * Set the image's parent UUID. Should not be used by normal applications.
2149 *
2150 * @return VBox status code.
2151 * @param pDisk Pointer to HDD container.
2152 * @param nImage Image number, counts from 0. 0 is always base image of container.
2153 * @param pUuid New parent UUID of the image. If NULL, a new UUID is created.
2154 */
2155VBOXDDU_DECL(int) VDSetParentUuid(PVBOXHDD pDisk, unsigned nImage,
2156 PCRTUUID pUuid);
2157
2158
2159/**
2160 * Debug helper - dumps all opened images in HDD container into the log file.
2161 *
2162 * @param pDisk Pointer to HDD container.
2163 */
2164VBOXDDU_DECL(void) VDDumpImages(PVBOXHDD pDisk);
2165
2166
2167/**
2168 * Query if asynchronous operations are supported for this disk.
2169 *
2170 * @return VBox status code.
2171 * @return VERR_VD_IMAGE_NOT_FOUND if image with specified number was not opened.
2172 * @param pDisk Pointer to the HDD container.
2173 * @param nImage Image number, counts from 0. 0 is always base image of container.
2174 * @param pfAIOSupported Where to store if async IO is supported.
2175 */
2176VBOXDDU_DECL(int) VDImageIsAsyncIOSupported(PVBOXHDD pDisk, unsigned nImage, bool *pfAIOSupported);
2177
2178
2179/**
2180 * Start a asynchronous read request.
2181 *
2182 * @return VBox status code.
2183 * @param pDisk Pointer to the HDD container.
2184 * @param uOffset The offset of the virtual disk to read from.
2185 * @param cbRead How many bytes to read.
2186 * @param paSeg Pointer to an array of segments.
2187 * @param cSeg Number of segments in the array.
2188 * @param pfnComplete Completion callback.
2189 * @param pvUser User data which is passed on completion
2190 */
2191VBOXDDU_DECL(int) VDAsyncRead(PVBOXHDD pDisk, uint64_t uOffset, size_t cbRead,
2192 PPDMDATASEG paSeg, unsigned cSeg,
2193 PFNVDASYNCTRANSFERCOMPLETE pfnComplete,
2194 void *pvUser1, void *pvUser2);
2195
2196
2197/**
2198 * Start a asynchronous write request.
2199 *
2200 * @return VBox status code.
2201 * @param pDisk Pointer to the HDD container.
2202 * @param uOffset The offset of the virtual disk to write to.
2203 * @param cbWrtie How many bytes to write.
2204 * @param paSeg Pointer to an array of segments.
2205 * @param cSeg Number of segments in the array.
2206 * @param pfnComplete Completion callback.
2207 * @param pvUser User data which is passed on completion.
2208 */
2209VBOXDDU_DECL(int) VDAsyncWrite(PVBOXHDD pDisk, uint64_t uOffset, size_t cbWrite,
2210 PPDMDATASEG paSeg, unsigned cSeg,
2211 PFNVDASYNCTRANSFERCOMPLETE pfnComplete,
2212 void *pvUser1, void *pvUser2);
2213
2214
2215RT_C_DECLS_END
2216
2217/** @} */
2218
2219#endif
Note: See TracBrowser for help on using the repository browser.

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