VirtualBox

Changeset 26987 in vbox


Ignore:
Timestamp:
Mar 3, 2010 1:33:47 PM (15 years ago)
Author:
vboxsync
Message:

Oops

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Storage/VBoxHDD.cpp

    r26986 r26987  
    4141
    4242#include <VBox/VBoxHDD-Plugin.h>
    43 #include "VBoxHDDInternal.h"
     43
     44
     45#define VBOXHDDDISK_SIGNATURE 0x6f0e2a7d
     46
     47/** Buffer size used for merging images. */
     48#define VD_MERGE_BUFFER_SIZE    (16 * _1M)
     49
     50/**
     51 * VD async I/O interface storage descriptor.
     52 */
     53typedef struct VDIASYNCIOSTORAGE
     54{
     55    /** File handle. */
     56    RTFILE         File;
     57    /** Completion callback. */
     58    PFNVDCOMPLETED pfnCompleted;
     59    /** Thread for async access. */
     60    RTTHREAD       ThreadAsync;
     61} VDIASYNCIOSTORAGE, *PVDIASYNCIOSTORAGE;
     62
     63/**
     64 * VBox HDD Container image descriptor.
     65 */
     66typedef struct VDIMAGE
     67{
     68    /** Link to parent image descriptor, if any. */
     69    struct VDIMAGE  *pPrev;
     70    /** Link to child image descriptor, if any. */
     71    struct VDIMAGE  *pNext;
     72    /** Container base filename. (UTF-8) */
     73    char            *pszFilename;
     74    /** Data managed by the backend which keeps the actual info. */
     75    void            *pvBackendData;
     76    /** Cached sanitized image flags. */
     77    unsigned        uImageFlags;
     78    /** Image open flags (only those handled generically in this code and which
     79     * the backends will never ever see). */
     80    unsigned        uOpenFlags;
     81
     82    /** Function pointers for the various backend methods. */
     83    PCVBOXHDDBACKEND    Backend;
     84
     85    /** Pointer to list of VD interfaces, per-image. */
     86    PVDINTERFACE        pVDIfsImage;
     87} VDIMAGE, *PVDIMAGE;
     88
     89/**
     90 * uModified bit flags.
     91 */
     92#define VD_IMAGE_MODIFIED_FLAG                  RT_BIT(0)
     93#define VD_IMAGE_MODIFIED_FIRST                 RT_BIT(1)
     94#define VD_IMAGE_MODIFIED_DISABLE_UUID_UPDATE   RT_BIT(2)
     95
     96
     97/**
     98 * VBox HDD Container main structure, private part.
     99 */
     100struct VBOXHDD
     101{
     102    /** Structure signature (VBOXHDDDISK_SIGNATURE). */
     103    uint32_t            u32Signature;
     104
     105    /** Number of opened images. */
     106    unsigned            cImages;
     107
     108    /** Base image. */
     109    PVDIMAGE            pBase;
     110
     111    /** Last opened image in the chain.
     112     * The same as pBase if only one image is used. */
     113    PVDIMAGE            pLast;
     114
     115    /** Flags representing the modification state. */
     116    unsigned            uModified;
     117
     118    /** Cached size of this disk. */
     119    uint64_t            cbSize;
     120    /** Cached PCHS geometry for this disk. */
     121    PDMMEDIAGEOMETRY    PCHSGeometry;
     122    /** Cached LCHS geometry for this disk. */
     123    PDMMEDIAGEOMETRY    LCHSGeometry;
     124
     125    /** Pointer to list of VD interfaces, per-disk. */
     126    PVDINTERFACE        pVDIfsDisk;
     127    /** Pointer to the common interface structure for error reporting. */
     128    PVDINTERFACE        pInterfaceError;
     129    /** Pointer to the error interface we use if available. */
     130    PVDINTERFACEERROR   pInterfaceErrorCallbacks;
     131
     132    /** Fallback async interface. */
     133    VDINTERFACE         VDIAsyncIO;
     134    /** Fallback async I/O interface callback table. */
     135    VDINTERFACEASYNCIO  VDIAsyncIOCallbacks;
     136};
     137
     138
     139/**
     140 * VBox parent read descriptor, used internally for compaction.
     141 */
     142typedef struct VDPARENTSTATEDESC
     143{
     144    /** Pointer to disk descriptor. */
     145    PVBOXHDD pDisk;
     146    /** Pointer to image descriptor. */
     147    PVDIMAGE pImage;
     148} VDPARENTSTATEDESC, *PVDPARENTSTATEDESC;
    44149
    45150
     
    178283 * internal: find image by index into the images list.
    179284 */
    180 PVDIMAGE vdGetImageByNumber(PVBOXHDD pDisk, unsigned nImage)
     285static PVDIMAGE vdGetImageByNumber(PVBOXHDD pDisk, unsigned nImage)
    181286{
    182287    PVDIMAGE pImage = pDisk->pBase;
     
    268373 * internal: mark the disk as modified.
    269374 */
    270 void vdSetModifiedFlag(PVBOXHDD pDisk)
     375static void vdSetModifiedFlag(PVBOXHDD pDisk)
    271376{
    272377    pDisk->uModified |= VD_IMAGE_MODIFIED_FLAG;
     
    765870}
    766871
    767 /**
    768  * internal: send output to the log (unconditionally).
    769  */
    770 void vdLogError(void *pvUser, int rc, RT_SRC_POS_DECL, const char *pszFormat, va_list va)
    771 {
    772     NOREF(pvUser);
    773     RTLogPrintf("Error occurred: %Rrc\n", rc);
    774     RTLogPrintf(pszFormat, va);
    775 }
    776872
    777873/**
     
    9481044            if (pDisk->pInterfaceError)
    9491045                pDisk->pInterfaceErrorCallbacks = VDGetInterfaceError(pDisk->pInterfaceError);
    950             else
    951             {
    952                 /* Provide our own interface */
    953                 pDisk->VDIErrorCallbacks.cbSize        = sizeof(VDINTERFACEERROR);
    954                 pDisk->VDIErrorCallbacks.enmInterface  = VDINTERFACETYPE_ERROR;
    955                 pDisk->VDIErrorCallbacks.pfnMessage    = vdLogMessage;
    956                 pDisk->VDIErrorCallbacks.pfnError      = vdLogError;
    957                 rc = VDInterfaceAdd(&pDisk->VDIError, "VD_Error", VDINTERFACETYPE_ERROR,
    958                                     &pDisk->VDIErrorCallbacks, pDisk, &pDisk->pVDIfsDisk);
    959                 AssertRC(rc);
    960             }
    9611046
    9621047            /* Use the fallback async I/O interface if the caller doesn't provide one. */
     
    36403725}
    36413726
     3727/**
     3728 * Query if asynchronous operations are supported for this disk.
     3729 *
     3730 * @returns VBox status code.
     3731 * @returns VERR_VD_IMAGE_NOT_FOUND if image with specified number was not opened.
     3732 * @param   pDisk           Pointer to the HDD container.
     3733 * @param   nImage          Image number, counts from 0. 0 is always base image of container.
     3734 * @param   pfAIOSupported  Where to store if async IO is supported.
     3735 */
     3736VBOXDDU_DECL(int) VDImageIsAsyncIOSupported(PVBOXHDD pDisk, unsigned nImage, bool *pfAIOSupported)
     3737{
     3738    int rc = VINF_SUCCESS;
     3739
     3740    LogFlowFunc(("pDisk=%#p nImage=%u pfAIOSupported=%#p\n", pDisk, nImage, pfAIOSupported));
     3741    do
     3742    {
     3743        /* sanity check */
     3744        AssertPtrBreakStmt(pDisk, rc = VERR_INVALID_PARAMETER);
     3745        AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature));
     3746
     3747        /* Check arguments. */
     3748        AssertMsgBreakStmt(VALID_PTR(pfAIOSupported),
     3749                           ("pfAIOSupported=%#p\n", pfAIOSupported),
     3750                           rc = VERR_INVALID_PARAMETER);
     3751
     3752        PVDIMAGE pImage = vdGetImageByNumber(pDisk, nImage);
     3753        AssertPtrBreakStmt(pImage, rc = VERR_VD_IMAGE_NOT_FOUND);
     3754
     3755        if (pImage->Backend->uBackendCaps & VD_CAP_ASYNC)
     3756            *pfAIOSupported = pImage->Backend->pfnIsAsyncIOSupported(pImage->pvBackendData);
     3757        else
     3758            *pfAIOSupported = false;
     3759    } while (0);
     3760
     3761    LogFlowFunc(("returns %Rrc, fAIOSupported=%u\n", rc, *pfAIOSupported));
     3762    return rc;
     3763}
     3764
     3765/**
     3766 * Start a asynchronous read request.
     3767 *
     3768 * @returns VBox status code.
     3769 * @param   pDisk           Pointer to the HDD container.
     3770 * @param   uOffset         The offset of the virtual disk to read from.
     3771 * @param   cbRead          How many bytes to read.
     3772 * @param   paSeg           Pointer to an array of segments.
     3773 * @param   cSeg            Number of segments in the array.
     3774 * @param   pvUser          User data which is passed on completion
     3775 */
     3776VBOXDDU_DECL(int) VDAsyncRead(PVBOXHDD pDisk, uint64_t uOffset, size_t cbRead,
     3777                              PPDMDATASEG paSeg, unsigned cSeg,
     3778                              void *pvUser)
     3779{
     3780    int rc = VERR_VD_BLOCK_FREE;
     3781
     3782    LogFlowFunc(("pDisk=%#p uOffset=%llu paSeg=%p cSeg=%u cbRead=%zu\n",
     3783                 pDisk, uOffset, paSeg, cSeg, cbRead));
     3784    do
     3785    {
     3786        /* sanity check */
     3787        AssertPtrBreakStmt(pDisk, rc = VERR_INVALID_PARAMETER);
     3788        AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature));
     3789
     3790        /* Check arguments. */
     3791        AssertMsgBreakStmt(cbRead,
     3792                           ("cbRead=%zu\n", cbRead),
     3793                           rc = VERR_INVALID_PARAMETER);
     3794        AssertMsgBreakStmt(uOffset + cbRead <= pDisk->cbSize,
     3795                           ("uOffset=%llu cbRead=%zu pDisk->cbSize=%llu\n",
     3796                            uOffset, cbRead, pDisk->cbSize),
     3797                           rc = VERR_INVALID_PARAMETER);
     3798        AssertMsgBreakStmt(VALID_PTR(paSeg),
     3799                           ("paSeg=%#p\n", paSeg),
     3800                           rc = VERR_INVALID_PARAMETER);
     3801        AssertMsgBreakStmt(cSeg,
     3802                           ("cSeg=%zu\n", cSeg),
     3803                           rc = VERR_INVALID_PARAMETER);
     3804
     3805
     3806        PVDIMAGE pImage = pDisk->pLast;
     3807        AssertPtrBreakStmt(pImage, rc = VERR_VD_NOT_OPENED);
     3808
     3809        /* @todo: This does not work for images which do not have all meta data in memory. */
     3810        for (PVDIMAGE pCurrImage = pImage;
     3811             pCurrImage != NULL && rc == VERR_VD_BLOCK_FREE;
     3812             pCurrImage = pCurrImage->pPrev)
     3813        {
     3814            rc = pCurrImage->Backend->pfnAsyncRead(pCurrImage->pvBackendData,
     3815                                                   uOffset, cbRead, paSeg, cSeg,
     3816                                                   pvUser);
     3817        }
     3818
     3819        /* No image in the chain contains the data for the block. */
     3820        if (rc == VERR_VD_BLOCK_FREE)
     3821        {
     3822            for (unsigned i = 0; i < cSeg && (cbRead > 0); i++)
     3823            {
     3824                memset(paSeg[i].pvSeg, '\0', paSeg[i].cbSeg);
     3825                cbRead -= paSeg[i].cbSeg;
     3826            }
     3827            /* Request finished without the need to enqueue a async I/O request. Tell caller. */
     3828            rc = VINF_VD_ASYNC_IO_FINISHED;
     3829        }
     3830
     3831    } while (0);
     3832
     3833    LogFlowFunc(("returns %Rrc\n", rc));
     3834    return rc;
     3835}
     3836
     3837
     3838/**
     3839 * Start a asynchronous write request.
     3840 *
     3841 * @returns VBox status code.
     3842 * @param   pDisk           Pointer to the HDD container.
     3843 * @param   uOffset         The offset of the virtual disk to write to.
     3844 * @param   cbWrtie         How many bytes to write.
     3845 * @param   paSeg           Pointer to an array of segments.
     3846 * @param   cSeg            Number of segments in the array.
     3847 * @param   pvUser          User data which is passed on completion.
     3848 */
     3849VBOXDDU_DECL(int) VDAsyncWrite(PVBOXHDD pDisk, uint64_t uOffset, size_t cbWrite,
     3850                               PPDMDATASEG paSeg, unsigned cSeg,
     3851                               void *pvUser)
     3852{
     3853    int rc;
     3854
     3855    LogFlowFunc(("pDisk=%#p uOffset=%llu paSeg=%p cSeg=%u cbWrite=%zu\n",
     3856                 pDisk, uOffset, paSeg, cSeg, cbWrite));
     3857    do
     3858    {
     3859        /* sanity check */
     3860        AssertPtrBreakStmt(pDisk, rc = VERR_INVALID_PARAMETER);
     3861        AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature));
     3862
     3863        /* Check arguments. */
     3864        AssertMsgBreakStmt(cbWrite,
     3865                           ("cbWrite=%zu\n", cbWrite),
     3866                           rc = VERR_INVALID_PARAMETER);
     3867        AssertMsgBreakStmt(uOffset + cbWrite <= pDisk->cbSize,
     3868                           ("uOffset=%llu cbWrite=%zu pDisk->cbSize=%llu\n",
     3869                            uOffset, cbWrite, pDisk->cbSize),
     3870                           rc = VERR_INVALID_PARAMETER);
     3871        AssertMsgBreakStmt(VALID_PTR(paSeg),
     3872                           ("paSeg=%#p\n", paSeg),
     3873                           rc = VERR_INVALID_PARAMETER);
     3874        AssertMsgBreakStmt(cSeg,
     3875                           ("cSeg=%zu\n", cSeg),
     3876                           rc = VERR_INVALID_PARAMETER);
     3877
     3878
     3879        PVDIMAGE pImage = pDisk->pLast;
     3880        AssertPtrBreakStmt(pImage, rc = VERR_VD_NOT_OPENED);
     3881
     3882        vdSetModifiedFlag(pDisk);
     3883        rc = pImage->Backend->pfnAsyncWrite(pImage->pvBackendData,
     3884                                            uOffset, cbWrite,
     3885                                            paSeg, cSeg, pvUser);
     3886    } while (0);
     3887
     3888    LogFlowFunc(("returns %Rrc\n", rc));
     3889    return rc;
     3890
     3891}
     3892
    36423893#if 0
    36433894/** @copydoc VBOXHDDBACKEND::pfnComposeLocation */
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette