DrvVD.cpp revision b7a5b3f9f9ecce32ddacf8404c625ce0451bbdc1
77b1a2d8b5dbe2c0b5200794914239fee3c8ee5dvboxsync/** $Id$ */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/** @file
77b1a2d8b5dbe2c0b5200794914239fee3c8ee5dvboxsync *
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * VBox storage devices:
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * Media implementation for VBox disk container
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync */
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/*
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * Copyright (C) 2006-2008 Sun Microsystems, Inc.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync *
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * available from http://www.virtualbox.org. This file is free software;
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * 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
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync *
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * additional information or have any questions.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/*******************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync* Header files *
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync*******************************************************************************/
da957c069c2a3c582fe265ff88170ce4c42b499dvboxsync#define LOG_GROUP LOG_GROUP_DRV_VD
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync#include <VBox/VBoxHDD-new.h>
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync#include <VBox/pdmdrv.h>
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync#include <iprt/alloc.h>
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync#include <iprt/assert.h>
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync#include <iprt/uuid.h>
9496f2d398b49813176939d7a339ae513d5175efvboxsync#include <iprt/file.h>
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync#include <iprt/string.h>
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync#include <iprt/cache.h>
a3369a746b56a8966dd78619f4d191c9662f400dvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync#include "Builtins.h"
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync/*******************************************************************************
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync* Defined types, constants and macros *
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync*******************************************************************************/
a3369a746b56a8966dd78619f4d191c9662f400dvboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/** Converts a pointer to VDIDISK::IMedia to a PVBOXDISK. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync#define PDMIMEDIA_2_VBOXDISK(pInterface) \
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync ( (PVBOXDISK)((uintptr_t)pInterface - RT_OFFSETOF(VBOXDISK, IMedia)) )
a3369a746b56a8966dd78619f4d191c9662f400dvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync/** Converts a pointer to PDMDRVINS::IBase to a PPDMDRVINS. */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync#define PDMIBASE_2_DRVINS(pInterface) \
a3369a746b56a8966dd78619f4d191c9662f400dvboxsync ( (PPDMDRVINS)((uintptr_t)pInterface - RT_OFFSETOF(PDMDRVINS, IBase)) )
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/** Converts a pointer to PDMDRVINS::IBase to a PVBOXDISK. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync#define PDMIBASE_2_VBOXDISK(pInterface) \
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync ( PDMINS2DATA(PDMIBASE_2_DRVINS(pInterface), PVBOXDISK) )
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/** Converts a pointer to VBOXDISK::IMediaAsync to a PVBOXDISK. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync#define PDMIMEDIAASYNC_2_VBOXDISK(pInterface) \
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync ( (PVBOXDISK)((uintptr_t)pInterface - RT_OFFSETOF(VBOXDISK, IMediaAsync)) )
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/** Converts a pointer to VBOXDISK::ITransportAsyncPort to a PVBOXDISK. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync#define PDMITRANSPORTASYNCPORT_2_VBOXDISK(pInterface) \
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync ( (PVBOXDISK)((uintptr_t)pInterface - RT_OFFSETOF(VBOXDISK, ITransportAsyncPort)) )
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/**
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * Structure for an async I/O task.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync */
0abd77741a608f6c41c8dfcd4781b8b84adf1044vboxsynctypedef struct DRVVDASYNCTASK
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync{
9496f2d398b49813176939d7a339ae513d5175efvboxsync /** Callback which is called on completion. */
9496f2d398b49813176939d7a339ae513d5175efvboxsync PFNVDCOMPLETED pfnCompleted;
9496f2d398b49813176939d7a339ae513d5175efvboxsync /** Opqaue user data which is passed on completion. */
9496f2d398b49813176939d7a339ae513d5175efvboxsync void *pvUser;
9496f2d398b49813176939d7a339ae513d5175efvboxsync /** Opaque user data the caller passed on transfer initiation. */
9496f2d398b49813176939d7a339ae513d5175efvboxsync void *pvUserCaller;
9496f2d398b49813176939d7a339ae513d5175efvboxsync} DRVVDASYNCTASK, *PDRVVDASYNCTASK;
9496f2d398b49813176939d7a339ae513d5175efvboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsync/**
9496f2d398b49813176939d7a339ae513d5175efvboxsync * VBox disk container media main structure, private part.
9496f2d398b49813176939d7a339ae513d5175efvboxsync */
9496f2d398b49813176939d7a339ae513d5175efvboxsynctypedef struct VBOXDISK
9496f2d398b49813176939d7a339ae513d5175efvboxsync{
9496f2d398b49813176939d7a339ae513d5175efvboxsync /** The VBox disk container. */
9496f2d398b49813176939d7a339ae513d5175efvboxsync PVBOXHDD pDisk;
9496f2d398b49813176939d7a339ae513d5175efvboxsync /** The media interface. */
9496f2d398b49813176939d7a339ae513d5175efvboxsync PDMIMEDIA IMedia;
9496f2d398b49813176939d7a339ae513d5175efvboxsync /** Pointer to the driver instance. */
9496f2d398b49813176939d7a339ae513d5175efvboxsync PPDMDRVINS pDrvIns;
9496f2d398b49813176939d7a339ae513d5175efvboxsync /** Flag whether suspend has changed image open mode to read only. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync bool fTempReadOnly;
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync /** Common structure for the supported error interface. */
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync VDINTERFACE VDIError;
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync /** Callback table for error interface. */
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync VDINTERFACEERROR VDIErrorCallbacks;
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync /** Common structure for the supported async I/O interface. */
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync VDINTERFACE VDIAsyncIO;
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync /** Callback table for async I/O interface. */
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync VDINTERFACEASYNCIO VDIAsyncIOCallbacks;
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync /** Common structure for the configuration information interface. */
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync VDINTERFACE VDIConfig;
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync /** Callback table for the configuration information interface. */
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync VDINTERFACECONFIG VDIConfigCallbacks;
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync /** Flag whether opened disk suppports async I/O operations. */
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync bool fAsyncIOSupported;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /** The async media interface. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync PDMIMEDIAASYNC IMediaAsync;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /** The async media port interface above. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync PPDMIMEDIAASYNCPORT pDrvMediaAsyncPort;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /** Pointer to the asynchronous media driver below. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync PPDMITRANSPORTASYNC pDrvTransportAsync;
9496f2d398b49813176939d7a339ae513d5175efvboxsync /** Async transport port interface. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync PDMITRANSPORTASYNCPORT ITransportAsyncPort;
9496f2d398b49813176939d7a339ae513d5175efvboxsync /** Our cache to reduce allocation overhead. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync PRTOBJCACHE pCache;
9496f2d398b49813176939d7a339ae513d5175efvboxsync} VBOXDISK, *PVBOXDISK;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsync/*******************************************************************************
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync* Error reporting callback *
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync*******************************************************************************/
9496f2d398b49813176939d7a339ae513d5175efvboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsyncstatic void drvvdErrorCallback(void *pvUser, int rc, RT_SRC_POS_DECL,
9496f2d398b49813176939d7a339ae513d5175efvboxsync const char *pszFormat, va_list va)
9496f2d398b49813176939d7a339ae513d5175efvboxsync{
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync PPDMDRVINS pDrvIns = (PPDMDRVINS)pvUser;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync pDrvIns->pDrvHlp->pfnVMSetErrorV(pDrvIns, rc, RT_SRC_POS_ARGS, pszFormat, va);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync}
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsync/*******************************************************************************
9496f2d398b49813176939d7a339ae513d5175efvboxsync* VD Async I/O interface implementation *
9496f2d398b49813176939d7a339ae513d5175efvboxsync*******************************************************************************/
9496f2d398b49813176939d7a339ae513d5175efvboxsync
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsyncstatic DECLCALLBACK(int) drvvdAsyncIOOpen(void *pvUser, const char *pszLocation, bool fReadonly, void **ppStorage)
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync{
9496f2d398b49813176939d7a339ae513d5175efvboxsync PVBOXDISK pDrvVD = (PVBOXDISK)pvUser;
9496f2d398b49813176939d7a339ae513d5175efvboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsync return pDrvVD->pDrvTransportAsync->pfnOpen(pDrvVD->pDrvTransportAsync, pszLocation, fReadonly, ppStorage);
9496f2d398b49813176939d7a339ae513d5175efvboxsync}
9496f2d398b49813176939d7a339ae513d5175efvboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsyncstatic DECLCALLBACK(int) drvvdAsyncIOClose(void *pvUser, void *pStorage)
9496f2d398b49813176939d7a339ae513d5175efvboxsync{
9496f2d398b49813176939d7a339ae513d5175efvboxsync PVBOXDISK pDrvVD = (PVBOXDISK)pvUser;
9496f2d398b49813176939d7a339ae513d5175efvboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsync AssertMsg(pDrvVD->pDrvTransportAsync, ("Asynchronous function called but no async transport interface below\n"));
9496f2d398b49813176939d7a339ae513d5175efvboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsync return pDrvVD->pDrvTransportAsync->pfnClose(pDrvVD->pDrvTransportAsync, pStorage);
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync}
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic DECLCALLBACK(int) drvvdAsyncIORead(void *pvUser, void *pStorage, uint64_t uOffset,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync size_t cbRead, void *pvBuf, size_t *pcbRead)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync{
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync PVBOXDISK pDrvVD = (PVBOXDISK)pvUser;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync AssertMsg(pDrvVD->pDrvTransportAsync, ("Asynchronous function called but no async transport interface below\n"));
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync return pDrvVD->pDrvTransportAsync->pfnReadSynchronous(pDrvVD->pDrvTransportAsync,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pStorage,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync uOffset, pvBuf, cbRead, pcbRead);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync}
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic DECLCALLBACK(int) drvvdAsyncIOWrite(void *pvUser, void *pStorage, uint64_t uOffset,
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync size_t cbWrite, const void *pvBuf, size_t *pcbWritten)
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync{
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync PVBOXDISK pDrvVD = (PVBOXDISK)pvUser;
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync AssertMsg(pDrvVD->pDrvTransportAsync, ("Asynchronous function called but no async transport interface below\n"));
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync return pDrvVD->pDrvTransportAsync->pfnWriteSynchronous(pDrvVD->pDrvTransportAsync,
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync pStorage,
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync uOffset, pvBuf, cbWrite, pcbWritten);
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync}
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsyncstatic DECLCALLBACK(int) drvvdAsyncIOFlush(void *pvUser, void *pStorage)
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync{
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync PVBOXDISK pDrvVD = (PVBOXDISK)pvUser;
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync AssertMsg(pDrvVD->pDrvTransportAsync, ("Asynchronous function called but no async transport interface below\n"));
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync return pDrvVD->pDrvTransportAsync->pfnFlushSynchronous(pDrvVD->pDrvTransportAsync, pStorage);
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync}
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsyncstatic DECLCALLBACK(int) drvvdAsyncIOPrepareRead(void *pvUser, void *pStorage, uint64_t uOffset, void *pvBuf, size_t cbRead, void **ppTask)
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync{
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync PVBOXDISK pDrvVD = (PVBOXDISK)pvUser;
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync AssertMsg(pDrvVD->pDrvTransportAsync, ("Asynchronous function called but no async transport interface below\n"));
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync return pDrvVD->pDrvTransportAsync->pfnPrepareRead(pDrvVD->pDrvTransportAsync, pStorage, uOffset, pvBuf, cbRead, ppTask);
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync}
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsyncstatic DECLCALLBACK(int) drvvdAsyncIOPrepareWrite(void *pvUser, void *pStorage, uint64_t uOffset, void *pvBuf, size_t cbWrite, void **ppTask)
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync{
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync PVBOXDISK pDrvVD = (PVBOXDISK)pvUser;
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync AssertMsg(pDrvVD->pDrvTransportAsync, ("Asynchronous function called but no async transport interface below\n"));
9496f2d398b49813176939d7a339ae513d5175efvboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsync return pDrvVD->pDrvTransportAsync->pfnPrepareWrite(pDrvVD->pDrvTransportAsync, pStorage, uOffset, pvBuf, cbWrite, ppTask);
9496f2d398b49813176939d7a339ae513d5175efvboxsync}
9496f2d398b49813176939d7a339ae513d5175efvboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsyncstatic DECLCALLBACK(int) drvvdAsyncIOTasksSubmit(void *pvUser, void *apTasks[], unsigned cTasks, void *pvUser2,
9496f2d398b49813176939d7a339ae513d5175efvboxsync void *pvUserCaller, PFNVDCOMPLETED pfnTasksCompleted)
9496f2d398b49813176939d7a339ae513d5175efvboxsync{
9496f2d398b49813176939d7a339ae513d5175efvboxsync PVBOXDISK pDrvVD = (PVBOXDISK)pvUser;
9496f2d398b49813176939d7a339ae513d5175efvboxsync PDRVVDASYNCTASK pDrvVDAsyncTask;
9496f2d398b49813176939d7a339ae513d5175efvboxsync int rc;
9496f2d398b49813176939d7a339ae513d5175efvboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsync AssertMsg(pDrvVD->pDrvTransportAsync, ("Asynchronous function called but no async transport interface below\n"));
9496f2d398b49813176939d7a339ae513d5175efvboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsync rc = RTCacheRequest(pDrvVD->pCache, (void **)&pDrvVDAsyncTask);
9496f2d398b49813176939d7a339ae513d5175efvboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsync if (RT_FAILURE(rc))
9496f2d398b49813176939d7a339ae513d5175efvboxsync return rc;
9496f2d398b49813176939d7a339ae513d5175efvboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsync pDrvVDAsyncTask->pfnCompleted = pfnTasksCompleted;
9496f2d398b49813176939d7a339ae513d5175efvboxsync pDrvVDAsyncTask->pvUser = pvUser2;
b7a5b3f9f9ecce32ddacf8404c625ce0451bbdc1vboxsync pDrvVDAsyncTask->pvUserCaller = pvUserCaller;
9496f2d398b49813176939d7a339ae513d5175efvboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsync return pDrvVD->pDrvTransportAsync->pfnTasksSubmit(pDrvVD->pDrvTransportAsync, apTasks, cTasks, pDrvVDAsyncTask);
9496f2d398b49813176939d7a339ae513d5175efvboxsync}
9496f2d398b49813176939d7a339ae513d5175efvboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsync/*******************************************************************************
9496f2d398b49813176939d7a339ae513d5175efvboxsync* VD Configuration interface implementation *
9496f2d398b49813176939d7a339ae513d5175efvboxsync*******************************************************************************/
9496f2d398b49813176939d7a339ae513d5175efvboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsyncstatic bool drvvdCfgAreValuesValid(PVDCFGNODE pNode, const char *pszzValid)
9496f2d398b49813176939d7a339ae513d5175efvboxsync{
9496f2d398b49813176939d7a339ae513d5175efvboxsync return CFGMR3AreValuesValid((PCFGMNODE)pNode, pszzValid);
b7a5b3f9f9ecce32ddacf8404c625ce0451bbdc1vboxsync}
9496f2d398b49813176939d7a339ae513d5175efvboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsyncstatic int drvvdCfgQueryType(PVDCFGNODE pNode, const char *pszName, PVDCFGVALUETYPE penmType)
9496f2d398b49813176939d7a339ae513d5175efvboxsync{
9496f2d398b49813176939d7a339ae513d5175efvboxsync Assert(VDCFGVALUETYPE_INTEGER == CFGMVALUETYPE_INTEGER);
9496f2d398b49813176939d7a339ae513d5175efvboxsync Assert(VDCFGVALUETYPE_STRING == CFGMVALUETYPE_STRING);
9496f2d398b49813176939d7a339ae513d5175efvboxsync Assert(VDCFGVALUETYPE_BYTES == CFGMVALUETYPE_BYTES);
9496f2d398b49813176939d7a339ae513d5175efvboxsync return CFGMR3QueryType((PCFGMNODE)pNode, pszName, (PCFGMVALUETYPE)penmType);
9496f2d398b49813176939d7a339ae513d5175efvboxsync}
9496f2d398b49813176939d7a339ae513d5175efvboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsyncstatic int drvvdCfgQuerySize(PVDCFGNODE pNode, const char *pszName, size_t *pcb)
9496f2d398b49813176939d7a339ae513d5175efvboxsync{
9496f2d398b49813176939d7a339ae513d5175efvboxsync return CFGMR3QuerySize((PCFGMNODE)pNode, pszName, pcb);
9496f2d398b49813176939d7a339ae513d5175efvboxsync}
9496f2d398b49813176939d7a339ae513d5175efvboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsyncstatic int drvvdCfgQueryInteger(PVDCFGNODE pNode, const char *pszName, uint64_t *pu64)
9496f2d398b49813176939d7a339ae513d5175efvboxsync{
9496f2d398b49813176939d7a339ae513d5175efvboxsync return CFGMR3QueryInteger((PCFGMNODE)pNode, pszName, pu64);
9496f2d398b49813176939d7a339ae513d5175efvboxsync}
9496f2d398b49813176939d7a339ae513d5175efvboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsyncstatic int drvvdCfgQueryIntegerDef(PVDCFGNODE pNode, const char *pszName, uint64_t *pu64, uint64_t u64Def)
9496f2d398b49813176939d7a339ae513d5175efvboxsync{
9496f2d398b49813176939d7a339ae513d5175efvboxsync return CFGMR3QueryInteger((PCFGMNODE)pNode, pszName, pu64);
9496f2d398b49813176939d7a339ae513d5175efvboxsync}
9496f2d398b49813176939d7a339ae513d5175efvboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsyncstatic int drvvdCfgQueryString(PVDCFGNODE pNode, const char *pszName, char *pszString, size_t cchString)
9496f2d398b49813176939d7a339ae513d5175efvboxsync{
9496f2d398b49813176939d7a339ae513d5175efvboxsync return CFGMR3QueryString((PCFGMNODE)pNode, pszName, pszString, cchString);
9496f2d398b49813176939d7a339ae513d5175efvboxsync}
9496f2d398b49813176939d7a339ae513d5175efvboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsyncstatic int drvvdCfgQueryStringDef(PVDCFGNODE pNode, const char *pszName, char *pszString, size_t cchString, const char *pszDef)
9496f2d398b49813176939d7a339ae513d5175efvboxsync{
9496f2d398b49813176939d7a339ae513d5175efvboxsync return CFGMR3QueryStringDef((PCFGMNODE)pNode, pszName, pszString, cchString, pszDef);
9496f2d398b49813176939d7a339ae513d5175efvboxsync}
9496f2d398b49813176939d7a339ae513d5175efvboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsyncstatic int drvvdCfgQueryBytes(PVDCFGNODE pNode, const char *pszName, void *pvData, size_t cbData)
9496f2d398b49813176939d7a339ae513d5175efvboxsync{
9496f2d398b49813176939d7a339ae513d5175efvboxsync return CFGMR3QueryBytes((PCFGMNODE)pNode, pszName, pvData, cbData);
9496f2d398b49813176939d7a339ae513d5175efvboxsync}
9496f2d398b49813176939d7a339ae513d5175efvboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsync/*******************************************************************************
9496f2d398b49813176939d7a339ae513d5175efvboxsync* Media interface methods *
9496f2d398b49813176939d7a339ae513d5175efvboxsync*******************************************************************************/
9496f2d398b49813176939d7a339ae513d5175efvboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsync/** @copydoc PDMIMEDIA::pfnRead */
9496f2d398b49813176939d7a339ae513d5175efvboxsyncstatic DECLCALLBACK(int) drvvdRead(PPDMIMEDIA pInterface,
9496f2d398b49813176939d7a339ae513d5175efvboxsync uint64_t off, void *pvBuf, size_t cbRead)
9496f2d398b49813176939d7a339ae513d5175efvboxsync{
9496f2d398b49813176939d7a339ae513d5175efvboxsync LogFlow(("%s: off=%#llx pvBuf=%p cbRead=%d\n", __FUNCTION__,
9496f2d398b49813176939d7a339ae513d5175efvboxsync off, pvBuf, cbRead));
9496f2d398b49813176939d7a339ae513d5175efvboxsync PVBOXDISK pData = PDMIMEDIA_2_VBOXDISK(pInterface);
9496f2d398b49813176939d7a339ae513d5175efvboxsync int rc = VDRead(pData->pDisk, off, pvBuf, cbRead);
9496f2d398b49813176939d7a339ae513d5175efvboxsync if (RT_SUCCESS(rc))
9496f2d398b49813176939d7a339ae513d5175efvboxsync Log2(("%s: off=%#llx pvBuf=%p cbRead=%d %.*Vhxd\n", __FUNCTION__,
9496f2d398b49813176939d7a339ae513d5175efvboxsync off, pvBuf, cbRead, cbRead, pvBuf));
9496f2d398b49813176939d7a339ae513d5175efvboxsync LogFlow(("%s: returns %Vrc\n", __FUNCTION__, rc));
9496f2d398b49813176939d7a339ae513d5175efvboxsync return rc;
9496f2d398b49813176939d7a339ae513d5175efvboxsync}
9496f2d398b49813176939d7a339ae513d5175efvboxsync
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync/** @copydoc PDMIMEDIA::pfnWrite */
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsyncstatic DECLCALLBACK(int) drvvdWrite(PPDMIMEDIA pInterface,
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync uint64_t off, const void *pvBuf,
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync size_t cbWrite)
975ad9d9bc9c4dc96b41d9f67a65228b1b338e2avboxsync{
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync LogFlow(("%s: off=%#llx pvBuf=%p cbWrite=%d\n", __FUNCTION__,
975ad9d9bc9c4dc96b41d9f67a65228b1b338e2avboxsync off, pvBuf, cbWrite));
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync PVBOXDISK pData = PDMIMEDIA_2_VBOXDISK(pInterface);
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync Log2(("%s: off=%#llx pvBuf=%p cbWrite=%d %.*Vhxd\n", __FUNCTION__,
975ad9d9bc9c4dc96b41d9f67a65228b1b338e2avboxsync off, pvBuf, cbWrite, cbWrite, pvBuf));
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync int rc = VDWrite(pData->pDisk, off, pvBuf, cbWrite);
975ad9d9bc9c4dc96b41d9f67a65228b1b338e2avboxsync LogFlow(("%s: returns %Vrc\n", __FUNCTION__, rc));
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync return rc;
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync}
975ad9d9bc9c4dc96b41d9f67a65228b1b338e2avboxsync
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync/** @copydoc PDMIMEDIA::pfnFlush */
975ad9d9bc9c4dc96b41d9f67a65228b1b338e2avboxsyncstatic DECLCALLBACK(int) drvvdFlush(PPDMIMEDIA pInterface)
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync{
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync LogFlow(("%s:\n", __FUNCTION__));
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync PVBOXDISK pData = PDMIMEDIA_2_VBOXDISK(pInterface);
a3369a746b56a8966dd78619f4d191c9662f400dvboxsync int rc = VDFlush(pData->pDisk);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync LogFlow(("%s: returns %Vrc\n", __FUNCTION__, rc));
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync return rc;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync}
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync/** @copydoc PDMIMEDIA::pfnGetSize */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsyncstatic DECLCALLBACK(uint64_t) drvvdGetSize(PPDMIMEDIA pInterface)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync{
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync LogFlow(("%s:\n", __FUNCTION__));
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync PVBOXDISK pData = PDMIMEDIA_2_VBOXDISK(pInterface);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync uint64_t cb = VDGetSize(pData->pDisk, VD_LAST_IMAGE);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync LogFlow(("%s: returns %#llx (%llu)\n", __FUNCTION__, cb, cb));
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync return cb;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync}
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync/** @copydoc PDMIMEDIA::pfnIsReadOnly */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsyncstatic DECLCALLBACK(bool) drvvdIsReadOnly(PPDMIMEDIA pInterface)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync{
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync LogFlow(("%s:\n", __FUNCTION__));
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync PVBOXDISK pData = PDMIMEDIA_2_VBOXDISK(pInterface);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync bool f = VDIsReadOnly(pData->pDisk);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync LogFlow(("%s: returns %d\n", __FUNCTION__, f));
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync return f;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync}
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync/** @copydoc PDMIMEDIA::pfnBiosGetPCHSGeometry */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsyncstatic DECLCALLBACK(int) drvvdBiosGetPCHSGeometry(PPDMIMEDIA pInterface,
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync PPDMMEDIAGEOMETRY pPCHSGeometry)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync{
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync LogFlow(("%s:\n", __FUNCTION__));
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync PVBOXDISK pData = PDMIMEDIA_2_VBOXDISK(pInterface);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync int rc = VDGetPCHSGeometry(pData->pDisk, VD_LAST_IMAGE, pPCHSGeometry);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync if (RT_FAILURE(rc))
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync {
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync Log(("%s: geometry not available.\n", __FUNCTION__));
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync rc = VERR_PDM_GEOMETRY_NOT_SET;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync }
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync LogFlow(("%s: returns %Vrc (CHS=%d/%d/%d)\n", __FUNCTION__,
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync rc, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors));
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync return rc;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync}
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync/** @copydoc PDMIMEDIA::pfnBiosSetPCHSGeometry */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsyncstatic DECLCALLBACK(int) drvvdBiosSetPCHSGeometry(PPDMIMEDIA pInterface,
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync PCPDMMEDIAGEOMETRY pPCHSGeometry)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync{
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync LogFlow(("%s: CHS=%d/%d/%d\n", __FUNCTION__,
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors));
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync PVBOXDISK pData = PDMIMEDIA_2_VBOXDISK(pInterface);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync int rc = VDSetPCHSGeometry(pData->pDisk, VD_LAST_IMAGE, pPCHSGeometry);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync LogFlow(("%s: returns %Vrc\n", __FUNCTION__, rc));
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync return rc;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync}
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync/** @copydoc PDMIMEDIA::pfnBiosGetLCHSGeometry */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsyncstatic DECLCALLBACK(int) drvvdBiosGetLCHSGeometry(PPDMIMEDIA pInterface,
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync PPDMMEDIAGEOMETRY pLCHSGeometry)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync{
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync LogFlow(("%s:\n", __FUNCTION__));
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync PVBOXDISK pData = PDMIMEDIA_2_VBOXDISK(pInterface);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync int rc = VDGetLCHSGeometry(pData->pDisk, VD_LAST_IMAGE, pLCHSGeometry);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync if (RT_FAILURE(rc))
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync {
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync Log(("%s: geometry not available.\n", __FUNCTION__));
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync rc = VERR_PDM_GEOMETRY_NOT_SET;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync }
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync LogFlow(("%s: returns %Vrc (CHS=%d/%d/%d)\n", __FUNCTION__,
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync rc, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors));
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync return rc;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync}
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync/** @copydoc PDMIMEDIA::pfnBiosSetLCHSGeometry */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsyncstatic DECLCALLBACK(int) drvvdBiosSetLCHSGeometry(PPDMIMEDIA pInterface,
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync PCPDMMEDIAGEOMETRY pLCHSGeometry)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync{
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync LogFlow(("%s: CHS=%d/%d/%d\n", __FUNCTION__,
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors));
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync PVBOXDISK pData = PDMIMEDIA_2_VBOXDISK(pInterface);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync int rc = VDSetLCHSGeometry(pData->pDisk, VD_LAST_IMAGE, pLCHSGeometry);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync LogFlow(("%s: returns %Vrc\n", __FUNCTION__, rc));
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync return rc;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync}
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync/** @copydoc PDMIMEDIA::pfnGetUuid */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsyncstatic DECLCALLBACK(int) drvvdGetUuid(PPDMIMEDIA pInterface, PRTUUID pUuid)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync{
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync LogFlow(("%s:\n", __FUNCTION__));
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync PVBOXDISK pData = PDMIMEDIA_2_VBOXDISK(pInterface);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync int rc = VDGetUuid(pData->pDisk, 0, pUuid);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync LogFlow(("%s: returns %Vrc ({%Vuuid})\n", __FUNCTION__, rc, pUuid));
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync return rc;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync}
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync/*******************************************************************************
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync* Async Media interface methods *
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync*******************************************************************************/
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsyncstatic DECLCALLBACK(int) drvvdStartRead(PPDMIMEDIAASYNC pInterface, uint64_t uOffset,
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync PPDMDATASEG paSeg, unsigned cSeg,
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync size_t cbRead, void *pvUser)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync{
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync LogFlow(("%s: uOffset=%#llx paSeg=%#p cSeg=%u cbRead=%d\n pvUser=%#p", __FUNCTION__,
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync uOffset, paSeg, cSeg, cbRead, pvUser));
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync PVBOXDISK pData = PDMIMEDIAASYNC_2_VBOXDISK(pInterface);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync int rc = VDAsyncRead(pData->pDisk, uOffset, cbRead, paSeg, cSeg, pvUser);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync LogFlow(("%s: returns %Vrc\n", __FUNCTION__, rc));
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync return rc;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync}
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsyncstatic DECLCALLBACK(int) drvvdStartWrite(PPDMIMEDIAASYNC pInterface, uint64_t uOffset,
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync PPDMDATASEG paSeg, unsigned cSeg,
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync size_t cbWrite, void *pvUser)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync{
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync LogFlow(("%s: uOffset=%#llx paSeg=%#p cSeg=%u cbWrite=%d\n pvUser=%#p", __FUNCTION__,
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync uOffset, paSeg, cSeg, cbWrite, pvUser));
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync PVBOXDISK pData = PDMIMEDIAASYNC_2_VBOXDISK(pInterface);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync int rc = VDAsyncWrite(pData->pDisk, uOffset, cbWrite, paSeg, cSeg, pvUser);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync LogFlow(("%s: returns %Vrc\n", __FUNCTION__, rc));
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync return rc;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync}
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync/*******************************************************************************
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync* Async transport port interface methods *
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync*******************************************************************************/
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsyncstatic DECLCALLBACK(int) drvvdTasksCompleteNotify(PPDMITRANSPORTASYNCPORT pInterface, void *pvUser)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync{
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync PVBOXDISK pData = PDMITRANSPORTASYNCPORT_2_VBOXDISK(pInterface);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync PDRVVDASYNCTASK pDrvVDAsyncTask = (PDRVVDASYNCTASK)pvUser;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync int rc = VINF_VDI_ASYNC_IO_FINISHED;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync /* Having a completion callback for a task is not mandatory. */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync if (pDrvVDAsyncTask->pfnCompleted)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync rc = pDrvVDAsyncTask->pfnCompleted(pDrvVDAsyncTask->pvUser);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync /* Check if the request is finished. */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync if (rc == VINF_VDI_ASYNC_IO_FINISHED)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync {
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync rc = pData->pDrvMediaAsyncPort->pfnTransferCompleteNotify(pData->pDrvMediaAsyncPort, pDrvVDAsyncTask->pvUserCaller);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync }
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync else if (rc == VERR_VDI_ASYNC_IO_IN_PROGRESS)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync rc = VINF_SUCCESS;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync rc = RTCacheInsert(pData->pCache, pDrvVDAsyncTask);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync AssertRC(rc);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync return rc;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync}
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync/*******************************************************************************
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync* Base interface methods *
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync*******************************************************************************/
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync/** @copydoc PDMIBASE::pfnQueryInterface */
a3369a746b56a8966dd78619f4d191c9662f400dvboxsyncstatic DECLCALLBACK(void *) drvvdQueryInterface(PPDMIBASE pInterface,
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync PDMINTERFACE enmInterface)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync{
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync PPDMDRVINS pDrvIns = PDMIBASE_2_DRVINS(pInterface);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync PVBOXDISK pData = PDMINS2DATA(pDrvIns, PVBOXDISK);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync switch (enmInterface)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync {
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync case PDMINTERFACE_BASE:
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync return &pDrvIns->IBase;
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync case PDMINTERFACE_MEDIA:
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync return &pData->IMedia;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync case PDMINTERFACE_MEDIA_ASYNC:
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync return pData->fAsyncIOSupported ? &pData->IMediaAsync : NULL;
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync case PDMINTERFACE_TRANSPORT_ASYNC_PORT:
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync return &pData->ITransportAsyncPort;
b7a5b3f9f9ecce32ddacf8404c625ce0451bbdc1vboxsync default:
ff88d4153cd65650577e8c2d1a5a3fdfa0404a80vboxsync return NULL;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync }
fe813b3594039ba864493438e78ee0e7132bc445vboxsync}
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/*******************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync* Driver methods *
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync*******************************************************************************/
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/**
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * Construct a VBox disk media driver instance.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync *
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync * @returns VBox status.
ff88d4153cd65650577e8c2d1a5a3fdfa0404a80vboxsync * @param pDrvIns The driver instance data.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * If the registration structure is needed, pDrvIns->pDrvReg points to it.
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync * @param pCfgHandle Configuration node handle for the driver. Use this to obtain the configuration
fe813b3594039ba864493438e78ee0e7132bc445vboxsync * of the driver instance. It's also found in pDrvIns->pCfgHandle as it's expected
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * to be used frequently in this function.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic DECLCALLBACK(int) drvvdConstruct(PPDMDRVINS pDrvIns,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync PCFGMNODE pCfgHandle)
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync{
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync LogFlow(("%s:\n", __FUNCTION__));
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync PVBOXDISK pData = PDMINS2DATA(pDrvIns, PVBOXDISK);
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync int rc = VINF_SUCCESS;
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync char *pszName = NULL; /**< The path of the disk image file. */
fe813b3594039ba864493438e78ee0e7132bc445vboxsync char *pszFormat = NULL; /**< The format backed to use for this image. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync bool fReadOnly; /**< True if the media is readonly. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync bool fHonorZeroWrites; /**< True if zero blocks should be written. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /*
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync * Init the static parts.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pDrvIns->IBase.pfnQueryInterface = drvvdQueryInterface;
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync pData->pDrvIns = pDrvIns;
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync pData->fTempReadOnly = false;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pData->pDisk = NULL;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* IMedia */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pData->IMedia.pfnRead = drvvdRead;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pData->IMedia.pfnWrite = drvvdWrite;
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync pData->IMedia.pfnFlush = drvvdFlush;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pData->IMedia.pfnGetSize = drvvdGetSize;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pData->IMedia.pfnIsReadOnly = drvvdIsReadOnly;
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync pData->IMedia.pfnBiosGetPCHSGeometry = drvvdBiosGetPCHSGeometry;
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync pData->IMedia.pfnBiosSetPCHSGeometry = drvvdBiosSetPCHSGeometry;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pData->IMedia.pfnBiosGetLCHSGeometry = drvvdBiosGetLCHSGeometry;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pData->IMedia.pfnBiosSetLCHSGeometry = drvvdBiosSetLCHSGeometry;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pData->IMedia.pfnGetUuid = drvvdGetUuid;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync /* IMediaAsync */
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync pData->IMediaAsync.pfnStartRead = drvvdStartRead;
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync pData->IMediaAsync.pfnStartWrite = drvvdStartWrite;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* ITransportAsyncPort */
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync pData->ITransportAsyncPort.pfnTaskCompleteNotify = drvvdTasksCompleteNotify;
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync
b7a5b3f9f9ecce32ddacf8404c625ce0451bbdc1vboxsync /* Initialize supported VD interfaces. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pData->VDIErrorCallbacks.cbSize = sizeof(VDINTERFACEERROR);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pData->VDIErrorCallbacks.enmInterface = VDINTERFACETYPE_ERROR;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pData->VDIErrorCallbacks.pfnError = drvvdErrorCallback;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
fe813b3594039ba864493438e78ee0e7132bc445vboxsync rc = VDInterfaceCreate(&pData->VDIError, "DrvVD_VDIError", VDINTERFACETYPE_ERROR,
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync &pData->VDIErrorCallbacks, pDrvIns, NULL);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync AssertRC(rc);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pData->VDIAsyncIOCallbacks.cbSize = sizeof(VDINTERFACEASYNCIO);
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync pData->VDIAsyncIOCallbacks.enmInterface = VDINTERFACETYPE_ASYNCIO;
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync pData->VDIAsyncIOCallbacks.pfnOpen = drvvdAsyncIOOpen;
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync pData->VDIAsyncIOCallbacks.pfnClose = drvvdAsyncIOClose;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pData->VDIAsyncIOCallbacks.pfnRead = drvvdAsyncIORead;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pData->VDIAsyncIOCallbacks.pfnWrite = drvvdAsyncIOWrite;
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync pData->VDIAsyncIOCallbacks.pfnFlush = drvvdAsyncIOFlush;
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync pData->VDIAsyncIOCallbacks.pfnPrepareRead = drvvdAsyncIOPrepareRead;
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync pData->VDIAsyncIOCallbacks.pfnPrepareWrite = drvvdAsyncIOPrepareWrite;
594521f7faf13f7a88f31e6cd76629bd67340229vboxsync pData->VDIAsyncIOCallbacks.pfnTasksSubmit = drvvdAsyncIOTasksSubmit;
e04eeee1b306d610b0441cee9bf1c750100254d5vboxsync
fe813b3594039ba864493438e78ee0e7132bc445vboxsync rc = VDInterfaceCreate(&pData->VDIAsyncIO, "DrvVD_AsyncIO", VDINTERFACETYPE_ASYNCIO,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync &pData->VDIAsyncIOCallbacks, pData, &pData->VDIError);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync AssertRC(rc);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync pData->VDIConfigCallbacks.cbSize = sizeof(VDINTERFACECONFIG);
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync pData->VDIConfigCallbacks.enmInterface = VDINTERFACETYPE_CONFIG;
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync pData->VDIConfigCallbacks.pfnAreValuesValid = drvvdCfgAreValuesValid;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pData->VDIConfigCallbacks.pfnQueryType = drvvdCfgQueryType;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pData->VDIConfigCallbacks.pfnQuerySize = drvvdCfgQuerySize;
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync pData->VDIConfigCallbacks.pfnQueryInteger = drvvdCfgQueryInteger;
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync pData->VDIConfigCallbacks.pfnQueryIntegerDef = drvvdCfgQueryIntegerDef;
b7a5b3f9f9ecce32ddacf8404c625ce0451bbdc1vboxsync pData->VDIConfigCallbacks.pfnQueryString = drvvdCfgQueryString;
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync pData->VDIConfigCallbacks.pfnQueryStringDef = drvvdCfgQueryStringDef;
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync pData->VDIConfigCallbacks.pfnQueryBytes = drvvdCfgQueryBytes;
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync /** @todo TEMP! this isn't really correct - this needs to be made per image,
fe813b3594039ba864493438e78ee0e7132bc445vboxsync * as CFGM needs access to the right configuration node for each image.
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync * At the moment this is harmless, as iSCSI can only be used as a base
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * image, and no other backend uses the private data for these callbacks. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync rc = VDInterfaceCreate(&pData->VDIConfig, "DrvVD_Config", VDINTERFACETYPE_CONFIG,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync &pData->VDIConfigCallbacks, NULL /**< @todo TEMP */, &pData->VDIAsyncIO);
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync AssertRC(rc);
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync /* Try to attach async media port interface above.*/
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pData->pDrvMediaAsyncPort = (PPDMIMEDIAASYNCPORT)pDrvIns->pUpBase->pfnQueryInterface(pDrvIns->pUpBase, PDMINTERFACE_MEDIA_ASYNC_PORT);
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync /*
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync * Attach the async transport driver below of the device above us implements the
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync * async interface.
594521f7faf13f7a88f31e6cd76629bd67340229vboxsync */
e04eeee1b306d610b0441cee9bf1c750100254d5vboxsync if (pData->pDrvMediaAsyncPort)
fe813b3594039ba864493438e78ee0e7132bc445vboxsync {
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* Try to attach the driver. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync PPDMIBASE pBase;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync rc = pDrvIns->pDrvHlp->pfnAttach(pDrvIns, &pBase);
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync if (rc == VERR_PDM_NO_ATTACHED_DRIVER)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync {
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /*
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync * Though the device supports async I/O the backend seems to not support it.
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync * Revert to non async I/O.
af90f37ee9175da3aed36bda13519a917cc4effbvboxsync */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pData->pDrvMediaAsyncPort = NULL;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync }
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync else if (RT_FAILURE(rc))
9496f2d398b49813176939d7a339ae513d5175efvboxsync {
9496f2d398b49813176939d7a339ae513d5175efvboxsync AssertMsgFailed(("Failed to attach async transport driver below rc=%Vrc\n", rc));
9496f2d398b49813176939d7a339ae513d5175efvboxsync }
9496f2d398b49813176939d7a339ae513d5175efvboxsync else
b7a5b3f9f9ecce32ddacf8404c625ce0451bbdc1vboxsync {
9496f2d398b49813176939d7a339ae513d5175efvboxsync /* Success query the async transport interface. */
9496f2d398b49813176939d7a339ae513d5175efvboxsync pData->pDrvTransportAsync = (PPDMITRANSPORTASYNC)pBase->pfnQueryInterface(pBase, PDMINTERFACE_TRANSPORT_ASYNC);
9496f2d398b49813176939d7a339ae513d5175efvboxsync if (!pData->pDrvTransportAsync)
9496f2d398b49813176939d7a339ae513d5175efvboxsync {
9496f2d398b49813176939d7a339ae513d5175efvboxsync /* Whoops. */
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync AssertMsgFailed(("Configuration error: No async transport interface below!\n"));
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync return VERR_PDM_MISSING_INTERFACE_ABOVE;
fe813b3594039ba864493438e78ee0e7132bc445vboxsync }
9496f2d398b49813176939d7a339ae513d5175efvboxsync }
9496f2d398b49813176939d7a339ae513d5175efvboxsync }
9496f2d398b49813176939d7a339ae513d5175efvboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsync /*
9496f2d398b49813176939d7a339ae513d5175efvboxsync * Validate configuration and find all parent images.
9496f2d398b49813176939d7a339ae513d5175efvboxsync * It's sort of up side down from the image dependency tree.
9496f2d398b49813176939d7a339ae513d5175efvboxsync */
9496f2d398b49813176939d7a339ae513d5175efvboxsync unsigned iLevel = 0;
9496f2d398b49813176939d7a339ae513d5175efvboxsync PCFGMNODE pCurNode = pCfgHandle;
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync for (;;)
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync {
fe813b3594039ba864493438e78ee0e7132bc445vboxsync bool fValid;
9496f2d398b49813176939d7a339ae513d5175efvboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsync if (pCurNode == pCfgHandle)
9496f2d398b49813176939d7a339ae513d5175efvboxsync {
9496f2d398b49813176939d7a339ae513d5175efvboxsync /* Toplevel configuration additionally contains the global image
9496f2d398b49813176939d7a339ae513d5175efvboxsync * open flags. Some might be converted to per-image flags later. */
9496f2d398b49813176939d7a339ae513d5175efvboxsync fValid = CFGMR3AreValuesValid(pCurNode,
9496f2d398b49813176939d7a339ae513d5175efvboxsync "Format\0Path\0"
9496f2d398b49813176939d7a339ae513d5175efvboxsync "ReadOnly\0HonorZeroWrites\0");
9496f2d398b49813176939d7a339ae513d5175efvboxsync }
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync else
9496f2d398b49813176939d7a339ae513d5175efvboxsync {
594521f7faf13f7a88f31e6cd76629bd67340229vboxsync /* All other image configurations only contain image name and
b7a5b3f9f9ecce32ddacf8404c625ce0451bbdc1vboxsync * the format information. */
9496f2d398b49813176939d7a339ae513d5175efvboxsync fValid = CFGMR3AreValuesValid(pCurNode, "Format\0Path\0");
9496f2d398b49813176939d7a339ae513d5175efvboxsync }
9496f2d398b49813176939d7a339ae513d5175efvboxsync if (!fValid)
9496f2d398b49813176939d7a339ae513d5175efvboxsync {
9496f2d398b49813176939d7a339ae513d5175efvboxsync rc = PDMDrvHlpVMSetError(pDrvIns, VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES,
594521f7faf13f7a88f31e6cd76629bd67340229vboxsync RT_SRC_POS, N_("DrvVD: Configuration error: keys incorrect at level %d"), iLevel);
9496f2d398b49813176939d7a339ae513d5175efvboxsync break;
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync }
9496f2d398b49813176939d7a339ae513d5175efvboxsync
594521f7faf13f7a88f31e6cd76629bd67340229vboxsync PCFGMNODE pParent = CFGMR3GetChild(pCurNode, "Parent");
9496f2d398b49813176939d7a339ae513d5175efvboxsync if (!pParent)
9496f2d398b49813176939d7a339ae513d5175efvboxsync break;
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync pCurNode = pParent;
9496f2d398b49813176939d7a339ae513d5175efvboxsync iLevel++;
9496f2d398b49813176939d7a339ae513d5175efvboxsync }
9496f2d398b49813176939d7a339ae513d5175efvboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsync /*
9496f2d398b49813176939d7a339ae513d5175efvboxsync * Open the images.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync if (RT_SUCCESS(rc))
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync {
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /** @todo TEMP! later the iSCSI config callbacks won't be included here */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync rc = VDCreate(&pData->VDIConfig, &pData->pDisk);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* Error message is already set correctly. */
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync }
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync unsigned cImages = iLevel;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync while (pCurNode && RT_SUCCESS(rc))
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync {
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /*
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * Read the image configuration.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync rc = CFGMR3QueryStringAlloc(pCurNode, "Path", &pszName);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync if (RT_FAILURE(rc))
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync {
9496f2d398b49813176939d7a339ae513d5175efvboxsync rc = PDMDRV_SET_ERROR(pDrvIns, rc,
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync N_("DrvVD: Configuration error: Querying \"Path\" as string failed"));
9496f2d398b49813176939d7a339ae513d5175efvboxsync break;
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync }
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync rc = CFGMR3QueryStringAlloc(pCfgHandle, "Format", &pszFormat);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync if (RT_FAILURE(rc))
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync {
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync rc = PDMDRV_SET_ERROR(pDrvIns, rc,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync N_("DrvVD: Configuration error: Querying \"Format\" as string failed"));
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync break;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync }
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync if (iLevel == 0)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync {
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync rc = CFGMR3QueryBool(pCurNode, "ReadOnly", &fReadOnly);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync if (rc == VERR_CFGM_VALUE_NOT_FOUND)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync fReadOnly = false;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync else if (RT_FAILURE(rc))
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync {
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync rc = PDMDRV_SET_ERROR(pDrvIns, rc,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync N_("DrvVD: Configuration error: Querying \"ReadOnly\" as boolean failed"));
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync break;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync }
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync rc = CFGMR3QueryBool(pCfgHandle, "HonorZeroWrites", &fHonorZeroWrites);
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync if (rc == VERR_CFGM_VALUE_NOT_FOUND)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync fHonorZeroWrites = false;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync else if (RT_FAILURE(rc))
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync {
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync rc = PDMDRV_SET_ERROR(pDrvIns, rc,
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync N_("DrvVD: Configuration error: Querying \"HonorZeroWrites\" as boolean failed"));
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync break;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync }
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync }
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync else
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync {
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync fReadOnly = true;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync fHonorZeroWrites = false;
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync }
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync /** @todo TEMP! Later this needs to be done for each image. */
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync if (iLevel == cImages)
090d729e786b999dc285f8ea267f9effd1319544vboxsync {
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync PCFGMNODE pCfg = CFGMR3GetChild(pCurNode, "VDConfig");
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pData->VDIConfig.pvUser = pCfg; /**< @todo TEMP! */
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync }
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync /*
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync * Open the image.
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync */
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync unsigned uOpenFlags;
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync if (fReadOnly)
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync uOpenFlags = VD_OPEN_FLAGS_READONLY;
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync else
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync uOpenFlags = VD_OPEN_FLAGS_NORMAL;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync if (fHonorZeroWrites)
9496f2d398b49813176939d7a339ae513d5175efvboxsync uOpenFlags |= VD_OPEN_FLAGS_HONOR_ZEROES;
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync if (pData->pDrvMediaAsyncPort)
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync uOpenFlags |= VD_OPEN_FLAGS_ASYNC_IO;
9496f2d398b49813176939d7a339ae513d5175efvboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsync /** Try to open backend in asyc I/O mode first. */
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync rc = VDOpen(pData->pDisk, pszFormat, pszName, uOpenFlags);
9496f2d398b49813176939d7a339ae513d5175efvboxsync if (rc == VERR_NOT_SUPPORTED)
9496f2d398b49813176939d7a339ae513d5175efvboxsync {
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync /* Seems async I/O is not supported by the backend, open in normal mode. */
68a4ee3a31a0807abd03eae881c1bbaf4d42ee6dvboxsync uOpenFlags &= ~VD_OPEN_FLAGS_ASYNC_IO;
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync rc = VDOpen(pData->pDisk, pszFormat, pszName, uOpenFlags);
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync }
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsync if (RT_SUCCESS(rc))
68a4ee3a31a0807abd03eae881c1bbaf4d42ee6dvboxsync Log(("%s: %d - Opened '%s' in %s mode\n", __FUNCTION__,
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync iLevel, pszName,
9496f2d398b49813176939d7a339ae513d5175efvboxsync VDIsReadOnly(pData->pDisk) ? "read-only" : "read-write"));
9496f2d398b49813176939d7a339ae513d5175efvboxsync else
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync {
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync AssertMsgFailed(("Failed to open image '%s' rc=%Vrc\n", pszName, rc));
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync break;
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync }
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync MMR3HeapFree(pszName);
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync pszName = NULL;
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync MMR3HeapFree(pszFormat);
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync pszFormat = NULL;
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync
68a4ee3a31a0807abd03eae881c1bbaf4d42ee6dvboxsync /* next */
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync iLevel--;
9496f2d398b49813176939d7a339ae513d5175efvboxsync pCurNode = CFGMR3GetParent(pCurNode);
9496f2d398b49813176939d7a339ae513d5175efvboxsync }
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync if (RT_FAILURE(rc))
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync {
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync if (VALID_PTR(pData->pDisk))
975ad9d9bc9c4dc96b41d9f67a65228b1b338e2avboxsync {
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync VDDestroy(pData->pDisk);
975ad9d9bc9c4dc96b41d9f67a65228b1b338e2avboxsync pData->pDisk = NULL;
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync }
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync if (VALID_PTR(pszName))
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync MMR3HeapFree(pszName);
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync if (VALID_PTR(pszFormat))
9496f2d398b49813176939d7a339ae513d5175efvboxsync MMR3HeapFree(pszFormat);
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync }
9496f2d398b49813176939d7a339ae513d5175efvboxsync
b7a5b3f9f9ecce32ddacf8404c625ce0451bbdc1vboxsync /*
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync * Check for async I/O support. Every opened image has to support
9496f2d398b49813176939d7a339ae513d5175efvboxsync * it.
9496f2d398b49813176939d7a339ae513d5175efvboxsync */
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync pData->fAsyncIOSupported = true;
9496f2d398b49813176939d7a339ae513d5175efvboxsync for (unsigned i = 0; i < VDGetCount(pData->pDisk); i++)
9496f2d398b49813176939d7a339ae513d5175efvboxsync {
9496f2d398b49813176939d7a339ae513d5175efvboxsync VDBACKENDINFO vdBackendInfo;
9496f2d398b49813176939d7a339ae513d5175efvboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsync rc = VDBackendInfoSingle(pData->pDisk, i, &vdBackendInfo);
9496f2d398b49813176939d7a339ae513d5175efvboxsync AssertRC(rc);
9496f2d398b49813176939d7a339ae513d5175efvboxsync
b7a5b3f9f9ecce32ddacf8404c625ce0451bbdc1vboxsync if (vdBackendInfo.uBackendCaps & VD_CAP_ASYNC)
090d729e786b999dc285f8ea267f9effd1319544vboxsync {
090d729e786b999dc285f8ea267f9effd1319544vboxsync /*
9496f2d398b49813176939d7a339ae513d5175efvboxsync * Backend indicates support for at least some files.
9496f2d398b49813176939d7a339ae513d5175efvboxsync * Check if current file is supported with async I/O)
090d729e786b999dc285f8ea267f9effd1319544vboxsync */
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync rc = VDImageIsAsyncIOSupported(pData->pDisk, i, &pData->fAsyncIOSupported);
090d729e786b999dc285f8ea267f9effd1319544vboxsync AssertRC(rc);
9496f2d398b49813176939d7a339ae513d5175efvboxsync
b7a5b3f9f9ecce32ddacf8404c625ce0451bbdc1vboxsync /*
9496f2d398b49813176939d7a339ae513d5175efvboxsync * Check if current image is supported.
fe813b3594039ba864493438e78ee0e7132bc445vboxsync * If not we can stop checking because
9496f2d398b49813176939d7a339ae513d5175efvboxsync * at least one does not support it.
9496f2d398b49813176939d7a339ae513d5175efvboxsync */
9496f2d398b49813176939d7a339ae513d5175efvboxsync if (!pData->fAsyncIOSupported)
090d729e786b999dc285f8ea267f9effd1319544vboxsync break;
090d729e786b999dc285f8ea267f9effd1319544vboxsync }
090d729e786b999dc285f8ea267f9effd1319544vboxsync else
090d729e786b999dc285f8ea267f9effd1319544vboxsync {
090d729e786b999dc285f8ea267f9effd1319544vboxsync pData->fAsyncIOSupported = false;
090d729e786b999dc285f8ea267f9effd1319544vboxsync break;
090d729e786b999dc285f8ea267f9effd1319544vboxsync }
9496f2d398b49813176939d7a339ae513d5175efvboxsync }
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync /* Create cache if async I/O is supported. */
9496f2d398b49813176939d7a339ae513d5175efvboxsync if (pData->fAsyncIOSupported)
090d729e786b999dc285f8ea267f9effd1319544vboxsync {
9496f2d398b49813176939d7a339ae513d5175efvboxsync rc = RTCacheCreate(&pData->pCache, 0, sizeof(DRVVDASYNCTASK), RTOBJCACHE_PROTECT_INSERT);
9496f2d398b49813176939d7a339ae513d5175efvboxsync AssertMsg(RT_SUCCESS(rc), ("Failed to create cache rc=%Vrc\n", rc));
9496f2d398b49813176939d7a339ae513d5175efvboxsync }
9496f2d398b49813176939d7a339ae513d5175efvboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsync LogFlow(("%s: returns %Vrc\n", __FUNCTION__, rc));
9496f2d398b49813176939d7a339ae513d5175efvboxsync return rc;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync}
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/**
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * Destruct a driver instance.
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync *
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * Most VM resources are freed by the VM. This callback is provided so that any non-VM
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * resources can be freed correctly.
090d729e786b999dc285f8ea267f9effd1319544vboxsync *
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * @param pDrvIns The driver instance data.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic DECLCALLBACK(void) drvvdDestruct(PPDMDRVINS pDrvIns)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync{
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync int rc;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync PVBOXDISK pData = PDMINS2DATA(pDrvIns, PVBOXDISK);
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync LogFlow(("%s:\n", __FUNCTION__));
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync if (pData->pCache)
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync {
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync rc = RTCacheDestroy(pData->pCache);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync AssertRC(rc);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync }
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync}
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
3858c38e71b06f72b8747e37973c71b433199f32vboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync/**
3858c38e71b06f72b8747e37973c71b433199f32vboxsync * When the VM has been suspended we'll change the image mode to read-only
3858c38e71b06f72b8747e37973c71b433199f32vboxsync * so that main and others can read the VDIs. This is important when
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync * saving state and so forth.
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync *
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync * @param pDrvIns The driver instance data.
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsyncstatic DECLCALLBACK(void) drvvdSuspend(PPDMDRVINS pDrvIns)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync{
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync LogFlow(("%s:\n", __FUNCTION__));
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync PVBOXDISK pData = PDMINS2DATA(pDrvIns, PVBOXDISK);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync if (!VDIsReadOnly(pData->pDisk))
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync {
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync unsigned uOpenFlags;
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync int rc = VDGetOpenFlags(pData->pDisk, VD_LAST_IMAGE, &uOpenFlags);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync AssertRC(rc);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync uOpenFlags |= VD_OPEN_FLAGS_READONLY;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync rc = VDSetOpenFlags(pData->pDisk, VD_LAST_IMAGE, uOpenFlags);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync AssertRC(rc);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pData->fTempReadOnly = true;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync }
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync}
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/**
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * Before the VM resumes we'll have to undo the read-only mode change
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * done in drvvdSuspend.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync *
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * @param pDrvIns The driver instance data.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic DECLCALLBACK(void) drvvdResume(PPDMDRVINS pDrvIns)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync{
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync LogFlow(("%s:\n", __FUNCTION__));
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync PVBOXDISK pData = PDMINS2DATA(pDrvIns, PVBOXDISK);
b7a5b3f9f9ecce32ddacf8404c625ce0451bbdc1vboxsync if (pData->fTempReadOnly)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync {
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync unsigned uOpenFlags;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync int rc = VDGetOpenFlags(pData->pDisk, VD_LAST_IMAGE, &uOpenFlags);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync AssertRC(rc);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync uOpenFlags &= ~VD_OPEN_FLAGS_READONLY;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync rc = VDSetOpenFlags(pData->pDisk, VD_LAST_IMAGE, uOpenFlags);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync AssertRC(rc);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync pData->fTempReadOnly = false;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync }
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync}
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsyncstatic DECLCALLBACK(void) drvvdPowerOff(PPDMDRVINS pDrvIns)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync{
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync LogFlow(("%s:\n", __FUNCTION__));
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync PVBOXDISK pData = PDMINS2DATA(pDrvIns, PVBOXDISK);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync /*
a3369a746b56a8966dd78619f4d191c9662f400dvboxsync * We must close the disk here to ensure that
a3369a746b56a8966dd78619f4d191c9662f400dvboxsync * the backend closes all files before the
a3369a746b56a8966dd78619f4d191c9662f400dvboxsync * async transport driver is destructed.
a3369a746b56a8966dd78619f4d191c9662f400dvboxsync */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync int rc = VDCloseAll(pData->pDisk);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync AssertRC(rc);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync}
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync/**
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync * VBox disk container media driver registration record.
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsyncconst PDMDRVREG g_DrvVD =
a3369a746b56a8966dd78619f4d191c9662f400dvboxsync{
a3369a746b56a8966dd78619f4d191c9662f400dvboxsync /* u32Version */
a3369a746b56a8966dd78619f4d191c9662f400dvboxsync PDM_DRVREG_VERSION,
a3369a746b56a8966dd78619f4d191c9662f400dvboxsync /* szDriverName */
a3369a746b56a8966dd78619f4d191c9662f400dvboxsync "VD",
a3369a746b56a8966dd78619f4d191c9662f400dvboxsync /* pszDescription */
a3369a746b56a8966dd78619f4d191c9662f400dvboxsync "Generic VBox disk media driver.",
a3369a746b56a8966dd78619f4d191c9662f400dvboxsync /* fFlags */
a3369a746b56a8966dd78619f4d191c9662f400dvboxsync PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT,
a3369a746b56a8966dd78619f4d191c9662f400dvboxsync /* fClass. */
a3369a746b56a8966dd78619f4d191c9662f400dvboxsync PDM_DRVREG_CLASS_MEDIA,
a3369a746b56a8966dd78619f4d191c9662f400dvboxsync /* cMaxInstances */
a3369a746b56a8966dd78619f4d191c9662f400dvboxsync ~0,
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync /* cbInstance */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync sizeof(VBOXDISK),
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* pfnConstruct */
b7a5b3f9f9ecce32ddacf8404c625ce0451bbdc1vboxsync drvvdConstruct,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* pfnDestruct */
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync drvvdDestruct,
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync /* pfnIOCtl */
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync NULL,
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync /* pfnPowerOn */
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync NULL,
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync /* pfnReset */
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync NULL,
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync /* pfnSuspend */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync drvvdSuspend,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* pfnResume */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync drvvdResume,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* pfnDetach */
b7a5b3f9f9ecce32ddacf8404c625ce0451bbdc1vboxsync NULL,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* pfnPowerOff */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync drvvdPowerOff
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync};
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync