VirtualBox

Changeset 22792 in vbox


Ignore:
Timestamp:
Sep 4, 2009 6:38:32 PM (15 years ago)
Author:
vboxsync
Message:

SSM: Live snapshot and migration coding.

Location:
trunk
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/err.h

    r22609 r22792  
    567567/** Trying to read a 64-bit guest virtual address into a 32-bit variable. */
    568568#define VERR_SSM_GCPTR_OVERFLOW                 (-1850)
     569/** Vote for another pass.  */
     570#define VINF_SSM_VOTE_FOR_ANOTHER_PASS          1851
     571/** Vote for giving up.  */
     572#define VERR_SSM_VOTE_FOR_GIVING_UP             (-1852)
    569573/** @} */
    570574
     
    10021006#define VERR_PDM_DEVICE_NO_RT_ATTACH                (-2853)
    10031007/** The driver doesn't support runtime driver attaching.
    1004  * The PDMDRVREG::pfnAttach callback function is NULL. */ 
     1008 * The PDMDRVREG::pfnAttach callback function is NULL. */
    10051009#define VERR_PDM_DRIVER_NO_RT_ATTACH                (-2854)
    10061010/** Invalid host interface version. */
  • trunk/include/VBox/ssm.h

    r22559 r22792  
    167167 * being called every time.
    168168 *
    169  * @returns true if done, false if there is more that needs to be saved first.
     169 * @returns VBox status code.
     170 * @retval  VINF_SUCCESS if done.
     171 * @retval  VINF_SSM_VOTE_FOR_ANOTHER_PASS if another pass is needed.
     172 * @retval  VERR_SSM_VOTE_FOR_GIVING_UP if its time to give up.
     173 *
    170174 * @param   pDevIns         Device instance of the device which registered the data unit.
    171175 * @param   pSSM            SSM operation handle.
     
    288292 * being called every time.
    289293 *
    290  * @returns true if done, false if there is more that needs to be saved first.
     294 * @returns VBox status code.
     295 * @retval  VINF_SUCCESS if done.
     296 * @retval  VINF_SSM_VOTE_FOR_ANOTHER_PASS if another pass is needed.
     297 * @retval  VERR_SSM_VOTE_FOR_GIVING_UP if its time to give up.
     298 *
    291299 * @param   pDrvIns         Driver instance of the device which registered the
    292300 *                          data unit.
     
    410418 * being called every time.
    411419 *
    412  * @returns true if done, false if there is more that needs to be saved first.
    413  * @param   pVM             VM Handle.
    414  * @param   pSSM            SSM operation handle.
    415  * @thread  Any.
    416  */
    417 typedef DECLCALLBACK(bool) FNSSMINTLIVEVOTE(PVM pVM, PSSMHANDLE pSSM);
     420 * @returns VBox status code.
     421 * @retval  VINF_SUCCESS if done.
     422 * @retval  VINF_SSM_VOTE_FOR_ANOTHER_PASS if another pass is needed.
     423 * @retval  VERR_SSM_VOTE_FOR_GIVING_UP if its time to give up.
     424 *
     425 * @param   pVM             VM Handle.
     426 * @param   pSSM            SSM operation handle.
     427 * @thread  Any.
     428 */
     429typedef DECLCALLBACK(int) FNSSMINTLIVEVOTE(PVM pVM, PSSMHANDLE pSSM);
    418430/** Pointer to a FNSSMINTLIVEVOTE() function. */
    419431typedef FNSSMINTLIVEVOTE *PFNSSMINTLIVEVOTE;
     
    632644VMMR3DECL(int) SSMR3DeregisterExternal(PVM pVM, const char *pszName);
    633645VMMR3DECL(int) SSMR3Save(PVM pVM, const char *pszFilename, SSMAFTER enmAfter, PFNVMPROGRESS pfnProgress, void *pvUser);
     646VMMR3DECL(int) SSMR3LiveToFile(PVM pVM, const char *pszFilename, SSMAFTER enmAfter,
     647                               PFNVMPROGRESS pfnProgress, void *pvUser, PSSMHANDLE *ppSSM);
     648VMMR3DECL(int) SSMR3LiveDoStep1(PSSMHANDLE pSSM);
     649VMMR3DECL(int) SSMR3LiveDoStep2(PSSMHANDLE pSSM);
     650VMMR3DECL(int) SSMR3LiveDone(PSSMHANDLE pSSM);
    634651VMMR3DECL(int) SSMR3Load(PVM pVM, const char *pszFilename, SSMAFTER enmAfter, PFNVMPROGRESS pfnProgress, void *pvUser);
    635652VMMR3DECL(int) SSMR3ValidateFile(const char *pszFilename, bool fChecksumIt);
  • trunk/src/VBox/VMM/SSM.cpp

    r22781 r22792  
    425425    /** the amount of % we reserve for the 'done' stage */
    426426    unsigned        uPercentDone;
     427    /** The filename, NULL if remote stream. */
     428    const char     *pszFilename;
    427429
    428430    union
     
    25752577    int rc = ssmR3DataFlushBuffer(pSSM);
    25762578    if (RT_SUCCESS(rc))
     2579    {
     2580        pSSM->offUnit = UINT64_MAX;
    25772581        return VINF_SUCCESS;
     2582    }
    25782583
    25792584    if (RT_SUCCESS(pSSM->rc))
     
    32823287
    32833288/**
     3289 * Worker for SSMR3LiveDone and SSMR3Save that closes the handle and deletes the
     3290 * saved state file on failure.
     3291 *
     3292 * @returns VBox status code (pSSM->rc).
     3293 * @param   pVM                 The VM handle.
     3294 * @param   pSSM                The saved state handle.
     3295 */
     3296static int ssmR3SaveDoClose(PVM pVM, PSSMHANDLE pSSM)
     3297{
     3298    VM_ASSERT_EMT0(pVM);
     3299
     3300    /*
     3301     * Close the stream and delete the file on failure.
     3302     */
     3303    int rc = ssmR3StrmClose(&pSSM->Strm);
     3304    if (RT_SUCCESS(rc))
     3305        rc = pSSM->rc;
     3306    if (RT_SUCCESS(rc))
     3307    {
     3308        if (pSSM->pfnProgress)
     3309            pSSM->pfnProgress(pVM, 100, pSSM->pvUser);
     3310        LogRel(("SSM: Successfully saved the VM state to '%s'\n",
     3311                pSSM->pszFilename ? pSSM->pszFilename : "<remote-machine>"));
     3312    }
     3313    else
     3314    {
     3315        if (pSSM->pszFilename)
     3316        {
     3317            int rc2 = RTFileDelete(pSSM->pszFilename);
     3318            AssertRC(rc2);
     3319            if (RT_SUCCESS(rc2))
     3320                LogRel(("SSM: Failed to save the VM state to '%s' (file deleted): %Rrc\n",
     3321                        pSSM->pszFilename, rc));
     3322            else
     3323                LogRel(("SSM: Failed to save the VM state to '%s' (file deletion failed, rc2=%Rrc): %Rrc\n",
     3324                        pSSM->pszFilename, rc2, rc));
     3325        }
     3326        else
     3327            LogRel(("SSM: Failed to save the VM state.\n"));
     3328    }
     3329
     3330    /*
     3331     * Trash the handle before freeing it.
     3332     */
     3333    pSSM->pVM = NULL;
     3334    pSSM->enmAfter = SSMAFTER_INVALID;
     3335    pSSM->enmOp = SSMSTATE_INVALID;
     3336    RTMemFree(pSSM);
     3337
     3338    return rc;
     3339}
     3340
     3341
     3342/**
     3343 * Closes the SSM handle.
     3344 *
     3345 * This must always be called on a handled returned by SSMR3LiveToFile or
     3346 * SSMR3LiveToRemote.
     3347 *
     3348 * @returns VBox status.
     3349 *
     3350 * @param   pSSM            The SSM handle returned by SSMR3LiveToFile or
     3351 *                          SSMR3LiveToRemote.
     3352 *
     3353 * @thread  EMT(0).
     3354 */
     3355VMMR3DECL(int) SSMR3LiveDone(PSSMHANDLE pSSM)
     3356{
     3357    LogFlow(("SSMR3LiveDone: pSSM=%p\n", pSSM));
     3358
     3359    /*
     3360     * Validate input.
     3361     */
     3362    AssertPtrReturn(pSSM, VERR_INVALID_POINTER);
     3363    PVM pVM = pSSM->pVM;
     3364    VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
     3365    VM_ASSERT_EMT0(pVM);
     3366    AssertMsgReturn(   pSSM->enmAfter == SSMAFTER_DESTROY
     3367                    || pSSM->enmAfter == SSMAFTER_CONTINUE,
     3368                    ("%d\n", pSSM->enmAfter),
     3369                    VERR_INVALID_PARAMETER);
     3370    AssertMsgReturn(    pSSM->enmOp >= SSMSTATE_LIVE_PREP
     3371                    &&  pSSM->enmOp <= SSMSTATE_SAVE_DONE,
     3372                    ("%d\n", pSSM->enmOp), VERR_INVALID_STATE);
     3373
     3374    /*
     3375     * Join paths with SSMR3Save again.
     3376     */
     3377    return ssmR3SaveDoClose(pVM, pSSM);
     3378}
     3379
     3380
     3381/**
     3382 * Do the pfnSaveDone run.
     3383 *
     3384 * @returns VBox status code (pSSM->rc).
     3385 * @param   pVM                 The VM handle.
     3386 * @param   pSSM                The saved state handle.
     3387 */
     3388static int ssmR3SaveDoDoneRun(PVM pVM, PSSMHANDLE pSSM)
     3389{
     3390    VM_ASSERT_EMT0(pVM);
     3391
     3392    /*
     3393     * Do the done run.
     3394     */
     3395    pSSM->enmOp = SSMSTATE_SAVE_DONE;
     3396    for (PSSMUNIT pUnit = pVM->ssm.s.pHead; pUnit; pUnit = pUnit->pNext)
     3397    {
     3398        if (    pUnit->u.Common.pfnSaveDone
     3399            &&  (   pUnit->fCalled
     3400                 || (!pUnit->u.Common.pfnSavePrep && !pUnit->u.Common.pfnSaveExec)))
     3401        {
     3402            int rcOld = pSSM->rc;
     3403            int rc;
     3404            switch (pUnit->enmType)
     3405            {
     3406                case SSMUNITTYPE_DEV:
     3407                    rc = pUnit->u.Dev.pfnSaveDone(pUnit->u.Dev.pDevIns, pSSM);
     3408                    break;
     3409                case SSMUNITTYPE_DRV:
     3410                    rc = pUnit->u.Drv.pfnSaveDone(pUnit->u.Drv.pDrvIns, pSSM);
     3411                    break;
     3412                case SSMUNITTYPE_INTERNAL:
     3413                    rc = pUnit->u.Internal.pfnSaveDone(pVM, pSSM);
     3414                    break;
     3415                case SSMUNITTYPE_EXTERNAL:
     3416                    rc = pUnit->u.External.pfnSaveDone(pSSM, pUnit->u.External.pvUser);
     3417                    break;
     3418                default:
     3419                    rc = VERR_INTERNAL_ERROR;
     3420                    break;
     3421            }
     3422            if (RT_SUCCESS(rc) && pSSM->rc != rcOld)
     3423                rc = pSSM->rc;
     3424            if (RT_FAILURE(rc))
     3425            {
     3426                LogRel(("SSM: Done save failed with rc=%Rrc for data unit '%s.\n", rc, pUnit->szName));
     3427                if (RT_SUCCESS(pSSM->rc))
     3428                    pSSM->rc = rc;
     3429            }
     3430        }
     3431    }
     3432    return pSSM->rc;
     3433}
     3434
     3435
     3436/**
    32843437 * Writes the directory.
    32853438 *
     
    32913444static int ssmR3WriteDirectory(PVM pVM, PSSMHANDLE pSSM, uint32_t *pcEntries)
    32923445{
     3446    VM_ASSERT_EMT0(pVM);
     3447
    32933448    /*
    32943449     * Grab some temporary memory for the dictionary.
     
    33333488
    33343489/**
     3490 * Finalize the saved state stream, i.e. add the end unit, directory
     3491 * and footer.
     3492 *
     3493 * @returns VBox status code (pSSM->rc).
     3494 * @param   pVM                 The VM handle.
     3495 * @param   pSSM                The saved state handle.
     3496 */
     3497static int ssmR3SaveDoFinalization(PVM pVM, PSSMHANDLE pSSM)
     3498{
     3499    VM_ASSERT_EMT0(pVM);
     3500    Assert(RT_SUCCESS(pSSM->rc));
     3501
     3502    /*
     3503     * Write the end unit.
     3504     */
     3505    SSMFILEUNITHDRV2 UnitHdr;
     3506    memcpy(&UnitHdr.szMagic[0], SSMFILEUNITHDR_END, sizeof(UnitHdr.szMagic));
     3507    UnitHdr.offStream       = ssmR3StrmTell(&pSSM->Strm);
     3508    UnitHdr.u32CurStreamCRC = ssmR3StrmCurCRC(&pSSM->Strm);
     3509    UnitHdr.u32CRC          = 0;
     3510    UnitHdr.u32Version      = 0;
     3511    UnitHdr.u32Instance     = 0;
     3512    UnitHdr.u32Phase        = SSM_PHASE_FINAL;
     3513    UnitHdr.fFlags          = 0;
     3514    UnitHdr.cbName          = 0;
     3515    UnitHdr.u32CRC          = RTCrc32(&UnitHdr, RT_OFFSETOF(SSMFILEUNITHDRV2, szName[0]));
     3516    Log(("SSM: Unit at %#9llx: END UNIT\n", UnitHdr.offStream));
     3517    int rc = ssmR3StrmWrite(&pSSM->Strm, &UnitHdr, RT_OFFSETOF(SSMFILEUNITHDRV2, szName[0]));
     3518    if (RT_FAILURE(rc))
     3519    {
     3520        LogRel(("SSM: Failed writing the end unit: %Rrc\n", rc));
     3521        return pSSM->rc = rc;
     3522    }
     3523
     3524    /*
     3525     * Write the directory for the final units and then the footer.
     3526     */
     3527    SSMFILEFTR Footer;
     3528    rc = ssmR3WriteDirectory(pVM, pSSM, &Footer.cDirEntries);
     3529    if (RT_FAILURE(rc))
     3530    {
     3531        LogRel(("SSM: Failed writing the directory: %Rrc\n", rc));
     3532        return pSSM->rc = rc;
     3533    }
     3534
     3535    memcpy(Footer.szMagic, SSMFILEFTR_MAGIC, sizeof(Footer.szMagic));
     3536    Footer.offStream    = ssmR3StrmTell(&pSSM->Strm);
     3537    Footer.u32StreamCRC = ssmR3StrmFinalCRC(&pSSM->Strm);
     3538    Footer.u32Reserved  = 0;
     3539    Footer.u32CRC       = 0;
     3540    Footer.u32CRC       = RTCrc32(&Footer, sizeof(Footer));
     3541    Log(("SSM: Footer at %#9llx: \n", Footer.offStream));
     3542    rc = ssmR3StrmWrite(&pSSM->Strm, &Footer, sizeof(Footer));
     3543    if (RT_SUCCESS(rc))
     3544        rc = ssmR3StrmSetEnd(&pSSM->Strm);
     3545    if (RT_FAILURE(rc))
     3546    {
     3547        LogRel(("SSM: Failed writing the footer: %Rrc\n", rc));
     3548        return pSSM->rc = rc;
     3549    }
     3550
     3551    LogRel(("SSM: Footer at %#llx (%lld), %u directory entries.\n",
     3552            Footer.offStream, Footer.offStream, Footer.cDirEntries));
     3553    return VINF_SUCCESS;
     3554}
     3555
     3556
     3557/**
     3558 * Do the pfnSaveExec run.
     3559 *
     3560 * @returns VBox status code (pSSM->rc).
     3561 * @param   pVM                 The VM handle.
     3562 * @param   pSSM                The saved state handle.
     3563 */
     3564static int ssmR3SaveDoExecRun(PVM pVM, PSSMHANDLE pSSM)
     3565{
     3566    VM_ASSERT_EMT0(pVM);
     3567    Assert(RT_SUCCESS(pSSM->rc));
     3568
     3569    pSSM->enmOp = SSMSTATE_SAVE_EXEC;
     3570    for (PSSMUNIT pUnit = pVM->ssm.s.pHead; pUnit; pUnit = pUnit->pNext)
     3571    {
     3572        /*
     3573         * Not all unit have a callback. Skip those which don't and
     3574         * make sure to keep the progress indicator up to date.
     3575         */
     3576        pSSM->offEstUnitEnd += pUnit->cbGuess;
     3577        if (!pUnit->u.Common.pfnSaveExec)
     3578        {
     3579            pUnit->fCalled = true;
     3580            if (pUnit->cbGuess)
     3581                ssmR3Progress(pSSM, pSSM->offEstUnitEnd - pSSM->offEst);
     3582            continue;
     3583        }
     3584        pUnit->offStream = ssmR3StrmTell(&pSSM->Strm);
     3585
     3586        /*
     3587         * Write data unit header
     3588         */
     3589        SSMFILEUNITHDRV2 UnitHdr;
     3590        memcpy(&UnitHdr.szMagic[0], SSMFILEUNITHDR_MAGIC, sizeof(UnitHdr.szMagic));
     3591        UnitHdr.offStream       = pUnit->offStream;
     3592        UnitHdr.u32CurStreamCRC = ssmR3StrmCurCRC(&pSSM->Strm);
     3593        UnitHdr.u32CRC          = 0;
     3594        UnitHdr.u32Version      = pUnit->u32Version;
     3595        UnitHdr.u32Instance     = pUnit->u32Instance;
     3596        UnitHdr.u32Phase        = SSM_PHASE_FINAL;
     3597        UnitHdr.fFlags          = 0;
     3598        UnitHdr.cbName          = (uint32_t)pUnit->cchName + 1;
     3599        memcpy(&UnitHdr.szName[0], &pUnit->szName[0], UnitHdr.cbName);
     3600        UnitHdr.u32CRC          = RTCrc32(&UnitHdr, RT_OFFSETOF(SSMFILEUNITHDRV2, szName[UnitHdr.cbName]));
     3601        Log(("SSM: Unit at %#9llx: '%s', instance %u, phase %#x, version %u\n",
     3602             UnitHdr.offStream, UnitHdr.szName, UnitHdr.u32Instance, UnitHdr.u32Phase, UnitHdr.u32Version));
     3603        int rc = ssmR3StrmWrite(&pSSM->Strm, &UnitHdr, RT_OFFSETOF(SSMFILEUNITHDRV2, szName[UnitHdr.cbName]));
     3604        if (RT_FAILURE(rc))
     3605        {
     3606            LogRel(("SSM: Failed to write unit header. rc=%Rrc\n", rc));
     3607            return pSSM->rc = rc;
     3608        }
     3609
     3610        /*
     3611         * Call the execute handler.
     3612         */
     3613        ssmR3DataWriteBegin(pSSM);
     3614        switch (pUnit->enmType)
     3615        {
     3616            case SSMUNITTYPE_DEV:
     3617                rc = pUnit->u.Dev.pfnSaveExec(pUnit->u.Dev.pDevIns, pSSM);
     3618                break;
     3619            case SSMUNITTYPE_DRV:
     3620                rc = pUnit->u.Drv.pfnSaveExec(pUnit->u.Drv.pDrvIns, pSSM);
     3621                break;
     3622            case SSMUNITTYPE_INTERNAL:
     3623                rc = pUnit->u.Internal.pfnSaveExec(pVM, pSSM);
     3624                break;
     3625            case SSMUNITTYPE_EXTERNAL:
     3626                pUnit->u.External.pfnSaveExec(pSSM, pUnit->u.External.pvUser);
     3627                rc = pSSM->rc;
     3628                break;
     3629            default:
     3630                rc = VERR_INTERNAL_ERROR;
     3631                break;
     3632        }
     3633        pUnit->fCalled = true;
     3634        if (RT_SUCCESS(rc))
     3635            rc = ssmR3DataFlushBuffer(pSSM); /* will return SSMHANDLE::rc if it is set */
     3636        if (RT_FAILURE(rc))
     3637        {
     3638            LogRel(("SSM: Execute save failed with rc=%Rrc for data unit '%s'/#%u.\n", rc, pUnit->szName, pUnit->u32Instance));
     3639            if (RT_SUCCESS(pSSM->rc))
     3640                pSSM->rc = rc;
     3641            return rc;
     3642        }
     3643
     3644        /*
     3645         * Write the termination record and flush the compression stream.
     3646         */
     3647        SSMRECTERM TermRec;
     3648        TermRec.u8TypeAndFlags   = SSM_REC_FLAGS_FIXED | SSM_REC_FLAGS_IMPORTANT | SSM_REC_TYPE_TERM;
     3649        TermRec.cbRec            = sizeof(TermRec) - 2;
     3650        if (pSSM->Strm.fChecksummed)
     3651        {
     3652            TermRec.fFlags       = SSMRECTERM_FLAGS_CRC32;
     3653            TermRec.u32StreamCRC = RTCrc32Finish(RTCrc32Process(ssmR3StrmCurCRC(&pSSM->Strm), &TermRec, 2));
     3654        }
     3655        else
     3656        {
     3657            TermRec.fFlags       = 0;
     3658            TermRec.u32StreamCRC = 0;
     3659        }
     3660        TermRec.cbUnit           = pSSM->offUnit + sizeof(TermRec);
     3661        rc = ssmR3DataWriteRaw(pSSM, &TermRec, sizeof(TermRec));
     3662        if (RT_SUCCESS(rc))
     3663            rc = ssmR3DataWriteFinish(pSSM);
     3664        if (RT_FAILURE(rc))
     3665        {
     3666            LogRel(("SSM: Failed ending compression stream. rc=%Rrc\n", rc));
     3667            return pSSM->rc = rc;
     3668        }
     3669
     3670        /*
     3671         * Advance the progress indicator to the end of the current unit.
     3672         */
     3673        ssmR3Progress(pSSM, pSSM->offEstUnitEnd - pSSM->offEst);
     3674    } /* for each unit */
     3675
     3676
     3677    /* (progress should be pending 99% now) */
     3678    AssertMsg(pSSM->uPercent == (101 - pSSM->uPercentDone), ("%d\n", pSSM->uPercent));
     3679    return VINF_SUCCESS;
     3680}
     3681
     3682
     3683/**
     3684 * Do the pfnSavePrep run.
     3685 *
     3686 * @returns VBox status code (pSSM->rc).
     3687 * @param   pVM                 The VM handle.
     3688 * @param   pSSM                The saved state handle.
     3689 */
     3690static int ssmR3SaveDoPrepRun(PVM pVM, PSSMHANDLE pSSM)
     3691{
     3692    VM_ASSERT_EMT0(pVM);
     3693    Assert(RT_SUCCESS(pSSM->rc));
     3694
     3695    /*
     3696     * Do the prepare run.
     3697     */
     3698    pSSM->enmOp = SSMSTATE_SAVE_PREP;
     3699    for (PSSMUNIT pUnit = pVM->ssm.s.pHead; pUnit; pUnit = pUnit->pNext)
     3700    {
     3701        if (pUnit->u.Common.pfnSavePrep)
     3702        {
     3703            int rc;
     3704            switch (pUnit->enmType)
     3705            {
     3706                case SSMUNITTYPE_DEV:
     3707                    rc = pUnit->u.Dev.pfnSavePrep(pUnit->u.Dev.pDevIns, pSSM);
     3708                    break;
     3709                case SSMUNITTYPE_DRV:
     3710                    rc = pUnit->u.Drv.pfnSavePrep(pUnit->u.Drv.pDrvIns, pSSM);
     3711                    break;
     3712                case SSMUNITTYPE_INTERNAL:
     3713                    rc = pUnit->u.Internal.pfnSavePrep(pVM, pSSM);
     3714                    break;
     3715                case SSMUNITTYPE_EXTERNAL:
     3716                    rc = pUnit->u.External.pfnSavePrep(pSSM, pUnit->u.External.pvUser);
     3717                    break;
     3718                default:
     3719                    rc = VERR_INTERNAL_ERROR;
     3720                    break;
     3721            }
     3722            pUnit->fCalled = true;
     3723            if (RT_SUCCESS(rc))
     3724                rc = pSSM->rc;
     3725            if (RT_FAILURE(rc))
     3726            {
     3727                LogRel(("SSM: Prepare save failed with rc=%Rrc for data unit '%s.\n", rc, pUnit->szName));
     3728                if (RT_SUCCESS(pSSM->rc))
     3729                    pSSM->rc = rc;
     3730                return rc;
     3731            }
     3732        }
     3733
     3734        pSSM->cbEstTotal += pUnit->cbGuess;
     3735    }
     3736
     3737    /*
     3738     * Work the progress indicator if we got one.
     3739     */
     3740    if (pSSM->pfnProgress)
     3741        pSSM->pfnProgress(pVM, pSSM->uPercentPrepare-1, pSSM->pvUser);
     3742    pSSM->uPercent = pSSM->uPercentPrepare;
     3743
     3744    return VINF_SUCCESS;
     3745}
     3746
     3747
     3748/**
     3749 * Common worker for SSMR3Save and SSMR3Migrate.
     3750 *
     3751 * @returns VBox status code (no need to check pSSM->rc).
     3752 * @param   pVM                 The VM handle.
     3753 * @param   pSSM                The state handle.
     3754 *
     3755 * @thread  EMT(0)
     3756 */
     3757static int ssmR3SaveDoCommon(PVM pVM, PSSMHANDLE pSSM)
     3758{
     3759    VM_ASSERT_EMT0(pVM);
     3760
     3761    /*
     3762     * Do the work.
     3763     */
     3764    int rc = ssmR3SaveDoPrepRun(pVM, pSSM);
     3765    if (RT_SUCCESS(rc))
     3766    {
     3767        rc = ssmR3SaveDoExecRun(pVM, pSSM);
     3768        if (RT_SUCCESS(rc))
     3769            rc = ssmR3SaveDoFinalization(pVM, pSSM);
     3770    }
     3771    Assert(pSSM->rc == rc);
     3772    int rc2 = ssmR3SaveDoDoneRun(pVM, pSSM);
     3773    if (RT_SUCCESS(rc))
     3774        rc = rc2;
     3775
     3776    return rc;
     3777}
     3778
     3779
     3780/**
     3781 * Saves the rest of the state on EMT0.
     3782 *
     3783 * @returns VBox status.
     3784 *
     3785 * @param   pSSM            The SSM handle returned by SSMR3LiveToFile or
     3786 *                          SSMR3LiveToRemote.
     3787 *
     3788 * @thread  Non-EMT thread. Will involve the EMT at the end of the operation.
     3789 */
     3790VMMR3DECL(int) SSMR3LiveDoStep2(PSSMHANDLE pSSM)
     3791{
     3792    LogFlow(("SSMR3LiveDoStep2: pSSM=%p\n", pSSM));
     3793
     3794    /*
     3795     * Validate input.
     3796     */
     3797    AssertPtrReturn(pSSM, VERR_INVALID_POINTER);
     3798    PVM pVM = pSSM->pVM;
     3799    VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
     3800    VM_ASSERT_EMT0(pVM);
     3801    AssertMsgReturn(   pSSM->enmAfter == SSMAFTER_DESTROY
     3802                    || pSSM->enmAfter == SSMAFTER_CONTINUE,
     3803                    ("%d\n", pSSM->enmAfter),
     3804                    VERR_INVALID_PARAMETER);
     3805    AssertMsgReturn(pSSM->enmOp == SSMSTATE_SAVE_PREP, ("%d\n", pSSM->enmOp), VERR_INVALID_STATE);
     3806
     3807    /*
     3808     * Join paths with VMMR3Save.
     3809     */
     3810    return ssmR3SaveDoCommon(pVM, pSSM);
     3811}
     3812
     3813
     3814/**
     3815 * Writes the file header and clear the per-unit data.
     3816 *
     3817 * @returns VBox status code.
     3818 * @param   pVM                 The VM handle.
     3819 * @param   pSSM                The SSM handle.
     3820 */
     3821static int ssmR3WriteHeaderAndClearPerUnitData(PVM pVM, PSSMHANDLE pSSM)
     3822{
     3823    /*
     3824     * Write the header.
     3825     */
     3826    SSMFILEHDR FileHdr;
     3827    memcpy(&FileHdr.szMagic, SSMFILEHDR_MAGIC_V2_0, sizeof(FileHdr.szMagic));
     3828    FileHdr.u16VerMajor  = VBOX_VERSION_MAJOR;
     3829    FileHdr.u16VerMinor  = VBOX_VERSION_MINOR;
     3830    FileHdr.u32VerBuild  = VBOX_VERSION_BUILD;
     3831    FileHdr.u32SvnRev    = VMMGetSvnRev(),
     3832    FileHdr.cHostBits    = HC_ARCH_BITS;
     3833    FileHdr.cbGCPhys     = sizeof(RTGCPHYS);
     3834    FileHdr.cbGCPtr      = sizeof(RTGCPTR);
     3835    FileHdr.u8Reserved   = 0;
     3836    FileHdr.cUnits       = pVM->ssm.s.cUnits;
     3837    FileHdr.fFlags       = SSMFILEHDR_FLAGS_STREAM_CRC32;
     3838    FileHdr.cbMaxDecompr = RT_SIZEOFMEMB(SSMHANDLE, u.Read.abDataBuffer);
     3839    FileHdr.u32CRC       = 0;
     3840    FileHdr.u32CRC       = RTCrc32(&FileHdr, sizeof(FileHdr));
     3841    int rc = ssmR3StrmWrite(&pSSM->Strm, &FileHdr, sizeof(FileHdr));
     3842    if (RT_SUCCESS(rc))
     3843        return rc;
     3844
     3845    /*
     3846     * Clear the per unit flags and offsets.
     3847     */
     3848    for (PSSMUNIT pUnit = pVM->ssm.s.pHead; pUnit; pUnit = pUnit->pNext)
     3849    {
     3850        pUnit->fCalled   = false;
     3851        pUnit->offStream = RTFOFF_MIN;
     3852    }
     3853
     3854    return VINF_SUCCESS;
     3855}
     3856
     3857
     3858/**
     3859 * Creates a new saved state file.
     3860 *
     3861 * @returns VBox status code.
     3862 * @param   pVM                 The VM handle.
     3863 * @param   pszFilename         The name of the file.
     3864 * @param   enmAfter            What to do afterwards.
     3865 * @param   pfnProgress         The progress callback.
     3866 * @param   pvUser              The progress callback user argument.
     3867 * @param   ppSSM               Where to return the pointer to the saved state
     3868 *                              handle upon successful return.  Free it using
     3869 *                              RTMemFree after closing the stream.
     3870 */
     3871static int ssmR3SaveDoCreateFile(PVM pVM, const char *pszFilename, SSMAFTER enmAfter,
     3872                                 PFNVMPROGRESS pfnProgress, void *pvUser, PSSMHANDLE *ppSSM)
     3873{
     3874    PSSMHANDLE pSSM = (PSSMHANDLE)RTMemAllocZ(sizeof(*pSSM));
     3875    if (!pSSM)
     3876        return VERR_NO_MEMORY;
     3877
     3878    pSSM->pVM                   = pVM;
     3879    pSSM->enmOp                 = SSMSTATE_INVALID;
     3880    pSSM->enmAfter              = enmAfter;
     3881    pSSM->rc                    = VINF_SUCCESS;
     3882    pSSM->cbUnitLeftV1          = 0;
     3883    pSSM->offUnit               = UINT64_MAX;
     3884    pSSM->pfnProgress           = pfnProgress;
     3885    pSSM->pvUser                = pvUser;
     3886    pSSM->uPercent              = 0;
     3887    pSSM->offEstProgress        = 0;
     3888    pSSM->cbEstTotal            = 0;
     3889    pSSM->offEst                = 0;
     3890    pSSM->offEstUnitEnd         = 0;
     3891    pSSM->uPercentPrepare       = 0;
     3892    pSSM->uPercentDone          = 0;
     3893    pSSM->pszFilename           = pszFilename;
     3894    pSSM->u.Write.offDataBuffer = 0;
     3895
     3896    int rc = ssmR3StrmOpenFile(&pSSM->Strm, pszFilename, true /*fWrite*/, true /*fChecksummed*/, 8 /*cBuffers*/);
     3897    if (RT_FAILURE(rc))
     3898    {
     3899        LogRel(("SSM: Failed to create save state file '%s', rc=%Rrc.\n",  pszFilename, rc));
     3900        RTMemFree(pSSM);
     3901        return rc;
     3902    }
     3903
     3904    *ppSSM = pSSM;
     3905    return VINF_SUCCESS;
     3906}
     3907
     3908
     3909/**
    33353910 * Start VM save operation.
    33363911 *
     
    33483923{
    33493924    LogFlow(("SSMR3Save: pszFilename=%p:{%s} enmAfter=%d pfnProgress=%p pvUser=%p\n", pszFilename, pszFilename, enmAfter, pfnProgress, pvUser));
    3350     VM_ASSERT_EMT(pVM);
     3925    VM_ASSERT_EMT0(pVM);
    33513926
    33523927    /*
     
    33543929     */
    33553930    AssertMsgReturn(   enmAfter == SSMAFTER_DESTROY
    3356                     || enmAfter == SSMAFTER_CONTINUE
    3357                     || enmAfter == SSMAFTER_MIGRATE,
     3931                    || enmAfter == SSMAFTER_CONTINUE,
    33583932                    ("%d\n", enmAfter),
    33593933                    VERR_INVALID_PARAMETER);
    33603934
    33613935    /*
    3362      * Create the handle and try open the file.
     3936     * Create the saved state file and handle.
    33633937     *
    33643938     * Note that there might be quite some work to do after executing the saving,
    3365      * so we reserve 20% for the 'Done' period.  The checksumming and closing of
    3366      * the saved state file might take a long time.
    3367      */
    3368     SSMHANDLE Handle;
    3369     RT_ZERO(Handle);
    3370     Handle.pVM              = pVM;
    3371     Handle.enmOp            = SSMSTATE_INVALID;
    3372     Handle.enmAfter         = enmAfter;
    3373     Handle.rc               = VINF_SUCCESS;
    3374     Handle.cbUnitLeftV1     = 0;
    3375     Handle.offUnit          = UINT64_MAX;
    3376     Handle.pfnProgress      = pfnProgress;
    3377     Handle.pvUser           = pvUser;
    3378     Handle.uPercent         = 0;
    3379     Handle.offEstProgress   = 0;
    3380     Handle.cbEstTotal       = 0;
    3381     Handle.offEst           = 0;
    3382     Handle.offEstUnitEnd    = 0;
    3383     Handle.uPercentPrepare  = 20;
    3384     Handle.uPercentDone     = 2;
    3385     Handle.u.Write.offDataBuffer    = 0;
    3386 
    3387     int rc = ssmR3StrmOpenFile(&Handle.Strm, pszFilename, true /*fWrite*/, true /*fChecksummed*/, 8 /*cBuffers*/);
     3939     * so we reserve 20% for the 'Done' period.
     3940     */
     3941    PSSMHANDLE pSSM;
     3942    int rc = ssmR3SaveDoCreateFile(pVM, pszFilename, enmAfter, pfnProgress, pvUser, &pSSM);
    33883943    if (RT_FAILURE(rc))
    3389     {
    3390         LogRel(("SSM: Failed to create save state file '%s', rc=%Rrc.\n",  pszFilename, rc));
    33913944        return rc;
    3392     }
    3393 
     3945    pSSM->uPercentPrepare = 20;
     3946    pSSM->uPercentDone    = 2;
     3947
     3948    /*
     3949     * Write the saved state stream header and join paths with
     3950     * the other save methods for the rest of the job.
     3951     */
    33943952    Log(("SSM: Starting state save to file '%s'...\n", pszFilename));
    3395     ssmR3StrmStartIoThread(&Handle.Strm);
    3396 
    3397     /*
    3398      * Write header.
    3399      */
    3400     union
    3401     {
    3402         SSMFILEHDR          FileHdr;
    3403         SSMFILEUNITHDRV2    UnitHdr;
    3404         SSMFILEFTR          Footer;
    3405     } u;
    3406 
    3407     memcpy(&u.FileHdr.szMagic, SSMFILEHDR_MAGIC_V2_0, sizeof(u.FileHdr.szMagic));
    3408     u.FileHdr.u16VerMajor  = VBOX_VERSION_MAJOR;
    3409     u.FileHdr.u16VerMinor  = VBOX_VERSION_MINOR;
    3410     u.FileHdr.u32VerBuild  = VBOX_VERSION_BUILD;
    3411     u.FileHdr.u32SvnRev    = VMMGetSvnRev(),
    3412     u.FileHdr.cHostBits    = HC_ARCH_BITS;
    3413     u.FileHdr.cbGCPhys     = sizeof(RTGCPHYS);
    3414     u.FileHdr.cbGCPtr      = sizeof(RTGCPTR);
    3415     u.FileHdr.u8Reserved   = 0;
    3416     u.FileHdr.cUnits       = pVM->ssm.s.cUnits;
    3417     u.FileHdr.fFlags       = SSMFILEHDR_FLAGS_STREAM_CRC32;
    3418     u.FileHdr.cbMaxDecompr = RT_SIZEOFMEMB(SSMHANDLE, u.Read.abDataBuffer);
    3419     u.FileHdr.u32CRC       = 0;
    3420     u.FileHdr.u32CRC       = RTCrc32(&u.FileHdr, sizeof(u.FileHdr));
    3421     rc = ssmR3StrmWrite(&Handle.Strm, &u.FileHdr, sizeof(u.FileHdr));
     3953    ssmR3StrmStartIoThread(&pSSM->Strm);
     3954    rc = ssmR3WriteHeaderAndClearPerUnitData(pVM, pSSM);
    34223955    if (RT_SUCCESS(rc))
    3423     {
    3424         /*
    3425          * Clear the per unit flags and offsets.
    3426          */
    3427         PSSMUNIT pUnit;
    3428         for (pUnit = pVM->ssm.s.pHead; pUnit; pUnit = pUnit->pNext)
    3429         {
    3430             pUnit->fCalled   = false;
    3431             pUnit->offStream = RTFOFF_MIN;
    3432         }
    3433 
    3434         /*
    3435          * Do the prepare run.
    3436          */
    3437         Handle.rc = VINF_SUCCESS;
    3438         Handle.enmOp = SSMSTATE_SAVE_PREP;
    3439         for (pUnit = pVM->ssm.s.pHead; pUnit; pUnit = pUnit->pNext)
    3440         {
    3441             if (pUnit->u.Common.pfnSavePrep)
     3956        ssmR3SaveDoCommon(pVM, pSSM);
     3957    return ssmR3SaveDoClose(pVM, pSSM);
     3958}
     3959
     3960
     3961/**
     3962 * Calls pfnLiveVote for all units.
     3963 *
     3964 * @returns VBox status code (no need to check pSSM->rc).
     3965 * @param   pVM                 The VM handle.
     3966 * @param   pSSM                The saved state handle.
     3967 */
     3968static int ssmR3DoLiveVoteRun(PVM pVM, PSSMHANDLE pSSM)
     3969{
     3970    /*
     3971     * Do the prepare run.
     3972     */
     3973    AssertRCReturn(pSSM->rc, pSSM->rc);
     3974    pSSM->rc = VINF_SUCCESS;
     3975    pSSM->enmOp = SSMSTATE_LIVE_VOTE;
     3976    for (PSSMUNIT pUnit = pVM->ssm.s.pHead; pUnit; pUnit = pUnit->pNext)
     3977    {
     3978        if (pUnit->u.Common.pfnLiveVote)
     3979        {
     3980            int rc;
     3981            switch (pUnit->enmType)
    34423982            {
    3443                 switch (pUnit->enmType)
     3983                case SSMUNITTYPE_DEV:
     3984                    rc = pUnit->u.Dev.pfnLiveVote(pUnit->u.Dev.pDevIns, pSSM);
     3985                    break;
     3986                case SSMUNITTYPE_DRV:
     3987                    rc = pUnit->u.Drv.pfnLiveVote(pUnit->u.Drv.pDrvIns, pSSM);
     3988                    break;
     3989                case SSMUNITTYPE_INTERNAL:
     3990                    rc = pUnit->u.Internal.pfnLiveVote(pVM, pSSM);
     3991                    break;
     3992                case SSMUNITTYPE_EXTERNAL:
     3993                    rc = pUnit->u.External.pfnLiveVote(pSSM, pUnit->u.External.pvUser);
     3994                    break;
     3995                default:
     3996                    rc = VERR_INTERNAL_ERROR;
     3997                    break;
     3998            }
     3999            Assert(pSSM->rc == VINF_SUCCESS);
     4000
     4001            pUnit->fCalled = true;
     4002            if (rc != VINF_SUCCESS)
     4003            {
     4004                if (rc == VINF_SSM_VOTE_FOR_ANOTHER_PASS)
    34444005                {
    3445                     case SSMUNITTYPE_DEV:
    3446                         rc = pUnit->u.Dev.pfnSavePrep(pUnit->u.Dev.pDevIns, &Handle);
    3447                         break;
    3448                     case SSMUNITTYPE_DRV:
    3449                         rc = pUnit->u.Drv.pfnSavePrep(pUnit->u.Drv.pDrvIns, &Handle);
    3450                         break;
    3451                     case SSMUNITTYPE_INTERNAL:
    3452                         rc = pUnit->u.Internal.pfnSavePrep(pVM, &Handle);
    3453                         break;
    3454                     case SSMUNITTYPE_EXTERNAL:
    3455                         rc = pUnit->u.External.pfnSavePrep(&Handle, pUnit->u.External.pvUser);
    3456                         break;
     4006                    Log(("ssmR3DoLiveVoteRun: '%s'/#%u -> VINF_SSM_VOTE_FOR_ANOTHER_PASS\n", pUnit, pUnit->u32Instance));
     4007                    return VINF_SSM_VOTE_FOR_ANOTHER_PASS;
    34574008                }
    3458                 pUnit->fCalled = true;
    3459                 if (RT_FAILURE(rc))
    3460                 {
    3461                     LogRel(("SSM: Prepare save failed with rc=%Rrc for data unit '%s.\n", rc, pUnit->szName));
     4009                Log(("ssmR3DoLiveVoteRun: '%s'/#%u -> %Rrc!!\n", pUnit, pUnit->u32Instance, rc));
     4010                AssertMsgReturn(RT_FAILURE(rc), ("%Rrc; '%s'\n", rc, pUnit->szName), pSSM->rc = VERR_IPE_UNEXPECTED_INFO_STATUS);
     4011                return rc;
     4012            }
     4013        }
     4014    }
     4015    return VINF_SUCCESS;
     4016}
     4017
     4018
     4019/**
     4020 * Continue a live state saving operation on the worker thread.
     4021 *
     4022 * The
     4023 *
     4024 * @returns VBox status.
     4025 *
     4026 * @param   pSSM            The SSM handle returned by SSMR3LiveToFile or
     4027 *                          SSMR3LiveToRemote.
     4028 *
     4029 * @thread  Non-EMT thread. Will involve the EMT at the end of the operation.
     4030 */
     4031VMMR3DECL(int) SSMR3LiveDoStep1(PSSMHANDLE pSSM)
     4032{
     4033    LogFlow(("SSMR3LiveDoStep1: pSSM=%p\n", pSSM));
     4034
     4035    /*
     4036     * Validate input.
     4037     */
     4038    AssertPtrReturn(pSSM, VERR_INVALID_POINTER);
     4039    PVM pVM = pSSM->pVM;
     4040    VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
     4041    VM_ASSERT_OTHER_THREAD(pVM);
     4042    AssertMsgReturn(   pSSM->enmAfter == SSMAFTER_DESTROY
     4043                    || pSSM->enmAfter == SSMAFTER_CONTINUE,
     4044                    ("%d\n", pSSM->enmAfter),
     4045                    VERR_INVALID_PARAMETER);
     4046    AssertMsgReturn(pSSM->enmOp == SSMSTATE_LIVE_EXEC, ("%d\n", pSSM->enmOp), VERR_INVALID_STATE);
     4047
     4048    /*
     4049     * ...
     4050     */
     4051
     4052    return VERR_NOT_IMPLEMENTED;
     4053}
     4054
     4055
     4056/**
     4057 * Calls pfnLivePrep for all units.
     4058 *
     4059 * @returns VBox status code (no need to check pSSM->rc).
     4060 * @param   pVM                 The VM handle.
     4061 * @param   pSSM                The saved state handle.
     4062 */
     4063static int ssmR3DoLivePrepRun(PVM pVM, PSSMHANDLE pSSM)
     4064{
     4065    /*
     4066     * Do the prepare run.
     4067     */
     4068    pSSM->rc = VINF_SUCCESS;
     4069    pSSM->enmOp = SSMSTATE_SAVE_PREP;
     4070    for (PSSMUNIT pUnit = pVM->ssm.s.pHead; pUnit; pUnit = pUnit->pNext)
     4071    {
     4072        if (pUnit->u.Common.pfnLivePrep)
     4073        {
     4074            int rc;
     4075            switch (pUnit->enmType)
     4076            {
     4077                case SSMUNITTYPE_DEV:
     4078                    rc = pUnit->u.Dev.pfnLivePrep(pUnit->u.Dev.pDevIns, pSSM);
    34624079                    break;
    3463                 }
     4080                case SSMUNITTYPE_DRV:
     4081                    rc = pUnit->u.Drv.pfnLivePrep(pUnit->u.Drv.pDrvIns, pSSM);
     4082                    break;
     4083                case SSMUNITTYPE_INTERNAL:
     4084                    rc = pUnit->u.Internal.pfnLivePrep(pVM, pSSM);
     4085                    break;
     4086                case SSMUNITTYPE_EXTERNAL:
     4087                    rc = pUnit->u.External.pfnLivePrep(pSSM, pUnit->u.External.pvUser);
     4088                    break;
     4089                default:
     4090                    rc = VERR_INTERNAL_ERROR;
     4091                    break;
    34644092            }
    3465 
    3466             Handle.cbEstTotal += pUnit->cbGuess;
    3467         }
    3468 
    3469         /* Progress. */
    3470         if (pfnProgress)
    3471             pfnProgress(pVM, Handle.uPercentPrepare-1, pvUser);
    3472         Handle.uPercent = Handle.uPercentPrepare;
    3473 
    3474         /*
    3475          * Do the execute run.
    3476          */
     4093            pUnit->fCalled = true;
     4094            if (RT_SUCCESS(rc))
     4095                rc = pSSM->rc;
     4096            if (RT_FAILURE(rc))
     4097            {
     4098                LogRel(("SSM: Prepare save failed with rc=%Rrc for data unit '%s.\n", rc, pUnit->szName));
     4099                if (RT_SUCCESS(pSSM->rc))
     4100                    pSSM->rc = rc;
     4101                return rc;
     4102            }
     4103        }
     4104
     4105        pSSM->cbEstTotal += pUnit->cbGuess;
     4106    }
     4107
     4108    /*
     4109     * Work the progress indicator if we got one.
     4110     */
     4111    if (pSSM->pfnProgress)
     4112        pSSM->pfnProgress(pVM, 2, pSSM->pvUser);
     4113    pSSM->uPercent = 2;
     4114
     4115    return VINF_SUCCESS;
     4116}
     4117
     4118
     4119/**
     4120 * Start saving the live state to a file.
     4121 *
     4122 * The live saving sequence is something like this:
     4123 *
     4124 *      -# SSMR3LiveToFile is called on EMT0.  It returns a saved state
     4125 *         handle.
     4126 *      -# SSMR3LiveDoStep1 is called on a non-EMT.  This will save the major
     4127 *         parts of the state while the VM may still be running.
     4128 *      -# The VM is suspended.
     4129 *      -# SSMR3LiveDoStep2 is called on EMT0 to save the remainder of the state
     4130 *         in the normal way.
     4131 *      -# The client does any necessary reconfiguration of harddisks and
     4132 *         similar.
     4133 *      -# SSMR3LiveDone is called on EMT0 to close the handle.
     4134 *      -# The VM is resumed or powered off and destroyed.
     4135 *
     4136 * SSMR3LiveDone should be called even if SSMR3LiveDoStep1 or SSMR3LiveDoStep2
     4137 * fails.
     4138 *
     4139 * @returns VBox status.
     4140 *
     4141 * @param   pVM             The VM handle.
     4142 * @param   pszFilename     Name of the file to save the state in.  This string
     4143 *                          must remain valid until SSMR3LiveDone is called.
     4144 * @param   enmAfter        What is planned after a successful save operation.
     4145 * @param   pfnProgress     Progress callback. Optional.
     4146 * @param   pvUser          User argument for the progress callback.
     4147 *
     4148 * @thread  EMT0
     4149 */
     4150VMMR3DECL(int) SSMR3LiveToFile(PVM pVM, const char *pszFilename, SSMAFTER enmAfter,
     4151                               PFNVMPROGRESS pfnProgress, void *pvUser, PSSMHANDLE *ppSSM)
     4152{
     4153    LogFlow(("SSMR3LiveToFile: pszFilename=%p:{%s} enmAfter=%d pfnProgress=%p pvUser=%p\n", pszFilename, pszFilename, enmAfter, pfnProgress, pvUser));
     4154    VM_ASSERT_EMT0(pVM);
     4155
     4156    /*
     4157     * Validate input.
     4158     */
     4159    AssertMsgReturn(   enmAfter == SSMAFTER_DESTROY
     4160                    || enmAfter == SSMAFTER_CONTINUE,
     4161                    ("%d\n", enmAfter),
     4162                    VERR_INVALID_PARAMETER);
     4163
     4164    /*
     4165     * Create the saved state file and handle.
     4166     *
     4167     * Note that there might be quite some work to do after executing the saving,
     4168     * so we reserve 20% for the 'Done' period.
     4169     */
     4170    PSSMHANDLE pSSM;
     4171    int rc = ssmR3SaveDoCreateFile(pVM, pszFilename, enmAfter, pfnProgress, pvUser, &pSSM);
     4172    if (RT_FAILURE(rc))
     4173        return rc;
     4174    pSSM->uPercentPrepare = 20; /** @todo fix these. */
     4175    pSSM->uPercentDone    = 2;
     4176
     4177    /*
     4178     * Write the saved state stream header and do the prep run for live saving.
     4179     */
     4180    Log(("SSM: Starting state save to file '%s'...\n", pszFilename));
     4181    ssmR3StrmStartIoThread(&pSSM->Strm);
     4182    rc = ssmR3WriteHeaderAndClearPerUnitData(pVM, pSSM);
     4183    if (RT_SUCCESS(rc))
     4184    {
     4185/** @todo If it turns out we don't need to do ssmR3DoLivePrepRun on EMT0,
     4186 *        simply move the code to SSMR3LiveDoStep1. */
     4187        rc = ssmR3DoLivePrepRun(pVM, pSSM);
    34774188        if (RT_SUCCESS(rc))
    34784189        {
    3479             Handle.enmOp = SSMSTATE_SAVE_EXEC;
    3480             for (pUnit = pVM->ssm.s.pHead; pUnit; pUnit = pUnit->pNext)
    3481             {
    3482                 /*
    3483                  * Estimate.
    3484                  */
    3485                 ssmR3Progress(&Handle, Handle.offEstUnitEnd - Handle.offEst);
    3486                 Handle.offEstUnitEnd += pUnit->cbGuess;
    3487 
    3488                 /*
    3489                  * Does this unit have a callback? If, not skip it.
    3490                  */
    3491                 if (!pUnit->u.Common.pfnSaveExec)
    3492                 {
    3493                     pUnit->fCalled = true;
    3494                     continue;
    3495                 }
    3496                 pUnit->offStream = ssmR3StrmTell(&Handle.Strm);
    3497 
    3498                 /*
    3499                  * Write data unit header
    3500                  */
    3501                 memcpy(&u.UnitHdr.szMagic[0], SSMFILEUNITHDR_MAGIC, sizeof(u.UnitHdr.szMagic));
    3502                 u.UnitHdr.offStream       = pUnit->offStream;
    3503                 u.UnitHdr.u32CurStreamCRC = ssmR3StrmCurCRC(&Handle.Strm);
    3504                 u.UnitHdr.u32CRC          = 0;
    3505                 u.UnitHdr.u32Version      = pUnit->u32Version;
    3506                 u.UnitHdr.u32Instance     = pUnit->u32Instance;
    3507                 u.UnitHdr.u32Phase        = SSM_PHASE_FINAL;
    3508                 u.UnitHdr.fFlags          = 0;
    3509                 u.UnitHdr.cbName          = (uint32_t)pUnit->cchName + 1;
    3510                 memcpy(&u.UnitHdr.szName[0], &pUnit->szName[0], u.UnitHdr.cbName);
    3511                 u.UnitHdr.u32CRC          = RTCrc32(&u.UnitHdr, RT_OFFSETOF(SSMFILEUNITHDRV2, szName[u.UnitHdr.cbName]));
    3512                 Log(("SSM: Unit at %#9llx: '%s', instance %u, phase %#x, version %u\n",
    3513                      u.UnitHdr.offStream, u.UnitHdr.szName, u.UnitHdr.u32Instance, u.UnitHdr.u32Phase, u.UnitHdr.u32Version));
    3514                 rc = ssmR3StrmWrite(&Handle.Strm, &u.UnitHdr, RT_OFFSETOF(SSMFILEUNITHDRV2, szName[u.UnitHdr.cbName]));
    3515                 if (RT_SUCCESS(rc))
    3516                 {
    3517                     /*
    3518                      * Call the execute handler.
    3519                      */
    3520                     ssmR3DataWriteBegin(&Handle);
    3521                     switch (pUnit->enmType)
    3522                     {
    3523                         case SSMUNITTYPE_DEV:
    3524                             rc = pUnit->u.Dev.pfnSaveExec(pUnit->u.Dev.pDevIns, &Handle);
    3525                             break;
    3526                         case SSMUNITTYPE_DRV:
    3527                             rc = pUnit->u.Drv.pfnSaveExec(pUnit->u.Drv.pDrvIns, &Handle);
    3528                             break;
    3529                         case SSMUNITTYPE_INTERNAL:
    3530                             rc = pUnit->u.Internal.pfnSaveExec(pVM, &Handle);
    3531                             break;
    3532                         case SSMUNITTYPE_EXTERNAL:
    3533                             pUnit->u.External.pfnSaveExec(&Handle, pUnit->u.External.pvUser);
    3534                             rc = Handle.rc;
    3535                             break;
    3536                     }
    3537                     pUnit->fCalled = true;
    3538                     if (RT_SUCCESS(rc))
    3539                         rc = ssmR3DataFlushBuffer(&Handle); /* will return SSMHANDLE::rc if its set */
    3540                     if (RT_SUCCESS(rc))
    3541                     {
    3542                         /*
    3543                          * Write the termination record and flush the compression stream.
    3544                          */
    3545                         SSMRECTERM TermRec;
    3546                         TermRec.u8TypeAndFlags = SSM_REC_FLAGS_FIXED | SSM_REC_FLAGS_IMPORTANT | SSM_REC_TYPE_TERM;
    3547                         TermRec.cbRec       = sizeof(TermRec) - 2;
    3548                         if (Handle.Strm.fChecksummed)
    3549                         {
    3550                             TermRec.fFlags       = SSMRECTERM_FLAGS_CRC32;
    3551                             TermRec.u32StreamCRC = RTCrc32Finish(RTCrc32Process(ssmR3StrmCurCRC(&Handle.Strm), &TermRec, 2));
    3552                         }
    3553                         else
    3554                         {
    3555                             TermRec.fFlags       = 0;
    3556                             TermRec.u32StreamCRC = 0;
    3557                         }
    3558                         TermRec.cbUnit      = Handle.offUnit + sizeof(TermRec);
    3559                         rc = ssmR3DataWriteRaw(&Handle, &TermRec, sizeof(TermRec));
    3560                         if (RT_SUCCESS(rc))
    3561                             rc = ssmR3DataWriteFinish(&Handle);
    3562                         if (RT_SUCCESS(rc))
    3563                             Handle.offUnit     = UINT64_MAX;
    3564                         else
    3565                         {
    3566                             LogRel(("SSM: Failed ending compression stream. rc=%Rrc\n", rc));
    3567                             break;
    3568                         }
    3569                     }
    3570                     else
    3571                     {
    3572                         LogRel(("SSM: Execute save failed with rc=%Rrc for data unit '%s.\n", rc, pUnit->szName));
    3573                         break;
    3574                     }
    3575                 }
    3576                 if (RT_FAILURE(rc))
    3577                 {
    3578                     LogRel(("SSM: Failed to write unit header. rc=%Rrc\n", rc));
    3579                     break;
    3580                 }
    3581             } /* for each unit */
    3582 
    3583             /* finish the progress. */
    3584             if (RT_SUCCESS(rc))
    3585                 ssmR3Progress(&Handle, Handle.offEstUnitEnd - Handle.offEst);
    3586         }
    3587         /* (progress should be pending 99% now) */
    3588         AssertMsg(RT_FAILURE(rc) || Handle.uPercent == (101-Handle.uPercentDone), ("%d\n", Handle.uPercent));
    3589 
    3590         /*
    3591          * Finalize the file if successfully saved.
    3592          */
    3593         if (RT_SUCCESS(rc))
    3594         {
    3595             /* Write the end unit. */
    3596             memcpy(&u.UnitHdr.szMagic[0], SSMFILEUNITHDR_END, sizeof(u.UnitHdr.szMagic));
    3597             u.UnitHdr.offStream       = ssmR3StrmTell(&Handle.Strm);
    3598             u.UnitHdr.u32CurStreamCRC = ssmR3StrmCurCRC(&Handle.Strm);
    3599             u.UnitHdr.u32CRC          = 0;
    3600             u.UnitHdr.u32Version      = 0;
    3601             u.UnitHdr.u32Instance     = 0;
    3602             u.UnitHdr.u32Phase        = SSM_PHASE_FINAL;
    3603             u.UnitHdr.fFlags          = 0;
    3604             u.UnitHdr.cbName          = 0;
    3605             u.UnitHdr.u32CRC          = RTCrc32(&u.UnitHdr, RT_OFFSETOF(SSMFILEUNITHDRV2, szName[0]));
    3606             Log(("SSM: Unit at %#9llx: END UNIT\n", u.UnitHdr.offStream));
    3607             rc = ssmR3StrmWrite(&Handle.Strm,  &u.UnitHdr, RT_OFFSETOF(SSMFILEUNITHDRV2, szName[0]));
    3608             if (RT_SUCCESS(rc))
    3609             {
    3610                 /* Write the directory for the final units and then the footer. */
    3611                 rc = ssmR3WriteDirectory(pVM, &Handle, &u.Footer.cDirEntries);
    3612                 if (RT_SUCCESS(rc))
    3613                 {
    3614                     memcpy(u.Footer.szMagic, SSMFILEFTR_MAGIC, sizeof(u.Footer.szMagic));
    3615                     u.Footer.offStream    = ssmR3StrmTell(&Handle.Strm);
    3616                     u.Footer.u32StreamCRC = ssmR3StrmFinalCRC(&Handle.Strm);
    3617                     u.Footer.u32Reserved  = 0;
    3618                     u.Footer.u32CRC       = 0;
    3619                     u.Footer.u32CRC       = RTCrc32(&u.Footer, sizeof(u.Footer));
    3620                     Log(("SSM: Footer at %#9llx: \n", u.Footer.offStream));
    3621                     rc = ssmR3StrmWrite(&Handle.Strm, &u.Footer, sizeof(u.Footer));
    3622                     if (RT_SUCCESS(rc))
    3623                         rc = ssmR3StrmSetEnd(&Handle.Strm);
    3624                 }
    3625             }
    3626             if (RT_FAILURE(rc))
    3627                 LogRel(("SSM: Failed to finalize state file! rc=%Rrc\n", rc));
    3628         }
    3629 
    3630         /*
    3631          * Do the done run.
    3632          */
    3633         Handle.rc = rc;
    3634         Handle.enmOp = SSMSTATE_SAVE_DONE;
    3635         for (pUnit = pVM->ssm.s.pHead; pUnit; pUnit = pUnit->pNext)
    3636         {
    3637             if (    pUnit->u.Common.pfnSaveDone
    3638                 &&  (   pUnit->fCalled
    3639                      || (!pUnit->u.Common.pfnSavePrep && !pUnit->u.Common.pfnSaveExec)))
    3640             {
    3641                 switch (pUnit->enmType)
    3642                 {
    3643                     case SSMUNITTYPE_DEV:
    3644                         rc = pUnit->u.Dev.pfnSaveDone(pUnit->u.Dev.pDevIns, &Handle);
    3645                         break;
    3646                     case SSMUNITTYPE_DRV:
    3647                         rc = pUnit->u.Drv.pfnSaveDone(pUnit->u.Drv.pDrvIns, &Handle);
    3648                         break;
    3649                     case SSMUNITTYPE_INTERNAL:
    3650                         rc = pUnit->u.Internal.pfnSaveDone(pVM, &Handle);
    3651                         break;
    3652                     case SSMUNITTYPE_EXTERNAL:
    3653                         rc = pUnit->u.External.pfnSaveDone(&Handle, pUnit->u.External.pvUser);
    3654                         break;
    3655                 }
    3656                 if (RT_FAILURE(rc))
    3657                 {
    3658                     LogRel(("SSM: Done save failed with rc=%Rrc for data unit '%s.\n", rc, pUnit->szName));
    3659                     if (RT_SUCCESS(Handle.rc))
    3660                         Handle.rc = rc;
    3661                 }
    3662             }
    3663         }
    3664         rc = Handle.rc;
    3665 
    3666         /*
    3667          * Close the file and return if we've succeeded.
    3668          */
    3669         if (RT_SUCCESS(rc))
    3670             rc = ssmR3StrmClose(&Handle.Strm);
    3671         if (RT_SUCCESS(rc))
    3672         {
    3673             if (pfnProgress)
    3674                 pfnProgress(pVM, 100, pvUser);
    3675             LogRel(("SSM: Successfully saved the VM state to '%s'\n"
    3676                     "SSM: Footer at %#llx (%lld), %u directory entries.\n",
    3677                     pszFilename, u.Footer.offStream, u.Footer.offStream, u.Footer.cDirEntries));
     4190            /*
     4191             * Return and let the requstor thread do the pfnLiveExec/Vote part
     4192             * via SSMR3SaveFinishLive
     4193             */
     4194            *ppSSM = pSSM;
    36784195            return VINF_SUCCESS;
    36794196        }
    36804197    }
    3681 
    3682     /*
    3683      * Delete the file on failure.
    3684      */
    3685     ssmR3StrmClose(&Handle.Strm);
    3686     int rc2 = RTFileDelete(pszFilename);
     4198    /* bail out. */
     4199    int rc2 = ssmR3StrmClose(&pSSM->Strm);
     4200    RTMemFree(pSSM);
     4201    rc2 = RTFileDelete(pszFilename);
    36874202    AssertRC(rc2);
    3688 
    36894203    return rc;
     4204}
     4205
     4206
     4207VMMR3DECL(int) SSMR3LiveToRemote(PVM pVM, PFNVMPROGRESS pfnProgress, void *pvUser /*,
     4208                                 invent stream interface and stuff */)
     4209{
     4210    return VERR_NOT_IMPLEMENTED;
    36904211}
    36914212
     
    54535974    pSSM->uPercentPrepare  = 5;
    54545975    pSSM->uPercentDone     = 2;
     5976    pSSM->pszFilename      = pszFilename;
    54555977
    54565978    pSSM->u.Read.pZipDecompV1   = NULL;
     
    56126134                                rc = pUnit->u.External.pfnLoadExec(pSSM, pUnit->u.External.pvUser, UnitHdr.u32Version, SSM_PHASE_FINAL);
    56136135                                break;
     6136                            default:
     6137                                rc = VERR_INTERNAL_ERROR;
     6138                                break;
    56146139                        }
    56156140
     
    57916316                    rc = pUnit->u.External.pfnLoadExec(pSSM, pUnit->u.External.pvUser, UnitHdr.u32Version, UnitHdr.u32Phase);
    57926317                    break;
     6318                default:
     6319                    rc = VERR_INTERNAL_ERROR;
     6320                    break;
    57936321            }
    57946322            ssmR3DataReadFinishV2(pSSM);
     
    58416369{
    58426370    LogFlow(("SSMR3Load: pszFilename=%p:{%s} enmAfter=%d pfnProgress=%p pvUser=%p\n", pszFilename, pszFilename, enmAfter, pfnProgress, pvUser));
    5843     VM_ASSERT_EMT(pVM);
     6371    VM_ASSERT_EMT0(pVM);
    58446372
    58456373    /*
     
    59086436                    case SSMUNITTYPE_EXTERNAL:
    59096437                        rc = pUnit->u.External.pfnLoadPrep(&Handle, pUnit->u.External.pvUser);
     6438                        break;
     6439                    default:
     6440                        rc = VERR_INTERNAL_ERROR;
    59106441                        break;
    59116442                }
     
    59646495                        rc = pUnit->u.External.pfnLoadDone(&Handle, pUnit->u.External.pvUser);
    59656496                        break;
     6497                    default:
     6498                        rc = VERR_INTERNAL_ERROR;
     6499                        break;
    59666500                }
    59676501                if (RT_FAILURE(rc))
     
    63996933VMMR3DECL(int) SSMR3HandleSetStatus(PSSMHANDLE pSSM, int iStatus)
    64006934{
     6935    Assert(pSSM->enmOp != SSMSTATE_LIVE_VOTE);
    64016936    if (RT_FAILURE(iStatus))
    64026937    {
  • trunk/src/VBox/VMM/VM.cpp

    r22784 r22792  
    14731473     * Change the state and perform the save.
    14741474     */
     1475    bool fLive = pVM->enmVMState == VMSTATE_RUNNING;
    14751476    vmR3SetState(pVM, VMSTATE_SAVING); /** @todo Should probably use a different state for live snapshots and/or live migration. Will fix the state machine later. */
    1476     int rc = SSMR3Save(pVM, pszFilename, enmAfter, pfnProgress,  pvUser);
     1477    int rc = SSMR3Save(pVM, pszFilename, enmAfter, pfnProgress, pvUser);
    14771478    vmR3SetState(pVM, VMSTATE_SUSPENDED);
    14781479
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