DrvVD.cpp revision cab115cfa31c584def7069312a1e23c3fc88533b
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * DrvVD - Generic VBox disk media driver.
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * Copyright (C) 2006-2010 Oracle Corporation
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * available from http://www.virtualbox.org. This file is free software;
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * you can redistribute it and/or modify it under the terms of the GNU
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * General Public License (GPL) as published by the Free Software
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync/*******************************************************************************
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync* Header files *
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync*******************************************************************************/
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync/* All lwip header files are not C++ safe. So hack around this. */
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync#endif /* VBOX_WITH_INIP */
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync/* Small hack to get at lwIP initialized status */
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsyncextern bool DevINIPConfigured(void);
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync#endif /* VBOX_WITH_INIP */
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync/*******************************************************************************
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync* Defined types, constants and macros *
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync*******************************************************************************/
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync/** Converts a pointer to VBOXDISK::IMedia to a PVBOXDISK. */
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync ( (PVBOXDISK)((uintptr_t)pInterface - RT_OFFSETOF(VBOXDISK, IMedia)) )
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync/** Converts a pointer to PDMDRVINS::IBase to a PPDMDRVINS. */
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync ( (PPDMDRVINS)((uintptr_t)pInterface - RT_OFFSETOF(PDMDRVINS, IBase)) )
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync/** Converts a pointer to PDMDRVINS::IBase to a PVBOXDISK. */
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync ( PDMINS_2_DATA(PDMIBASE_2_DRVINS(pInterface), PVBOXDISK) )
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync/** Converts a pointer to VBOXDISK::IMediaAsync to a PVBOXDISK. */
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync ( (PVBOXDISK)((uintptr_t)pInterface - RT_OFFSETOF(VBOXDISK, IMediaAsync)) )
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * VBox disk container, image information, private part.
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsynctypedef struct VBOXIMAGE
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync /** Pointer to next image. */
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync /** Pointer to list of VD interfaces. Per-image. */
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync /** Common structure for the configuration information interface. */
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync /** Common structure for the supported TCP network stack interface. */
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync /** Common structure for the supported I/O interface. */
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * Storage backend data.
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync /** PDM async completion end point. */
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync /** The template. */
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync /** Event semaphore for synchronous operations. */
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync /** Flag whether a synchronous operation is currently pending. */
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync volatile bool fSyncIoPending;
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync /** Return code of the last completed request. */
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync /** Callback routine */
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * VBox disk container media main structure, private part.
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * @implements PDMIMEDIA
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * @implements PDMIMEDIAASYNC
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * @implements VDINTERFACEERROR
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * @implements VDINTERFACETCPNET
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * @implements VDINTERFACEASYNCIO
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * @implements VDINTERFACECONFIG
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsynctypedef struct VBOXDISK
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync /** The VBox disk container. */
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync /** The media interface. */
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync /** Media port. */
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync /** Pointer to the driver instance. */
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync /** Flag whether suspend has changed image open mode to read only. */
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync /** Flag whether to use the runtime (true) or startup error facility. */
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync /** Pointer to list of VD interfaces. Per-disk. */
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync /** Common structure for the supported error interface. */
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync /** Callback table for error interface. */
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync /** Common structure for the supported thread synchronization interface. */
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync /** Callback table for thread synchronization interface. */
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync /** Callback table for the configuration information interface. */
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync /** Callback table for TCP network stack interface. */
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync /** Callback table for I/O interface. */
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync /** Flag whether opened disk supports async I/O operations. */
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync /** The async media interface. */
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync /** The async media port interface above. */
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync /** Pointer to the list of data we need to keep per image. */
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync /** Flag whether the media should allow concurrent open for writing. */
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync /** Flag whether a merge operation has been set up. */
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync /** Synchronization to prevent destruction before merge finishes. */
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync /** Synchronization between merge and other image accesses. */
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync /** Source image index for merging. */
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync /** Target image index for merging. */
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync /** Flag whether boot acceleration is enabled. */
bool fBootAccelActive;
char *pszBwGroup;
if (pImage)
return pImage;
RTMemFree(p);
unsigned uOpenFlags;
return rc;
unsigned uOpenFlags;
return rc;
static DECLCALLBACK(void) drvvdAsyncTaskCompleted(PPDMDRVINS pDrvIns, void *pvTemplateUser, void *pvUser, int rcReq)
int rc;
void **ppStorage)
PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)RTMemAllocZ(sizeof(DRVVDSTORAGEBACKEND));
if (pStorageBackend)
return VINF_SUCCESS;
return rc;
return VINF_SUCCESS;;
int rc = PDMR3AsyncCompletionEpRead(pStorageBackend->pEndpoint, uOffset, &DataSeg, 1, cbRead, NULL, &pTask);
return rc;
if (pcbRead)
int rc = PDMR3AsyncCompletionEpWrite(pStorageBackend->pEndpoint, uOffset, &DataSeg, 1, cbWrite, NULL, &pTask);
return rc;
if (pcbWritten)
return rc;
void **ppTask)
int rc = PDMR3AsyncCompletionEpRead(pStorageBackend->pEndpoint, uOffset, paSegments, cSegments, cbRead,
return rc;
void **ppTask)
int rc = PDMR3AsyncCompletionEpWrite(pStorageBackend->pEndpoint, uOffset, paSegments, cSegments, cbWrite,
return rc;
return rc;
return rc;
#ifdef VBOX_WITH_INIP
typedef union INIPSOCKADDRUNION
typedef struct INIPSOCKET
int hSock;
return VERR_NOT_SUPPORTED;
if (pSocketInt)
return VINF_SUCCESS;
return VERR_NO_MEMORY;
return VINF_SUCCESS;
static DECLCALLBACK(int) drvvdINIPClientConnect(VDSOCKET Sock, const char *pszAddress, uint32_t uPort)
if (!DevINIPConfigured())
return VERR_NET_HOST_UNREACHABLE;
return VERR_NET_HOST_UNREACHABLE;
return VINF_SUCCESS;
return rc;
int rc;
if (rc > 0)
return VINF_SUCCESS;
if (rc == 0)
return VERR_TIMEOUT;
static DECLCALLBACK(int) drvvdINIPRead(VDSOCKET Sock, void *pvBuffer, size_t cbBuffer, size_t *pcbRead)
return VERR_INVALID_PARAMETER;
if (cbBytesRead < 0)
if (cbBytesRead == 0 && errno) /** @todo r=bird: lwip_recv will not touch errno on Windows. This may apply to other hosts as well */
if (pcbRead)
return VINF_SUCCESS;
if (cbWritten < 0)
AssertMsg(cbBuffer >= (size_t)cbWritten, ("Wrote more than we requested!!! cbWritten=%d cbBuffer=%d\n",
} while (cbBuffer);
return VINF_SUCCESS;
return rc;
fFlag = 0;
return VINF_SUCCESS;
return VINF_SUCCESS;
RT_ZERO(u);
return VINF_SUCCESS;
return VERR_NET_OPERATION_NOT_SUPPORTED;
RT_ZERO(u);
return VINF_SUCCESS;
return VERR_NET_OPERATION_NOT_SUPPORTED;
static DECLCALLBACK(int) drvvdINIPSelectOneEx(VDSOCKET Sock, uint32_t fEvents, uint32_t *pfEvents, RTMSINTERVAL cMillies)
return VERR_NOT_SUPPORTED;
return VERR_NOT_SUPPORTED;
typedef struct VDSOCKETINT
volatile bool fWokenUp;
volatile bool fWaiting;
#define VDSOCKET_POLL_ID_SOCKET 0
if (!pSockInt)
return VERR_NO_MEMORY;
return VINF_SUCCESS;
return VINF_SUCCESS;
return rc;
return rc;
static DECLCALLBACK(int) drvvdTcpClientConnect(VDSOCKET Sock, const char *pszAddress, uint32_t uPort)
return VINF_SUCCESS;
return rc;
return rc;
static DECLCALLBACK(int) drvvdTcpRead(VDSOCKET Sock, void *pvBuffer, size_t cbBuffer, size_t *pcbRead)
static DECLCALLBACK(int) drvvdTcpReadNB(VDSOCKET Sock, void *pvBuffer, size_t cbBuffer, size_t *pcbRead)
static DECLCALLBACK(int) drvvdTcpWriteNB(VDSOCKET Sock, const void *pvBuffer, size_t cbBuffer, size_t *pcbWritten)
*pfEvents = 0;
return rc;
return VERR_INTERRUPTED;
return rc;
*pfEvents = 0;
return VERR_INTERRUPTED;
|| !fEvents)
char ch = 0;
char ch = 0;
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;
switch (enmXferDir)
case PDMBLKCACHEXFERDIR_READ:
case PDMBLKCACHEXFERDIR_WRITE:
case PDMBLKCACHEXFERDIR_FLUSH:
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;
unsigned iLevel = 0;
bool fValid;
if (!fValid)
rc = CFGMR3QueryU32Def(pCurNode, "BootAccelerationBuffer", (uint32_t *)&pThis->cbBootAccelBuffer, 16 * _1K);
char *psz;
if (pszCachePath)
if (!pParent)
iLevel++;
if (fHostIP)
#ifndef VBOX_WITH_INIP
fUseNewIo = false;
unsigned iImageIdx = 0;
if (!pImage)
bool fMergeSource;
if (fMergeSource)
bool fMergeTarget;
if (fMergeTarget)
if (fUseNewIo)
unsigned uOpenFlags;
if (fHonorZeroWrites)
&& !fReadOnly
&& !fMaybeReadOnly
&& iLevel == 0)
pszName);
iLevel--;
iImageIdx++;
if (fUseNewIo)
rc = VDCacheOpen(pThis->pDisk, pszCacheFormat, pszCachePath, VD_OPEN_FLAGS_NORMAL, pThis->pVDIfsCache);
if ( fUseBlockCache
const char *pcszController;
if (cbStr > 0)
pszId);
return rc;
sizeof(VBOXDISK),
NULL,
NULL,
NULL,
NULL,
NULL,