VirtualBox

Changeset 59539 in vbox for trunk/src/VBox/Devices/Storage


Ignore:
Timestamp:
Feb 1, 2016 11:52:58 AM (9 years ago)
Author:
vboxsync
Message:

Storage/DrvVD: Add methods to PDMIMEDIAEX for saving the request state of suspended requests. Required for making saving/restoring the VM state work when the user saved a VM state after it got suspended due to a recoverable I/O error

File:
1 edited

Legend:

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

    r59538 r59539  
    2626#include <VBox/vmm/pdmasynccompletion.h>
    2727#include <VBox/vmm/pdmblkcache.h>
     28#include <VBox/vmm/ssm.h>
    2829#include <iprt/asm.h>
    2930#include <iprt/alloc.h>
     
    99100#define PDMIMEDIAASYNC_2_VBOXDISK(pInterface) \
    100101    ( (PVBOXDISK)((uintptr_t)pInterface - RT_OFFSETOF(VBOXDISK, IMediaAsync)) )
     102
     103/** Saved state version of an I/O request .*/
     104#define DRVVD_IOREQ_SAVED_STATE_VERSION UINT32_C(1)
    101105
    102106/** Forward declaration for the dis kcontainer. */
     
    32393243                /*
    32403244                 * We might have to try canceling the request multiple times if it transitioned from
    3241                  * ALLOCATED to ACTIVE between reading the state and trying to change it.
     3245                 * ALLOCATED to ACTIVE or to SUSPENDED between reading the state and trying to change it.
    32423246                 */
    32433247                while (   (   enmStateOld == VDIOREQSTATE_ALLOCATED
    3244                            || enmStateOld == VDIOREQSTATE_ACTIVE)
     3248                           || enmStateOld == VDIOREQSTATE_ACTIVE
     3249                           || enmStateOld == VDIOREQSTATE_SUSPENDED)
    32453250                       && !fXchg)
    32463251                {
     
    34903495
    34913496    return VINF_SUCCESS;
     3497}
     3498
     3499/**
     3500 * @interface_method_impl{PDMIMEDIAEX,pfnIoReqSuspendedSave}
     3501 */
     3502static DECLCALLBACK(int) drvvdIoReqSuspendedSave(PPDMIMEDIAEX pInterface, PSSMHANDLE pSSM, PDMMEDIAEXIOREQ hIoReq)
     3503{
     3504    PVBOXDISK pThis = RT_FROM_MEMBER(pInterface, VBOXDISK, IMediaEx);
     3505    PPDMMEDIAEXIOREQINT pIoReq = hIoReq;
     3506
     3507    AssertReturn(!drvvdMediaExIoReqIsVmRunning(pThis), VERR_INVALID_STATE);
     3508    AssertPtrReturn(pIoReq, VERR_INVALID_HANDLE);
     3509    AssertReturn(pIoReq->enmState == VDIOREQSTATE_SUSPENDED, VERR_INVALID_STATE);
     3510
     3511    SSMR3PutU32(pSSM, DRVVD_IOREQ_SAVED_STATE_VERSION);
     3512    SSMR3PutU32(pSSM, (uint32_t)pIoReq->enmType);
     3513    SSMR3PutU32(pSSM, pIoReq->uIoReqId);
     3514    SSMR3PutU32(pSSM, pIoReq->fFlags);
     3515    if (   pIoReq->enmType == PDMMEDIAEXIOREQTYPE_READ
     3516        || pIoReq->enmType == PDMMEDIAEXIOREQTYPE_WRITE)
     3517    {
     3518        SSMR3PutU64(pSSM, pIoReq->ReadWrite.offStart);
     3519        SSMR3PutU64(pSSM, pIoReq->ReadWrite.cbReq);
     3520        SSMR3PutU64(pSSM, pIoReq->ReadWrite.cbReqLeft);
     3521    }
     3522    else if (pIoReq->enmType == PDMMEDIAEXIOREQTYPE_DISCARD)
     3523    {
     3524        SSMR3PutU32(pSSM, pIoReq->Discard.cRanges);
     3525        for (unsigned i = 0; i < pIoReq->Discard.cRanges; i++)
     3526        {
     3527            SSMR3PutU64(pSSM, pIoReq->Discard.paRanges[i].offStart);
     3528            SSMR3PutU64(pSSM, pIoReq->Discard.paRanges[i].cbRange);
     3529        }
     3530    }
     3531
     3532    return SSMR3PutU32(pSSM, UINT32_MAX); /* sanity/terminator */
     3533}
     3534
     3535/**
     3536 * @interface_method_impl{PDMIMEDIAEX,pfnIoReqSuspendedLoad}
     3537 */
     3538static DECLCALLBACK(int) drvvdIoReqSuspendedLoad(PPDMIMEDIAEX pInterface, PSSMHANDLE pSSM, PDMMEDIAEXIOREQ hIoReq)
     3539{
     3540    PVBOXDISK pThis = RT_FROM_MEMBER(pInterface, VBOXDISK, IMediaEx);
     3541    PPDMMEDIAEXIOREQINT pIoReq = hIoReq;
     3542
     3543    AssertReturn(!drvvdMediaExIoReqIsVmRunning(pThis), VERR_INVALID_STATE);
     3544    AssertPtrReturn(pIoReq, VERR_INVALID_HANDLE);
     3545    AssertReturn(pIoReq->enmState == VDIOREQSTATE_ALLOCATED, VERR_INVALID_STATE);
     3546
     3547    uint32_t u32;
     3548    uint64_t u64;
     3549    int rc = VINF_SUCCESS;
     3550    bool fPlaceOnRedoList = true;
     3551
     3552    SSMR3GetU32(pSSM, &u32);
     3553    if (u32 <= DRVVD_IOREQ_SAVED_STATE_VERSION)
     3554    {
     3555        SSMR3GetU32(pSSM, &u32);
     3556        AssertReturn(   u32 == PDMMEDIAEXIOREQTYPE_WRITE
     3557                     || u32 == PDMMEDIAEXIOREQTYPE_READ
     3558                     || u32 == PDMMEDIAEXIOREQTYPE_DISCARD
     3559                     || u32 == PDMMEDIAEXIOREQTYPE_FLUSH,
     3560                     VERR_SSM_DATA_UNIT_FORMAT_CHANGED);
     3561        pIoReq->enmType = (PDMMEDIAEXIOREQTYPE)u32;
     3562
     3563        SSMR3GetU32(pSSM, &u32);
     3564        AssertReturn(u32 == pIoReq->uIoReqId, VERR_SSM_DATA_UNIT_FORMAT_CHANGED);
     3565
     3566        SSMR3GetU32(pSSM, &u32);
     3567        AssertReturn(u32 == pIoReq->fFlags, VERR_SSM_DATA_UNIT_FORMAT_CHANGED);
     3568
     3569        if (   pIoReq->enmType == PDMMEDIAEXIOREQTYPE_READ
     3570            || pIoReq->enmType == PDMMEDIAEXIOREQTYPE_WRITE)
     3571        {
     3572            SSMR3GetU64(pSSM, &pIoReq->ReadWrite.offStart);
     3573            SSMR3GetU64(pSSM, &u64);
     3574            pIoReq->ReadWrite.cbReq = (size_t)u64;
     3575            SSMR3GetU64(pSSM, &u64);
     3576            pIoReq->ReadWrite.cbReqLeft = (size_t)u64;
     3577
     3578            /*
     3579             * Try to allocate enough I/O buffer, if this fails for some reason put it onto the
     3580             * waitign list instead of the redo list.
     3581             */
     3582            pIoReq->ReadWrite.cbIoBuf = 0;
     3583            rc = IOBUFMgrAllocBuf(pThis->hIoBufMgr, &pIoReq->ReadWrite.IoBuf, pIoReq->ReadWrite.cbReqLeft,
     3584                                  &pIoReq->ReadWrite.cbIoBuf);
     3585            if (rc == VERR_NO_MEMORY)
     3586            {
     3587                pIoReq->enmState = VDIOREQSTATE_ALLOCATED;
     3588                ASMAtomicIncU32(&pThis->cIoReqsWaiting);
     3589                RTListAppend(&pThis->LstIoReqIoBufWait, &pIoReq->NdLstWait);
     3590                fPlaceOnRedoList = false;
     3591                rc = VINF_SUCCESS;
     3592            }
     3593        }
     3594        else if (pIoReq->enmType == PDMMEDIAEXIOREQTYPE_DISCARD)
     3595        {
     3596            rc = SSMR3GetU32(pSSM, &pIoReq->Discard.cRanges);
     3597            if (RT_SUCCESS(rc))
     3598            {
     3599                pIoReq->Discard.paRanges = (PRTRANGE)RTMemAllocZ(pIoReq->Discard.cRanges * sizeof(RTRANGE));
     3600                if (RT_LIKELY(pIoReq->Discard.paRanges))
     3601                {
     3602                    for (unsigned i = 0; i < pIoReq->Discard.cRanges; i++)
     3603                    {
     3604                        SSMR3GetU64(pSSM, &pIoReq->Discard.paRanges[i].offStart);
     3605                        SSMR3GetU64(pSSM, &u64);
     3606                        pIoReq->Discard.paRanges[i].cbRange = (size_t)u64;
     3607                    }
     3608                }
     3609                else
     3610                    rc = VERR_NO_MEMORY;
     3611            }
     3612        }
     3613
     3614        if (RT_SUCCESS(rc))
     3615            rc = SSMR3GetU32(pSSM, &u32); /* sanity/terminator */
     3616        if (RT_SUCCESS(rc))
     3617            AssertReturn(u32 == UINT32_MAX, VERR_SSM_DATA_UNIT_FORMAT_CHANGED);
     3618        if (   RT_SUCCESS(rc)
     3619            && fPlaceOnRedoList)
     3620        {
     3621            /* Mark as suspended */
     3622            pIoReq->enmState = VDIOREQSTATE_SUSPENDED;
     3623
     3624            /* Link into suspended list so it gets kicked off again when we resume. */
     3625            RTCritSectEnter(&pThis->CritSectIoReqRedo);
     3626            RTListAppend(&pThis->LstIoReqRedo, &pIoReq->NdLstWait);
     3627            RTCritSectLeave(&pThis->CritSectIoReqRedo);
     3628        }
     3629    }
     3630
     3631    return rc;
    34923632}
    34933633
     
    40384178    pThis->IMediaEx.pfnIoReqQuerySuspendedStart = drvvdIoReqQuerySuspendedStart;
    40394179    pThis->IMediaEx.pfnIoReqQuerySuspendedNext  = drvvdIoReqQuerySuspendedNext;
     4180    pThis->IMediaEx.pfnIoReqSuspendedSave       = drvvdIoReqSuspendedSave;
     4181    pThis->IMediaEx.pfnIoReqSuspendedLoad       = drvvdIoReqSuspendedLoad;
    40404182
    40414183    /* Initialize supported VD interfaces. */
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