DrvBlock.cpp revision 16a9adc14900ca18e6909679a579f6833425e030
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * VBox storage devices: Generic block driver
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * Copyright (C) 2006-2010 Sun Microsystems, Inc.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * available from http://www.virtualbox.org. This file is free software;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * you can redistribute it and/or modify it under the terms of the GNU
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * General Public License (GPL) as published by the Free Software
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * additional information or have any questions.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync/*******************************************************************************
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync* Header Files *
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync*******************************************************************************/
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync/** @def VBOX_PERIODIC_FLUSH
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * Enable support for periodically flushing the VDI to disk. This may prove
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * useful for those nasty problems with the ultra-slow host filesystems.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * If this is enabled, it can be configured via the CFGM key
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * "VBoxInternal/Devices/piix3ide/0/LUN#<x>/Config/FlushInterval". <x>
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * must be replaced with the correct LUN number of the disk that should
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * do the periodic flushes. The value of the key is the number of bytes
31a6dbe4e9a540cfbb21d594683d81dadd1d3c65vboxsync * written between flushes. A value of 0 (the default) denotes no flushes. */
31a6dbe4e9a540cfbb21d594683d81dadd1d3c65vboxsync/** @def VBOX_IGNORE_FLUSH
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * Enable support for ignoring VDI flush requests. This can be useful for
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * filesystems that show bad guest IDE write performance (especially with
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * Windows guests). NOTE that this does not disable the flushes caused by
2f44080df90cb90c1e524d97c8e327b40298f3c6vboxsync * the periodic flush cache feature above.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * If this feature is enabled, it can be configured via the CFGM key
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * "VBoxInternal/Devices/piix3ide/0/LUN#<x>/Config/IgnoreFlush". <x>
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * must be replaced with the correct LUN number of the disk that should
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * ignore flush requests. The value of the key is a boolean. The default
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * is to ignore flushes, i.e. true. */
typedef struct DRVBLOCK
bool fLocked;
bool fMountable;
bool fBiosVisible;
#ifdef VBOX_PERIODIC_FLUSH
#ifdef VBOX_IGNORE_FLUSH
bool fIgnoreFlush;
#define PDMIBLOCK_2_DRVBLOCK(pInterface) ( (PDRVBLOCK)((uintptr_t)pInterface - RT_OFFSETOF(DRVBLOCK, IBlock)) )
static DECLCALLBACK(int) drvblockRead(PPDMIBLOCK pInterface, uint64_t off, void *pvBuf, size_t cbRead)
return VERR_PDM_MEDIA_NOT_MOUNTED;
return rc;
static DECLCALLBACK(int) drvblockWrite(PPDMIBLOCK pInterface, uint64_t off, const void *pvBuf, size_t cbWrite)
return VERR_PDM_MEDIA_NOT_MOUNTED;
#ifdef VBOX_PERIODIC_FLUSH
return rc;
return VERR_PDM_MEDIA_NOT_MOUNTED;
#ifdef VBOX_IGNORE_FLUSH
return VINF_SUCCESS;
return rc;
void *pvUser)
return VERR_PDM_MEDIA_NOT_MOUNTED;
return VERR_NOT_SUPPORTED;
return rc;
return fRc;
return cb;
return VINF_SUCCESS;
#define PDMIBLOCKASYNC_2_DRVBLOCK(pInterface) ( (PDRVBLOCK)((uintptr_t)pInterface - RT_OFFSETOF(DRVBLOCK, IBlockAsync)) )
static DECLCALLBACK(int) drvblockAsyncReadStart(PPDMIBLOCKASYNC pInterface, uint64_t off, PPDMDATASEG pSeg, unsigned cSeg, size_t cbRead, void *pvUser)
return VERR_PDM_MEDIA_NOT_MOUNTED;
int rc = pThis->pDrvMediaAsync->pfnStartRead(pThis->pDrvMediaAsync, off, pSeg, cSeg, cbRead, pvUser);
return rc;
static DECLCALLBACK(int) drvblockAsyncWriteStart(PPDMIBLOCKASYNC pInterface, uint64_t off, PPDMDATASEG pSeg, unsigned cSeg, size_t cbWrite, void *pvUser)
return VERR_PDM_MEDIA_NOT_MOUNTED;
int rc = pThis->pDrvMediaAsync->pfnStartWrite(pThis->pDrvMediaAsync, off, pSeg, cSeg, cbWrite, pvUser);
return rc;
#define PDMIMEDIAASYNCPORT_2_DRVBLOCK(pInterface) ( (PDRVBLOCK((uintptr_t)pInterface - RT_OFFSETOF(DRVBLOCK, IMediaAsyncPort))) )
static DECLCALLBACK(int) drvblockAsyncTransferCompleteNotify(PPDMIMEDIAASYNCPORT pInterface, void *pvUser)
#define PDMIBLOCKBIOS_2_DRVBLOCK(pInterface) ( (PDRVBLOCK((uintptr_t)pInterface - RT_OFFSETOF(DRVBLOCK, IBlockBios))) )
static DECLCALLBACK(int) drvblockGetPCHSGeometry(PPDMIBLOCKBIOS pInterface, PPDMMEDIAGEOMETRY pPCHSGeometry)
return VERR_PDM_MEDIA_NOT_MOUNTED;
* Use configured/cached values if present.
LogFlow(("%s: returns VINF_SUCCESS {%d,%d,%d}\n", __FUNCTION__, pThis->PCHSGeometry.cCylinders, pThis->PCHSGeometry.cHeads, pThis->PCHSGeometry.cSectors));
return VINF_SUCCESS;
LogFlow(("%s: returns %Rrc {%d,%d,%d}\n", __FUNCTION__, rc, pThis->PCHSGeometry.cCylinders, pThis->PCHSGeometry.cHeads, pThis->PCHSGeometry.cSectors));
return rc;
static DECLCALLBACK(int) drvblockSetPCHSGeometry(PPDMIBLOCKBIOS pInterface, PCPDMMEDIAGEOMETRY pPCHSGeometry)
LogFlow(("%s: cCylinders=%d cHeads=%d cSectors=%d\n", __FUNCTION__, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors));
return VERR_PDM_MEDIA_NOT_MOUNTED;
return rc;
static DECLCALLBACK(int) drvblockGetLCHSGeometry(PPDMIBLOCKBIOS pInterface, PPDMMEDIAGEOMETRY pLCHSGeometry)
return VERR_PDM_MEDIA_NOT_MOUNTED;
* Use configured/cached values if present.
LogFlow(("%s: returns VINF_SUCCESS {%d,%d,%d}\n", __FUNCTION__, pThis->LCHSGeometry.cCylinders, pThis->LCHSGeometry.cHeads, pThis->LCHSGeometry.cSectors));
return VINF_SUCCESS;
LogFlow(("%s: returns %Rrc {%d,%d,%d}\n", __FUNCTION__, rc, pThis->LCHSGeometry.cCylinders, pThis->LCHSGeometry.cHeads, pThis->LCHSGeometry.cSectors));
return rc;
static DECLCALLBACK(int) drvblockSetLCHSGeometry(PPDMIBLOCKBIOS pInterface, PCPDMMEDIAGEOMETRY pLCHSGeometry)
LogFlow(("%s: cCylinders=%d cHeads=%d cSectors=%d\n", __FUNCTION__, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors));
return VERR_PDM_MEDIA_NOT_MOUNTED;
return rc;
#define PDMIMOUNT_2_DRVBLOCK(pInterface) ( (PDRVBLOCK)((uintptr_t)pInterface - RT_OFFSETOF(DRVBLOCK, IMount)) )
static DECLCALLBACK(int) drvblockMount(PPDMIMOUNT pInterface, const char *pszFilename, const char *pszCoreDriver)
LogFlow(("drvblockMount: pszFilename=%p:{%s} pszCoreDriver=%p:{%s}\n", pszFilename, pszFilename, pszCoreDriver, pszCoreDriver));
return VERR_PDM_MEDIA_MOUNTED;
if (pszFilename)
return rc;
return rc;
#ifdef VBOX_PERIODIC_FLUSH
return VINF_SUCCESS;
return rc;
return VERR_PDM_MEDIA_NOT_MOUNTED;
return VERR_PDM_MEDIA_LOCKED;
return rc;
return VINF_SUCCESS;
return VINF_SUCCESS;
return VINF_SUCCESS;
PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBLOCKASYNC, pThis->pDrvMediaAsync ? &pThis->IBlockAsync : NULL);
PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIAASYNCPORT, pThis->pDrvBlockAsyncPort ? &pThis->IMediaAsyncPort : NULL);
return NULL;
if (!CFGMR3AreValuesValid(pCfg, "Type\0Locked\0BIOSVisible\0AttachFailError\0Cylinders\0Heads\0Sectors\0Mountable\0FlushInterval\0IgnoreFlush\0"))
if (!CFGMR3AreValuesValid(pCfg, "Type\0Locked\0BIOSVisible\0AttachFailError\0Cylinders\0Heads\0Sectors\0Mountable\0"))
char *psz;
return VERR_PDM_BLOCK_UNKNOWN_TYPE;
return rc;
#ifdef VBOX_PERIODIC_FLUSH
#ifdef VBOX_IGNORE_FLUSH
return VINF_SUCCESS;
return VINF_SUCCESS;
sizeof(DRVBLOCK),
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,