DrvVD.cpp revision 670b83d458bceb92123155b5b47a39b9d24e3266
5964f60ed7fb52a3c4becbe83c9429f9b2f119c2vboxsync * DrvVD - Generic VBox disk media driver.
5964f60ed7fb52a3c4becbe83c9429f9b2f119c2vboxsync * Copyright (C) 2006-2008 Sun Microsystems, Inc.
5964f60ed7fb52a3c4becbe83c9429f9b2f119c2vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
5964f60ed7fb52a3c4becbe83c9429f9b2f119c2vboxsync * available from http://www.virtualbox.org. This file is free software;
5964f60ed7fb52a3c4becbe83c9429f9b2f119c2vboxsync * you can redistribute it and/or modify it under the terms of the GNU
5964f60ed7fb52a3c4becbe83c9429f9b2f119c2vboxsync * General Public License (GPL) as published by the Free Software
5964f60ed7fb52a3c4becbe83c9429f9b2f119c2vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
5964f60ed7fb52a3c4becbe83c9429f9b2f119c2vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
5964f60ed7fb52a3c4becbe83c9429f9b2f119c2vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
5964f60ed7fb52a3c4becbe83c9429f9b2f119c2vboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
5964f60ed7fb52a3c4becbe83c9429f9b2f119c2vboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
5964f60ed7fb52a3c4becbe83c9429f9b2f119c2vboxsync * additional information or have any questions.
5964f60ed7fb52a3c4becbe83c9429f9b2f119c2vboxsync/*******************************************************************************
5964f60ed7fb52a3c4becbe83c9429f9b2f119c2vboxsync* Header files *
5964f60ed7fb52a3c4becbe83c9429f9b2f119c2vboxsync*******************************************************************************/
0d282f291fba8c5597b0cc338058a7976938975cvboxsync/* All lwip header files are not C++ safe. So hack around this. */
0d282f291fba8c5597b0cc338058a7976938975cvboxsync#endif /* VBOX_WITH_INIP */
5964f60ed7fb52a3c4becbe83c9429f9b2f119c2vboxsync/* Small hack to get at lwIP initialized status */
5964f60ed7fb52a3c4becbe83c9429f9b2f119c2vboxsyncextern bool DevINIPConfigured(void);
5964f60ed7fb52a3c4becbe83c9429f9b2f119c2vboxsync#endif /* VBOX_WITH_INIP */
0d282f291fba8c5597b0cc338058a7976938975cvboxsync/*******************************************************************************
0d282f291fba8c5597b0cc338058a7976938975cvboxsync* Defined types, constants and macros *
fff1586cd63d9b86dc6e14cb958a146446a60042vboxsync*******************************************************************************/
fff1586cd63d9b86dc6e14cb958a146446a60042vboxsync/** Converts a pointer to VBOXDISK::IMedia to a PVBOXDISK. */
fff1586cd63d9b86dc6e14cb958a146446a60042vboxsync ( (PVBOXDISK)((uintptr_t)pInterface - RT_OFFSETOF(VBOXDISK, IMedia)) )
fff1586cd63d9b86dc6e14cb958a146446a60042vboxsync/** Converts a pointer to PDMDRVINS::IBase to a PPDMDRVINS. */
0d282f291fba8c5597b0cc338058a7976938975cvboxsync ( (PPDMDRVINS)((uintptr_t)pInterface - RT_OFFSETOF(PDMDRVINS, IBase)) )
0d282f291fba8c5597b0cc338058a7976938975cvboxsync/** Converts a pointer to PDMDRVINS::IBase to a PVBOXDISK. */
5964f60ed7fb52a3c4becbe83c9429f9b2f119c2vboxsync ( PDMINS_2_DATA(PDMIBASE_2_DRVINS(pInterface), PVBOXDISK) )
5964f60ed7fb52a3c4becbe83c9429f9b2f119c2vboxsync/** Converts a pointer to VBOXDISK::IMediaAsync to a PVBOXDISK. */
549e45e906cbe16cbeb2704c3a7354aa8ab022b4vboxsync ( (PVBOXDISK)((uintptr_t)pInterface - RT_OFFSETOF(VBOXDISK, IMediaAsync)) )
549e45e906cbe16cbeb2704c3a7354aa8ab022b4vboxsync * VBox disk container, image information, private part.
549e45e906cbe16cbeb2704c3a7354aa8ab022b4vboxsynctypedef struct VBOXIMAGE
5964f60ed7fb52a3c4becbe83c9429f9b2f119c2vboxsync /** Pointer to next image. */
0d282f291fba8c5597b0cc338058a7976938975cvboxsync /** Pointer to list of VD interfaces. Per-image. */
5964f60ed7fb52a3c4becbe83c9429f9b2f119c2vboxsync /** Common structure for the configuration information interface. */
5964f60ed7fb52a3c4becbe83c9429f9b2f119c2vboxsync * Storage backend data.
fff1586cd63d9b86dc6e14cb958a146446a60042vboxsync /** PDM async completion end point. */
fff1586cd63d9b86dc6e14cb958a146446a60042vboxsync /** The template. */
0d282f291fba8c5597b0cc338058a7976938975cvboxsync /** Event semaphore for synchronous operations. */
549e45e906cbe16cbeb2704c3a7354aa8ab022b4vboxsync /** Flag whether a synchronous operation is currently pending. */
549e45e906cbe16cbeb2704c3a7354aa8ab022b4vboxsync volatile bool fSyncIoPending;
549e45e906cbe16cbeb2704c3a7354aa8ab022b4vboxsync /** Callback routine */
0d282f291fba8c5597b0cc338058a7976938975cvboxsync * VBox disk container media main structure, private part.
0d282f291fba8c5597b0cc338058a7976938975cvboxsync * @implements PDMIMEDIA
0d282f291fba8c5597b0cc338058a7976938975cvboxsync * @implements PDMIMEDIAASYNC
0d282f291fba8c5597b0cc338058a7976938975cvboxsync * @implements VDINTERFACEERROR
0d282f291fba8c5597b0cc338058a7976938975cvboxsync * @implements VDINTERFACETCPNET
0d282f291fba8c5597b0cc338058a7976938975cvboxsync * @implements VDINTERFACEASYNCIO
5964f60ed7fb52a3c4becbe83c9429f9b2f119c2vboxsync * @implements VDINTERFACECONFIG
5964f60ed7fb52a3c4becbe83c9429f9b2f119c2vboxsynctypedef struct VBOXDISK
5964f60ed7fb52a3c4becbe83c9429f9b2f119c2vboxsync /** The VBox disk container. */
0d282f291fba8c5597b0cc338058a7976938975cvboxsync /** The media interface. */
0d282f291fba8c5597b0cc338058a7976938975cvboxsync /** Pointer to the driver instance. */
5964f60ed7fb52a3c4becbe83c9429f9b2f119c2vboxsync /** Flag whether suspend has changed image open mode to read only. */
0d282f291fba8c5597b0cc338058a7976938975cvboxsync /** Flag whether to use the runtime (true) or startup error facility. */
0d282f291fba8c5597b0cc338058a7976938975cvboxsync /** Pointer to list of VD interfaces. Per-disk. */
0d282f291fba8c5597b0cc338058a7976938975cvboxsync /** Common structure for the supported error interface. */
0d282f291fba8c5597b0cc338058a7976938975cvboxsync /** Callback table for error interface. */
0d282f291fba8c5597b0cc338058a7976938975cvboxsync /** Common structure for the supported TCP network stack interface. */
0d282f291fba8c5597b0cc338058a7976938975cvboxsync /** Callback table for TCP network stack interface. */
0d282f291fba8c5597b0cc338058a7976938975cvboxsync /** Common structure for the supported async I/O interface. */
0d282f291fba8c5597b0cc338058a7976938975cvboxsync /** Callback table for async I/O interface. */
0d282f291fba8c5597b0cc338058a7976938975cvboxsync /** Callback table for the configuration information interface. */
0d282f291fba8c5597b0cc338058a7976938975cvboxsync /** Flag whether opened disk suppports async I/O operations. */
0d282f291fba8c5597b0cc338058a7976938975cvboxsync /** The async media interface. */
5964f60ed7fb52a3c4becbe83c9429f9b2f119c2vboxsync /** The async media port interface above. */
549e45e906cbe16cbeb2704c3a7354aa8ab022b4vboxsync /** Pointer to the list of data we need to keep per image. */
549e45e906cbe16cbeb2704c3a7354aa8ab022b4vboxsync/*******************************************************************************
549e45e906cbe16cbeb2704c3a7354aa8ab022b4vboxsync* Internal Functions *
549e45e906cbe16cbeb2704c3a7354aa8ab022b4vboxsync*******************************************************************************/
549e45e906cbe16cbeb2704c3a7354aa8ab022b4vboxsync * Internal: allocate new image descriptor and put it in the list
549e45e906cbe16cbeb2704c3a7354aa8ab022b4vboxsync PVBOXIMAGE pImage = (PVBOXIMAGE)RTMemAllocZ(sizeof(VBOXIMAGE));
0d282f291fba8c5597b0cc338058a7976938975cvboxsync * Internal: free the list of images descriptors.
fff1586cd63d9b86dc6e14cb958a146446a60042vboxsync * Undo the temporary read-only status of the image.
fff1586cd63d9b86dc6e14cb958a146446a60042vboxsync * @returns VBox status code.
fff1586cd63d9b86dc6e14cb958a146446a60042vboxsync * @param pThis The driver instance data.
0d282f291fba8c5597b0cc338058a7976938975cvboxsync rc = VDGetOpenFlags(pThis->pDisk, VD_LAST_IMAGE, &uOpenFlags);
e75313c24325ec7bec84fa349abb39e246b6cc86vboxsync rc = VDSetOpenFlags(pThis->pDisk, VD_LAST_IMAGE, uOpenFlags);
7f22d63b8c416918f318efcd1b28b883d934e84dvboxsync/*******************************************************************************
7f22d63b8c416918f318efcd1b28b883d934e84dvboxsync* Error reporting callback *
7f22d63b8c416918f318efcd1b28b883d934e84dvboxsync*******************************************************************************/
5964f60ed7fb52a3c4becbe83c9429f9b2f119c2vboxsyncstatic void drvvdErrorCallback(void *pvUser, int rc, RT_SRC_POS_DECL,
fff1586cd63d9b86dc6e14cb958a146446a60042vboxsync PVBOXDISK pThis = PDMINS_2_DATA(pDrvIns, PVBOXDISK);
fff1586cd63d9b86dc6e14cb958a146446a60042vboxsync /* We must not pass VMSETRTERR_FLAGS_FATAL as it could lead to a
fff1586cd63d9b86dc6e14cb958a146446a60042vboxsync * deadlock: We are probably executed in a thread context != EMT
5964f60ed7fb52a3c4becbe83c9429f9b2f119c2vboxsync * and the EM thread would wait until every thread is suspended
5964f60ed7fb52a3c4becbe83c9429f9b2f119c2vboxsync * but we would wait for the EM thread ... */
5964f60ed7fb52a3c4becbe83c9429f9b2f119c2vboxsync PDMDrvHlpVMSetRuntimeErrorV(pDrvIns, /* fFlags=*/ 0, "DrvVD", pszFormat, va);
5964f60ed7fb52a3c4becbe83c9429f9b2f119c2vboxsync PDMDrvHlpVMSetErrorV(pDrvIns, rc, RT_SRC_POS_ARGS, pszFormat, va);
5964f60ed7fb52a3c4becbe83c9429f9b2f119c2vboxsync/*******************************************************************************
5964f60ed7fb52a3c4becbe83c9429f9b2f119c2vboxsync* VD Async I/O interface implementation *
7f22d63b8c416918f318efcd1b28b883d934e84dvboxsync*******************************************************************************/
5964f60ed7fb52a3c4becbe83c9429f9b2f119c2vboxsyncstatic DECLCALLBACK(void) drvvdAsyncTaskCompleted(PPDMDRVINS pDrvIns, void *pvTemplateUser, void *pvUser)
5964f60ed7fb52a3c4becbe83c9429f9b2f119c2vboxsync PVBOXDISK pThis = PDMINS_2_DATA(pDrvIns, PVBOXDISK);
5964f60ed7fb52a3c4becbe83c9429f9b2f119c2vboxsync PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)pvTemplateUser;
0d282f291fba8c5597b0cc338058a7976938975cvboxsync rc = pStorageBackend->pfnCompleted(pvUser, &pvCallerUser);
4b0369e0c9bcae37f2801e0f7b92509bbbaf4becvboxsync rc = pThis->pDrvMediaAsyncPort->pfnTransferCompleteNotify(pThis->pDrvMediaAsyncPort, pvCallerUser);
0d282f291fba8c5597b0cc338058a7976938975cvboxsync AssertMsg(rc == VERR_VD_ASYNC_IO_IN_PROGRESS, ("Invalid return code from disk backend rc=%Rrc\n", rc));
0d282f291fba8c5597b0cc338058a7976938975cvboxsyncstatic DECLCALLBACK(int) drvvdAsyncIOOpen(void *pvUser, const char *pszLocation, unsigned uOpenFlags,
0d282f291fba8c5597b0cc338058a7976938975cvboxsync PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)RTMemAllocZ(sizeof(DRVVDSTORAGEBACKEND));
fff1586cd63d9b86dc6e14cb958a146446a60042vboxsync rc = PDMDrvHlpPDMAsyncCompletionTemplateCreate(pDrvVD->pDrvIns, &pStorageBackend->pTemplate,
fff1586cd63d9b86dc6e14cb958a146446a60042vboxsync drvvdAsyncTaskCompleted, pStorageBackend, "AsyncTaskCompleted");
e75313c24325ec7bec84fa349abb39e246b6cc86vboxsync rc = PDMR3AsyncCompletionEpCreateForFile(&pStorageBackend->pEndpoint, pszLocation,
fff1586cd63d9b86dc6e14cb958a146446a60042vboxsync uOpenFlags & VD_INTERFACEASYNCIO_OPEN_FLAGS_READONLY
fff1586cd63d9b86dc6e14cb958a146446a60042vboxsync ? PDMACEP_FILE_FLAGS_READ_ONLY | PDMACEP_FILE_FLAGS_CACHING
5964f60ed7fb52a3c4becbe83c9429f9b2f119c2vboxsync PDMR3AsyncCompletionTemplateDestroy(pStorageBackend->pTemplate);
0d282f291fba8c5597b0cc338058a7976938975cvboxsyncstatic DECLCALLBACK(int) drvvdAsyncIOClose(void *pvUser, void *pStorage)
5964f60ed7fb52a3c4becbe83c9429f9b2f119c2vboxsync PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)pStorage;
fff1586cd63d9b86dc6e14cb958a146446a60042vboxsync PDMR3AsyncCompletionEpClose(pStorageBackend->pEndpoint);
fff1586cd63d9b86dc6e14cb958a146446a60042vboxsync PDMR3AsyncCompletionTemplateDestroy(pStorageBackend->pTemplate);
a84b1f249b9c68d3a05455fe946d02cc9a6772b5vboxsyncstatic DECLCALLBACK(int) drvvdAsyncIOGetSize(void *pvUser, void *pStorage, uint64_t *pcbSize)
f847566a82fc74d59381a4a27553dbbf8c8061f4vboxsync PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)pStorage;
fff1586cd63d9b86dc6e14cb958a146446a60042vboxsync return PDMR3AsyncCompletionEpGetSize(pStorageBackend->pEndpoint, pcbSize);
return VERR_NOT_SUPPORTED;
int rc = PDMR3AsyncCompletionEpRead(pStorageBackend->pEndpoint, uOffset, &DataSeg, 1, cbRead, NULL, &pTask);
return rc;
if (pcbRead)
return VINF_SUCCESS;
int rc = PDMR3AsyncCompletionEpWrite(pStorageBackend->pEndpoint, uOffset, &DataSeg, 1, cbWrite, NULL, &pTask);
return rc;
if (pcbWritten)
return VINF_SUCCESS;
return rc;
return VINF_SUCCESS;
void **ppTask)
return PDMR3AsyncCompletionEpRead(pStorageBackend->pEndpoint, uOffset, paSegments, cSegments, cbRead,
void **ppTask)
return PDMR3AsyncCompletionEpWrite(pStorageBackend->pEndpoint, uOffset, paSegments, cSegments, cbWrite,
#ifdef VBOX_WITH_INIP
static DECLCALLBACK(int) drvvdINIPClientConnect(const char *pszAddress, uint32_t uPort, PRTSOCKET pSock)
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(RTSOCKET Sock, void *pvBuffer, size_t cbBuffer, size_t *pcbRead)
return VERR_INVALID_PARAMETER;
if (cbBytesRead < 0)
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;
fFlag = 0;
return VINF_SUCCESS;
return rc;
return rc;
return rc;
return cb;
return rc;
return rc;
return rc;
return rc;
return rc;
return rc;
return rc;
return VERR_NOT_IMPLEMENTED;
PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIAASYNC, pThis->fAsyncIOSupported ? &pThis->IMediaAsync : NULL);
return NULL;
return VINF_SUCCESS;
return VINF_SUCCESS;
unsigned uOpenFlags;
bool fHostIP = false;
bool fUseNewIo = false;
unsigned iLevel = 0;
bool fValid;
if (!fValid)
if (!pParent)
iLevel++;
if (fHostIP)
#ifndef VBOX_WITH_INIP
if (!pImage)
unsigned uOpenFlags;
if (fHonorZeroWrites)
&& !fReadOnly
&& iLevel == 0)
pszName);
iLevel--;
return rc;
sizeof(VBOXDISK),
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,