DrvVD.cpp revision 59a2c1c0a4a0762b46bc5ff056f5705ec9c0a660
77b1a2d8b5dbe2c0b5200794914239fee3c8ee5dvboxsync * DrvVD - Generic VBox disk media driver.
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * Copyright (C) 2006-2010 Oracle Corporation
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * available from http://www.virtualbox.org. This file is free software;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * you can redistribute it and/or modify it under the terms of the GNU
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * General Public License (GPL) as published by the Free Software
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync/*******************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync* Header files *
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync*******************************************************************************/
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync/* All lwip header files are not C++ safe. So hack around this. */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync#endif /* VBOX_WITH_INIP */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/* Small hack to get at lwIP initialized status */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncextern bool DevINIPConfigured(void);
efff36b306e370346025647a158689021df2e1d1vboxsync#endif /* VBOX_WITH_INIP */
efff36b306e370346025647a158689021df2e1d1vboxsync/*******************************************************************************
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync* Defined types, constants and macros *
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync*******************************************************************************/
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/** Converts a pointer to VBOXDISK::IMedia to a PVBOXDISK. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync ( (PVBOXDISK)((uintptr_t)pInterface - RT_OFFSETOF(VBOXDISK, IMedia)) )
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/** Converts a pointer to PDMDRVINS::IBase to a PPDMDRVINS. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync ( (PPDMDRVINS)((uintptr_t)pInterface - RT_OFFSETOF(PDMDRVINS, IBase)) )
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/** Converts a pointer to PDMDRVINS::IBase to a PVBOXDISK. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync ( PDMINS_2_DATA(PDMIBASE_2_DRVINS(pInterface), PVBOXDISK) )
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/** Converts a pointer to VBOXDISK::IMediaAsync to a PVBOXDISK. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync ( (PVBOXDISK)((uintptr_t)pInterface - RT_OFFSETOF(VBOXDISK, IMediaAsync)) )
9496f2d398b49813176939d7a339ae513d5175efvboxsync * VBox disk container, image information, private part.
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsynctypedef struct VBOXIMAGE
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync /** Pointer to next image. */
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync /** Pointer to list of VD interfaces. Per-image. */
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync /** Common structure for the configuration information interface. */
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync * Storage backend data.
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync /** PDM async completion end point. */
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync /** The template. */
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync /** Event semaphore for synchronous operations. */
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync /** Flag whether a synchronous operation is currently pending. */
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync volatile bool fSyncIoPending;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync /** Return code of the last completed request. */
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync /** Callback routine */
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync /** Pointer to the optional thread synchronization interface of the disk. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /** Pointer to the optional thread synchronization callbacks of the disk. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync PVDINTERFACETHREADSYNC pInterfaceThreadSyncCallbacks;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * VBox disk container media main structure, private part.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * @implements PDMIMEDIA
9496f2d398b49813176939d7a339ae513d5175efvboxsync * @implements PDMIMEDIAASYNC
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * @implements VDINTERFACEERROR
9496f2d398b49813176939d7a339ae513d5175efvboxsync * @implements VDINTERFACETCPNET
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * @implements VDINTERFACEASYNCIO
9496f2d398b49813176939d7a339ae513d5175efvboxsync * @implements VDINTERFACECONFIG
21029597fc4b76d0db0c9542daee201447281781vboxsynctypedef struct VBOXDISK
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync /** The VBox disk container. */
9496f2d398b49813176939d7a339ae513d5175efvboxsync /** The media interface. */
9496f2d398b49813176939d7a339ae513d5175efvboxsync /** Pointer to the driver instance. */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync /** Flag whether suspend has changed image open mode to read only. */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync /** Flag whether to use the runtime (true) or startup error facility. */
9496f2d398b49813176939d7a339ae513d5175efvboxsync /** Pointer to list of VD interfaces. Per-disk. */
9496f2d398b49813176939d7a339ae513d5175efvboxsync /** Common structure for the supported error interface. */
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync /** Callback table for error interface. */
9496f2d398b49813176939d7a339ae513d5175efvboxsync /** Common structure for the supported TCP network stack interface. */
9496f2d398b49813176939d7a339ae513d5175efvboxsync /** Callback table for TCP network stack interface. */
9496f2d398b49813176939d7a339ae513d5175efvboxsync /** Common structure for the supported async I/O interface. */
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync /** Callback table for async I/O interface. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /** Common structure for the supported thread synchronization interface. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /** Callback table for thread synchronization interface. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /** Callback table for the configuration information interface. */
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync /** Flag whether opened disk suppports async I/O operations. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /** The async media interface. */
21029597fc4b76d0db0c9542daee201447281781vboxsync /** The async media port interface above. */
20f97e6df28ebc0911dc42671222e0d494f034f3vboxsync /** Pointer to the list of data we need to keep per image. */
20f97e6df28ebc0911dc42671222e0d494f034f3vboxsync /** Flag whether a merge operation has been set up. */
21029597fc4b76d0db0c9542daee201447281781vboxsync /** Synchronization to prevent destruction before merge finishes. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /** Synchronization between merge and other image accesses. */
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync /** Source image index for merging. */
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync /** Target image index for merging. */
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync/*******************************************************************************
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync* Internal Functions *
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync*******************************************************************************/
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync * Internal: allocate new image descriptor and put it in the list
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync PVBOXIMAGE pImage = (PVBOXIMAGE)RTMemAllocZ(sizeof(VBOXIMAGE));
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync * Internal: free the list of images descriptors.
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync * Make the image temporarily read-only.
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync * @returns VBox status code.
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync * @param pThis The driver instance data.
5d0d754550d06b7d59a935e59caaf814462d53ccvboxsync rc = VDGetOpenFlags(pThis->pDisk, VD_LAST_IMAGE, &uOpenFlags);
5d0d754550d06b7d59a935e59caaf814462d53ccvboxsync rc = VDSetOpenFlags(pThis->pDisk, VD_LAST_IMAGE, uOpenFlags);
9496f2d398b49813176939d7a339ae513d5175efvboxsync * Undo the temporary read-only status of the image.
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync * @returns VBox status code.
9496f2d398b49813176939d7a339ae513d5175efvboxsync * @param pThis The driver instance data.
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync rc = VDGetOpenFlags(pThis->pDisk, VD_LAST_IMAGE, &uOpenFlags);
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync rc = VDSetOpenFlags(pThis->pDisk, VD_LAST_IMAGE, uOpenFlags);
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync/*******************************************************************************
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync* Error reporting callback *
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync*******************************************************************************/
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsyncstatic void drvvdErrorCallback(void *pvUser, int rc, RT_SRC_POS_DECL,
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync PVBOXDISK pThis = PDMINS_2_DATA(pDrvIns, PVBOXDISK);
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync /* We must not pass VMSETRTERR_FLAGS_FATAL as it could lead to a
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync * deadlock: We are probably executed in a thread context != EMT
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync * and the EM thread would wait until every thread is suspended
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync * but we would wait for the EM thread ... */
9496f2d398b49813176939d7a339ae513d5175efvboxsync PDMDrvHlpVMSetRuntimeErrorV(pDrvIns, /* fFlags=*/ 0, "DrvVD", pszFormat, va);
9496f2d398b49813176939d7a339ae513d5175efvboxsync PDMDrvHlpVMSetErrorV(pDrvIns, rc, RT_SRC_POS_ARGS, pszFormat, va);
9496f2d398b49813176939d7a339ae513d5175efvboxsync/*******************************************************************************
9496f2d398b49813176939d7a339ae513d5175efvboxsync* VD Async I/O interface implementation *
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync*******************************************************************************/
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsyncstatic DECLCALLBACK(void) drvvdAsyncTaskCompleted(PPDMDRVINS pDrvIns, void *pvTemplateUser, void *pvUser, int rcReq)
9496f2d398b49813176939d7a339ae513d5175efvboxsync PVBOXDISK pThis = PDMINS_2_DATA(pDrvIns, PVBOXDISK);
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)pvTemplateUser;
5d0d754550d06b7d59a935e59caaf814462d53ccvboxsyncstatic DECLCALLBACK(int) drvvdAsyncIOOpen(void *pvUser, const char *pszLocation,
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)RTMemAllocZ(sizeof(DRVVDSTORAGEBACKEND));
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync pStorageBackend->pInterfaceThreadSyncCallbacks = NULL;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync pStorageBackend->pInterfaceThreadSync = VDInterfaceGet(pVDIfsDisk, VDINTERFACETYPE_THREADSYNC);
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync if (RT_UNLIKELY(pStorageBackend->pInterfaceThreadSync))
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync pStorageBackend->pInterfaceThreadSyncCallbacks = VDGetInterfaceThreadSync(pStorageBackend->pInterfaceThreadSync);
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync rc = PDMDrvHlpAsyncCompletionTemplateCreate(pThis->pDrvIns, &pStorageBackend->pTemplate,
9496f2d398b49813176939d7a339ae513d5175efvboxsync drvvdAsyncTaskCompleted, pStorageBackend, "AsyncTaskCompleted");
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync rc = PDMR3AsyncCompletionEpCreateForFile(&pStorageBackend->pEndpoint, pszLocation,
9496f2d398b49813176939d7a339ae513d5175efvboxsync uOpenFlags & VD_INTERFACEASYNCIO_OPEN_FLAGS_READONLY
9496f2d398b49813176939d7a339ae513d5175efvboxsync ? PDMACEP_FILE_FLAGS_READ_ONLY | PDMACEP_FILE_FLAGS_CACHING
9496f2d398b49813176939d7a339ae513d5175efvboxsync PDMR3AsyncCompletionTemplateDestroy(pStorageBackend->pTemplate);
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsyncstatic DECLCALLBACK(int) drvvdAsyncIOClose(void *pvUser, void *pStorage)
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)pStorage;
9496f2d398b49813176939d7a339ae513d5175efvboxsync PDMR3AsyncCompletionEpClose(pStorageBackend->pEndpoint);
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync PDMR3AsyncCompletionTemplateDestroy(pStorageBackend->pTemplate);
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsyncstatic DECLCALLBACK(int) drvvdAsyncIOReadSync(void *pvUser, void *pStorage, uint64_t uOffset,
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)pStorage;
9496f2d398b49813176939d7a339ae513d5175efvboxsync ASMAtomicXchgBool(&pStorageBackend->fSyncIoPending, true);
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync int rc = PDMR3AsyncCompletionEpRead(pStorageBackend->pEndpoint, uOffset, &DataSeg, 1, cbRead, NULL, &pTask);
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync rc = RTSemEventWait(pStorageBackend->EventSem, RT_INDEFINITE_WAIT);
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync ASMAtomicXchgBool(&pStorageBackend->fSyncIoPending, false);
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsyncstatic DECLCALLBACK(int) drvvdAsyncIOWriteSync(void *pvUser, void *pStorage, uint64_t uOffset,
9496f2d398b49813176939d7a339ae513d5175efvboxsync size_t cbWrite, const void *pvBuf, size_t *pcbWritten)
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)pStorage;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync ASMAtomicXchgBool(&pStorageBackend->fSyncIoPending, true);
59d7f5939d42ad9d344fbad8401e00a900db92c5vboxsync int rc = PDMR3AsyncCompletionEpWrite(pStorageBackend->pEndpoint, uOffset, &DataSeg, 1, cbWrite, NULL, &pTask);
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync rc = RTSemEventWait(pStorageBackend->EventSem, RT_INDEFINITE_WAIT);
975ad9d9bc9c4dc96b41d9f67a65228b1b338e2avboxsync ASMAtomicXchgBool(&pStorageBackend->fSyncIoPending, false);
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsyncstatic DECLCALLBACK(int) drvvdAsyncIOFlushSync(void *pvUser, void *pStorage)
efff36b306e370346025647a158689021df2e1d1vboxsync PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)pStorage;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync ASMAtomicXchgBool(&pStorageBackend->fSyncIoPending, true);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync int rc = PDMR3AsyncCompletionEpFlush(pStorageBackend->pEndpoint, NULL, &pTask);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync rc = RTSemEventWait(pStorageBackend->EventSem, RT_INDEFINITE_WAIT);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync ASMAtomicXchgBool(&pStorageBackend->fSyncIoPending, false);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsyncstatic DECLCALLBACK(int) drvvdAsyncIOReadAsync(void *pvUser, void *pStorage, uint64_t uOffset,
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)pStorage;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync int rc = PDMR3AsyncCompletionEpRead(pStorageBackend->pEndpoint, uOffset, paSegments, cSegments, cbRead,
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsyncstatic DECLCALLBACK(int) drvvdAsyncIOWriteAsync(void *pvUser, void *pStorage, uint64_t uOffset,
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)pStorage;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync int rc = PDMR3AsyncCompletionEpWrite(pStorageBackend->pEndpoint, uOffset, paSegments, cSegments, cbWrite,
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsyncstatic DECLCALLBACK(int) drvvdAsyncIOFlushAsync(void *pvUser, void *pStorage,
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)pStorage;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync int rc = PDMR3AsyncCompletionEpFlush(pStorageBackend->pEndpoint, pvCompletion,
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsyncstatic DECLCALLBACK(int) drvvdAsyncIOGetSize(void *pvUser, void *pStorage, uint64_t *pcbSize)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)pStorage;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync return PDMR3AsyncCompletionEpGetSize(pStorageBackend->pEndpoint, pcbSize);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsyncstatic DECLCALLBACK(int) drvvdAsyncIOSetSize(void *pvUser, void *pStorage, uint64_t cbSize)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)pStorage;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync rc = PDMR3AsyncCompletionEpSetSize(pStorageBackend->pEndpoint, cbSize);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync#endif /* VBOX_WITH_PDM_ASYNC_COMPLETION */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync/*******************************************************************************
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync* VD Thread Synchronization interface implementation *
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync*******************************************************************************/
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsyncstatic DECLCALLBACK(int) drvvdThreadStartRead(void *pvUser)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync return RTSemRWRequestRead(pThis->MergeLock, RT_INDEFINITE_WAIT);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsyncstatic DECLCALLBACK(int) drvvdThreadFinishRead(void *pvUser)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsyncstatic DECLCALLBACK(int) drvvdThreadStartWrite(void *pvUser)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync return RTSemRWRequestWrite(pThis->MergeLock, RT_INDEFINITE_WAIT);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsyncstatic DECLCALLBACK(int) drvvdThreadFinishWrite(void *pvUser)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync/*******************************************************************************
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync* VD Configuration interface implementation *
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync*******************************************************************************/
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsyncstatic bool drvvdCfgAreKeysValid(void *pvUser, const char *pszzValid)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync return CFGMR3AreValuesValid((PCFGMNODE)pvUser, pszzValid);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsyncstatic int drvvdCfgQuerySize(void *pvUser, const char *pszName, size_t *pcb)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync return CFGMR3QuerySize((PCFGMNODE)pvUser, pszName, pcb);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsyncstatic int drvvdCfgQuery(void *pvUser, const char *pszName, char *pszString, size_t cchString)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync return CFGMR3QueryString((PCFGMNODE)pvUser, pszName, pszString, cchString);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync/*******************************************************************************
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync* VD TCP network stack interface implementation - INIP case *
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync*******************************************************************************/
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync/** @copydoc VDINTERFACETCPNET::pfnClientConnect */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsyncstatic DECLCALLBACK(int) drvvdINIPClientConnect(const char *pszAddress, uint32_t uPort, PRTSOCKET pSock)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync /* First check whether lwIP is set up in this VM instance. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* Resolve hostname. As there is no standard resolver for lwIP yet,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * just accept numeric IP addresses for now. */
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync LogRelFunc(("cannot resolve IP %s\n", pszAddress));
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* Create socket and connect. */
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync RTSOCKET Sock = lwip_socket(PF_INET, SOCK_STREAM, 0);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync if (!lwip_connect(Sock, (struct sockaddr *)&InAddr, sizeof(InAddr)))
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync rc = VERR_NET_CONNECTION_REFUSED; /* @todo real solution needed */
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync rc = VERR_NET_CONNECTION_REFUSED; /* @todo real solution needed */
fe813b3594039ba864493438e78ee0e7132bc445vboxsync/** @copydoc VDINTERFACETCPNET::pfnClientClose */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic DECLCALLBACK(int) drvvdINIPClientClose(RTSOCKET Sock)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync return VINF_SUCCESS; /** @todo real solution needed */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/** @copydoc VDINTERFACETCPNET::pfnSelectOne */
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsyncstatic DECLCALLBACK(int) drvvdINIPSelectOne(RTSOCKET Sock, RTMSINTERVAL cMillies)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync rc = lwip_select(Sock + 1, &fdsetR, NULL, &fdsetE, NULL);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync rc = lwip_select(Sock + 1, &fdsetR, NULL, &fdsetE, &timeout);
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync return VERR_NET_CONNECTION_REFUSED; /** @todo real solution needed */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/** @copydoc VDINTERFACETCPNET::pfnRead */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic DECLCALLBACK(int) drvvdINIPRead(RTSOCKET Sock, void *pvBuffer, size_t cbBuffer, size_t *pcbRead)
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync /* Do params checking */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * Read loop.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * If pcbRead is NULL we have to fill the entire buffer!
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /** @todo this clipping here is just in case (the send function
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync * needed it, so I added it here, too). Didn't investigate if this
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync * really has issues. Better be safe than sorry. */
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync ssize_t cbBytesRead = lwip_recv(Sock, (char *)pvBuffer + cbRead,
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync return VERR_NET_CONNECTION_REFUSED; /** @todo real solution */
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync if (cbBytesRead == 0 && errno) /** @todo r=bird: lwip_recv will not touch errno on Windows. This may apply to other hosts as well */
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync return VERR_NET_CONNECTION_REFUSED; /** @todo real solution */
fe813b3594039ba864493438e78ee0e7132bc445vboxsync /* return partial data */
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync /* read more? */
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync/** @copydoc VDINTERFACETCPNET::pfnWrite */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic DECLCALLBACK(int) drvvdINIPWrite(RTSOCKET Sock, const void *pvBuffer, size_t cbBuffer)
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync /** @todo lwip send only supports up to 65535 bytes in a single
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync * send (stupid limitation buried in the code), so make sure we
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * don't get any wraparounds. This should be moved to DevINIP
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync * stack interface once that's implemented. */
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync ssize_t cbWritten = lwip_send(Sock, (void *)pvBuffer,
594521f7faf13f7a88f31e6cd76629bd67340229vboxsync return VERR_NET_CONNECTION_REFUSED; /** @todo real solution needed */
e04eeee1b306d610b0441cee9bf1c750100254d5vboxsync AssertMsg(cbBuffer >= (size_t)cbWritten, ("Wrote more than we requested!!! cbWritten=%d cbBuffer=%d\n",
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync/** @copydoc VDINTERFACETCPNET::pfnFlush */
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsyncstatic DECLCALLBACK(int) drvvdINIPFlush(RTSOCKET Sock)
9496f2d398b49813176939d7a339ae513d5175efvboxsync/** @copydoc VDINTERFACETCPNET::pfnGetLocalAddress */
9496f2d398b49813176939d7a339ae513d5175efvboxsyncstatic DECLCALLBACK(int) drvvdINIPGetLocalAddress(RTSOCKET Sock, PRTNETADDR pAddr)
9496f2d398b49813176939d7a339ae513d5175efvboxsync * Convert the address.
9496f2d398b49813176939d7a339ae513d5175efvboxsync/** @copydoc VDINTERFACETCPNET::pfnGetPeerAddress */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic DECLCALLBACK(int) drvvdINIPGetPeerAddress(RTSOCKET Sock, PRTNETADDR pAddr)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * Convert the address.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync#endif /* VBOX_WITH_INIP */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/*******************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync* Media interface methods *
cba6719bd64ec749967bbe931230452664109857vboxsync*******************************************************************************/
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync/** @copydoc PDMIMEDIA::pfnRead */
cba6719bd64ec749967bbe931230452664109857vboxsyncstatic DECLCALLBACK(int) drvvdRead(PPDMIMEDIA pInterface,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync LogFlow(("%s: off=%#llx pvBuf=%p cbRead=%d\n", __FUNCTION__,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync PVBOXDISK pThis = PDMIMEDIA_2_VBOXDISK(pInterface);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync Log2(("%s: off=%#llx pvBuf=%p cbRead=%d %.*Rhxd\n", __FUNCTION__,
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync/** @copydoc PDMIMEDIA::pfnWrite */
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsyncstatic DECLCALLBACK(int) drvvdWrite(PPDMIMEDIA pInterface,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync LogFlow(("%s: off=%#llx pvBuf=%p cbWrite=%d\n", __FUNCTION__,
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync PVBOXDISK pThis = PDMIMEDIA_2_VBOXDISK(pInterface);
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync Log2(("%s: off=%#llx pvBuf=%p cbWrite=%d %.*Rhxd\n", __FUNCTION__,
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync int rc = VDWrite(pThis->pDisk, off, pvBuf, cbWrite);
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync/** @copydoc PDMIMEDIA::pfnFlush */
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsyncstatic DECLCALLBACK(int) drvvdFlush(PPDMIMEDIA pInterface)
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync PVBOXDISK pThis = PDMIMEDIA_2_VBOXDISK(pInterface);
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync/** @copydoc PDMIMEDIA::pfnMerge */
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsyncstatic DECLCALLBACK(int) drvvdMerge(PPDMIMEDIA pInterface,
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync PVBOXDISK pThis = PDMIMEDIA_2_VBOXDISK(pInterface);
59d7f5939d42ad9d344fbad8401e00a900db92c5vboxsync /* Note: There is an unavoidable race between destruction and another
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync * thread invoking this function. This is handled safely and gracefully by
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync * atomically invalidating the lock handle in drvvdDestruct. */
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync int rc2 = RTSemFastMutexRequest(pThis->MergeCompleteMutex);
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync /* Take shortcut: PFNSIMPLEPROGRESS is exactly the same type as
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync * PFNVDPROGRESS, so there's no need for a conversion function. */
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync /** @todo maybe introduce a conversion which limits update frequency. */
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync VDIProgressCallbacks.cbSize = sizeof(VDINTERFACEPROGRESS);
68a4ee3a31a0807abd03eae881c1bbaf4d42ee6dvboxsync VDIProgressCallbacks.enmInterface = VDINTERFACETYPE_PROGRESS;
9496f2d398b49813176939d7a339ae513d5175efvboxsync rc2 = VDInterfaceAdd(&VDIProgress, "DrvVD_VDIProgress", VDINTERFACETYPE_PROGRESS,
975ad9d9bc9c4dc96b41d9f67a65228b1b338e2avboxsync rc2 = RTSemFastMutexRelease(pThis->MergeCompleteMutex);
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync/** @copydoc PDMIMEDIA::pfnGetSize */
9496f2d398b49813176939d7a339ae513d5175efvboxsyncstatic DECLCALLBACK(uint64_t) drvvdGetSize(PPDMIMEDIA pInterface)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync PVBOXDISK pThis = PDMIMEDIA_2_VBOXDISK(pInterface);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync uint64_t cb = VDGetSize(pThis->pDisk, VD_LAST_IMAGE);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync LogFlow(("%s: returns %#llx (%llu)\n", __FUNCTION__, cb, cb));
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/** @copydoc PDMIMEDIA::pfnIsReadOnly */
090d729e786b999dc285f8ea267f9effd1319544vboxsyncstatic DECLCALLBACK(bool) drvvdIsReadOnly(PPDMIMEDIA pInterface)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync PVBOXDISK pThis = PDMIMEDIA_2_VBOXDISK(pInterface);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/** @copydoc PDMIMEDIA::pfnBiosGetPCHSGeometry */
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsyncstatic DECLCALLBACK(int) drvvdBiosGetPCHSGeometry(PPDMIMEDIA pInterface,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync PVBOXDISK pThis = PDMIMEDIA_2_VBOXDISK(pInterface);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync int rc = VDGetPCHSGeometry(pThis->pDisk, VD_LAST_IMAGE, pPCHSGeometry);
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync Log(("%s: geometry not available.\n", __FUNCTION__));
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync LogFlow(("%s: returns %Rrc (CHS=%d/%d/%d)\n", __FUNCTION__,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync rc, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors));
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/** @copydoc PDMIMEDIA::pfnBiosSetPCHSGeometry */
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsyncstatic DECLCALLBACK(int) drvvdBiosSetPCHSGeometry(PPDMIMEDIA pInterface,
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors));
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync PVBOXDISK pThis = PDMIMEDIA_2_VBOXDISK(pInterface);
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync int rc = VDSetPCHSGeometry(pThis->pDisk, VD_LAST_IMAGE, pPCHSGeometry);
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync/** @copydoc PDMIMEDIA::pfnBiosGetLCHSGeometry */
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsyncstatic DECLCALLBACK(int) drvvdBiosGetLCHSGeometry(PPDMIMEDIA pInterface,
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync PVBOXDISK pThis = PDMIMEDIA_2_VBOXDISK(pInterface);
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync int rc = VDGetLCHSGeometry(pThis->pDisk, VD_LAST_IMAGE, pLCHSGeometry);
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync Log(("%s: geometry not available.\n", __FUNCTION__));
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync LogFlow(("%s: returns %Rrc (CHS=%d/%d/%d)\n", __FUNCTION__,
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync rc, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors));
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync/** @copydoc PDMIMEDIA::pfnBiosSetLCHSGeometry */
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsyncstatic DECLCALLBACK(int) drvvdBiosSetLCHSGeometry(PPDMIMEDIA pInterface,
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors));
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync PVBOXDISK pThis = PDMIMEDIA_2_VBOXDISK(pInterface);
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync int rc = VDSetLCHSGeometry(pThis->pDisk, VD_LAST_IMAGE, pLCHSGeometry);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/** @copydoc PDMIMEDIA::pfnGetUuid */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic DECLCALLBACK(int) drvvdGetUuid(PPDMIMEDIA pInterface, PRTUUID pUuid)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync PVBOXDISK pThis = PDMIMEDIA_2_VBOXDISK(pInterface);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync LogFlow(("%s: returns %Rrc ({%RTuuid})\n", __FUNCTION__, rc, pUuid));
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync/*******************************************************************************
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync* Async Media interface methods *
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync*******************************************************************************/
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsyncstatic void drvvdAsyncReqComplete(void *pvUser1, void *pvUser2, int rcReq)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync int rc = pThis->pDrvMediaAsyncPort->pfnTransferCompleteNotify(pThis->pDrvMediaAsyncPort,
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsyncstatic DECLCALLBACK(int) drvvdStartRead(PPDMIMEDIAASYNC pInterface, uint64_t uOffset,
a3369a746b56a8966dd78619f4d191c9662f400dvboxsync LogFlow(("%s: uOffset=%#llx paSeg=%#p cSeg=%u cbRead=%d\n pvUser=%#p", __FUNCTION__,
efff36b306e370346025647a158689021df2e1d1vboxsync PVBOXDISK pThis = PDMIMEDIAASYNC_2_VBOXDISK(pInterface);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync int rc = VDAsyncRead(pThis->pDisk, uOffset, cbRead, paSeg, cSeg,
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsyncstatic DECLCALLBACK(int) drvvdStartWrite(PPDMIMEDIAASYNC pInterface, uint64_t uOffset,
a3369a746b56a8966dd78619f4d191c9662f400dvboxsync LogFlow(("%s: uOffset=%#llx paSeg=%#p cSeg=%u cbWrite=%d pvUser=%#p\n", __FUNCTION__,
a3369a746b56a8966dd78619f4d191c9662f400dvboxsync PVBOXDISK pThis = PDMIMEDIAASYNC_2_VBOXDISK(pInterface);
a3369a746b56a8966dd78619f4d191c9662f400dvboxsync int rc = VDAsyncWrite(pThis->pDisk, uOffset, cbWrite, paSeg, cSeg,
a3369a746b56a8966dd78619f4d191c9662f400dvboxsyncstatic DECLCALLBACK(int) drvvdStartFlush(PPDMIMEDIAASYNC pInterface, void *pvUser)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync LogFlow(("%s: pvUser=%#p\n", __FUNCTION__, pvUser));
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync PVBOXDISK pThis = PDMIMEDIAASYNC_2_VBOXDISK(pInterface);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync int rc = VDAsyncFlush(pThis->pDisk, drvvdAsyncReqComplete, pThis, pvUser);
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync/*******************************************************************************
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync* Base interface methods *
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync*******************************************************************************/
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync * @interface_method_impl{PDMIBASE,pfnQueryInterface}
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsyncstatic DECLCALLBACK(void *) drvvdQueryInterface(PPDMIBASE pInterface, const char *pszIID)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync PPDMDRVINS pDrvIns = PDMIBASE_2_DRVINS(pInterface);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync PVBOXDISK pThis = PDMINS_2_DATA(pDrvIns, PVBOXDISK);
b7a5b3f9f9ecce32ddacf8404c625ce0451bbdc1vboxsync PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDrvIns->IBase);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIA, &pThis->IMedia);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIAASYNC, pThis->fAsyncIOSupported ? &pThis->IMediaAsync : NULL);
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync/*******************************************************************************
b7a5b3f9f9ecce32ddacf8404c625ce0451bbdc1vboxsync* Saved state notification methods *
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync*******************************************************************************/
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync * Load done callback for re-opening the image writable during teleportation.
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync * This is called both for successful and failed load runs, we only care about
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync * successfull ones.
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync * @returns VBox status code.
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync * @param pDrvIns The driver instance.
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync * @param pSSM The saved state handle.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic DECLCALLBACK(int) drvvdLoadDone(PPDMDRVINS pDrvIns, PSSMHANDLE pSSM)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync PVBOXDISK pThis = PDMINS_2_DATA(pDrvIns, PVBOXDISK);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* Drop out if we don't have any work to do or if it's a failed load. */
9496f2d398b49813176939d7a339ae513d5175efvboxsync if (RT_FAILURE(rc)) /** @todo does the bugger set any errors? */
9496f2d398b49813176939d7a339ae513d5175efvboxsync/*******************************************************************************
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync* Driver methods *
9496f2d398b49813176939d7a339ae513d5175efvboxsync*******************************************************************************/
b7a5b3f9f9ecce32ddacf8404c625ce0451bbdc1vboxsyncstatic DECLCALLBACK(void) drvvdPowerOff(PPDMDRVINS pDrvIns)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync PVBOXDISK pThis = PDMINS_2_DATA(pDrvIns, PVBOXDISK);
d1bffa158f98ff3c18f7d085e7372c9ea00e9a43vboxsync * We must close the disk here to ensure that
d1bffa158f98ff3c18f7d085e7372c9ea00e9a43vboxsync * the backend closes all files before the
6b223679d40f5e57e55e867e806a9f194e2cde12vboxsync * async transport driver is destructed.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * VM resume notification that we use to undo what the temporary read-only image
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * mode set by drvvdSuspend.
6b223679d40f5e57e55e867e806a9f194e2cde12vboxsync * Also switch to runtime error mode if we're resuming after a state load
927320c7f81d3acdbccb5f3fea7548b4b7184b98vboxsync * without having been powered on first.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * @param pDrvIns The driver instance data.
9496f2d398b49813176939d7a339ae513d5175efvboxsync * @todo The VMSetError vs VMSetRuntimeError mess must be fixed elsewhere,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * we're making assumptions about Main behavior here!
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsyncstatic DECLCALLBACK(void) drvvdResume(PPDMDRVINS pDrvIns)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync PVBOXDISK pThis = PDMINS_2_DATA(pDrvIns, PVBOXDISK);
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync * The VM is being suspended, temporarily change to read-only image mode.
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync * This is important for several reasons:
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync * -# It makes sure that there are no pending writes to the image. Most
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync * backends implements this by closing and reopening the image in read-only
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync * -# It allows Main to read the images during snapshotting without having
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync * to account for concurrent writes.
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync * -# This is essential for making teleportation targets sharing images work
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync * right. Both with regards to caching and with regards to file sharing
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync * locks (RTFILE_O_DENY_*). (See also drvvdLoadDone.)
9a1ffdf6460d98ab356438aaa25b1115b0a72558vboxsync * @param pDrvIns The driver instance data.
090d729e786b999dc285f8ea267f9effd1319544vboxsyncstatic DECLCALLBACK(void) drvvdSuspend(PPDMDRVINS pDrvIns)
21029597fc4b76d0db0c9542daee201447281781vboxsync PVBOXDISK pThis = PDMINS_2_DATA(pDrvIns, PVBOXDISK);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * VM PowerOn notification for undoing the TempReadOnly config option and
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * changing to runtime error mode.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * @param pDrvIns The driver instance data.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * @todo The VMSetError vs VMSetRuntimeError mess must be fixed elsewhere,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * we're making assumptions about Main behavior here!
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic DECLCALLBACK(void) drvvdPowerOn(PPDMDRVINS pDrvIns)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync PVBOXDISK pThis = PDMINS_2_DATA(pDrvIns, PVBOXDISK);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * @copydoc FNPDMDRVDESTRUCT
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic DECLCALLBACK(void) drvvdDestruct(PPDMDRVINS pDrvIns)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync PVBOXDISK pThis = PDMINS_2_DATA(pDrvIns, PVBOXDISK);
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync ASMAtomicXchgHandle(&pThis->MergeCompleteMutex, NIL_RTSEMFASTMUTEX, &mutex);
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync /* Request the semaphore to wait until a potentially running merge
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync * operation has been finished. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * Construct a VBox disk media driver instance.
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync * @copydoc FNPDMDRVCONSTRUCT
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsyncstatic DECLCALLBACK(int) drvvdConstruct(PPDMDRVINS pDrvIns,
9496f2d398b49813176939d7a339ae513d5175efvboxsync PVBOXDISK pThis = PDMINS_2_DATA(pDrvIns, PVBOXDISK);
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync char *pszName = NULL; /**< The path of the disk image file. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync char *pszFormat = NULL; /**< The format backed to use for this image. */
b7a5b3f9f9ecce32ddacf8404c625ce0451bbdc1vboxsync bool fReadOnly; /**< True if the media is read-only. */
9496f2d398b49813176939d7a339ae513d5175efvboxsync bool fHonorZeroWrites; /**< True if zero blocks should be written. */
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync * Init the static parts.
9496f2d398b49813176939d7a339ae513d5175efvboxsync pDrvIns->IBase.pfnQueryInterface = drvvdQueryInterface;
09127e6ed46502ff8a6a521713ee8ace53667683vboxsync /* IMedia */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pThis->IMedia.pfnBiosGetPCHSGeometry = drvvdBiosGetPCHSGeometry;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pThis->IMedia.pfnBiosSetPCHSGeometry = drvvdBiosSetPCHSGeometry;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pThis->IMedia.pfnBiosGetLCHSGeometry = drvvdBiosGetLCHSGeometry;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pThis->IMedia.pfnBiosSetLCHSGeometry = drvvdBiosSetLCHSGeometry;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* IMediaAsync */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pThis->IMediaAsync.pfnStartWrite = drvvdStartWrite;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pThis->IMediaAsync.pfnStartFlush = drvvdStartFlush;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* Initialize supported VD interfaces. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pThis->VDIErrorCallbacks.cbSize = sizeof(VDINTERFACEERROR);
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync pThis->VDIErrorCallbacks.enmInterface = VDINTERFACETYPE_ERROR;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pThis->VDIErrorCallbacks.pfnError = drvvdErrorCallback;
cba6719bd64ec749967bbe931230452664109857vboxsync rc = VDInterfaceAdd(&pThis->VDIError, "DrvVD_VDIError", VDINTERFACETYPE_ERROR,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync &pThis->VDIErrorCallbacks, pDrvIns, &pThis->pVDIfsDisk);
cba6719bd64ec749967bbe931230452664109857vboxsync /* This is just prepared here, the actual interface is per-image, so it's
cba6719bd64ec749967bbe931230452664109857vboxsync * added later. No need to have separate callback tables. */
cba6719bd64ec749967bbe931230452664109857vboxsync pThis->VDIConfigCallbacks.cbSize = sizeof(VDINTERFACECONFIG);
cba6719bd64ec749967bbe931230452664109857vboxsync pThis->VDIConfigCallbacks.enmInterface = VDINTERFACETYPE_CONFIG;
cba6719bd64ec749967bbe931230452664109857vboxsync pThis->VDIConfigCallbacks.pfnAreKeysValid = drvvdCfgAreKeysValid;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pThis->VDIConfigCallbacks.pfnQuerySize = drvvdCfgQuerySize;
cba6719bd64ec749967bbe931230452664109857vboxsync pThis->VDIConfigCallbacks.pfnQuery = drvvdCfgQuery;
bool fHostIP = false;
bool fUseNewIo = false;
unsigned iLevel = 0;
bool fValid;
if (!fValid)
if (!pParent)
iLevel++;
if (fHostIP)
#ifndef VBOX_WITH_INIP
fUseNewIo = false;
unsigned iImageIdx = 0;
if (!pImage)
bool fMergeSource;
if (fMergeSource)
bool fMergeTarget;
if (fMergeTarget)
unsigned uOpenFlags;
if (fHonorZeroWrites)
&& !fReadOnly
&& iLevel == 0)
pszName);
iLevel--;
iImageIdx++;
return rc;
sizeof(VBOXDISK),
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,