VirtualBox

Changeset 24353 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Nov 4, 2009 7:06:09 PM (15 years ago)
Author:
vboxsync
Message:

Main,VM: Working the teleportation state. Made VMR3Teleport report back in clear text whether it suspended the VM or not.

Location:
trunk/src/VBox
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/ConsoleImpl.cpp

    r24301 r24353  
    15041504    AutoWriteLock alock(this);
    15051505
    1506     /** @todo Live Migration: Support powering down while teleporting. Maybe also
    1507      *        while taking a live snapshot.  (In case they never finish and you
    1508      *        or some other operator wish to shut down the VM.) */
    15091506    switch (mMachineState)
    15101507    {
     
    15141511            break;
    15151512
     1513        /* Try cancel the teleportation. */
     1514        case MachineState_Teleporting:
     1515        case MachineState_TeleportingPausedVM:
     1516            if (!mptrCancelableProgress.isNull())
     1517            {
     1518                HRESULT hrc = mptrCancelableProgress->Cancel();
     1519                if (SUCCEEDED(hrc))
     1520                    break;
     1521            }
     1522            return setError(VBOX_E_INVALID_VM_STATE, tr("Cannot power down at this point in a teleportation"));
     1523
     1524        /* Try cancel the live snapshot. */
     1525        case MachineState_LiveSnapshotting:
     1526            if (!mptrCancelableProgress.isNull())
     1527            {
     1528                HRESULT hrc = mptrCancelableProgress->Cancel();
     1529                if (SUCCEEDED(hrc))
     1530                    break;
     1531            }
     1532            return setError(VBOX_E_INVALID_VM_STATE, tr("Cannot power down at this point in a live snapshot"));
     1533
    15161534        /* extra nice error message for a common case */
    15171535        case MachineState_Saved:
    15181536            return setError(VBOX_E_INVALID_VM_STATE, tr("Cannot power down a saved virtual machine"));
    15191537        case MachineState_Stopping:
    1520             return setError(VBOX_E_INVALID_VM_STATE, tr("Virtual machine is being powered down."));
     1538            return setError(VBOX_E_INVALID_VM_STATE, tr("Virtual machine is being powered down"));
    15211539        default:
    15221540            return setError(VBOX_E_INVALID_VM_STATE,
     
    15351553
    15361554    /* setup task object and thread to carry out the operation asynchronously */
    1537     std::auto_ptr <VMProgressTask> task(
    1538         new VMProgressTask(this, progress, true /* aUsesVMPtr */));
     1555    std::auto_ptr<VMProgressTask> task(new VMProgressTask(this, progress, true /* aUsesVMPtr */));
    15391556    AssertReturn(task->isOk(), E_FAIL);
    15401557
     
    15431560                             RTTHREADTYPE_MAIN_WORKER, 0,
    15441561                             "VMPowerDown");
    1545     ComAssertMsgRCRet(vrc,
    1546          ("Could not create VMPowerDown thread (%Rrc)", vrc), E_FAIL);
     1562    ComAssertMsgRCRet(vrc, ("Could not create VMPowerDown thread (%Rrc)", vrc), E_FAIL);
    15471563
    15481564    /* task is now owned by powerDownThread(), so release it */
     
    16071623    AutoWriteLock alock(this);
    16081624
    1609     if (   mMachineState != MachineState_Running
    1610         && mMachineState != MachineState_Teleporting
    1611         && mMachineState != MachineState_LiveSnapshotting
    1612        )
    1613         return setError(VBOX_E_INVALID_VM_STATE,
    1614             tr("Invalid machine state: %s"),
    1615             Global::stringifyMachineState(mMachineState));
     1625    switch (mMachineState)
     1626    {
     1627        case MachineState_Running:
     1628        case MachineState_Teleporting:
     1629        case MachineState_LiveSnapshotting:
     1630            break;
     1631
     1632        case MachineState_Paused:
     1633        case MachineState_TeleportingPausedVM:
     1634            return setError(VBOX_E_INVALID_VM_STATE, tr("Already paused"));
     1635
     1636        default:
     1637            return setError(VBOX_E_INVALID_VM_STATE,
     1638                            tr("Invalid machine state: %s"),
     1639                            Global::stringifyMachineState(mMachineState));
     1640    }
    16161641
    16171642    /* protect mpVM */
     
    16261651    int vrc = VMR3Suspend(mpVM);
    16271652
    1628     HRESULT rc = RT_SUCCESS(vrc) ? S_OK :
    1629         setError(VBOX_E_VM_ERROR,
    1630             tr("Could not suspend the machine execution (%Rrc)"),
    1631             vrc);
    1632 
    1633     LogFlowThisFunc(("rc=%08X\n", rc));
     1653    HRESULT hrc = S_OK;
     1654    if (RT_FAILURE(vrc))
     1655        hrc = setError(VBOX_E_VM_ERROR, tr("Could not suspend the machine execution (%Rrc)"), vrc);
     1656
     1657    LogFlowThisFunc(("hrc=%Rhrc\n", hrc));
    16341658    LogFlowThisFuncLeave();
    1635     return rc;
     1659    return hrc;
    16361660}
    16371661
     
    48144838    AssertMsg(   mMachineState == MachineState_Running
    48154839              || mMachineState == MachineState_Paused
    4816               || mMachineState == MachineState_Teleporting           /** @todo Live Migration: ???*/
    4817               || mMachineState == MachineState_LiveSnapshotting      /** @todo Live Migration: ???*/
    48184840              || mMachineState == MachineState_Stuck
    48194841              || mMachineState == MachineState_Starting
     
    48214843              || mMachineState == MachineState_Saving
    48224844              || mMachineState == MachineState_Restoring
    4823               || mMachineState == MachineState_TeleportingPausedVM   /** @todo Teleportation ???*/
     4845              || mMachineState == MachineState_TeleportingPausedVM
    48244846              || mMachineState == MachineState_TeleportingIn         /** @todo Teleportation ???*/
    48254847              , ("Invalid machine state: %s\n", Global::stringifyMachineState(mMachineState)));
    48264848
    4827     LogRel(("Console::powerDown(): A request to power off the VM has been issued (mMachineState=%d, InUninit=%d)\n",
    4828              mMachineState, autoCaller.state() == InUninit));
     4849    LogRel(("Console::powerDown(): A request to power off the VM has been issued (mMachineState=%s, InUninit=%d)\n",
     4850            Global::stringifyMachineState(mMachineState), autoCaller.state() == InUninit));
    48294851
    48304852    /* Check if we need to power off the VM. In case of mVMPoweredOff=true, the
     
    48494871        && mMachineState != MachineState_Stopping
    48504872        && mMachineState != MachineState_TeleportingIn
    4851         && mMachineState != MachineState_Teleporting /** @todo Live Migration: what should really happen here? */
    48524873        && mMachineState != MachineState_TeleportingPausedVM
    4853         && mMachineState != MachineState_LiveSnapshotting /** @todo Live Migration: what should really happen here? */
    48544874       )
    48554875        setMachineState(MachineState_Stopping);
     
    48814901#ifdef VBOX_WITH_HGCM
    48824902
    4883 # ifdef VBOX_WITH_GUEST_PROPS
     4903# ifdef VBOX_WITH_GUEST_PROPS  /** @todo r=bird: This may be premature, the VM may still be running at this point! */
    48844904
    48854905    /* Save all guest property store entries to the machine XML file */
     
    48894909    com::SafeArray<BSTR> flagsOut;
    48904910    Bstr pattern("");
    4891     if (pattern.isNull())
     4911    if (pattern.isNull()) /** @todo r=bird: What is pattern actually used for?  And, again, what's is the out-of-memory policy in main? */
    48924912        rc = E_OUTOFMEMORY;
    48934913    else
  • trunk/src/VBox/Main/ConsoleImplTeleporter.cpp

    r24301 r24353  
    9393    uint32_t            muPort;
    9494    MachineState_T      menmOldMachineState;
     95    bool                mfSuspendedByUs;
    9596
    9697    TeleporterStateSrc(Console *pConsole, PVM pVM, Progress *pProgress, MachineState_T enmOldMachineState)
     
    9899        , muPort(UINT32_MAX)
    99100        , menmOldMachineState(enmOldMachineState)
     101        , mfSuspendedByUs(false)
    100102    {
    101103    }
     
    606608
    607609    /*
    608      * Do compatability checks of the VM config and the host hardware.
    609      */
    610     /** @todo later
    611      * Update: As much as possible will be taken care of by the first snapshot
    612      *         pass. */
    613 
    614     /*
    615610     * Start loading the state.
     611     *
     612     * Note! The saved state includes vital configuration data which will be
     613     *       verified against the VM config on the other end.  This is all done
     614     *       in the first pass, so we should fail pretty promptly on misconfig.
    616615     */
    617616    hrc = teleporterSrcSubmitCommand(pState, "load");
     
    620619
    621620    void *pvUser = static_cast<void *>(static_cast<TeleporterState *>(pState));
    622     vrc = VMR3Teleport(pState->mpVM, &g_teleporterTcpOps, pvUser, teleporterProgressCallback, pvUser);
     621    vrc = VMR3Teleport(pState->mpVM, &g_teleporterTcpOps, pvUser, teleporterProgressCallback, pvUser, &pState->mfSuspendedByUs);
    623622    if (RT_FAILURE(vrc))
    624623        return setError(E_FAIL, tr("VMR3Teleport -> %Rrc"), vrc);
     
    643642
    644643    /*
    645      * State fun? Automatic power off?
     644     * We're at the point of no return.
    646645     */
    647646    if (!pState->mptrProgress->notifyPointOfNoReturn())
     
    654653        return hrc;
    655654
     655    /*
     656     * teleporterSrcThreadWrapper will do the automatic power off because it
     657     * has to release the AutoVMCaller.
     658     */
    656659    return S_OK;
    657660}
     
    670673    TeleporterStateSrc *pState = (TeleporterStateSrc *)pvUser;
    671674
     675    /*
     676     * Console::teleporterSrc does the work, we just grab onto the VM handle
     677     * and do the cleanups afterwards.
     678     */
    672679    AutoVMCaller autoVMCaller(pState->mptrConsole);
    673680    HRESULT hrc = autoVMCaller.rc();
     
    676683        hrc = pState->mptrConsole->teleporterSrc(pState);
    677684
    678     /* (Ignore the return here as teleporterSrc deals with cancellation.) */
    679     pState->mptrProgress->notifyComplete(hrc);
     685    /* We can no longer be cancelled (success), or it doesn't matter any longer (failure). */
    680686    pState->mptrProgress->setCancelCallback(NULL, NULL);
    681687
    682     /*
    683      * Deal with the state machinery after taking the console object lock.
    684      */
     688    /* Write lock the console before resetting mptrCancelableProgress and fixing the state.  */
    685689    AutoWriteLock autoLock(pState->mptrConsole);
    686     if (   pState->mptrConsole->mMachineState == MachineState_Teleporting
    687         || pState->mptrConsole->mMachineState == MachineState_TeleportingPausedVM
    688        )
    689     {
    690 /** @todo shut down the VM and deal with Pause() and PowerDown() calls!! */
    691         VMSTATE enmVMState = VMR3GetState(pState->mpVM);
    692         if (SUCCEEDED(hrc))
    693         {
    694             if (enmVMState == VMSTATE_SUSPENDED)
    695                 pState->mptrConsole->setMachineState(MachineState_TeleportingPausedVM);
    696         }
    697         else
     690    pState->mptrConsole->mptrCancelableProgress.setNull();
     691
     692    VMSTATE const        enmVMState      = VMR3GetState(pState->mpVM);
     693    MachineState_T const enmMachineState = pState->mptrConsole->mMachineState;
     694    if (SUCCEEDED(hrc))
     695    {
     696        /*
     697         * Automatically shut down the VM on success.
     698         *
     699         * Note! We have to release the VM caller object or we'll deadlock in
     700         *       powerDown.
     701         */
     702        AssertLogRelMsg(enmVMState == VMSTATE_SUSPENDED, ("%s\n", VMR3GetStateName(enmVMState)));
     703        AssertLogRelMsg(enmMachineState == MachineState_TeleportingPausedVM, ("%s\n", Global::stringifyMachineState(enmMachineState)));
     704
     705        autoVMCaller.release();
     706        hrc = pState->mptrConsole->powerDown();
     707    }
     708    else
     709    {
     710        /*
     711         * Work the state machinery on failure.
     712         *
     713         * If the state is no longer 'Teleporting*', some other operation has
     714         * canceled us and there is nothing we need to do here.  In all other
     715         * cases, we've failed one way or another.
     716         */
     717        if (   enmMachineState == MachineState_Teleporting
     718            || enmMachineState == MachineState_TeleportingPausedVM
     719           )
    698720        {
    699721            switch (enmVMState)
     
    707729                case VMSTATE_RESETTING:
    708730                case VMSTATE_RESETTING_LS:
    709                     if (pState->menmOldMachineState == MachineState_Running)
    710                         pState->mptrConsole->setMachineState(MachineState_Running);
    711                     else
    712                         pState->mptrConsole->setMachineState(MachineState_Paused);
     731                    Assert(!pState->mfSuspendedByUs);
     732                    pState->mptrConsole->setMachineState(MachineState_Running);
    713733                    break;
     734
    714735                case VMSTATE_GURU_MEDITATION:
    715736                case VMSTATE_GURU_MEDITATION_LS:
    716737                    pState->mptrConsole->setMachineState(MachineState_Stuck);
    717738                    break;
     739
     740                case VMSTATE_FATAL_ERROR:
     741                case VMSTATE_FATAL_ERROR_LS:
     742                    pState->mptrConsole->setMachineState(MachineState_Paused);
     743                    break;
     744
    718745                default:
    719746                    AssertMsgFailed(("%s\n", VMR3GetStateName(enmVMState)));
     
    724751                case VMSTATE_SUSPENDING_EXT_LS:
    725752                    pState->mptrConsole->setMachineState(MachineState_Paused);
    726                     /** @todo somehow make the VMM report back external pause even on error. */
    727                     autoLock.leave();
    728                     VMR3Resume(pState->mpVM);
     753                    if (pState->mfSuspendedByUs)
     754                    {
     755                        autoLock.leave();
     756                        int rc = VMR3Resume(pState->mpVM);
     757                        AssertLogRelMsgRC(rc, ("VMR3Resume -> %Rrc\n", rc));
     758                        autoLock.enter();
     759                    }
    729760                    break;
    730761            }
    731762        }
    732763    }
     764    autoLock.leave();
     765
     766    pState->mptrProgress->notifyComplete(hrc);
    733767
    734768    /*
     
    791825     * Note! The thread won't start working until we release the lock.
    792826     */
    793     LogFlowThisFunc(("Initiating TELEPORTER request...\n"));
     827    LogFlowThisFunc(("Initiating TELEPORT request...\n"));
    794828
    795829    ComObjPtr<Progress> ptrProgress;
    796830    HRESULT hrc = ptrProgress.createObject();
    797831    CheckComRCReturnRC(hrc);
    798     hrc = ptrProgress->init(static_cast<IConsole *>(this),
    799                                         Bstr(tr("Teleporter")),
    800                                         TRUE /*aCancelable*/);
     832    hrc = ptrProgress->init(static_cast<IConsole *>(this), Bstr(tr("Teleporter")), TRUE /*aCancelable*/);
    801833    CheckComRCReturnRC(hrc);
    802834
     
    818850            hrc = setMachineState(MachineState_TeleportingPausedVM);
    819851        if (SUCCEEDED(hrc))
     852        {
    820853            ptrProgress.queryInterfaceTo(aProgress);
     854            mptrCancelableProgress = ptrProgress;
     855        }
    821856        else
    822857            ptrProgress->Cancel();
  • trunk/src/VBox/Main/include/ConsoleImpl.h

    r24299 r24353  
    584584    bool mVMStateChangeCallbackDisabled;
    585585
    586     /* Local machine state value */
     586    /** Local machine state value. */
    587587    MachineState_T mMachineState;
     588
     589    /** Pointer to the progress object of a live cancelable task.
     590     *
     591     * This is currently only used by Console::Teleport(), but is intended to later
     592     * be used by the live snapshot code path as well.  Actions like
     593     * Console::PowerDown, which automatically cancels out the running snapshot /
     594     * teleportion operation, will cancel the teleportation / live snapshot
     595     * operation before starting. */
     596    ComObjPtr<Progress> mptrCancelableProgress;
    588597
    589598    typedef std::list <ComPtr<IConsoleCallback> > CallbackList;
  • trunk/src/VBox/VMM/VM.cpp

    r24267 r24353  
    13991399 * @param   pVM             The VM handle.
    14001400 * @param   pVCpu           The VMCPU handle of the EMT.
    1401  * @param   pvUser          Ignored.
     1401 * @param   pvUser          The pfSuspended argument of vmR3SaveTeleport.
    14021402 */
    14031403static DECLCALLBACK(VBOXSTRICTRC) vmR3LiveDoSuspend(PVM pVM, PVMCPU pVCpu, void *pvUser)
    14041404{
    14051405    LogFlow(("vmR3LiveDoSuspend: pVM=%p pVCpu=%p/#%u\n", pVM, pVCpu, pVCpu->idCpu));
    1406     Assert(!pvUser); NOREF(pvUser);
     1406    bool *pfSuspended = (bool *)pvUser;
    14071407
    14081408    /*
     
    14791479        if (RT_FAILURE(rc))
    14801480            return VERR_INTERNAL_ERROR_3;
     1481
     1482        *pfSuspended = true;
    14811483    }
    14821484
     
    16461648 * @param   pfnProgress     Progress callback. Optional.
    16471649 * @param   pvProgressUser  User argument for the progress callback.
     1650 * @param   pfSuspended     Set if we suspended the VM.
    16481651 *
    16491652 * @thread  Non-EMT
    16501653 */
    16511654static int vmR3SaveTeleport(PVM pVM, const char *pszFilename, PCSSMSTRMOPS pStreamOps, void *pvStreamOpsUser,
    1652                             SSMAFTER enmAfter, PFNVMPROGRESS pfnProgress, void *pvProgressUser)
     1655                            SSMAFTER enmAfter, PFNVMPROGRESS pfnProgress, void *pvProgressUser, bool *pfSuspended)
    16531656{
    16541657    /*
     
    16761679                    /* Try suspend the VM. */
    16771680                    rc = VMMR3EmtRendezvous(pVM, VMMEMTRENDEZVOUS_FLAGS_TYPE_DESCENDING | VMMEMTRENDEZVOUS_FLAGS_STOP_ON_ERROR,
    1678                                             vmR3LiveDoSuspend, NULL);
     1681                                            vmR3LiveDoSuspend, pfSuspended);
    16791682                    if (rc != VERR_TRY_AGAIN)
    16801683                        break;
    16811684
    16821685                    /* Wait for the state to change. */
    1683                     RTThreadSleep(250); /** @todo LS: fix this polling wait by some smart use of multiple release event  semaphores.. */
     1686                    RTThreadSleep(250); /** @todo Live Migration: fix this polling wait by some smart use of multiple release event  semaphores.. */
    16841687                }
    16851688            if (RT_SUCCESS(rc))
     
    17481751     * Join paths with VMR3Teleport.
    17491752     */
     1753    bool fSuspended = false; /** @todo need this for live snapshots. */
    17501754    SSMAFTER enmAfter = fContinueAfterwards ? SSMAFTER_CONTINUE : SSMAFTER_DESTROY;
    17511755    int rc = vmR3SaveTeleport(pVM, pszFilename, NULL /*pStreamOps*/, NULL /*pvStreamOpsUser*/,
    1752                               enmAfter, pfnProgress, pvUser);
     1756                              enmAfter, pfnProgress, pvUser, &fSuspended);
    17531757    LogFlow(("VMR3Save: returns %Rrc\n", rc));
    17541758    return rc;
     
    17661770 * @param   pfnProgress         Progress callback. Optional.
    17671771 * @param   pvProgressUser      User argument for the progress callback.
     1772 * @param   pfSuspended         Set if we suspended the VM.
    17681773 *
    17691774 * @thread      Non-EMT.
     
    17721777 *              RunningLS+SuspeningLS+SuspendedLS+Saving+Suspended.
    17731778 */
    1774 VMMR3DECL(int) VMR3Teleport(PVM pVM, PCSSMSTRMOPS pStreamOps, void *pvStreamOpsUser, PFNVMPROGRESS pfnProgress, void *pvProgressUser)
     1779VMMR3DECL(int) VMR3Teleport(PVM pVM, PCSSMSTRMOPS pStreamOps, void *pvStreamOpsUser,
     1780                            PFNVMPROGRESS pfnProgress, void *pvProgressUser, bool *pfSuspended)
    17751781{
    17761782    LogFlow(("VMR3Teleport: pVM=%p pStreamOps=%p pvStreamOps=%p pfnProgress=%p pvProgressUser=%p\n",
     
    17801786     * Validate input.
    17811787     */
     1788    AssertPtr(pfSuspended);
     1789    *pfSuspended = false;
    17821790    VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
    17831791    VM_ASSERT_OTHER_THREAD(pVM);
     
    17891797     */
    17901798    int rc = vmR3SaveTeleport(pVM, NULL /*pszFilename*/, pStreamOps, pvStreamOpsUser,
    1791                               SSMAFTER_TELEPORT, pfnProgress, pvProgressUser);
    1792     LogFlow(("VMR3Teleport: returns %Rrc\n", rc));
     1799                              SSMAFTER_TELEPORT, pfnProgress, pvProgressUser, pfSuspended);
     1800    LogFlow(("VMR3Teleport: returns %Rrc (*pfSuspended=%RTbool)\n", rc, *pfSuspended));
    17931801    return rc;
    17941802}
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