Changeset 24353 in vbox for trunk/src/VBox
- Timestamp:
- Nov 4, 2009 7:06:09 PM (15 years ago)
- Location:
- trunk/src/VBox
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/ConsoleImpl.cpp
r24301 r24353 1504 1504 AutoWriteLock alock(this); 1505 1505 1506 /** @todo Live Migration: Support powering down while teleporting. Maybe also1507 * while taking a live snapshot. (In case they never finish and you1508 * or some other operator wish to shut down the VM.) */1509 1506 switch (mMachineState) 1510 1507 { … … 1514 1511 break; 1515 1512 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 1516 1534 /* extra nice error message for a common case */ 1517 1535 case MachineState_Saved: 1518 1536 return setError(VBOX_E_INVALID_VM_STATE, tr("Cannot power down a saved virtual machine")); 1519 1537 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")); 1521 1539 default: 1522 1540 return setError(VBOX_E_INVALID_VM_STATE, … … 1535 1553 1536 1554 /* 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 */)); 1539 1556 AssertReturn(task->isOk(), E_FAIL); 1540 1557 … … 1543 1560 RTTHREADTYPE_MAIN_WORKER, 0, 1544 1561 "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); 1547 1563 1548 1564 /* task is now owned by powerDownThread(), so release it */ … … 1607 1623 AutoWriteLock alock(this); 1608 1624 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 } 1616 1641 1617 1642 /* protect mpVM */ … … 1626 1651 int vrc = VMR3Suspend(mpVM); 1627 1652 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)); 1634 1658 LogFlowThisFuncLeave(); 1635 return rc;1659 return hrc; 1636 1660 } 1637 1661 … … 4814 4838 AssertMsg( mMachineState == MachineState_Running 4815 4839 || mMachineState == MachineState_Paused 4816 || mMachineState == MachineState_Teleporting /** @todo Live Migration: ???*/4817 || mMachineState == MachineState_LiveSnapshotting /** @todo Live Migration: ???*/4818 4840 || mMachineState == MachineState_Stuck 4819 4841 || mMachineState == MachineState_Starting … … 4821 4843 || mMachineState == MachineState_Saving 4822 4844 || mMachineState == MachineState_Restoring 4823 || mMachineState == MachineState_TeleportingPausedVM /** @todo Teleportation ???*/4845 || mMachineState == MachineState_TeleportingPausedVM 4824 4846 || mMachineState == MachineState_TeleportingIn /** @todo Teleportation ???*/ 4825 4847 , ("Invalid machine state: %s\n", Global::stringifyMachineState(mMachineState))); 4826 4848 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)); 4829 4851 4830 4852 /* Check if we need to power off the VM. In case of mVMPoweredOff=true, the … … 4849 4871 && mMachineState != MachineState_Stopping 4850 4872 && mMachineState != MachineState_TeleportingIn 4851 && mMachineState != MachineState_Teleporting /** @todo Live Migration: what should really happen here? */4852 4873 && mMachineState != MachineState_TeleportingPausedVM 4853 && mMachineState != MachineState_LiveSnapshotting /** @todo Live Migration: what should really happen here? */4854 4874 ) 4855 4875 setMachineState(MachineState_Stopping); … … 4881 4901 #ifdef VBOX_WITH_HGCM 4882 4902 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! */ 4884 4904 4885 4905 /* Save all guest property store entries to the machine XML file */ … … 4889 4909 com::SafeArray<BSTR> flagsOut; 4890 4910 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? */ 4892 4912 rc = E_OUTOFMEMORY; 4893 4913 else -
trunk/src/VBox/Main/ConsoleImplTeleporter.cpp
r24301 r24353 93 93 uint32_t muPort; 94 94 MachineState_T menmOldMachineState; 95 bool mfSuspendedByUs; 95 96 96 97 TeleporterStateSrc(Console *pConsole, PVM pVM, Progress *pProgress, MachineState_T enmOldMachineState) … … 98 99 , muPort(UINT32_MAX) 99 100 , menmOldMachineState(enmOldMachineState) 101 , mfSuspendedByUs(false) 100 102 { 101 103 } … … 606 608 607 609 /* 608 * Do compatability checks of the VM config and the host hardware.609 */610 /** @todo later611 * Update: As much as possible will be taken care of by the first snapshot612 * pass. */613 614 /*615 610 * 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. 616 615 */ 617 616 hrc = teleporterSrcSubmitCommand(pState, "load"); … … 620 619 621 620 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); 623 622 if (RT_FAILURE(vrc)) 624 623 return setError(E_FAIL, tr("VMR3Teleport -> %Rrc"), vrc); … … 643 642 644 643 /* 645 * State fun? Automatic power off?644 * We're at the point of no return. 646 645 */ 647 646 if (!pState->mptrProgress->notifyPointOfNoReturn()) … … 654 653 return hrc; 655 654 655 /* 656 * teleporterSrcThreadWrapper will do the automatic power off because it 657 * has to release the AutoVMCaller. 658 */ 656 659 return S_OK; 657 660 } … … 670 673 TeleporterStateSrc *pState = (TeleporterStateSrc *)pvUser; 671 674 675 /* 676 * Console::teleporterSrc does the work, we just grab onto the VM handle 677 * and do the cleanups afterwards. 678 */ 672 679 AutoVMCaller autoVMCaller(pState->mptrConsole); 673 680 HRESULT hrc = autoVMCaller.rc(); … … 676 683 hrc = pState->mptrConsole->teleporterSrc(pState); 677 684 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). */ 680 686 pState->mptrProgress->setCancelCallback(NULL, NULL); 681 687 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. */ 685 689 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 ) 698 720 { 699 721 switch (enmVMState) … … 707 729 case VMSTATE_RESETTING: 708 730 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); 713 733 break; 734 714 735 case VMSTATE_GURU_MEDITATION: 715 736 case VMSTATE_GURU_MEDITATION_LS: 716 737 pState->mptrConsole->setMachineState(MachineState_Stuck); 717 738 break; 739 740 case VMSTATE_FATAL_ERROR: 741 case VMSTATE_FATAL_ERROR_LS: 742 pState->mptrConsole->setMachineState(MachineState_Paused); 743 break; 744 718 745 default: 719 746 AssertMsgFailed(("%s\n", VMR3GetStateName(enmVMState))); … … 724 751 case VMSTATE_SUSPENDING_EXT_LS: 725 752 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 } 729 760 break; 730 761 } 731 762 } 732 763 } 764 autoLock.leave(); 765 766 pState->mptrProgress->notifyComplete(hrc); 733 767 734 768 /* … … 791 825 * Note! The thread won't start working until we release the lock. 792 826 */ 793 LogFlowThisFunc(("Initiating TELEPORT ERrequest...\n"));827 LogFlowThisFunc(("Initiating TELEPORT request...\n")); 794 828 795 829 ComObjPtr<Progress> ptrProgress; 796 830 HRESULT hrc = ptrProgress.createObject(); 797 831 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*/); 801 833 CheckComRCReturnRC(hrc); 802 834 … … 818 850 hrc = setMachineState(MachineState_TeleportingPausedVM); 819 851 if (SUCCEEDED(hrc)) 852 { 820 853 ptrProgress.queryInterfaceTo(aProgress); 854 mptrCancelableProgress = ptrProgress; 855 } 821 856 else 822 857 ptrProgress->Cancel(); -
trunk/src/VBox/Main/include/ConsoleImpl.h
r24299 r24353 584 584 bool mVMStateChangeCallbackDisabled; 585 585 586 /* Local machine state value*/586 /** Local machine state value. */ 587 587 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; 588 597 589 598 typedef std::list <ComPtr<IConsoleCallback> > CallbackList; -
trunk/src/VBox/VMM/VM.cpp
r24267 r24353 1399 1399 * @param pVM The VM handle. 1400 1400 * @param pVCpu The VMCPU handle of the EMT. 1401 * @param pvUser Ignored.1401 * @param pvUser The pfSuspended argument of vmR3SaveTeleport. 1402 1402 */ 1403 1403 static DECLCALLBACK(VBOXSTRICTRC) vmR3LiveDoSuspend(PVM pVM, PVMCPU pVCpu, void *pvUser) 1404 1404 { 1405 1405 LogFlow(("vmR3LiveDoSuspend: pVM=%p pVCpu=%p/#%u\n", pVM, pVCpu, pVCpu->idCpu)); 1406 Assert(!pvUser); NOREF(pvUser);1406 bool *pfSuspended = (bool *)pvUser; 1407 1407 1408 1408 /* … … 1479 1479 if (RT_FAILURE(rc)) 1480 1480 return VERR_INTERNAL_ERROR_3; 1481 1482 *pfSuspended = true; 1481 1483 } 1482 1484 … … 1646 1648 * @param pfnProgress Progress callback. Optional. 1647 1649 * @param pvProgressUser User argument for the progress callback. 1650 * @param pfSuspended Set if we suspended the VM. 1648 1651 * 1649 1652 * @thread Non-EMT 1650 1653 */ 1651 1654 static 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) 1653 1656 { 1654 1657 /* … … 1676 1679 /* Try suspend the VM. */ 1677 1680 rc = VMMR3EmtRendezvous(pVM, VMMEMTRENDEZVOUS_FLAGS_TYPE_DESCENDING | VMMEMTRENDEZVOUS_FLAGS_STOP_ON_ERROR, 1678 vmR3LiveDoSuspend, NULL);1681 vmR3LiveDoSuspend, pfSuspended); 1679 1682 if (rc != VERR_TRY_AGAIN) 1680 1683 break; 1681 1684 1682 1685 /* Wait for the state to change. */ 1683 RTThreadSleep(250); /** @todo L S: 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.. */ 1684 1687 } 1685 1688 if (RT_SUCCESS(rc)) … … 1748 1751 * Join paths with VMR3Teleport. 1749 1752 */ 1753 bool fSuspended = false; /** @todo need this for live snapshots. */ 1750 1754 SSMAFTER enmAfter = fContinueAfterwards ? SSMAFTER_CONTINUE : SSMAFTER_DESTROY; 1751 1755 int rc = vmR3SaveTeleport(pVM, pszFilename, NULL /*pStreamOps*/, NULL /*pvStreamOpsUser*/, 1752 enmAfter, pfnProgress, pvUser );1756 enmAfter, pfnProgress, pvUser, &fSuspended); 1753 1757 LogFlow(("VMR3Save: returns %Rrc\n", rc)); 1754 1758 return rc; … … 1766 1770 * @param pfnProgress Progress callback. Optional. 1767 1771 * @param pvProgressUser User argument for the progress callback. 1772 * @param pfSuspended Set if we suspended the VM. 1768 1773 * 1769 1774 * @thread Non-EMT. … … 1772 1777 * RunningLS+SuspeningLS+SuspendedLS+Saving+Suspended. 1773 1778 */ 1774 VMMR3DECL(int) VMR3Teleport(PVM pVM, PCSSMSTRMOPS pStreamOps, void *pvStreamOpsUser, PFNVMPROGRESS pfnProgress, void *pvProgressUser) 1779 VMMR3DECL(int) VMR3Teleport(PVM pVM, PCSSMSTRMOPS pStreamOps, void *pvStreamOpsUser, 1780 PFNVMPROGRESS pfnProgress, void *pvProgressUser, bool *pfSuspended) 1775 1781 { 1776 1782 LogFlow(("VMR3Teleport: pVM=%p pStreamOps=%p pvStreamOps=%p pfnProgress=%p pvProgressUser=%p\n", … … 1780 1786 * Validate input. 1781 1787 */ 1788 AssertPtr(pfSuspended); 1789 *pfSuspended = false; 1782 1790 VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE); 1783 1791 VM_ASSERT_OTHER_THREAD(pVM); … … 1789 1797 */ 1790 1798 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)); 1793 1801 return rc; 1794 1802 }
Note:
See TracChangeset
for help on using the changeset viewer.