DrvVD.cpp revision 9daee41d5cb5a2e8390f015a486e67a6cd52b836
77b1a2d8b5dbe2c0b5200794914239fee3c8ee5dvboxsync * DrvVD - Generic VBox disk media driver.
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * Copyright (C) 2006-2010 Oracle Corporation
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * available from http://www.virtualbox.org. This file is free software;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * you can redistribute it and/or modify it under the terms of the GNU
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * General Public License (GPL) as published by the Free Software
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync/*******************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync* Header files *
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync*******************************************************************************/
590bfe12ce22cd3716448fbb9f4dc51664bfe5e2vboxsync/* 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 VBOXDISK::IMediaAsync to a PVBOXDISK. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync ( (PVBOXDISK)((uintptr_t)pInterface - RT_OFFSETOF(VBOXDISK, IMediaAsync)) )
0abd77741a608f6c41c8dfcd4781b8b84adf1044vboxsync * VBox disk container, image information, private part.
9496f2d398b49813176939d7a339ae513d5175efvboxsynctypedef struct VBOXIMAGE
9496f2d398b49813176939d7a339ae513d5175efvboxsync /** Pointer to next image. */
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync /** Pointer to list of VD interfaces. Per-image. */
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync /** Configuration information interface. */
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync /** TCP network stack interface. */
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync /** I/O interface. */
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync * Storage backend data.
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync /** PDM async completion end point. */
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync /** The template. */
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync /** Event semaphore for synchronous operations. */
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync /** Flag whether a synchronous operation is currently pending. */
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync volatile bool fSyncIoPending;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync /** Return code of the last completed request. */
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync /** Callback routine */
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 /** Media port. */
9496f2d398b49813176939d7a339ae513d5175efvboxsync /** Pointer to the driver instance. */
9496f2d398b49813176939d7a339ae513d5175efvboxsync /** Flag whether suspend has changed image open mode to read only. */
21029597fc4b76d0db0c9542daee201447281781vboxsync /** Flag whether to use the runtime (true) or startup error facility. */
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync /** Pointer to list of VD interfaces. Per-disk. */
9496f2d398b49813176939d7a339ae513d5175efvboxsync /** Error interface. */
9496f2d398b49813176939d7a339ae513d5175efvboxsync /** Thread synchronization interface. */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync /** Flag whether opened disk supports async I/O operations. */
9496f2d398b49813176939d7a339ae513d5175efvboxsync /** The async media interface. */
9496f2d398b49813176939d7a339ae513d5175efvboxsync /** The async media port interface above. */
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync /** Pointer to the list of data we need to keep per image. */
9496f2d398b49813176939d7a339ae513d5175efvboxsync /** Flag whether the media should allow concurrent open for writing. */
9496f2d398b49813176939d7a339ae513d5175efvboxsync /** Flag whether a merge operation has been set up. */
9496f2d398b49813176939d7a339ae513d5175efvboxsync /** Synchronization to prevent destruction before merge finishes. */
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync /** Synchronization between merge and other image accesses. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /** Source image index for merging. */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync /** Target image index for merging. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /** Flag whether boot acceleration is enabled. */
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync /** Flag whether boot acceleration is currently active. */
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync /** 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 /** Bandwidth group the disk is assigned to. */
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync /** Flag whether async I/O using the host cache is enabled. */
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync /** I/O interface for a cache image. */
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync /** Interface list for the cache image. */
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync /** The block cache handle if configured. */
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync/*******************************************************************************
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync* Internal Functions *
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync*******************************************************************************/
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync * Internal: allocate new image descriptor and put it in the list
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync PVBOXIMAGE pImage = (PVBOXIMAGE)RTMemAllocZ(sizeof(VBOXIMAGE));
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync * Internal: free the list of images descriptors.
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync * Make the image temporarily read-only.
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync * @returns VBox status code.
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync * @param pThis The driver instance data.
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync rc = VDGetOpenFlags(pThis->pDisk, VD_LAST_IMAGE, &uOpenFlags);
9496f2d398b49813176939d7a339ae513d5175efvboxsync rc = VDSetOpenFlags(pThis->pDisk, VD_LAST_IMAGE, uOpenFlags);
9496f2d398b49813176939d7a339ae513d5175efvboxsync * Undo the temporary read-only status of the image.
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync * @returns VBox status code.
5d0d754550d06b7d59a935e59caaf814462d53ccvboxsync * @param pThis The driver instance data.
5d0d754550d06b7d59a935e59caaf814462d53ccvboxsync rc = VDGetOpenFlags(pThis->pDisk, VD_LAST_IMAGE, &uOpenFlags);
5d0d754550d06b7d59a935e59caaf814462d53ccvboxsync rc = VDSetOpenFlags(pThis->pDisk, VD_LAST_IMAGE, uOpenFlags);
9496f2d398b49813176939d7a339ae513d5175efvboxsync/*******************************************************************************
9496f2d398b49813176939d7a339ae513d5175efvboxsync* Error reporting callback *
5d0d754550d06b7d59a935e59caaf814462d53ccvboxsync*******************************************************************************/
9496f2d398b49813176939d7a339ae513d5175efvboxsyncstatic void drvvdErrorCallback(void *pvUser, int rc, RT_SRC_POS_DECL,
9496f2d398b49813176939d7a339ae513d5175efvboxsync PVBOXDISK pThis = PDMINS_2_DATA(pDrvIns, PVBOXDISK);
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync /* We must not pass VMSETRTERR_FLAGS_FATAL as it could lead to a
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync * deadlock: We are probably executed in a thread context != EMT
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync * and the EM thread would wait until every thread is suspended
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync * but we would wait for the EM thread ... */
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync PDMDrvHlpVMSetRuntimeErrorV(pDrvIns, /* fFlags=*/ 0, "DrvVD", pszFormat, va);
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync PDMDrvHlpVMSetErrorV(pDrvIns, rc, RT_SRC_POS_ARGS, pszFormat, va);
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync/*******************************************************************************
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync* VD Async I/O interface implementation *
5d0d754550d06b7d59a935e59caaf814462d53ccvboxsync*******************************************************************************/
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsyncstatic DECLCALLBACK(void) drvvdAsyncTaskCompleted(PPDMDRVINS pDrvIns, void *pvTemplateUser, void *pvUser, int rcReq)
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync PVBOXDISK pThis = PDMINS_2_DATA(pDrvIns, PVBOXDISK);
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)pvTemplateUser;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync LogFlowFunc(("pDrvIns=%#p pvTemplateUser=%#p pvUser=%#p rcReq=%d\n",
9496f2d398b49813176939d7a339ae513d5175efvboxsyncstatic DECLCALLBACK(int) drvvdAsyncIOOpen(void *pvUser, const char *pszLocation,
9496f2d398b49813176939d7a339ae513d5175efvboxsync PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)RTMemAllocZ(sizeof(DRVVDSTORAGEBACKEND));
5d0d754550d06b7d59a935e59caaf814462d53ccvboxsync rc = PDMDrvHlpAsyncCompletionTemplateCreate(pThis->pDrvIns, &pStorageBackend->pTemplate,
5d0d754550d06b7d59a935e59caaf814462d53ccvboxsync drvvdAsyncTaskCompleted, pStorageBackend, "AsyncTaskCompleted");
9496f2d398b49813176939d7a339ae513d5175efvboxsync uint32_t fFlags = (fOpen & RTFILE_O_ACCESS_MASK) == RTFILE_O_READ
9496f2d398b49813176939d7a339ae513d5175efvboxsync Assert((fOpen & RTFILE_O_DENY_MASK) == RTFILE_O_DENY_NONE);
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync rc = PDMR3AsyncCompletionEpCreateForFile(&pStorageBackend->pEndpoint,
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync rc = PDMR3AsyncCompletionEpSetBwMgr(pStorageBackend->pEndpoint, pThis->pszBwGroup);
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync PDMR3AsyncCompletionEpClose(pStorageBackend->pEndpoint);
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync PDMR3AsyncCompletionTemplateDestroy(pStorageBackend->pTemplate);
9496f2d398b49813176939d7a339ae513d5175efvboxsyncstatic DECLCALLBACK(int) drvvdAsyncIOClose(void *pvUser, void *pStorage)
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)pStorage;
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync PDMR3AsyncCompletionEpClose(pStorageBackend->pEndpoint);
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync PDMR3AsyncCompletionTemplateDestroy(pStorageBackend->pTemplate);
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsyncstatic DECLCALLBACK(int) drvvdAsyncIOReadSync(void *pvUser, void *pStorage, uint64_t uOffset,
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)pStorage;
9496f2d398b49813176939d7a339ae513d5175efvboxsync ASMAtomicXchgBool(&pStorageBackend->fSyncIoPending, true);
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync int rc = PDMR3AsyncCompletionEpRead(pStorageBackend->pEndpoint, uOffset, &DataSeg, 1, cbRead, NULL, &pTask);
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync rc = RTSemEventWait(pStorageBackend->EventSem, RT_INDEFINITE_WAIT);
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync ASMAtomicXchgBool(&pStorageBackend->fSyncIoPending, false);
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsyncstatic DECLCALLBACK(int) drvvdAsyncIOWriteSync(void *pvUser, void *pStorage, uint64_t uOffset,
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync const void *pvBuf, size_t cbWrite, size_t *pcbWritten)
9496f2d398b49813176939d7a339ae513d5175efvboxsync PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)pStorage;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync ASMAtomicXchgBool(&pStorageBackend->fSyncIoPending, true);
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync int rc = PDMR3AsyncCompletionEpWrite(pStorageBackend->pEndpoint, uOffset, &DataSeg, 1, cbWrite, NULL, &pTask);
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync rc = RTSemEventWait(pStorageBackend->EventSem, RT_INDEFINITE_WAIT);
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync ASMAtomicXchgBool(&pStorageBackend->fSyncIoPending, false);
9496f2d398b49813176939d7a339ae513d5175efvboxsyncstatic DECLCALLBACK(int) drvvdAsyncIOFlushSync(void *pvUser, void *pStorage)
59d7f5939d42ad9d344fbad8401e00a900db92c5vboxsync PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)pStorage;
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync LogFlowFunc(("pvUser=%#p pStorage=%#p\n", pvUser, pStorage));
975ad9d9bc9c4dc96b41d9f67a65228b1b338e2avboxsync ASMAtomicXchgBool(&pStorageBackend->fSyncIoPending, true);
975ad9d9bc9c4dc96b41d9f67a65228b1b338e2avboxsync int rc = PDMR3AsyncCompletionEpFlush(pStorageBackend->pEndpoint, NULL, &pTask);
975ad9d9bc9c4dc96b41d9f67a65228b1b338e2avboxsync rc = RTSemEventWait(pStorageBackend->EventSem, RT_INDEFINITE_WAIT);
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync 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)
7b067f3f07310bff46d1d6a4ac94d8b9bb7ccccdvboxsync 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 return PDMR3AsyncCompletionEpSetSize(pStorageBackend->pEndpoint, cbSize);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync#endif /* VBOX_WITH_PDM_ASYNC_COMPLETION */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync/*******************************************************************************
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync* VD Thread Synchronization interface implementation *
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync*******************************************************************************/
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsyncstatic DECLCALLBACK(int) drvvdThreadStartRead(void *pvUser)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync return RTSemRWRequestRead(pThis->MergeLock, RT_INDEFINITE_WAIT);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsyncstatic DECLCALLBACK(int) drvvdThreadFinishRead(void *pvUser)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsyncstatic DECLCALLBACK(int) drvvdThreadStartWrite(void *pvUser)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync return RTSemRWRequestWrite(pThis->MergeLock, RT_INDEFINITE_WAIT);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsyncstatic DECLCALLBACK(int) drvvdThreadFinishWrite(void *pvUser)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync/*******************************************************************************
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync* VD Configuration interface implementation *
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync*******************************************************************************/
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsyncstatic bool drvvdCfgAreKeysValid(void *pvUser, const char *pszzValid)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync return CFGMR3AreValuesValid((PCFGMNODE)pvUser, pszzValid);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsyncstatic int drvvdCfgQuerySize(void *pvUser, const char *pszName, size_t *pcb)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync return CFGMR3QuerySize((PCFGMNODE)pvUser, pszName, pcb);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsyncstatic int drvvdCfgQuery(void *pvUser, const char *pszName, char *pszString, size_t cchString)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync return CFGMR3QueryString((PCFGMNODE)pvUser, pszName, pszString, cchString);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync/*******************************************************************************
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync* VD TCP network stack interface implementation - INIP case *
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync*******************************************************************************/
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));
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/** @copydoc VDINTERFACETCPNET::pfnSocketCreate */
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsyncstatic DECLCALLBACK(int) drvvdINIPSocketDestroy(VDSOCKET Sock)
ff88d4153cd65650577e8c2d1a5a3fdfa0404a80vboxsync/** @copydoc VDINTERFACETCPNET::pfnClientConnect */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic DECLCALLBACK(int) drvvdINIPClientConnect(VDSOCKET Sock, const char *pszAddress, uint32_t uPort)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* Check whether lwIP is set up in this VM instance. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* Resolve hostname. As there is no standard resolver for lwIP yet,
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync * just accept numeric IP addresses for now. */
fe813b3594039ba864493438e78ee0e7132bc445vboxsync LogRelFunc(("cannot resolve IP %s\n", pszAddress));
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* Create socket and connect. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync if (!lwip_connect(iSock, (struct sockaddr *)&InAddr, sizeof(InAddr)))
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync rc = VERR_NET_CONNECTION_REFUSED; /* @todo real solution needed */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync rc = VERR_NET_CONNECTION_REFUSED; /* @todo real solution needed */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/** @copydoc VDINTERFACETCPNET::pfnClientClose */
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsyncstatic DECLCALLBACK(int) drvvdINIPClientClose(VDSOCKET Sock)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync return VINF_SUCCESS; /** @todo real solution needed */
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync/** @copydoc VDINTERFACETCPNET::pfnIsClientConnected */
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsyncstatic DECLCALLBACK(bool) drvvdINIPIsClientConnected(VDSOCKET Sock)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/** @copydoc VDINTERFACETCPNET::pfnSelectOne */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic DECLCALLBACK(int) drvvdINIPSelectOne(VDSOCKET Sock, RTMSINTERVAL cMillies)
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync rc = lwip_select(pSocketInt->hSock + 1, &fdsetR, NULL, &fdsetE, NULL);
594521f7faf13f7a88f31e6cd76629bd67340229vboxsync rc = lwip_select(pSocketInt->hSock + 1, &fdsetR, NULL, &fdsetE, &timeout);
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync return VERR_NET_CONNECTION_REFUSED; /** @todo real solution needed */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/** @copydoc VDINTERFACETCPNET::pfnRead */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic DECLCALLBACK(int) drvvdINIPRead(VDSOCKET Sock, void *pvBuffer, size_t cbBuffer, size_t *pcbRead)
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync /* Do params checking */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * Read loop.
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync * If pcbRead is NULL we have to fill the entire buffer!
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync /** @todo this clipping here is just in case (the send function
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync * needed it, so I added it here, too). Didn't investigate if this
594521f7faf13f7a88f31e6cd76629bd67340229vboxsync * really has issues. Better be safe than sorry. */
e04eeee1b306d610b0441cee9bf1c750100254d5vboxsync ssize_t cbBytesRead = lwip_recv(pSocketInt->hSock, (char *)pvBuffer + cbRead,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync return VERR_NET_CONNECTION_REFUSED; /** @todo real solution */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync if (cbBytesRead == 0 && errno) /** @todo r=bird: lwip_recv will not touch errno on Windows. This may apply to other hosts as well */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync return VERR_NET_CONNECTION_REFUSED; /** @todo real solution */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* return partial data */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* read more? */
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync/** @copydoc VDINTERFACETCPNET::pfnWrite */
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsyncstatic DECLCALLBACK(int) drvvdINIPWrite(VDSOCKET Sock, const void *pvBuffer, size_t cbBuffer)
9496f2d398b49813176939d7a339ae513d5175efvboxsync /** @todo lwip send only supports up to 65535 bytes in a single
9496f2d398b49813176939d7a339ae513d5175efvboxsync * 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(pSocketInt->hSock, (void *)pvBuffer,
fe813b3594039ba864493438e78ee0e7132bc445vboxsync return VERR_NET_CONNECTION_REFUSED; /** @todo real solution needed */
9496f2d398b49813176939d7a339ae513d5175efvboxsync AssertMsg(cbBuffer >= (size_t)cbWritten, ("Wrote more than we requested!!! cbWritten=%d cbBuffer=%d\n",
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync/** @copydoc VDINTERFACETCPNET::pfnSgWrite */
9496f2d398b49813176939d7a339ae513d5175efvboxsyncstatic 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)
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync lwip_setsockopt(pSocketInt->hSock, IPPROTO_TCP, TCP_NODELAY,
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync lwip_setsockopt(pSocketInt->hSock, IPPROTO_TCP, TCP_NODELAY,
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync/** @copydoc VDINTERFACETCPNET::pfnSetSendCoalescing */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsyncstatic DECLCALLBACK(int) drvvdINIPSetSendCoalescing(VDSOCKET Sock, bool fEnable)
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync lwip_setsockopt(pSocketInt->hSock, IPPROTO_TCP, TCP_NODELAY,
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync/** @copydoc VDINTERFACETCPNET::pfnGetLocalAddress */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsyncstatic DECLCALLBACK(int) drvvdINIPGetLocalAddress(VDSOCKET Sock, PRTNETADDR pAddr)
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync if (!lwip_getsockname(pSocketInt->hSock, &u.Addr, &cbAddr))
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * Convert the address.
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync/** @copydoc VDINTERFACETCPNET::pfnGetPeerAddress */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsyncstatic DECLCALLBACK(int) drvvdINIPGetPeerAddress(VDSOCKET Sock, PRTNETADDR pAddr)
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync if (!lwip_getpeername(pSocketInt->hSock, &u.Addr, &cbAddr))
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync * Convert the address.
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync/** @copydoc VDINTERFACETCPNET::pfnSelectOneEx */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsyncstatic DECLCALLBACK(int) drvvdINIPSelectOneEx(VDSOCKET Sock, uint32_t fEvents, uint32_t *pfEvents, RTMSINTERVAL cMillies)
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync/** @copydoc VDINTERFACETCPNET::pfnPoke */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsyncstatic DECLCALLBACK(int) drvvdINIPPoke(VDSOCKET Sock)
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync#endif /* VBOX_WITH_INIP */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync/*******************************************************************************
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync* VD TCP network stack interface implementation - Host TCP case *
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync*******************************************************************************/
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync * Socket data.
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsynctypedef struct VDSOCKETINT
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync /** IPRT socket handle. */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync /** Pollset with the wakeup pipe and socket. */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync /** Pipe endpoint - read (in the pollset). */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync /** Pipe endpoint - write. */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync /** Flag whether the thread was woken up. */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync volatile bool fWokenUp;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync /** Flag whether the thread is waiting in the select call. */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync volatile bool fWaiting;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync /** Old event mask. */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync/** Pollset id of the socket. */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync/** Pollset id of the pipe. */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync/** @copydoc VDINTERFACETCPNET::pfnSocketCreate */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsyncstatic DECLCALLBACK(int) drvvdTcpSocketCreate(uint32_t fFlags, PVDSOCKET pSock)
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pSockInt = (PVDSOCKETINT)RTMemAllocZ(sizeof(VDSOCKETINT));
c28fa006ba669ad8f26ae31d00a338379c04ea1bvboxsync if (fFlags & VD_INTERFACETCPNET_CONNECT_EXTENDED_SELECT)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* Init pipe and pollset. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync rc = RTPipeCreate(&pSockInt->hPipeR, &pSockInt->hPipeW, 0);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync rc = RTPollSetAddPipe(pSockInt->hPollSet, pSockInt->hPipeR,
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync RTPollSetRemove(pSockInt->hPollSet, VDSOCKET_POLL_ID_PIPE);
68a4ee3a31a0807abd03eae881c1bbaf4d42ee6dvboxsync/** @copydoc VDINTERFACETCPNET::pfnSocketDestroy */
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsyncstatic DECLCALLBACK(int) drvvdTcpSocketDestroy(VDSOCKET Sock)
68a4ee3a31a0807abd03eae881c1bbaf4d42ee6dvboxsync /* Destroy the pipe and pollset if necessary. */
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync rc = RTPollSetRemove(pSockInt->hPollSet, VDSOCKET_POLL_ID_SOCKET);
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync Assert(RT_SUCCESS(rc) || rc == VERR_POLL_HANDLE_ID_NOT_FOUND);
975ad9d9bc9c4dc96b41d9f67a65228b1b338e2avboxsync rc = RTPollSetRemove(pSockInt->hPollSet, VDSOCKET_POLL_ID_PIPE);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync rc = RTTcpClientCloseEx(pSockInt->hSocket, false /*fGracefulShutdown*/);
090d729e786b999dc285f8ea267f9effd1319544vboxsync/** @copydoc VDINTERFACETCPNET::pfnClientConnect */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic DECLCALLBACK(int) drvvdTcpClientConnect(VDSOCKET Sock, const char *pszAddress, uint32_t uPort)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync rc = RTTcpClientConnect(pszAddress, uPort, &pSockInt->hSocket);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* Add to the pollset if required. */
27b178e99b06a68ef52353b15bc647674d2006bcvboxsync pSockInt->fEventsOld = RTPOLL_EVT_READ | RTPOLL_EVT_WRITE | RTPOLL_EVT_ERROR;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync rc = RTPollSetAddSocket(pSockInt->hPollSet, pSockInt->hSocket,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync rc = RTTcpClientCloseEx(pSockInt->hSocket, false /*fGracefulShutdown*/);
c28fa006ba669ad8f26ae31d00a338379c04ea1bvboxsync/** @copydoc VDINTERFACETCPNET::pfnClientClose */
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsyncstatic DECLCALLBACK(int) drvvdTcpClientClose(VDSOCKET Sock)
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync rc = RTPollSetRemove(pSockInt->hPollSet, VDSOCKET_POLL_ID_SOCKET);
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync rc = RTTcpClientCloseEx(pSockInt->hSocket, false /*fGracefulShutdown*/);
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync/** @copydoc VDINTERFACETCPNET::pfnIsClientConnected */
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsyncstatic DECLCALLBACK(bool) drvvdTcpIsClientConnected(VDSOCKET Sock)
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync/** @copydoc VDINTERFACETCPNET::pfnSelectOne */
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsyncstatic DECLCALLBACK(int) drvvdTcpSelectOne(VDSOCKET Sock, RTMSINTERVAL cMillies)
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync return RTTcpSelectOne(pSockInt->hSocket, cMillies);
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync/** @copydoc VDINTERFACETCPNET::pfnRead */
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsyncstatic DECLCALLBACK(int) drvvdTcpRead(VDSOCKET Sock, void *pvBuffer, size_t cbBuffer, size_t *pcbRead)
38ceb5cfc147448ea4087a1f5971cb8fb4434bd9vboxsync return RTTcpRead(pSockInt->hSocket, pvBuffer, cbBuffer, pcbRead);
27b178e99b06a68ef52353b15bc647674d2006bcvboxsync/** @copydoc VDINTERFACETCPNET::pfnWrite */
27b178e99b06a68ef52353b15bc647674d2006bcvboxsyncstatic DECLCALLBACK(int) drvvdTcpWrite(VDSOCKET Sock, const void *pvBuffer, size_t cbBuffer)
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync return RTTcpWrite(pSockInt->hSocket, pvBuffer, cbBuffer);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/** @copydoc VDINTERFACETCPNET::pfnSgWrite */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic DECLCALLBACK(int) drvvdTcpSgWrite(VDSOCKET Sock, PCRTSGBUF pSgBuf)
b7a5b3f9f9ecce32ddacf8404c625ce0451bbdc1vboxsync/** @copydoc VDINTERFACETCPNET::pfnReadNB */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic DECLCALLBACK(int) drvvdTcpReadNB(VDSOCKET Sock, void *pvBuffer, size_t cbBuffer, size_t *pcbRead)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync return RTTcpReadNB(pSockInt->hSocket, pvBuffer, cbBuffer, pcbRead);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync/** @copydoc VDINTERFACETCPNET::pfnWriteNB */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsyncstatic DECLCALLBACK(int) drvvdTcpWriteNB(VDSOCKET Sock, const void *pvBuffer, size_t cbBuffer, size_t *pcbWritten)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync return RTTcpWriteNB(pSockInt->hSocket, pvBuffer, cbBuffer, pcbWritten);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync/** @copydoc VDINTERFACETCPNET::pfnSgWriteNB */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsyncstatic DECLCALLBACK(int) drvvdTcpSgWriteNB(VDSOCKET Sock, PRTSGBUF pSgBuf, size_t *pcbWritten)
efff36b306e370346025647a158689021df2e1d1vboxsync return RTTcpSgWriteNB(pSockInt->hSocket, pSgBuf, pcbWritten);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync/** @copydoc VDINTERFACETCPNET::pfnFlush */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsyncstatic DECLCALLBACK(int) drvvdTcpFlush(VDSOCKET Sock)
a3369a746b56a8966dd78619f4d191c9662f400dvboxsync/** @copydoc VDINTERFACETCPNET::pfnSetSendCoalescing */
a3369a746b56a8966dd78619f4d191c9662f400dvboxsyncstatic DECLCALLBACK(int) drvvdTcpSetSendCoalescing(VDSOCKET Sock, bool fEnable)
a3369a746b56a8966dd78619f4d191c9662f400dvboxsync return RTTcpSetSendCoalescing(pSockInt->hSocket, fEnable);
27b178e99b06a68ef52353b15bc647674d2006bcvboxsync/** @copydoc VDINTERFACETCPNET::pfnGetLocalAddress */
27b178e99b06a68ef52353b15bc647674d2006bcvboxsyncstatic DECLCALLBACK(int) drvvdTcpGetLocalAddress(VDSOCKET Sock, PRTNETADDR pAddr)
27b178e99b06a68ef52353b15bc647674d2006bcvboxsync return RTTcpGetLocalAddress(pSockInt->hSocket, pAddr);
27b178e99b06a68ef52353b15bc647674d2006bcvboxsync/** @copydoc VDINTERFACETCPNET::pfnGetPeerAddress */
27b178e99b06a68ef52353b15bc647674d2006bcvboxsyncstatic DECLCALLBACK(int) drvvdTcpGetPeerAddress(VDSOCKET Sock, PRTNETADDR pAddr)
27b178e99b06a68ef52353b15bc647674d2006bcvboxsync return RTTcpGetPeerAddress(pSockInt->hSocket, pAddr);
27b178e99b06a68ef52353b15bc647674d2006bcvboxsyncstatic int drvvdTcpSelectOneExPoll(VDSOCKET Sock, uint32_t fEvents,
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync rc = RTPollSetEventsChange(pSockInt->hPollSet, VDSOCKET_POLL_ID_SOCKET, fPollEvents);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync rc = RTPoll(pSockInt->hPollSet, cMillies, &fEventsRecv, &id);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync Assert((fEventsRecv & RTPOLL_EVT_VALID_MASK) == RTPOLL_EVT_READ);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* We got interrupted, drain the pipe. */
5d0d754550d06b7d59a935e59caaf814462d53ccvboxsync rc = RTPipeRead(pSockInt->hPipeR, abBuf, sizeof(abBuf), &cbRead);
b7a5b3f9f9ecce32ddacf8404c625ce0451bbdc1vboxsync/** @copydoc VDINTERFACETCPNET::pfnSelectOneEx */
6b223679d40f5e57e55e867e806a9f194e2cde12vboxsyncstatic DECLCALLBACK(int) drvvdTcpSelectOneExNoPoll(VDSOCKET Sock, uint32_t fEvents,
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync * Only the pipe is configured or the caller doesn't wait for a socket event,
9496f2d398b49813176939d7a339ae513d5175efvboxsync * wait until there is something to read from the pipe.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync rc = RTPipeReadBlocking(pSockInt->hPipeR, &ch, 1, &cbRead);
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync /* Make sure the socket is not in the pollset. */
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync rc = RTPollSetRemove(pSockInt->hPollSet, VDSOCKET_POLL_ID_SOCKET);
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync Assert(RT_SUCCESS(rc) || rc == VERR_POLL_HANDLE_ID_NOT_FOUND);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* Check the socket. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync rc = RTTcpSelectOneEx(pSockInt->hSocket, fSelectEvents, &fEventsRecv, 0);
ad77e3ec3cde24263bc7537575f5cae442bee3b1vboxsync break; /* Quit */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync Assert((fEventsRecv & RTPOLL_EVT_VALID_MASK) == RTPOLL_EVT_READ);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* We got interrupted, drain the pipe. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync rc = RTPipeRead(pSockInt->hPipeR, abBuf, sizeof(abBuf), &cbRead);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync else /* The caller waits for a socket event. */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync /* Loop until we got woken up or a socket event occurred. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /** @todo find an adaptive wait algorithm based on the
9496f2d398b49813176939d7a339ae513d5175efvboxsync * number of wakeups in the past. */
9496f2d398b49813176939d7a339ae513d5175efvboxsync rc = RTTcpSelectOneEx(pSockInt->hSocket, fSelectEvents, &fEventsRecv, 5);
cba6719bd64ec749967bbe931230452664109857vboxsync /* Check if there is an event pending. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync rc = RTPipeRead(pSockInt->hPipeR, &ch, 1, &cbRead);
return rc;
return VINF_SUCCESS;
if ( cbRead > 0
return rc;
return rc;
return rc;
void *pvUser)
return rc;
return cb;
return rc;
return rc;
return rc;
return rc;
return rc;
return rc;
return rc;
return rc;
return rc;
return rc;
switch (enmXferDir)
case PDMBLKCACHEXFERDIR_READ:
case PDMBLKCACHEXFERDIR_WRITE:
case PDMBLKCACHEXFERDIR_FLUSH:
return VINF_SUCCESS;
return VINF_SUCCESS;
PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIAASYNC, pThis->fAsyncIOSupported ? &pThis->IMediaAsync : NULL);
return NULL;
return VINF_SUCCESS;
return VINF_SUCCESS;
bool fHostIP = false;
bool fUseNewIo = false;
bool fUseBlockCache = false;
bool fDiscard = false;
unsigned iLevel = 0;
bool fValid;
if (!fValid)
rc = CFGMR3QueryU32Def(pCurNode, "BootAccelerationBuffer", (uint32_t *)&pThis->cbBootAccelBuffer, 16 * _1K);
char *psz;
if (pszCachePath)
if (!pParent)
iLevel++;
fUseNewIo = true;
fUseNewIo = false;
unsigned iImageIdx = 0;
if (!pImage)
bool fMergeSource;
if (fMergeSource)
bool fMergeTarget;
if (fMergeTarget)
if (fHostIP)
#ifndef VBOX_WITH_INIP
if (fUseNewIo)
unsigned uOpenFlags;
if (fHonorZeroWrites)
fDiscard = false;
if (!fDiscard)
&& !fReadOnly
&& !fMaybeReadOnly
&& iLevel == 0)
pszName);
iLevel--;
iImageIdx++;
if (fUseNewIo)
rc = VDCacheOpen(pThis->pDisk, pszCacheFormat, pszCachePath, VD_OPEN_FLAGS_NORMAL, pThis->pVDIfsCache);
if ( fUseBlockCache
&& !fDiscard
const char *pcszController;
if (cbStr > 0)
pszId);
return rc;
sizeof(VBOXDISK),
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,