DrvVD.cpp revision fbf08fabb4c4b383d6aa2830c2bd5b943a26f10c
77b1a2d8b5dbe2c0b5200794914239fee3c8ee5dvboxsync * DrvVD - Generic VBox disk media driver.
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * Copyright (C) 2006-2010 Sun Microsystems, Inc.
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 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * additional information or have any questions.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/*******************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync* Header files *
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync*******************************************************************************/
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync/* All lwip header files are not C++ safe. So hack around this. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync#endif /* VBOX_WITH_INIP */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync/* Small hack to get at lwIP initialized status */
efff36b306e370346025647a158689021df2e1d1vboxsyncextern bool DevINIPConfigured(void);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync#endif /* VBOX_WITH_INIP */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/*******************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync* 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) )
9496f2d398b49813176939d7a339ae513d5175efvboxsync/** Converts a pointer to VBOXDISK::IMediaAsync to a PVBOXDISK. */
9496f2d398b49813176939d7a339ae513d5175efvboxsync ( (PVBOXDISK)((uintptr_t)pInterface - RT_OFFSETOF(VBOXDISK, IMediaAsync)) )
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync * 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. */
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync * 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 */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /** 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
21029597fc4b76d0db0c9542daee201447281781vboxsync * @implements VDINTERFACEERROR
21029597fc4b76d0db0c9542daee201447281781vboxsync * @implements VDINTERFACETCPNET
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync * @implements VDINTERFACEASYNCIO
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync * @implements VDINTERFACECONFIG
9496f2d398b49813176939d7a339ae513d5175efvboxsynctypedef struct VBOXDISK
9496f2d398b49813176939d7a339ae513d5175efvboxsync /** The VBox disk container. */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync /** The media interface. */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync /** Pointer to the driver instance. */
9496f2d398b49813176939d7a339ae513d5175efvboxsync /** Flag whether suspend has changed image open mode to read only. */
9496f2d398b49813176939d7a339ae513d5175efvboxsync /** Flag whether to use the runtime (true) or startup error facility. */
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync /** Pointer to list of VD interfaces. Per-disk. */
9496f2d398b49813176939d7a339ae513d5175efvboxsync /** Common structure for the supported error interface. */
9496f2d398b49813176939d7a339ae513d5175efvboxsync /** Callback table for error interface. */
9496f2d398b49813176939d7a339ae513d5175efvboxsync /** Common structure for the supported TCP network stack interface. */
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync /** Callback table for TCP network stack interface. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /** Common structure for the supported async I/O interface. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /** Callback table for async I/O interface. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /** Common structure for the supported thread synchronization interface. */
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync /** Callback table for thread synchronization interface. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /** Callback table for the configuration information interface. */
21029597fc4b76d0db0c9542daee201447281781vboxsync /** Flag whether opened disk suppports async I/O operations. */
20f97e6df28ebc0911dc42671222e0d494f034f3vboxsync /** The async media interface. */
20f97e6df28ebc0911dc42671222e0d494f034f3vboxsync /** The async media port interface above. */
21029597fc4b76d0db0c9542daee201447281781vboxsync /** Pointer to the list of data we need to keep per image. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /** Flag whether a merge operation has been set up. */
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync /** Synchronization to prevent destruction before merge finishes. */
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync /** 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));
9496f2d398b49813176939d7a339ae513d5175efvboxsync * 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.
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync rc = VDGetOpenFlags(pThis->pDisk, VD_LAST_IMAGE, &uOpenFlags);
9496f2d398b49813176939d7a339ae513d5175efvboxsync rc = VDSetOpenFlags(pThis->pDisk, VD_LAST_IMAGE, uOpenFlags);
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync * Undo the temporary read-only status of the image.
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync * @returns VBox status code.
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync * @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);
9496f2d398b49813176939d7a339ae513d5175efvboxsync /* We must not pass VMSETRTERR_FLAGS_FATAL as it could lead to a
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync * deadlock: We are probably executed in a thread context != EMT
9496f2d398b49813176939d7a339ae513d5175efvboxsync * and the EM thread would wait until every thread is suspended
9496f2d398b49813176939d7a339ae513d5175efvboxsync * but we would wait for the EM thread ... */
9496f2d398b49813176939d7a339ae513d5175efvboxsync PDMDrvHlpVMSetRuntimeErrorV(pDrvIns, /* fFlags=*/ 0, "DrvVD", pszFormat, va);
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync PDMDrvHlpVMSetErrorV(pDrvIns, rc, RT_SRC_POS_ARGS, pszFormat, va);
9496f2d398b49813176939d7a339ae513d5175efvboxsync/*******************************************************************************
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync* VD Async I/O interface implementation *
9496f2d398b49813176939d7a339ae513d5175efvboxsync*******************************************************************************/
9496f2d398b49813176939d7a339ae513d5175efvboxsyncstatic DECLCALLBACK(void) drvvdAsyncTaskCompleted(PPDMDRVINS pDrvIns, void *pvTemplateUser, void *pvUser, int rcReq)
9496f2d398b49813176939d7a339ae513d5175efvboxsync PVBOXDISK pThis = PDMINS_2_DATA(pDrvIns, PVBOXDISK);
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)pvTemplateUser;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync /* If thread synchronization is active, then signal the end of the
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync * this disk read/write operation. */
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync /** @todo provide a way to determine the type of task (read/write)
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync * which was completed, see also VBoxHDD.cpp. */
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync if (RT_UNLIKELY(pStorageBackend->pInterfaceThreadSyncCallbacks))
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync int rc2 = pStorageBackend->pInterfaceThreadSyncCallbacks->pfnFinishWrite(pStorageBackend->pInterfaceThreadSync->pvUser);
9496f2d398b49813176939d7a339ae513d5175efvboxsyncstatic 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,
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync 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
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync PDMR3AsyncCompletionTemplateDestroy(pStorageBackend->pTemplate);
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsyncstatic DECLCALLBACK(int) drvvdAsyncIOClose(void *pvUser, void *pStorage)
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)pStorage;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync PDMR3AsyncCompletionEpClose(pStorageBackend->pEndpoint);
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync PDMR3AsyncCompletionTemplateDestroy(pStorageBackend->pTemplate);
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsyncstatic DECLCALLBACK(int) drvvdAsyncIOReadSync(void *pvUser, void *pStorage, uint64_t uOffset,
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)pStorage;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync ASMAtomicXchgBool(&pStorageBackend->fSyncIoPending, true);
9496f2d398b49813176939d7a339ae513d5175efvboxsync int rc = PDMR3AsyncCompletionEpRead(pStorageBackend->pEndpoint, uOffset, &DataSeg, 1, cbRead, NULL, &pTask);
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync rc = RTSemEventWait(pStorageBackend->EventSem, RT_INDEFINITE_WAIT);
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync ASMAtomicXchgBool(&pStorageBackend->fSyncIoPending, false);
975ad9d9bc9c4dc96b41d9f67a65228b1b338e2avboxsyncstatic DECLCALLBACK(int) drvvdAsyncIOWriteSync(void *pvUser, void *pStorage, uint64_t uOffset,
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync size_t cbWrite, const void *pvBuf, size_t *pcbWritten)
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)pStorage;
efff36b306e370346025647a158689021df2e1d1vboxsync ASMAtomicXchgBool(&pStorageBackend->fSyncIoPending, true);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync int rc = PDMR3AsyncCompletionEpWrite(pStorageBackend->pEndpoint, uOffset, &DataSeg, 1, cbWrite, NULL, &pTask);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync rc = RTSemEventWait(pStorageBackend->EventSem, RT_INDEFINITE_WAIT);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync ASMAtomicXchgBool(&pStorageBackend->fSyncIoPending, false);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsyncstatic DECLCALLBACK(int) drvvdAsyncIOFlushSync(void *pvUser, void *pStorage)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync 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);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic int drvvdCfgQuerySize(void *pvUser, const char *pszName, size_t *pcb)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync return CFGMR3QuerySize((PCFGMNODE)pvUser, pszName, pcb);
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsyncstatic int drvvdCfgQuery(void *pvUser, const char *pszName, char *pszString, size_t cchString)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync return CFGMR3QueryString((PCFGMNODE)pvUser, pszName, pszString, cchString);
ff88d4153cd65650577e8c2d1a5a3fdfa0404a80vboxsync/*******************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync* VD TCP network stack interface implementation - INIP case *
fe813b3594039ba864493438e78ee0e7132bc445vboxsync*******************************************************************************/
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/** @copydoc VDINTERFACETCPNET::pfnClientConnect */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic DECLCALLBACK(int) drvvdINIPClientConnect(const char *pszAddress, uint32_t uPort, PRTSOCKET pSock)
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync /* First check whether lwIP is set up in this VM instance. */
ff88d4153cd65650577e8c2d1a5a3fdfa0404a80vboxsync /* Resolve hostname. As there is no standard resolver for lwIP yet,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * just accept numeric IP addresses for now. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync LogRelFunc(("cannot resolve IP %s\n", pszAddress));
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync /* Create socket and connect. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync RTSOCKET Sock = lwip_socket(PF_INET, SOCK_STREAM, 0);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync if (!lwip_connect(Sock, (struct sockaddr *)&InAddr, sizeof(InAddr)))
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync rc = VERR_NET_CONNECTION_REFUSED; /* @todo real solution needed */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync rc = VERR_NET_CONNECTION_REFUSED; /* @todo real solution needed */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/** @copydoc VDINTERFACETCPNET::pfnClientClose */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic DECLCALLBACK(int) drvvdINIPClientClose(RTSOCKET Sock)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync return VINF_SUCCESS; /** @todo real solution needed */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/** @copydoc VDINTERFACETCPNET::pfnSelectOne */
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsyncstatic 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);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync return VERR_NET_CONNECTION_REFUSED; /** @todo real solution needed */
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync/** @copydoc VDINTERFACETCPNET::pfnRead */
594521f7faf13f7a88f31e6cd76629bd67340229vboxsyncstatic DECLCALLBACK(int) drvvdINIPRead(RTSOCKET Sock, void *pvBuffer, size_t cbBuffer, size_t *pcbRead)
fe813b3594039ba864493438e78ee0e7132bc445vboxsync /* Do params checking */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * Read loop.
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync * If pcbRead is NULL we have to fill the entire buffer!
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync /** @todo this clipping here is just in case (the send function
fe813b3594039ba864493438e78ee0e7132bc445vboxsync * needed it, so I added it here, too). Didn't investigate if this
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync * really has issues. Better be safe than sorry. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync ssize_t cbBytesRead = lwip_recv(Sock, (char *)pvBuffer + cbRead,
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync return VERR_NET_CONNECTION_REFUSED; /** @todo real solution */
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync return VERR_NET_CONNECTION_REFUSED; /** @todo real solution */
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync /* return partial data */
fe813b3594039ba864493438e78ee0e7132bc445vboxsync /* read more? */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/** @copydoc VDINTERFACETCPNET::pfnWrite */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic DECLCALLBACK(int) drvvdINIPWrite(RTSOCKET Sock, const void *pvBuffer, size_t cbBuffer)
9496f2d398b49813176939d7a339ae513d5175efvboxsync /** @todo lwip send only supports up to 65535 bytes in a single
b7a5b3f9f9ecce32ddacf8404c625ce0451bbdc1vboxsync * send (stupid limitation buried in the code), so make sure we
9496f2d398b49813176939d7a339ae513d5175efvboxsync * don't get any wraparounds. This should be moved to DevINIP
9496f2d398b49813176939d7a339ae513d5175efvboxsync * stack interface once that's implemented. */
9496f2d398b49813176939d7a339ae513d5175efvboxsync ssize_t cbWritten = lwip_send(Sock, (void *)pvBuffer,
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync return VERR_NET_CONNECTION_REFUSED; /** @todo real solution needed */
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync AssertMsg(cbBuffer >= (size_t)cbWritten, ("Wrote more than we requested!!! cbWritten=%d cbBuffer=%d\n",
9496f2d398b49813176939d7a339ae513d5175efvboxsync/** @copydoc VDINTERFACETCPNET::pfnFlush */
9496f2d398b49813176939d7a339ae513d5175efvboxsyncstatic DECLCALLBACK(int) drvvdINIPFlush(RTSOCKET Sock)
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync/** @copydoc VDINTERFACETCPNET::pfnGetLocalAddress */
9496f2d398b49813176939d7a339ae513d5175efvboxsyncstatic DECLCALLBACK(int) drvvdINIPGetLocalAddress(RTSOCKET Sock, PRTNETADDR pAddr)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * Convert the address.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/** @copydoc VDINTERFACETCPNET::pfnGetPeerAddress */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic DECLCALLBACK(int) drvvdINIPGetPeerAddress(RTSOCKET Sock, PRTNETADDR pAddr)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * Convert the address.
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync#endif /* VBOX_WITH_INIP */
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync/*******************************************************************************
090d729e786b999dc285f8ea267f9effd1319544vboxsync* Media interface methods *
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync*******************************************************************************/
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync/** @copydoc PDMIMEDIA::pfnRead */
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsyncstatic DECLCALLBACK(int) drvvdRead(PPDMIMEDIA pInterface,
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync LogFlow(("%s: off=%#llx pvBuf=%p cbRead=%d\n", __FUNCTION__,
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync PVBOXDISK pThis = PDMIMEDIA_2_VBOXDISK(pInterface);
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync Log2(("%s: off=%#llx pvBuf=%p cbRead=%d %.*Rhxd\n", __FUNCTION__,
9496f2d398b49813176939d7a339ae513d5175efvboxsync/** @copydoc PDMIMEDIA::pfnWrite */
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsyncstatic DECLCALLBACK(int) drvvdWrite(PPDMIMEDIA pInterface,
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync LogFlow(("%s: off=%#llx pvBuf=%p cbWrite=%d\n", __FUNCTION__,
68a4ee3a31a0807abd03eae881c1bbaf4d42ee6dvboxsync PVBOXDISK pThis = PDMIMEDIA_2_VBOXDISK(pInterface);
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync Log2(("%s: off=%#llx pvBuf=%p cbWrite=%d %.*Rhxd\n", __FUNCTION__,
9496f2d398b49813176939d7a339ae513d5175efvboxsync int rc = VDWrite(pThis->pDisk, off, pvBuf, cbWrite);
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync/** @copydoc PDMIMEDIA::pfnFlush */
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsyncstatic DECLCALLBACK(int) drvvdFlush(PPDMIMEDIA pInterface)
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync PVBOXDISK pThis = PDMIMEDIA_2_VBOXDISK(pInterface);
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync/** @copydoc PDMIMEDIA::pfnMerge */
9496f2d398b49813176939d7a339ae513d5175efvboxsyncstatic DECLCALLBACK(int) drvvdMerge(PPDMIMEDIA pInterface,
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync PVBOXDISK pThis = PDMIMEDIA_2_VBOXDISK(pInterface);
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync /* Note: There is an unavoidable race between destruction and another
975ad9d9bc9c4dc96b41d9f67a65228b1b338e2avboxsync * thread invoking this function. This is handled safely and gracefully by
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync * atomically invalidating the lock handle in drvvdDestruct. */
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync int rc2 = RTSemFastMutexRequest(pThis->MergeCompleteMutex);
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync /* Take shortcut: PFNSIMPLEPROGRESS is exactly the same type as
9496f2d398b49813176939d7a339ae513d5175efvboxsync * PFNVDPROGRESS, so there's no need for a conversion function. */
b7a5b3f9f9ecce32ddacf8404c625ce0451bbdc1vboxsync /** @todo maybe introduce a conversion which limits update frequency. */
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync VDIProgressCallbacks.cbSize = sizeof(VDINTERFACEPROGRESS);
9496f2d398b49813176939d7a339ae513d5175efvboxsync VDIProgressCallbacks.enmInterface = VDINTERFACETYPE_PROGRESS;
9496f2d398b49813176939d7a339ae513d5175efvboxsync rc2 = VDInterfaceAdd(&VDIProgress, "DrvVD_VDIProgress", VDINTERFACETYPE_PROGRESS,
090d729e786b999dc285f8ea267f9effd1319544vboxsync rc2 = RTSemFastMutexRelease(pThis->MergeCompleteMutex);
9496f2d398b49813176939d7a339ae513d5175efvboxsync/** @copydoc PDMIMEDIA::pfnGetSize */
b7a5b3f9f9ecce32ddacf8404c625ce0451bbdc1vboxsyncstatic DECLCALLBACK(uint64_t) drvvdGetSize(PPDMIMEDIA pInterface)
9496f2d398b49813176939d7a339ae513d5175efvboxsync PVBOXDISK pThis = PDMIMEDIA_2_VBOXDISK(pInterface);
9496f2d398b49813176939d7a339ae513d5175efvboxsync uint64_t cb = VDGetSize(pThis->pDisk, VD_LAST_IMAGE);
9496f2d398b49813176939d7a339ae513d5175efvboxsync LogFlow(("%s: returns %#llx (%llu)\n", __FUNCTION__, cb, cb));
090d729e786b999dc285f8ea267f9effd1319544vboxsync/** @copydoc PDMIMEDIA::pfnIsReadOnly */
090d729e786b999dc285f8ea267f9effd1319544vboxsyncstatic DECLCALLBACK(bool) drvvdIsReadOnly(PPDMIMEDIA pInterface)
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync PVBOXDISK pThis = PDMIMEDIA_2_VBOXDISK(pInterface);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/** @copydoc PDMIMEDIA::pfnBiosGetPCHSGeometry */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic DECLCALLBACK(int) drvvdBiosGetPCHSGeometry(PPDMIMEDIA pInterface,
090d729e786b999dc285f8ea267f9effd1319544vboxsync PVBOXDISK pThis = PDMIMEDIA_2_VBOXDISK(pInterface);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync int rc = VDGetPCHSGeometry(pThis->pDisk, VD_LAST_IMAGE, pPCHSGeometry);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync Log(("%s: geometry not available.\n", __FUNCTION__));
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync LogFlow(("%s: returns %Rrc (CHS=%d/%d/%d)\n", __FUNCTION__,
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync rc, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors));
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync/** @copydoc PDMIMEDIA::pfnBiosSetPCHSGeometry */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic DECLCALLBACK(int) drvvdBiosSetPCHSGeometry(PPDMIMEDIA pInterface,
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors));
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync PVBOXDISK pThis = PDMIMEDIA_2_VBOXDISK(pInterface);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync int rc = VDSetPCHSGeometry(pThis->pDisk, VD_LAST_IMAGE, pPCHSGeometry);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/** @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);
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync/** @copydoc PDMIMEDIA::pfnGetUuid */
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsyncstatic DECLCALLBACK(int) drvvdGetUuid(PPDMIMEDIA pInterface, PRTUUID pUuid)
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync PVBOXDISK pThis = PDMIMEDIA_2_VBOXDISK(pInterface);
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync LogFlow(("%s: returns %Rrc ({%RTuuid})\n", __FUNCTION__, rc, pUuid));
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync/*******************************************************************************
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync* Async Media interface methods *
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync*******************************************************************************/
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic void drvvdAsyncReqComplete(void *pvUser1, void *pvUser2)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync int rc = pThis->pDrvMediaAsyncPort->pfnTransferCompleteNotify(pThis->pDrvMediaAsyncPort,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic DECLCALLBACK(int) drvvdStartRead(PPDMIMEDIAASYNC pInterface, uint64_t uOffset,
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync LogFlow(("%s: uOffset=%#llx paSeg=%#p cSeg=%u cbRead=%d\n pvUser=%#p", __FUNCTION__,
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync 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,
efff36b306e370346025647a158689021df2e1d1vboxsync LogFlow(("%s: uOffset=%#llx paSeg=%#p cSeg=%u cbWrite=%d\n pvUser=%#p", __FUNCTION__,
efff36b306e370346025647a158689021df2e1d1vboxsync PVBOXDISK pThis = PDMIMEDIAASYNC_2_VBOXDISK(pInterface);
efff36b306e370346025647a158689021df2e1d1vboxsync int rc = VDAsyncWrite(pThis->pDisk, uOffset, cbWrite, paSeg, cSeg,
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync/*******************************************************************************
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync* Base interface methods *
efff36b306e370346025647a158689021df2e1d1vboxsync*******************************************************************************/
a3369a746b56a8966dd78619f4d191c9662f400dvboxsync * @interface_method_impl{PDMIBASE,pfnQueryInterface}
a3369a746b56a8966dd78619f4d191c9662f400dvboxsyncstatic DECLCALLBACK(void *) drvvdQueryInterface(PPDMIBASE pInterface, const char *pszIID)
a3369a746b56a8966dd78619f4d191c9662f400dvboxsync PPDMDRVINS pDrvIns = PDMIBASE_2_DRVINS(pInterface);
a3369a746b56a8966dd78619f4d191c9662f400dvboxsync PVBOXDISK pThis = PDMINS_2_DATA(pDrvIns, PVBOXDISK);
a3369a746b56a8966dd78619f4d191c9662f400dvboxsync PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDrvIns->IBase);
a3369a746b56a8966dd78619f4d191c9662f400dvboxsync PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIA, &pThis->IMedia);
a3369a746b56a8966dd78619f4d191c9662f400dvboxsync PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIAASYNC, pThis->fAsyncIOSupported ? &pThis->IMediaAsync : NULL);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/*******************************************************************************
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync* Saved state notification methods *
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync*******************************************************************************/
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync * Load done callback for re-opening the image writable during teleportation.
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync * This is called both for successful and failed load runs, we only care about
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync * successfull ones.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * @returns VBox status code.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * @param pDrvIns The driver instance.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * @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. */
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync if (RT_FAILURE(rc)) /** @todo does the bugger set any errors? */
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync/*******************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync* Driver methods *
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync*******************************************************************************/
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic DECLCALLBACK(void) drvvdPowerOff(PPDMDRVINS pDrvIns)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync PVBOXDISK pThis = PDMINS_2_DATA(pDrvIns, PVBOXDISK);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * We must close the disk here to ensure that
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync * the backend closes all files before the
9496f2d398b49813176939d7a339ae513d5175efvboxsync * async transport driver is destructed.
9496f2d398b49813176939d7a339ae513d5175efvboxsync * VM resume notification that we use to undo what the temporary read-only image
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync * mode set by drvvdSuspend.
9496f2d398b49813176939d7a339ae513d5175efvboxsync * Also switch to runtime error mode if we're resuming after a state load
b7a5b3f9f9ecce32ddacf8404c625ce0451bbdc1vboxsync * without having been powered on first.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * @param pDrvIns The driver instance data.
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync * @todo The VMSetError vs VMSetRuntimeError mess must be fixed elsewhere,
6b223679d40f5e57e55e867e806a9f194e2cde12vboxsync * we're making assumptions about Main behavior here!
d1bffa158f98ff3c18f7d085e7372c9ea00e9a43vboxsyncstatic DECLCALLBACK(void) drvvdResume(PPDMDRVINS pDrvIns)
6b223679d40f5e57e55e867e806a9f194e2cde12vboxsync PVBOXDISK pThis = PDMINS_2_DATA(pDrvIns, PVBOXDISK);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * The VM is being suspended, temporarily change to read-only image mode.
6b223679d40f5e57e55e867e806a9f194e2cde12vboxsync * This is important for several reasons:
927320c7f81d3acdbccb5f3fea7548b4b7184b98vboxsync * -# It makes sure that there are no pending writes to the image. Most
9496f2d398b49813176939d7a339ae513d5175efvboxsync * backends implements this by closing and reopening the image in read-only
9496f2d398b49813176939d7a339ae513d5175efvboxsync * -# It allows Main to read the images during snapshotting without having
9496f2d398b49813176939d7a339ae513d5175efvboxsync * to account for concurrent writes.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * -# 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.)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * @param pDrvIns The driver instance data.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic DECLCALLBACK(void) drvvdSuspend(PPDMDRVINS pDrvIns)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync PVBOXDISK pThis = PDMINS_2_DATA(pDrvIns, PVBOXDISK);
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync * VM PowerOn notification for undoing the TempReadOnly config option and
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync * changing to runtime error mode.
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync * @param pDrvIns The driver instance data.
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync * @todo The VMSetError vs VMSetRuntimeError mess must be fixed elsewhere,
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync * we're making assumptions about Main behavior here!
9a1ffdf6460d98ab356438aaa25b1115b0a72558vboxsyncstatic DECLCALLBACK(void) drvvdPowerOn(PPDMDRVINS pDrvIns)
090d729e786b999dc285f8ea267f9effd1319544vboxsync PVBOXDISK pThis = PDMINS_2_DATA(pDrvIns, PVBOXDISK);
090d729e786b999dc285f8ea267f9effd1319544vboxsync * @copydoc FNPDMDRVDESTRUCT
090d729e786b999dc285f8ea267f9effd1319544vboxsyncstatic DECLCALLBACK(void) drvvdDestruct(PPDMDRVINS pDrvIns)
090d729e786b999dc285f8ea267f9effd1319544vboxsync PVBOXDISK pThis = PDMINS_2_DATA(pDrvIns, PVBOXDISK);
090d729e786b999dc285f8ea267f9effd1319544vboxsync RTSEMFASTMUTEX mutex = (RTSEMFASTMUTEX)ASMAtomicXchgPtr((void **)&pThis->MergeCompleteMutex,
090d729e786b999dc285f8ea267f9effd1319544vboxsync /* Request the semaphore to wait until a potentially running merge
090d729e786b999dc285f8ea267f9effd1319544vboxsync * operation has been finished. */
fe813b3594039ba864493438e78ee0e7132bc445vboxsync * Construct a VBox disk media driver instance.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * @copydoc FNPDMDRVCONSTRUCT
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic DECLCALLBACK(int) drvvdConstruct(PPDMDRVINS pDrvIns,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync PVBOXDISK pThis = PDMINS_2_DATA(pDrvIns, PVBOXDISK);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync char *pszName = NULL; /**< The path of the disk image file. */
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync char *pszFormat = NULL; /**< The format backed to use for this image. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync bool fReadOnly; /**< True if the media is read-only. */
9496f2d398b49813176939d7a339ae513d5175efvboxsync bool fHonorZeroWrites; /**< True if zero blocks should be written. */
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync * Init the static parts.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pDrvIns->IBase.pfnQueryInterface = drvvdQueryInterface;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* IMedia */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pThis->IMedia.pfnBiosGetPCHSGeometry = drvvdBiosGetPCHSGeometry;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pThis->IMedia.pfnBiosSetPCHSGeometry = drvvdBiosSetPCHSGeometry;
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync pThis->IMedia.pfnBiosGetLCHSGeometry = drvvdBiosGetLCHSGeometry;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pThis->IMedia.pfnBiosSetLCHSGeometry = drvvdBiosSetLCHSGeometry;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* IMediaAsync */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pThis->IMediaAsync.pfnStartWrite = drvvdStartWrite;
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync /* Initialize supported VD interfaces. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pThis->VDIErrorCallbacks.cbSize = sizeof(VDINTERFACEERROR);
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync pThis->VDIErrorCallbacks.enmInterface = VDINTERFACETYPE_ERROR;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pThis->VDIErrorCallbacks.pfnError = drvvdErrorCallback;
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync rc = VDInterfaceAdd(&pThis->VDIError, "DrvVD_VDIError", VDINTERFACETYPE_ERROR,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync &pThis->VDIErrorCallbacks, pDrvIns, &pThis->pVDIfsDisk);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* This is just prepared here, the actual interface is per-image, so it's
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * added later. No need to have separate callback tables. */
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync pThis->VDIConfigCallbacks.cbSize = sizeof(VDINTERFACECONFIG);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pThis->VDIConfigCallbacks.enmInterface = VDINTERFACETYPE_CONFIG;
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync pThis->VDIConfigCallbacks.pfnAreKeysValid = drvvdCfgAreKeysValid;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pThis->VDIConfigCallbacks.pfnQuerySize = drvvdCfgQuerySize;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pThis->VDIConfigCallbacks.pfnQuery = drvvdCfgQuery;
9496f2d398b49813176939d7a339ae513d5175efvboxsync /* List of images is empty now. */
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync /* Try to attach async media port interface above.*/
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pThis->pDrvMediaAsyncPort = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMIMEDIAASYNCPORT);
9496f2d398b49813176939d7a339ae513d5175efvboxsync * Validate configuration and find all parent images.
9496f2d398b49813176939d7a339ae513d5175efvboxsync * It's sort of up side down from the image dependency tree.
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync bool fHostIP = false;
9496f2d398b49813176939d7a339ae513d5175efvboxsync bool fUseNewIo = false;
9496f2d398b49813176939d7a339ae513d5175efvboxsync unsigned iLevel = 0;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* Toplevel configuration additionally contains the global image
09127e6ed46502ff8a6a521713ee8ace53667683vboxsync * open flags. Some might be converted to per-image flags later. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync "Format\0Path\0"
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync "ReadOnly\0TempReadOnly\0HonorZeroWrites\0"
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync "HostIPStack\0UseNewIo\0SetupMerge\0");
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* All other image configurations only contain image name and
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * the format information. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync fValid = CFGMR3AreValuesValid(pCurNode, "Format\0Path\0"
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync "MergeSource\0MergeTarget\0");
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync rc = PDMDrvHlpVMSetError(pDrvIns, VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync RT_SRC_POS, N_("DrvVD: Configuration error: keys incorrect at level %d"), iLevel);
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync rc = CFGMR3QueryBoolDef(pCurNode, "HostIPStack", &fHostIP, true);
9496f2d398b49813176939d7a339ae513d5175efvboxsync N_("DrvVD: Configuration error: Querying \"HostIPStack\" as boolean failed"));
if (!pParent)
iLevel++;
if (fHostIP)
#ifndef VBOX_WITH_INIP
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,