DrvVD.cpp revision e4f367251aede667a6de69baa54ef9eb5f150871
af062818b47340eef15700d2f0211576ba3506eevboxsync * DrvVD - Generic VBox disk media driver.
af062818b47340eef15700d2f0211576ba3506eevboxsync * Copyright (C) 2006-2010 Oracle Corporation
af062818b47340eef15700d2f0211576ba3506eevboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
af062818b47340eef15700d2f0211576ba3506eevboxsync * available from http://www.virtualbox.org. This file is free software;
af062818b47340eef15700d2f0211576ba3506eevboxsync * you can redistribute it and/or modify it under the terms of the GNU
af062818b47340eef15700d2f0211576ba3506eevboxsync * General Public License (GPL) as published by the Free Software
af062818b47340eef15700d2f0211576ba3506eevboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
af062818b47340eef15700d2f0211576ba3506eevboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
af062818b47340eef15700d2f0211576ba3506eevboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
b955672b950093ff7416d1269dd4d3b69983bd8fvboxsync/*******************************************************************************
b955672b950093ff7416d1269dd4d3b69983bd8fvboxsync* Header files *
b955672b950093ff7416d1269dd4d3b69983bd8fvboxsync*******************************************************************************/
af062818b47340eef15700d2f0211576ba3506eevboxsync/* All lwip header files are not C++ safe. So hack around this. */
af062818b47340eef15700d2f0211576ba3506eevboxsync#endif /* VBOX_WITH_INIP */
af062818b47340eef15700d2f0211576ba3506eevboxsync/* Small hack to get at lwIP initialized status */
af062818b47340eef15700d2f0211576ba3506eevboxsyncextern bool DevINIPConfigured(void);
af062818b47340eef15700d2f0211576ba3506eevboxsync#endif /* VBOX_WITH_INIP */
af062818b47340eef15700d2f0211576ba3506eevboxsync/*******************************************************************************
af062818b47340eef15700d2f0211576ba3506eevboxsync* Defined types, constants and macros *
af062818b47340eef15700d2f0211576ba3506eevboxsync*******************************************************************************/
af062818b47340eef15700d2f0211576ba3506eevboxsync/** Converts a pointer to VBOXDISK::IMedia to a PVBOXDISK. */
af062818b47340eef15700d2f0211576ba3506eevboxsync ( (PVBOXDISK)((uintptr_t)pInterface - RT_OFFSETOF(VBOXDISK, IMedia)) )
af062818b47340eef15700d2f0211576ba3506eevboxsync/** Converts a pointer to PDMDRVINS::IBase to a PPDMDRVINS. */
af062818b47340eef15700d2f0211576ba3506eevboxsync ( (PPDMDRVINS)((uintptr_t)pInterface - RT_OFFSETOF(PDMDRVINS, IBase)) )
af062818b47340eef15700d2f0211576ba3506eevboxsync/** Converts a pointer to PDMDRVINS::IBase to a PVBOXDISK. */
af062818b47340eef15700d2f0211576ba3506eevboxsync ( PDMINS_2_DATA(PDMIBASE_2_DRVINS(pInterface), PVBOXDISK) )
af062818b47340eef15700d2f0211576ba3506eevboxsync/** Converts a pointer to VBOXDISK::IMediaAsync to a PVBOXDISK. */
af062818b47340eef15700d2f0211576ba3506eevboxsync ( (PVBOXDISK)((uintptr_t)pInterface - RT_OFFSETOF(VBOXDISK, IMediaAsync)) )
af062818b47340eef15700d2f0211576ba3506eevboxsync * VBox disk container, image information, private part.
af062818b47340eef15700d2f0211576ba3506eevboxsynctypedef struct VBOXIMAGE
af062818b47340eef15700d2f0211576ba3506eevboxsync /** Pointer to next image. */
af062818b47340eef15700d2f0211576ba3506eevboxsync /** Pointer to list of VD interfaces. Per-image. */
af062818b47340eef15700d2f0211576ba3506eevboxsync /** Configuration information interface. */
af062818b47340eef15700d2f0211576ba3506eevboxsync /** TCP network stack interface. */
af062818b47340eef15700d2f0211576ba3506eevboxsync /** I/O interface. */
af062818b47340eef15700d2f0211576ba3506eevboxsync * Storage backend data.
af062818b47340eef15700d2f0211576ba3506eevboxsync /** PDM async completion end point. */
af062818b47340eef15700d2f0211576ba3506eevboxsync /** The template. */
af062818b47340eef15700d2f0211576ba3506eevboxsync /** Event semaphore for synchronous operations. */
af062818b47340eef15700d2f0211576ba3506eevboxsync /** Flag whether a synchronous operation is currently pending. */
af062818b47340eef15700d2f0211576ba3506eevboxsync volatile bool fSyncIoPending;
af062818b47340eef15700d2f0211576ba3506eevboxsync /** Return code of the last completed request. */
af062818b47340eef15700d2f0211576ba3506eevboxsync /** Callback routine */
af062818b47340eef15700d2f0211576ba3506eevboxsync * VBox disk container media main structure, private part.
af062818b47340eef15700d2f0211576ba3506eevboxsync * @implements PDMIMEDIA
af062818b47340eef15700d2f0211576ba3506eevboxsync * @implements PDMIMEDIAASYNC
af062818b47340eef15700d2f0211576ba3506eevboxsync * @implements VDINTERFACEERROR
af062818b47340eef15700d2f0211576ba3506eevboxsync * @implements VDINTERFACETCPNET
af062818b47340eef15700d2f0211576ba3506eevboxsync * @implements VDINTERFACEASYNCIO
af062818b47340eef15700d2f0211576ba3506eevboxsync * @implements VDINTERFACECONFIG
af062818b47340eef15700d2f0211576ba3506eevboxsynctypedef struct VBOXDISK
af062818b47340eef15700d2f0211576ba3506eevboxsync /** The VBox disk container. */
af062818b47340eef15700d2f0211576ba3506eevboxsync /** The media interface. */
af062818b47340eef15700d2f0211576ba3506eevboxsync /** Media port. */
af062818b47340eef15700d2f0211576ba3506eevboxsync /** Pointer to the driver instance. */
af062818b47340eef15700d2f0211576ba3506eevboxsync /** Flag whether suspend has changed image open mode to read only. */
af062818b47340eef15700d2f0211576ba3506eevboxsync /** Flag whether to use the runtime (true) or startup error facility. */
af062818b47340eef15700d2f0211576ba3506eevboxsync /** Pointer to list of VD interfaces. Per-disk. */
af062818b47340eef15700d2f0211576ba3506eevboxsync /** Error interface. */
af062818b47340eef15700d2f0211576ba3506eevboxsync /** Thread synchronization interface. */
af062818b47340eef15700d2f0211576ba3506eevboxsync /** Flag whether opened disk supports async I/O operations. */
af062818b47340eef15700d2f0211576ba3506eevboxsync /** The async media interface. */
af062818b47340eef15700d2f0211576ba3506eevboxsync /** The async media port interface above. */
af062818b47340eef15700d2f0211576ba3506eevboxsync /** Pointer to the list of data we need to keep per image. */
af062818b47340eef15700d2f0211576ba3506eevboxsync /** Flag whether the media should allow concurrent open for writing. */
af062818b47340eef15700d2f0211576ba3506eevboxsync /** Flag whether a merge operation has been set up. */
af062818b47340eef15700d2f0211576ba3506eevboxsync /** Synchronization to prevent destruction before merge finishes. */
af062818b47340eef15700d2f0211576ba3506eevboxsync /** Synchronization between merge and other image accesses. */
af062818b47340eef15700d2f0211576ba3506eevboxsync /** Source image index for merging. */
af062818b47340eef15700d2f0211576ba3506eevboxsync /** Target image index for merging. */
af062818b47340eef15700d2f0211576ba3506eevboxsync /** Flag whether boot acceleration is enabled. */
af062818b47340eef15700d2f0211576ba3506eevboxsync /** Flag whether boot acceleration is currently active. */
af062818b47340eef15700d2f0211576ba3506eevboxsync /** Size of the disk, used for read truncation. */
af062818b47340eef15700d2f0211576ba3506eevboxsync /** Size of the configured buffer. */
af062818b47340eef15700d2f0211576ba3506eevboxsync /** Start offset for which the buffer holds data. */
af062818b47340eef15700d2f0211576ba3506eevboxsync /** Number of valid bytes in the buffer. */
af062818b47340eef15700d2f0211576ba3506eevboxsync /** The disk buffer. */
af062818b47340eef15700d2f0211576ba3506eevboxsync /** Bandwidth group the disk is assigned to. */
af062818b47340eef15700d2f0211576ba3506eevboxsync /** Flag whether async I/O using the host cache is enabled. */
af062818b47340eef15700d2f0211576ba3506eevboxsync /** I/O interface for a cache image. */
af062818b47340eef15700d2f0211576ba3506eevboxsync /** Interface list for the cache image. */
5112e32d7072e280613921c982a6672f2c859cf3vboxsync /** The block cache handle if configured. */
5112e32d7072e280613921c982a6672f2c859cf3vboxsync/*******************************************************************************
5112e32d7072e280613921c982a6672f2c859cf3vboxsync* Internal Functions *
5112e32d7072e280613921c982a6672f2c859cf3vboxsync*******************************************************************************/
5112e32d7072e280613921c982a6672f2c859cf3vboxsync * Internal: allocate new image descriptor and put it in the list
5112e32d7072e280613921c982a6672f2c859cf3vboxsync PVBOXIMAGE pImage = (PVBOXIMAGE)RTMemAllocZ(sizeof(VBOXIMAGE));
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++;
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)
&& !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,
NULL,