DrvVD.cpp revision 1189c7dde5d7f6c26f338ced3d40fc830b822e68
77b1a2d8b5dbe2c0b5200794914239fee3c8ee5dvboxsync * DrvVD - Generic VBox disk media driver.
bbede9c189def47a9880f0ffb03c0c230c774185vboxsync * 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*******************************************************************************/
efff36b306e370346025647a158689021df2e1d1vboxsync/* All lwip header files are not C++ safe. So hack around this. */
590bfe12ce22cd3716448fbb9f4dc51664bfe5e2vboxsync#endif /* VBOX_WITH_INIP */
efff36b306e370346025647a158689021df2e1d1vboxsync/* Small hack to get at lwIP initialized status */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsyncextern 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) )
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/** 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. */
7766bf675357fd940d8c49e69a5d72dc6eaa6be4vboxsync /** Callback routine */
bbede9c189def47a9880f0ffb03c0c230c774185vboxsync /** Pointer to the optional thread synchronization interface of the disk. */
bbede9c189def47a9880f0ffb03c0c230c774185vboxsync /** Pointer to the optional thread synchronization callbacks of the disk. */
bbede9c189def47a9880f0ffb03c0c230c774185vboxsync PVDINTERFACETHREADSYNC pInterfaceThreadSyncCallbacks;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * VBox disk container media main structure, private part.
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync * @implements PDMIMEDIA
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync * @implements PDMIMEDIAASYNC
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync * @implements VDINTERFACEERROR
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync * @implements VDINTERFACETCPNET
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync * @implements VDINTERFACEASYNCIO
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync * @implements VDINTERFACECONFIG
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsynctypedef struct VBOXDISK
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /** The VBox disk container. */
9496f2d398b49813176939d7a339ae513d5175efvboxsync /** The media interface. */
9496f2d398b49813176939d7a339ae513d5175efvboxsync /** 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. */
21029597fc4b76d0db0c9542daee201447281781vboxsync /** Pointer to list of VD interfaces. Per-disk. */
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync /** Common structure for the supported error interface. */
9496f2d398b49813176939d7a339ae513d5175efvboxsync /** Callback table for error interface. */
9496f2d398b49813176939d7a339ae513d5175efvboxsync /** Common structure for the supported TCP network stack interface. */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync /** Callback table for TCP network stack interface. */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync /** Common structure for the supported async I/O interface. */
9496f2d398b49813176939d7a339ae513d5175efvboxsync /** Callback table for async I/O interface. */
9496f2d398b49813176939d7a339ae513d5175efvboxsync /** Common structure for the supported thread synchronization interface. */
16a9adc14900ca18e6909679a579f6833425e030vboxsync /** Callback table for thread synchronization interface. */
16a9adc14900ca18e6909679a579f6833425e030vboxsync /** Callback table for the configuration information interface. */
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync /** Flag whether opened disk suppports async I/O operations. */
9496f2d398b49813176939d7a339ae513d5175efvboxsync /** The async media interface. */
9496f2d398b49813176939d7a339ae513d5175efvboxsync /** The async media port interface above. */
9496f2d398b49813176939d7a339ae513d5175efvboxsync /** Pointer to the list of data we need to keep per image. */
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync /** Flag whether the media should allow concurrent open for writing. */
16a9adc14900ca18e6909679a579f6833425e030vboxsync /** Flag whether a merge operation has been set up. */
16a9adc14900ca18e6909679a579f6833425e030vboxsync /** Synchronization to prevent destruction before merge finishes. */
16a9adc14900ca18e6909679a579f6833425e030vboxsync /** Synchronization between merge and other image accesses. */
16a9adc14900ca18e6909679a579f6833425e030vboxsync /** Source image index for merging. */
16a9adc14900ca18e6909679a579f6833425e030vboxsync /** Target image index for merging. */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync /** Flag whether boot acceleration is enabled. */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync /** Flag whether boot acceleration is currently active. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /** Size of the disk, used for read truncation. */
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync /** Size of the configured buffer. */
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync /** Start offset for which the buffer holds data. */
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync /** Number of valid bytes in the buffer. */
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync /** The disk buffer. */
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync/*******************************************************************************
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync* Internal Functions *
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync*******************************************************************************/
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync * Internal: allocate new image descriptor and put it in the list
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync PVBOXIMAGE pImage = (PVBOXIMAGE)RTMemAllocZ(sizeof(VBOXIMAGE));
16a9adc14900ca18e6909679a579f6833425e030vboxsync * Internal: free the list of images descriptors.
16a9adc14900ca18e6909679a579f6833425e030vboxsync * Make the image temporarily read-only.
16a9adc14900ca18e6909679a579f6833425e030vboxsync * @returns VBox status code.
16a9adc14900ca18e6909679a579f6833425e030vboxsync * @param pThis The driver instance data.
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync rc = VDGetOpenFlags(pThis->pDisk, VD_LAST_IMAGE, &uOpenFlags);
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync rc = VDSetOpenFlags(pThis->pDisk, VD_LAST_IMAGE, uOpenFlags);
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync * Undo the temporary read-only status of the image.
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync * @returns VBox status code.
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync * @param pThis The driver instance data.
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync rc = VDGetOpenFlags(pThis->pDisk, VD_LAST_IMAGE, &uOpenFlags);
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync rc = VDSetOpenFlags(pThis->pDisk, VD_LAST_IMAGE, uOpenFlags);
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync/*******************************************************************************
a9d49c8f2b28a72e6a4db86eee91e4569290157bvboxsync* Error reporting callback *
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync*******************************************************************************/
9496f2d398b49813176939d7a339ae513d5175efvboxsyncstatic void drvvdErrorCallback(void *pvUser, int rc, RT_SRC_POS_DECL,
59d7f5939d42ad9d344fbad8401e00a900db92c5vboxsync PVBOXDISK pThis = PDMINS_2_DATA(pDrvIns, PVBOXDISK);
22ec733a5e041fcdfe02fce2eafc9faf8b0077ddvboxsync /* We must not pass VMSETRTERR_FLAGS_FATAL as it could lead to a
9496f2d398b49813176939d7a339ae513d5175efvboxsync * 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 ... */
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync PDMDrvHlpVMSetRuntimeErrorV(pDrvIns, /* fFlags=*/ 0, "DrvVD", pszFormat, va);
7766bf675357fd940d8c49e69a5d72dc6eaa6be4vboxsync PDMDrvHlpVMSetErrorV(pDrvIns, rc, RT_SRC_POS_ARGS, pszFormat, va);
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync/*******************************************************************************
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync* VD Async I/O interface implementation *
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync*******************************************************************************/
d5ea45cc92d7f1d3ade8189944531f665bfe8ed5vboxsyncstatic DECLCALLBACK(void) drvvdAsyncTaskCompleted(PPDMDRVINS pDrvIns, void *pvTemplateUser, void *pvUser, int rcReq)
5d0d754550d06b7d59a935e59caaf814462d53ccvboxsync PVBOXDISK pThis = PDMINS_2_DATA(pDrvIns, PVBOXDISK);
bbede9c189def47a9880f0ffb03c0c230c774185vboxsync PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)pvTemplateUser;
bbede9c189def47a9880f0ffb03c0c230c774185vboxsync LogFlowFunc(("pDrvIns=%#p pvTemplateUser=%#p pvUser=%#p rcReq\n",
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsyncstatic DECLCALLBACK(int) drvvdAsyncIOOpen(void *pvUser, const char *pszLocation,
bbede9c189def47a9880f0ffb03c0c230c774185vboxsync PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)RTMemAllocZ(sizeof(DRVVDSTORAGEBACKEND));
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync pStorageBackend->pInterfaceThreadSyncCallbacks = NULL;
5d0d754550d06b7d59a935e59caaf814462d53ccvboxsync 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 uint32_t fFlags = (fOpen & RTFILE_O_ACCESS_MASK) == RTFILE_O_READ
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync ? PDMACEP_FILE_FLAGS_READ_ONLY | PDMACEP_FILE_FLAGS_CACHING
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync Assert((fOpen & RTFILE_O_DENY_MASK) == RTFILE_O_DENY_NONE);
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync rc = PDMR3AsyncCompletionEpCreateForFile(&pStorageBackend->pEndpoint,
9496f2d398b49813176939d7a339ae513d5175efvboxsync PDMR3AsyncCompletionTemplateDestroy(pStorageBackend->pTemplate);
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsyncstatic DECLCALLBACK(int) drvvdAsyncIOClose(void *pvUser, void *pStorage)
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)pStorage;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync PDMR3AsyncCompletionEpClose(pStorageBackend->pEndpoint);
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync PDMR3AsyncCompletionTemplateDestroy(pStorageBackend->pTemplate);
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsyncstatic DECLCALLBACK(int) drvvdAsyncIOReadSync(void *pvUser, void *pStorage, uint64_t uOffset,
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)pStorage;
9496f2d398b49813176939d7a339ae513d5175efvboxsync ASMAtomicXchgBool(&pStorageBackend->fSyncIoPending, true);
9496f2d398b49813176939d7a339ae513d5175efvboxsync int rc = PDMR3AsyncCompletionEpRead(pStorageBackend->pEndpoint, uOffset, &DataSeg, 1, cbRead, NULL, &pTask);
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync rc = RTSemEventWait(pStorageBackend->EventSem, RT_INDEFINITE_WAIT);
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync ASMAtomicXchgBool(&pStorageBackend->fSyncIoPending, false);
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsyncstatic DECLCALLBACK(int) drvvdAsyncIOWriteSync(void *pvUser, void *pStorage, uint64_t uOffset,
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync const void *pvBuf, size_t cbWrite, size_t *pcbWritten)
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)pStorage;
9496f2d398b49813176939d7a339ae513d5175efvboxsync ASMAtomicXchgBool(&pStorageBackend->fSyncIoPending, true);
16a9adc14900ca18e6909679a579f6833425e030vboxsync int rc = PDMR3AsyncCompletionEpWrite(pStorageBackend->pEndpoint, uOffset, &DataSeg, 1, cbWrite, NULL, &pTask);
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync rc = RTSemEventWait(pStorageBackend->EventSem, RT_INDEFINITE_WAIT);
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync ASMAtomicXchgBool(&pStorageBackend->fSyncIoPending, false);
9496f2d398b49813176939d7a339ae513d5175efvboxsyncstatic DECLCALLBACK(int) drvvdAsyncIOFlushSync(void *pvUser, void *pStorage)
9496f2d398b49813176939d7a339ae513d5175efvboxsync PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)pStorage;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync LogFlowFunc(("pvUser=%#p pStorage=%#p\n", pvUser, pStorage));
16a9adc14900ca18e6909679a579f6833425e030vboxsync ASMAtomicXchgBool(&pStorageBackend->fSyncIoPending, true);
9496f2d398b49813176939d7a339ae513d5175efvboxsync int rc = PDMR3AsyncCompletionEpFlush(pStorageBackend->pEndpoint, NULL, &pTask);
9496f2d398b49813176939d7a339ae513d5175efvboxsync rc = RTSemEventWait(pStorageBackend->EventSem, RT_INDEFINITE_WAIT);
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync ASMAtomicXchgBool(&pStorageBackend->fSyncIoPending, false);
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsyncstatic DECLCALLBACK(int) drvvdAsyncIOReadAsync(void *pvUser, void *pStorage, uint64_t uOffset,
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)pStorage;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync int rc = PDMR3AsyncCompletionEpRead(pStorageBackend->pEndpoint, uOffset, paSegments, cSegments, cbRead,
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsyncstatic DECLCALLBACK(int) drvvdAsyncIOWriteAsync(void *pvUser, void *pStorage, uint64_t uOffset,
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsync PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)pStorage;
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsync int rc = PDMR3AsyncCompletionEpWrite(pStorageBackend->pEndpoint, uOffset, paSegments, cSegments, cbWrite,
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsyncstatic DECLCALLBACK(int) drvvdAsyncIOFlushAsync(void *pvUser, void *pStorage,
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsync PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)pStorage;
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsync int rc = PDMR3AsyncCompletionEpFlush(pStorageBackend->pEndpoint, pvCompletion,
16a9adc14900ca18e6909679a579f6833425e030vboxsyncstatic DECLCALLBACK(int) drvvdAsyncIOGetSize(void *pvUser, void *pStorage, uint64_t *pcbSize)
16a9adc14900ca18e6909679a579f6833425e030vboxsync PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)pStorage;
16a9adc14900ca18e6909679a579f6833425e030vboxsync return PDMR3AsyncCompletionEpGetSize(pStorageBackend->pEndpoint, pcbSize);
16a9adc14900ca18e6909679a579f6833425e030vboxsyncstatic DECLCALLBACK(int) drvvdAsyncIOSetSize(void *pvUser, void *pStorage, uint64_t cbSize)
16a9adc14900ca18e6909679a579f6833425e030vboxsync PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)pStorage;
16a9adc14900ca18e6909679a579f6833425e030vboxsync rc = PDMR3AsyncCompletionEpSetSize(pStorageBackend->pEndpoint, cbSize);
16a9adc14900ca18e6909679a579f6833425e030vboxsync#endif /* VBOX_WITH_PDM_ASYNC_COMPLETION */
16a9adc14900ca18e6909679a579f6833425e030vboxsync/*******************************************************************************
16a9adc14900ca18e6909679a579f6833425e030vboxsync* VD Thread Synchronization interface implementation *
16a9adc14900ca18e6909679a579f6833425e030vboxsync*******************************************************************************/
16a9adc14900ca18e6909679a579f6833425e030vboxsyncstatic DECLCALLBACK(int) drvvdThreadStartRead(void *pvUser)
16a9adc14900ca18e6909679a579f6833425e030vboxsync return RTSemRWRequestRead(pThis->MergeLock, RT_INDEFINITE_WAIT);
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsyncstatic DECLCALLBACK(int) drvvdThreadFinishRead(void *pvUser)
975ad9d9bc9c4dc96b41d9f67a65228b1b338e2avboxsyncstatic DECLCALLBACK(int) drvvdThreadStartWrite(void *pvUser)
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync return RTSemRWRequestWrite(pThis->MergeLock, RT_INDEFINITE_WAIT);
975ad9d9bc9c4dc96b41d9f67a65228b1b338e2avboxsyncstatic 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*******************************************************************************/
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsynctypedef struct INIPSOCKET
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsyncstatic DECLCALLBACK(int) drvvdINIPFlush(VDSOCKET Sock);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync/** @copydoc VDINTERFACETCPNET::pfnSocketCreate */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsyncstatic DECLCALLBACK(int) drvvdINIPSocketCreate(uint32_t fFlags, PVDSOCKET pSock)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync * The extended select method is not supported because it is impossible to wakeup
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync * the thread.
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync if (fFlags & VD_INTERFACETCPNET_CONNECT_EXTENDED_SELECT)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync pSocketInt = (PINIPSOCKET)RTMemAllocZ(sizeof(INIPSOCKET));
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync/** @copydoc VDINTERFACETCPNET::pfnSocketCreate */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsyncstatic DECLCALLBACK(int) drvvdINIPSocketDestroy(VDSOCKET Sock)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync/** @copydoc VDINTERFACETCPNET::pfnClientConnect */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsyncstatic DECLCALLBACK(int) drvvdINIPClientConnect(VDSOCKET Sock, const char *pszAddress, uint32_t uPort)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync /* Check whether lwIP is set up in this VM instance. */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync /* Resolve hostname. As there is no standard resolver for lwIP yet,
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync * just accept numeric IP addresses for now. */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync LogRelFunc(("cannot resolve IP %s\n", pszAddress));
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync /* Create socket and connect. */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync if (!lwip_connect(iSock, (struct sockaddr *)&InAddr, sizeof(InAddr)))
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync rc = VERR_NET_CONNECTION_REFUSED; /* @todo real solution needed */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync rc = VERR_NET_CONNECTION_REFUSED; /* @todo real solution needed */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync/** @copydoc VDINTERFACETCPNET::pfnClientClose */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsyncstatic DECLCALLBACK(int) drvvdINIPClientClose(VDSOCKET Sock)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync return VINF_SUCCESS; /** @todo real solution needed */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync/** @copydoc VDINTERFACETCPNET::pfnIsClientConnected */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsyncstatic DECLCALLBACK(bool) drvvdINIPIsClientConnected(VDSOCKET Sock)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync/** @copydoc VDINTERFACETCPNET::pfnSelectOne */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsyncstatic DECLCALLBACK(int) drvvdINIPSelectOne(VDSOCKET Sock, RTMSINTERVAL cMillies)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync rc = lwip_select(pSocketInt->hSock + 1, &fdsetR, NULL, &fdsetE, NULL);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync rc = lwip_select(pSocketInt->hSock + 1, &fdsetR, NULL, &fdsetE, &timeout);
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync return VERR_NET_CONNECTION_REFUSED; /** @todo real solution needed */
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync/** @copydoc VDINTERFACETCPNET::pfnRead */
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsyncstatic DECLCALLBACK(int) drvvdINIPRead(VDSOCKET Sock, void *pvBuffer, size_t cbBuffer, size_t *pcbRead)
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync /* Do params checking */
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync * Read loop.
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync * If pcbRead is NULL we have to fill the entire buffer!
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync /** @todo this clipping here is just in case (the send function
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync * needed it, so I added it here, too). Didn't investigate if this
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync * really has issues. Better be safe than sorry. */
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync ssize_t cbBytesRead = lwip_recv(pSocketInt->hSock, (char *)pvBuffer + cbRead,
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync return VERR_NET_CONNECTION_REFUSED; /** @todo real solution */
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync if (cbBytesRead == 0 && errno) /** @todo r=bird: lwip_recv will not touch errno on Windows. This may apply to other hosts as well */
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync return VERR_NET_CONNECTION_REFUSED; /** @todo real solution */
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync /* return partial data */
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync /* read more? */
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync/** @copydoc VDINTERFACETCPNET::pfnWrite */
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsyncstatic DECLCALLBACK(int) drvvdINIPWrite(VDSOCKET Sock, const void *pvBuffer, size_t cbBuffer)
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync /** @todo lwip send only supports up to 65535 bytes in a single
efff36b306e370346025647a158689021df2e1d1vboxsync * send (stupid limitation buried in the code), so make sure we
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync * don't get any wraparounds. This should be moved to DevINIP
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync * stack interface once that's implemented. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync ssize_t cbWritten = lwip_send(pSocketInt->hSock, (void *)pvBuffer,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync return VERR_NET_CONNECTION_REFUSED; /** @todo real solution needed */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync AssertMsg(cbBuffer >= (size_t)cbWritten, ("Wrote more than we requested!!! cbWritten=%d cbBuffer=%d\n",
ff88d4153cd65650577e8c2d1a5a3fdfa0404a80vboxsync/** @copydoc VDINTERFACETCPNET::pfnSgWrite */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic DECLCALLBACK(int) drvvdINIPSgWrite(VDSOCKET Sock, PCRTSGBUF pSgBuf)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* This is an extremely crude emulation, however it's good enough
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * for our iSCSI code. INIP has no sendmsg(). */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/** @copydoc VDINTERFACETCPNET::pfnFlush */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic DECLCALLBACK(int) drvvdINIPFlush(VDSOCKET Sock)
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync lwip_setsockopt(pSocketInt->hSock, IPPROTO_TCP, TCP_NODELAY,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync lwip_setsockopt(pSocketInt->hSock, IPPROTO_TCP, TCP_NODELAY,
16a9adc14900ca18e6909679a579f6833425e030vboxsync/** @copydoc VDINTERFACETCPNET::pfnSetSendCoalescing */
16a9adc14900ca18e6909679a579f6833425e030vboxsyncstatic DECLCALLBACK(int) drvvdINIPSetSendCoalescing(VDSOCKET Sock, bool fEnable)
16a9adc14900ca18e6909679a579f6833425e030vboxsync lwip_setsockopt(pSocketInt->hSock, IPPROTO_TCP, TCP_NODELAY,
16a9adc14900ca18e6909679a579f6833425e030vboxsync/** @copydoc VDINTERFACETCPNET::pfnGetLocalAddress */
16a9adc14900ca18e6909679a579f6833425e030vboxsyncstatic DECLCALLBACK(int) drvvdINIPGetLocalAddress(VDSOCKET Sock, PRTNETADDR pAddr)
16a9adc14900ca18e6909679a579f6833425e030vboxsync if (!lwip_getsockname(pSocketInt->hSock, &u.Addr, &cbAddr))
16a9adc14900ca18e6909679a579f6833425e030vboxsync * Convert the address.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/** @copydoc VDINTERFACETCPNET::pfnGetPeerAddress */
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsyncstatic DECLCALLBACK(int) drvvdINIPGetPeerAddress(VDSOCKET Sock, PRTNETADDR pAddr)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync if (!lwip_getpeername(pSocketInt->hSock, &u.Addr, &cbAddr))
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * Convert the address.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/** @copydoc VDINTERFACETCPNET::pfnSelectOneEx */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic DECLCALLBACK(int) drvvdINIPSelectOneEx(VDSOCKET Sock, uint32_t fEvents, uint32_t *pfEvents, RTMSINTERVAL cMillies)
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync/** @copydoc VDINTERFACETCPNET::pfnPoke */
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsyncstatic DECLCALLBACK(int) drvvdINIPPoke(VDSOCKET Sock)
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync#endif /* VBOX_WITH_INIP */
fe813b3594039ba864493438e78ee0e7132bc445vboxsync/*******************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync* VD TCP network stack interface implementation - Host TCP case *
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync*******************************************************************************/
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync * Socket data.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsynctypedef struct VDSOCKETINT
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync /** IPRT socket handle. */
b7a5b3f9f9ecce32ddacf8404c625ce0451bbdc1vboxsync /** Pollset with the wakeup pipe and socket. */
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync /** Pipe endpoint - read (in the pollset). */
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync /** Pipe endpoint - write. */
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync /** Flag whether the thread was woken up. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync volatile bool fWokenUp;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /** Flag whether the thread is waiting in the select call. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync volatile bool fWaiting;
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync /** Old event mask. */
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync/** Pollset id of the socket. */
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync/** Pollset id of the pipe. */
e04eeee1b306d610b0441cee9bf1c750100254d5vboxsync/** @copydoc VDINTERFACETCPNET::pfnSocketCreate */
fe813b3594039ba864493438e78ee0e7132bc445vboxsyncstatic DECLCALLBACK(int) drvvdTcpSocketCreate(uint32_t fFlags, PVDSOCKET pSock)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pSockInt = (PVDSOCKETINT)RTMemAllocZ(sizeof(VDSOCKETINT));
9496f2d398b49813176939d7a339ae513d5175efvboxsync if (fFlags & VD_INTERFACETCPNET_CONNECT_EXTENDED_SELECT)
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync /* Init pipe and pollset. */
7a3f491705173bc08122f2c7d26d48a8b4c5ceecvboxsync rc = RTPipeCreate(&pSockInt->hPipeR, &pSockInt->hPipeW, 0);
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync rc = RTPollSetAddPipe(pSockInt->hPollSet, pSockInt->hPipeR,
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync RTPollSetRemove(pSockInt->hPollSet, VDSOCKET_POLL_ID_PIPE);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/** @copydoc VDINTERFACETCPNET::pfnSocketDestroy */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic DECLCALLBACK(int) drvvdTcpSocketDestroy(VDSOCKET Sock)
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync /* Destroy the pipe and pollset if necessary. */
da3503c04ce76e653401396fe2795a9bc2427a1dvboxsync rc = RTPollSetRemove(pSockInt->hPollSet, VDSOCKET_POLL_ID_SOCKET);
da3503c04ce76e653401396fe2795a9bc2427a1dvboxsync Assert(RT_SUCCESS(rc) || rc == VERR_POLL_HANDLE_ID_NOT_FOUND);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync rc = RTPollSetRemove(pSockInt->hPollSet, VDSOCKET_POLL_ID_PIPE);
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync/** @copydoc VDINTERFACETCPNET::pfnClientConnect */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsyncstatic DECLCALLBACK(int) drvvdTcpClientConnect(VDSOCKET Sock, const char *pszAddress, uint32_t uPort)
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync rc = RTTcpClientConnect(pszAddress, uPort, &pSockInt->hSocket);
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync /* Add to the pollset if required. */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pSockInt->fEventsOld = RTPOLL_EVT_READ | RTPOLL_EVT_WRITE | RTPOLL_EVT_ERROR;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync rc = RTPollSetAddSocket(pSockInt->hPollSet, pSockInt->hSocket,
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync/** @copydoc VDINTERFACETCPNET::pfnClientClose */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsyncstatic DECLCALLBACK(int) drvvdTcpClientClose(VDSOCKET Sock)
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync rc = RTPollSetRemove(pSockInt->hPollSet, VDSOCKET_POLL_ID_SOCKET);
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync/** @copydoc VDINTERFACETCPNET::pfnIsClientConnected */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsyncstatic DECLCALLBACK(bool) drvvdTcpIsClientConnected(VDSOCKET Sock)
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync/** @copydoc VDINTERFACETCPNET::pfnSelectOne */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsyncstatic DECLCALLBACK(int) drvvdTcpSelectOne(VDSOCKET Sock, RTMSINTERVAL cMillies)
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync return RTTcpSelectOne(pSockInt->hSocket, cMillies);
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync/** @copydoc VDINTERFACETCPNET::pfnRead */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsyncstatic DECLCALLBACK(int) drvvdTcpRead(VDSOCKET Sock, void *pvBuffer, size_t cbBuffer, size_t *pcbRead)
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync return RTTcpRead(pSockInt->hSocket, pvBuffer, cbBuffer, pcbRead);
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync/** @copydoc VDINTERFACETCPNET::pfnWrite */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsyncstatic DECLCALLBACK(int) drvvdTcpWrite(VDSOCKET Sock, const void *pvBuffer, size_t cbBuffer)
16a9adc14900ca18e6909679a579f6833425e030vboxsync return RTTcpWrite(pSockInt->hSocket, pvBuffer, cbBuffer);
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync/** @copydoc VDINTERFACETCPNET::pfnSgWrite */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsyncstatic DECLCALLBACK(int) drvvdTcpSgWrite(VDSOCKET Sock, PCRTSGBUF pSgBuf)
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync/** @copydoc VDINTERFACETCPNET::pfnReadNB */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsyncstatic DECLCALLBACK(int) drvvdTcpReadNB(VDSOCKET Sock, void *pvBuffer, size_t cbBuffer, size_t *pcbRead)
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync return RTTcpReadNB(pSockInt->hSocket, pvBuffer, cbBuffer, pcbRead);
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync/** @copydoc VDINTERFACETCPNET::pfnWriteNB */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsyncstatic DECLCALLBACK(int) drvvdTcpWriteNB(VDSOCKET Sock, const void *pvBuffer, size_t cbBuffer, size_t *pcbWritten)
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync return RTTcpWriteNB(pSockInt->hSocket, pvBuffer, cbBuffer, pcbWritten);
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync/** @copydoc VDINTERFACETCPNET::pfnSgWriteNB */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsyncstatic DECLCALLBACK(int) drvvdTcpSgWriteNB(VDSOCKET Sock, PRTSGBUF pSgBuf, size_t *pcbWritten)
16a9adc14900ca18e6909679a579f6833425e030vboxsync return RTTcpSgWriteNB(pSockInt->hSocket, pSgBuf, pcbWritten);
16a9adc14900ca18e6909679a579f6833425e030vboxsync/** @copydoc VDINTERFACETCPNET::pfnFlush */
16a9adc14900ca18e6909679a579f6833425e030vboxsyncstatic DECLCALLBACK(int) drvvdTcpFlush(VDSOCKET Sock)
16a9adc14900ca18e6909679a579f6833425e030vboxsync/** @copydoc VDINTERFACETCPNET::pfnSetSendCoalescing */
16a9adc14900ca18e6909679a579f6833425e030vboxsyncstatic DECLCALLBACK(int) drvvdTcpSetSendCoalescing(VDSOCKET Sock, bool fEnable)
16a9adc14900ca18e6909679a579f6833425e030vboxsync return RTTcpSetSendCoalescing(pSockInt->hSocket, fEnable);
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync/** @copydoc VDINTERFACETCPNET::pfnGetLocalAddress */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsyncstatic DECLCALLBACK(int) drvvdTcpGetLocalAddress(VDSOCKET Sock, PRTNETADDR pAddr)
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync return RTTcpGetLocalAddress(pSockInt->hSocket, pAddr);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/** @copydoc VDINTERFACETCPNET::pfnGetPeerAddress */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic DECLCALLBACK(int) drvvdTcpGetPeerAddress(VDSOCKET Sock, PRTNETADDR pAddr)
c28fa006ba669ad8f26ae31d00a338379c04ea1bvboxsync return RTTcpGetPeerAddress(pSockInt->hSocket, pAddr);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic int drvvdTcpSelectOneExPoll(VDSOCKET Sock, uint32_t fEvents,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync rc = RTPollSetEventsChange(pSockInt->hPollSet, VDSOCKET_POLL_ID_SOCKET, fPollEvents);
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync rc = RTPoll(pSockInt->hPollSet, cMillies, &fEventsRecv, &id);
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync Assert((fEventsRecv & RTPOLL_EVT_VALID_MASK) == RTPOLL_EVT_READ);
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync /* We got interrupted, drain the pipe. */
9496f2d398b49813176939d7a339ae513d5175efvboxsync rc = RTPipeRead(pSockInt->hPipeR, abBuf, sizeof(abBuf), &cbRead);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/** @copydoc VDINTERFACETCPNET::pfnSelectOneEx */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic DECLCALLBACK(int) drvvdTcpSelectOneExNoPoll(VDSOCKET Sock, uint32_t fEvents,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * Only the pipe is configured or the caller doesn't wait for a socket event,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * wait until there is something to read from the pipe.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync rc = RTPipeReadBlocking(pSockInt->hPipeR, &ch, 1, &cbRead);
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync /* Make sure the socket is not in the pollset. */
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync rc = RTPollSetRemove(pSockInt->hPollSet, VDSOCKET_POLL_ID_SOCKET);
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync Assert(RT_SUCCESS(rc) || rc == VERR_POLL_HANDLE_ID_NOT_FOUND);
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync /* Check the socket. */
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync rc = RTTcpSelectOneEx(pSockInt->hSocket, fSelectEvents, &fEventsRecv, 0);
27b178e99b06a68ef52353b15bc647674d2006bcvboxsync break; /* Quit */
16a9adc14900ca18e6909679a579f6833425e030vboxsync Assert((fEventsRecv & RTPOLL_EVT_VALID_MASK) == RTPOLL_EVT_READ);
16a9adc14900ca18e6909679a579f6833425e030vboxsync /* We got interrupted, drain the pipe. */
16a9adc14900ca18e6909679a579f6833425e030vboxsync rc = RTPipeRead(pSockInt->hPipeR, abBuf, sizeof(abBuf), &cbRead);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync else /* The caller waits for a socket event. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* Loop until we got woken up or a socket event occurred. */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync /** @todo find an adaptive wait algorithm based on the
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync * number of wakeups in the past. */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync rc = RTTcpSelectOneEx(pSockInt->hSocket, fSelectEvents, &fEventsRecv, 5);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync /* Check if there is an event pending. */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync rc = RTPipeRead(pSockInt->hPipeR, &ch, 1, &cbRead);
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync break; /* Quit */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync break; /* Quit */
a3369a746b56a8966dd78619f4d191c9662f400dvboxsync/** @copydoc VDINTERFACETCPNET::pfnPoke */
27b178e99b06a68ef52353b15bc647674d2006bcvboxsyncstatic DECLCALLBACK(int) drvvdTcpPoke(VDSOCKET Sock)
27b178e99b06a68ef52353b15bc647674d2006bcvboxsync rc = RTPipeWrite(pSockInt->hPipeW, "", 1, &cbWritten);
27b178e99b06a68ef52353b15bc647674d2006bcvboxsync/*******************************************************************************
27b178e99b06a68ef52353b15bc647674d2006bcvboxsync* Media interface methods *
27b178e99b06a68ef52353b15bc647674d2006bcvboxsync*******************************************************************************/
27b178e99b06a68ef52353b15bc647674d2006bcvboxsync/** @copydoc PDMIMEDIA::pfnRead */
27b178e99b06a68ef52353b15bc647674d2006bcvboxsyncstatic DECLCALLBACK(int) drvvdRead(PPDMIMEDIA pInterface,
16a9adc14900ca18e6909679a579f6833425e030vboxsync LogFlowFunc(("off=%#llx pvBuf=%p cbRead=%d\n", off, pvBuf, cbRead));
16a9adc14900ca18e6909679a579f6833425e030vboxsync PVBOXDISK pThis = PDMIMEDIA_2_VBOXDISK(pInterface);
16a9adc14900ca18e6909679a579f6833425e030vboxsync /* Can we serve the request from the buffer? */
16a9adc14900ca18e6909679a579f6833425e030vboxsync size_t cbToCopy = RT_MIN(cbRead, pThis->offDisk + pThis->cbDataValid - off);
16a9adc14900ca18e6909679a579f6833425e030vboxsync memcpy(pvBuf, pThis->pbData + (off - pThis->offDisk), cbToCopy);
a3369a746b56a8966dd78619f4d191c9662f400dvboxsync /* Increase request to the buffer size and read. */
a3369a746b56a8966dd78619f4d191c9662f400dvboxsync pThis->cbDataValid = RT_MIN(pThis->cbDisk - off, pThis->cbBootAccelBuffer);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync rc = VDRead(pThis->pDisk, off, pThis->pbData, pThis->cbDataValid);
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync Log2(("%s: off=%#llx pvBuf=%p cbRead=%d %.*Rhxd\n", __FUNCTION__,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/** @copydoc PDMIMEDIA::pfnWrite */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic DECLCALLBACK(int) drvvdWrite(PPDMIMEDIA pInterface,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync LogFlowFunc(("off=%#llx pvBuf=%p cbWrite=%d\n", off, pvBuf, cbWrite));
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync PVBOXDISK pThis = PDMIMEDIA_2_VBOXDISK(pInterface);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync Log2(("%s: off=%#llx pvBuf=%p cbWrite=%d %.*Rhxd\n", __FUNCTION__,
b7a5b3f9f9ecce32ddacf8404c625ce0451bbdc1vboxsync /* Invalidate any buffer if boot acceleration is enabled. */
16a9adc14900ca18e6909679a579f6833425e030vboxsync int rc = VDWrite(pThis->pDisk, off, pvBuf, cbWrite);
16a9adc14900ca18e6909679a579f6833425e030vboxsync/** @copydoc PDMIMEDIA::pfnFlush */
16a9adc14900ca18e6909679a579f6833425e030vboxsyncstatic DECLCALLBACK(int) drvvdFlush(PPDMIMEDIA pInterface)
16a9adc14900ca18e6909679a579f6833425e030vboxsync PVBOXDISK pThis = PDMIMEDIA_2_VBOXDISK(pInterface);
16a9adc14900ca18e6909679a579f6833425e030vboxsync/** @copydoc PDMIMEDIA::pfnMerge */
16a9adc14900ca18e6909679a579f6833425e030vboxsyncstatic DECLCALLBACK(int) drvvdMerge(PPDMIMEDIA pInterface,
16a9adc14900ca18e6909679a579f6833425e030vboxsync PVBOXDISK pThis = PDMIMEDIA_2_VBOXDISK(pInterface);
16a9adc14900ca18e6909679a579f6833425e030vboxsync /* Note: There is an unavoidable race between destruction and another
16a9adc14900ca18e6909679a579f6833425e030vboxsync * thread invoking this function. This is handled safely and gracefully by
16a9adc14900ca18e6909679a579f6833425e030vboxsync * atomically invalidating the lock handle in drvvdDestruct. */
16a9adc14900ca18e6909679a579f6833425e030vboxsync int rc2 = RTSemFastMutexRequest(pThis->MergeCompleteMutex);
16a9adc14900ca18e6909679a579f6833425e030vboxsync /* Take shortcut: PFNSIMPLEPROGRESS is exactly the same type as
16a9adc14900ca18e6909679a579f6833425e030vboxsync * PFNVDPROGRESS, so there's no need for a conversion function. */
16a9adc14900ca18e6909679a579f6833425e030vboxsync /** @todo maybe introduce a conversion which limits update frequency. */
16a9adc14900ca18e6909679a579f6833425e030vboxsync VDIProgressCallbacks.cbSize = sizeof(VDINTERFACEPROGRESS);
16a9adc14900ca18e6909679a579f6833425e030vboxsync VDIProgressCallbacks.enmInterface = VDINTERFACETYPE_PROGRESS;
670b83d458bceb92123155b5b47a39b9d24e3266vboxsync rc2 = VDInterfaceAdd(&VDIProgress, "DrvVD_VDIProgress", VDINTERFACETYPE_PROGRESS,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync rc2 = RTSemFastMutexRelease(pThis->MergeCompleteMutex);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/** @copydoc PDMIMEDIA::pfnGetSize */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic DECLCALLBACK(uint64_t) drvvdGetSize(PPDMIMEDIA pInterface)
9496f2d398b49813176939d7a339ae513d5175efvboxsync PVBOXDISK pThis = PDMIMEDIA_2_VBOXDISK(pInterface);
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync uint64_t cb = VDGetSize(pThis->pDisk, VD_LAST_IMAGE);
9496f2d398b49813176939d7a339ae513d5175efvboxsync/** @copydoc PDMIMEDIA::pfnIsReadOnly */
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsyncstatic DECLCALLBACK(bool) drvvdIsReadOnly(PPDMIMEDIA pInterface)
b7a5b3f9f9ecce32ddacf8404c625ce0451bbdc1vboxsync PVBOXDISK pThis = PDMIMEDIA_2_VBOXDISK(pInterface);
d1bffa158f98ff3c18f7d085e7372c9ea00e9a43vboxsync/** @copydoc PDMIMEDIA::pfnBiosGetPCHSGeometry */
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsyncstatic DECLCALLBACK(int) drvvdBiosGetPCHSGeometry(PPDMIMEDIA pInterface,
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync PVBOXDISK pThis = PDMIMEDIA_2_VBOXDISK(pInterface);
6b223679d40f5e57e55e867e806a9f194e2cde12vboxsync int rc = VDGetPCHSGeometry(pThis->pDisk, VD_LAST_IMAGE, &geo);
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync rc, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors));
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/** @copydoc PDMIMEDIA::pfnBiosSetPCHSGeometry */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic DECLCALLBACK(int) drvvdBiosSetPCHSGeometry(PPDMIMEDIA pInterface,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors));
16a9adc14900ca18e6909679a579f6833425e030vboxsync PVBOXDISK pThis = PDMIMEDIA_2_VBOXDISK(pInterface);
16a9adc14900ca18e6909679a579f6833425e030vboxsync int rc = VDSetPCHSGeometry(pThis->pDisk, VD_LAST_IMAGE, &geo);
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync/** @copydoc PDMIMEDIA::pfnBiosGetLCHSGeometry */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsyncstatic DECLCALLBACK(int) drvvdBiosGetLCHSGeometry(PPDMIMEDIA pInterface,
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync PVBOXDISK pThis = PDMIMEDIA_2_VBOXDISK(pInterface);
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync int rc = VDGetLCHSGeometry(pThis->pDisk, VD_LAST_IMAGE, &geo);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync rc, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors));
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/** @copydoc PDMIMEDIA::pfnBiosSetLCHSGeometry */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic DECLCALLBACK(int) drvvdBiosSetLCHSGeometry(PPDMIMEDIA pInterface,
09127e6ed46502ff8a6a521713ee8ace53667683vboxsync pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors));
ad77e3ec3cde24263bc7537575f5cae442bee3b1vboxsync PVBOXDISK pThis = PDMIMEDIA_2_VBOXDISK(pInterface);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync int rc = VDSetLCHSGeometry(pThis->pDisk, VD_LAST_IMAGE, &geo);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/** @copydoc PDMIMEDIA::pfnGetUuid */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic DECLCALLBACK(int) drvvdGetUuid(PPDMIMEDIA pInterface, PRTUUID pUuid)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync PVBOXDISK pThis = PDMIMEDIA_2_VBOXDISK(pInterface);
ad77e3ec3cde24263bc7537575f5cae442bee3b1vboxsync LogFlowFunc(("returns %Rrc ({%RTuuid})\n", rc, pUuid));
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/*******************************************************************************
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync* Async Media interface methods *
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync*******************************************************************************/
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic void drvvdAsyncReqComplete(void *pvUser1, void *pvUser2, int rcReq)
cba6719bd64ec749967bbe931230452664109857vboxsync int rc = pThis->pDrvMediaAsyncPort->pfnTransferCompleteNotify(pThis->pDrvMediaAsyncPort,
cba6719bd64ec749967bbe931230452664109857vboxsyncstatic DECLCALLBACK(int) drvvdStartRead(PPDMIMEDIAASYNC pInterface, uint64_t uOffset,
cba6719bd64ec749967bbe931230452664109857vboxsync LogFlowFunc(("uOffset=%#llx paSeg=%#p cSeg=%u cbRead=%d\n pvUser=%#p",
cba6719bd64ec749967bbe931230452664109857vboxsync PVBOXDISK pThis = PDMIMEDIAASYNC_2_VBOXDISK(pInterface);
return rc;
return rc;
return rc;
PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIAASYNC, pThis->fAsyncIOSupported ? &pThis->IMediaAsync : NULL);
return NULL;
return VINF_SUCCESS;
return VINF_SUCCESS;
bool fHostIP = false;
bool fUseNewIo = false;
unsigned iLevel = 0;
bool fValid;
if (!fValid)
rc = CFGMR3QueryU32Def(pCurNode, "BootAccelerationBuffer", (uint32_t *)&pThis->cbBootAccelBuffer, 16 * _1K);
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
&& !fMaybeReadOnly
&& iLevel == 0)
pszName);
iLevel--;
iImageIdx++;
return rc;
sizeof(VBOXDISK),
NULL,
NULL,
NULL,
NULL,
NULL,