Changeset 50723 in vbox
- Timestamp:
- Mar 7, 2014 10:11:38 AM (11 years ago)
- svn:sync-xref-src-repo-rev:
- 92694
- Location:
- trunk/src/VBox/Main
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/include/ConsoleImpl.h
r50686 r50723 5 5 6 6 /* 7 * Copyright (C) 2005-201 3Oracle Corporation7 * Copyright (C) 2005-2014 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 570 570 HRESULT removeSharedFolder(const Utf8Str &strName); 571 571 572 int suspendBeforeConfigChange(PUVM pUVM, AutoWriteLock *pAlock, bool *pfResume); 573 void resumeAfterConfigChange(PUVM pUVM); 574 572 575 static DECLCALLBACK(int) configConstructor(PUVM pUVM, PVM pVM, void *pvConsole); 573 576 int configConstructorInner(PUVM pUVM, PVM pVM, AutoWriteLock *pAlock); … … 597 600 bool fHotplug, 598 601 PUVM pUVM, 599 DeviceType_T *paLedDevType); 602 DeviceType_T *paLedDevType, 603 PCFGMNODE *ppLunL0); 600 604 int configMedium(PCFGMNODE pLunL0, 601 605 bool fPassthrough, … … 611 615 MachineState_T aMachineState, 612 616 HRESULT *phrc); 613 static DECLCALLBACK(int) reconfigureMediumAttachment(Console *p Console,617 static DECLCALLBACK(int) reconfigureMediumAttachment(Console *pThis, 614 618 PUVM pUVM, 615 619 const char *pcszDevice, -
trunk/src/VBox/Main/src-client/ConsoleImpl.cpp
r50686 r50723 5 5 6 6 /* 7 * Copyright (C) 2005-201 3Oracle Corporation7 * Copyright (C) 2005-2014 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 2412 2412 PVMREQ pReq; 2413 2413 vrc = VMR3ReqCallU(pUVM, 0, &pReq, 0 /* no wait! */, VMREQFLAGS_VBOX_STATUS, 2414 (PFNRT) Console::unplugCpu, 3,2414 (PFNRT)unplugCpu, 3, 2415 2415 this, pUVM, (VMCPUID)aCpu); 2416 2416 if (vrc == VERR_TIMEOUT || RT_SUCCESS(vrc)) … … 2518 2518 PVMREQ pReq; 2519 2519 int vrc = VMR3ReqCallU(pUVM, 0, &pReq, 0 /* no wait! */, VMREQFLAGS_VBOX_STATUS, 2520 (PFNRT) Console::plugCpu, 3,2520 (PFNRT)plugCpu, 3, 2521 2521 this, pUVM, aCpu); 2522 2522 … … 3534 3534 // private methods 3535 3535 ///////////////////////////////////////////////////////////////////////////// 3536 3537 /** 3538 * Suspend the VM before we do any medium or network attachment change. 3539 * 3540 * @param pUVM Safe VM handle. 3541 * @param pAlock The automatic lock instance. This is for when we have 3542 * to leave it in order to avoid deadlocks. 3543 * @param pfSuspend where to store the information if we need to resume 3544 * afterwards. 3545 */ 3546 int Console::suspendBeforeConfigChange(PUVM pUVM, AutoWriteLock *pAlock, bool *pfResume) 3547 { 3548 *pfResume = false; 3549 VMSTATE enmVMState = VMR3GetStateU(pUVM); 3550 switch (enmVMState) 3551 { 3552 case VMSTATE_RESETTING: 3553 case VMSTATE_RUNNING: 3554 { 3555 LogFlowFunc(("Suspending the VM...\n")); 3556 /* disable the callback to prevent Console-level state change */ 3557 mVMStateChangeCallbackDisabled = true; 3558 if (pAlock) 3559 pAlock->release(); 3560 int rc = VMR3Suspend(pUVM, VMSUSPENDREASON_RECONFIG); 3561 if (pAlock) 3562 pAlock->acquire(); 3563 mVMStateChangeCallbackDisabled = false; 3564 AssertRCReturn(rc, rc); 3565 *pfResume = true; 3566 break; 3567 } 3568 case VMSTATE_SUSPENDED: 3569 break; 3570 default: 3571 return VERR_INVALID_STATE; 3572 } 3573 3574 return VINF_SUCCESS; 3575 } 3576 3577 /** 3578 * Resume the VM after we did any medium or network attachment change. 3579 * This is the counterpart to Console::suspendBeforeConfigChange(). 3580 * 3581 * @param pUVM Safe VM handle. 3582 */ 3583 void Console::resumeAfterConfigChange(PUVM pUVM) 3584 { 3585 LogFlowFunc(("Resuming the VM...\n")); 3586 /* disable the callback to prevent Console-level state change */ 3587 mVMStateChangeCallbackDisabled = true; 3588 int rc = VMR3Resume(pUVM, VMRESUMEREASON_RECONFIG); 3589 mVMStateChangeCallbackDisabled = false; 3590 AssertRC(rc); 3591 if (RT_FAILURE(rc)) 3592 { 3593 VMSTATE enmVMState = VMR3GetStateU(pUVM); 3594 if (enmVMState == VMSTATE_SUSPENDED) 3595 { 3596 /* too bad, we failed. try to sync the console state with the VMM state */ 3597 vmstateChangeCallback(pUVM, VMSTATE_SUSPENDED, enmVMState, this); 3598 } 3599 } 3600 } 3536 3601 3537 3602 /** … … 3603 3668 3604 3669 /* 3670 * Suspend the VM first. The VM must not be running since it might have 3671 * pending I/O to the drive which is being changed. 3672 */ 3673 bool fResume = false; 3674 int vrc = suspendBeforeConfigChange(pUVM, &alock, &fResume); 3675 if (RT_FAILURE(vrc)) 3676 return vrc; 3677 3678 /* 3605 3679 * Call worker in EMT, that's faster and safer than doing everything 3606 3680 * using VMR3ReqCall. Note that we separate VMR3ReqCall from VMR3ReqWait … … 3608 3682 */ 3609 3683 PVMREQ pReq; 3610 int vrc = VMR3ReqCallU(pUVM, 3611 VMCPUID_ANY, 3612 &pReq, 3613 0 /* no wait! */, 3614 VMREQFLAGS_VBOX_STATUS, 3615 (PFNRT)Console::changeRemovableMedium, 3616 8, 3617 this, 3618 pUVM, 3619 pszDevice, 3620 uInstance, 3621 enmBus, 3622 fUseHostIOCache, 3623 aMediumAttachment, 3624 fForce); 3684 vrc = VMR3ReqCallU(pUVM, VMCPUID_ANY, &pReq, 0 /* no wait! */, VMREQFLAGS_VBOX_STATUS, 3685 (PFNRT)changeRemovableMedium, 8, 3686 this, pUVM, pszDevice, uInstance, enmBus, fUseHostIOCache, aMediumAttachment, fForce); 3625 3687 3626 3688 /* release the lock before waiting for a result (EMT will call us back!) */ … … 3635 3697 } 3636 3698 VMR3ReqFree(pReq); 3699 3700 if (fResume) 3701 resumeAfterConfigChange(pUVM); 3637 3702 3638 3703 if (RT_SUCCESS(vrc)) … … 3671 3736 * 3672 3737 * @thread EMT 3738 * @note The VM must not be running since it might have pending I/O to the drive which is being changed. 3673 3739 */ 3674 DECLCALLBACK(int) Console::changeRemovableMedium(Console *p Console,3740 DECLCALLBACK(int) Console::changeRemovableMedium(Console *pThis, 3675 3741 PUVM pUVM, 3676 3742 const char *pcszDevice, … … 3681 3747 bool fForce) 3682 3748 { 3683 LogFlowFunc(("p Console=%p uInstance=%u pszDevice=%p:{%s} enmBus=%u, aMediumAtt=%p, fForce=%d\n",3684 p Console, uInstance, pcszDevice, pcszDevice, enmBus, aMediumAtt, fForce));3685 3686 AssertReturn(p Console, VERR_INVALID_PARAMETER);3687 3688 AutoCaller autoCaller(p Console);3749 LogFlowFunc(("pThis=%p uInstance=%u pszDevice=%p:{%s} enmBus=%u, aMediumAtt=%p, fForce=%d\n", 3750 pThis, uInstance, pcszDevice, pcszDevice, enmBus, aMediumAtt, fForce)); 3751 3752 AssertReturn(pThis, VERR_INVALID_PARAMETER); 3753 3754 AutoCaller autoCaller(pThis); 3689 3755 AssertComRCReturn(autoCaller.rc(), VERR_ACCESS_DENIED); 3690 3756 3691 3757 /* 3692 * Suspend the VM first. 3693 * 3694 * The VM must not be running since it might have pending I/O to 3695 * the drive which is being changed. 3758 * Check the VM for correct state. 3696 3759 */ 3697 bool fResume;3698 3760 VMSTATE enmVMState = VMR3GetStateU(pUVM); 3699 switch (enmVMState) 3700 { 3701 case VMSTATE_RESETTING: 3702 case VMSTATE_RUNNING: 3703 { 3704 LogFlowFunc(("Suspending the VM...\n")); 3705 /* disable the callback to prevent Console-level state change */ 3706 pConsole->mVMStateChangeCallbackDisabled = true; 3707 int rc = VMR3Suspend(pUVM, VMSUSPENDREASON_RECONFIG); 3708 pConsole->mVMStateChangeCallbackDisabled = false; 3709 AssertRCReturn(rc, rc); 3710 fResume = true; 3711 break; 3712 } 3713 3714 case VMSTATE_SUSPENDED: 3715 case VMSTATE_CREATED: 3716 case VMSTATE_OFF: 3717 fResume = false; 3718 break; 3719 3720 case VMSTATE_RUNNING_LS: 3721 case VMSTATE_RUNNING_FT: 3722 return setErrorInternal(VBOX_E_INVALID_VM_STATE, 3723 COM_IIDOF(IConsole), 3724 getStaticComponentName(), 3725 (enmVMState == VMSTATE_RUNNING_LS) ? Utf8Str(tr("Cannot change drive during live migration")) : Utf8Str(tr("Cannot change drive during fault tolerant syncing")), 3726 false /*aWarning*/, 3727 true /*aLogIt*/); 3728 3729 default: 3730 AssertMsgFailedReturn(("enmVMState=%d\n", enmVMState), VERR_ACCESS_DENIED); 3731 } 3761 AssertReturn(enmVMState == VMSTATE_SUSPENDED, VERR_INVALID_STATE); 3732 3762 3733 3763 /* Determine the base path for the device instance. */ … … 3736 3766 AssertReturn(pCtlInst, VERR_INTERNAL_ERROR); 3737 3767 3738 int rc = VINF_SUCCESS; 3739 int rcRet = VINF_SUCCESS; 3740 3741 rcRet = pConsole->configMediumAttachment(pCtlInst, 3742 pcszDevice, 3743 uInstance, 3744 enmBus, 3745 fUseHostIOCache, 3746 false /* fSetupMerge */, 3747 false /* fBuiltinIOCache */, 3748 0 /* uMergeSource */, 3749 0 /* uMergeTarget */, 3750 aMediumAtt, 3751 pConsole->mMachineState, 3752 NULL /* phrc */, 3753 true /* fAttachDetach */, 3754 fForce /* fForceUnmount */, 3755 false /* fHotplug */, 3756 pUVM, 3757 NULL /* paLedDevType */); 3758 /** @todo this dumps everything attached to this device instance, which 3759 * is more than necessary. Dumping the changed LUN would be enough. */ 3760 CFGMR3Dump(pCtlInst); 3761 3762 /* 3763 * Resume the VM if necessary. 3764 */ 3765 if (fResume) 3766 { 3767 LogFlowFunc(("Resuming the VM...\n")); 3768 /* disable the callback to prevent Console-level state change */ 3769 pConsole->mVMStateChangeCallbackDisabled = true; 3770 rc = VMR3Resume(pUVM, VMRESUMEREASON_RECONFIG); 3771 pConsole->mVMStateChangeCallbackDisabled = false; 3772 AssertRC(rc); 3773 if (RT_FAILURE(rc)) 3774 { 3775 /* too bad, we failed. try to sync the console state with the VMM state */ 3776 vmstateChangeCallback(pUVM, VMSTATE_SUSPENDED, enmVMState, pConsole); 3777 } 3778 /// @todo (r=dmik) if we failed with drive mount, then the VMR3Resume 3779 // error (if any) will be hidden from the caller. For proper reporting 3780 // of such multiple errors to the caller we need to enhance the 3781 // IVirtualBoxError interface. For now, give the first error the higher 3782 // priority. 3783 if (RT_SUCCESS(rcRet)) 3784 rcRet = rc; 3785 } 3786 3787 LogFlowFunc(("Returning %Rrc\n", rcRet)); 3788 return rcRet; 3768 PCFGMNODE pLunL0 = NULL; 3769 int rc = pThis->configMediumAttachment(pCtlInst, 3770 pcszDevice, 3771 uInstance, 3772 enmBus, 3773 fUseHostIOCache, 3774 false /* fSetupMerge */, 3775 false /* fBuiltinIOCache */, 3776 0 /* uMergeSource */, 3777 0 /* uMergeTarget */, 3778 aMediumAtt, 3779 pThis->mMachineState, 3780 NULL /* phrc */, 3781 true /* fAttachDetach */, 3782 fForce /* fForceUnmount */, 3783 false /* fHotplug */, 3784 pUVM, 3785 NULL /* paLedDevType */, 3786 &pLunL0); 3787 /* Dump the changed LUN if possible, dump the complete device otherwise */ 3788 CFGMR3Dump(pLunL0 ? pLunL0 : pCtlInst); 3789 3790 LogFlowFunc(("Returning %Rrc\n", rc)); 3791 return rc; 3789 3792 } 3790 3793 … … 3858 3861 3859 3862 /* 3863 * Suspend the VM first. The VM must not be running since it might have 3864 * pending I/O to the drive which is being changed. 3865 */ 3866 bool fResume = false; 3867 int vrc = suspendBeforeConfigChange(pUVM, &alock, &fResume); 3868 if (RT_FAILURE(vrc)) 3869 return vrc; 3870 3871 /* 3860 3872 * Call worker in EMT, that's faster and safer than doing everything 3861 3873 * using VMR3ReqCall. Note that we separate VMR3ReqCall from VMR3ReqWait … … 3863 3875 */ 3864 3876 PVMREQ pReq; 3865 int vrc = VMR3ReqCallU(pUVM, 3866 VMCPUID_ANY, 3867 &pReq, 3868 0 /* no wait! */, 3869 VMREQFLAGS_VBOX_STATUS, 3870 (PFNRT)Console::attachStorageDevice, 3871 8, 3872 this, 3873 pUVM, 3874 pszDevice, 3875 uInstance, 3876 enmBus, 3877 fUseHostIOCache, 3878 aMediumAttachment, 3879 fSilent); 3877 vrc = VMR3ReqCallU(pUVM, VMCPUID_ANY, &pReq, 0 /* no wait! */, VMREQFLAGS_VBOX_STATUS, 3878 (PFNRT)attachStorageDevice, 8, 3879 this, pUVM, pszDevice, uInstance, enmBus, fUseHostIOCache, aMediumAttachment, fSilent); 3880 3880 3881 3881 /* release the lock before waiting for a result (EMT will call us back!) */ … … 3890 3890 } 3891 3891 VMR3ReqFree(pReq); 3892 3893 if (fResume) 3894 resumeAfterConfigChange(pUVM); 3892 3895 3893 3896 if (RT_SUCCESS(vrc)) … … 3920 3923 * 3921 3924 * @thread EMT 3925 * @note The VM must not be running since it might have pending I/O to the drive which is being changed. 3922 3926 */ 3923 DECLCALLBACK(int) Console::attachStorageDevice(Console *p Console,3927 DECLCALLBACK(int) Console::attachStorageDevice(Console *pThis, 3924 3928 PUVM pUVM, 3925 3929 const char *pcszDevice, … … 3930 3934 bool fSilent) 3931 3935 { 3932 LogFlowFunc(("p Console=%p uInstance=%u pszDevice=%p:{%s} enmBus=%u, aMediumAtt=%p\n",3933 p Console, uInstance, pcszDevice, pcszDevice, enmBus, aMediumAtt));3934 3935 AssertReturn(p Console, VERR_INVALID_PARAMETER);3936 3937 AutoCaller autoCaller(p Console);3936 LogFlowFunc(("pThis=%p uInstance=%u pszDevice=%p:{%s} enmBus=%u, aMediumAtt=%p\n", 3937 pThis, uInstance, pcszDevice, pcszDevice, enmBus, aMediumAtt)); 3938 3939 AssertReturn(pThis, VERR_INVALID_PARAMETER); 3940 3941 AutoCaller autoCaller(pThis); 3938 3942 AssertComRCReturn(autoCaller.rc(), VERR_ACCESS_DENIED); 3939 3943 3940 3944 /* 3941 * Suspend the VM first. 3942 * 3943 * The VM must not be running since it might have pending I/O to 3944 * the drive which is being changed. 3945 * Check the VM for correct state. 3945 3946 */ 3946 bool fResume;3947 3947 VMSTATE enmVMState = VMR3GetStateU(pUVM); 3948 switch (enmVMState) 3949 { 3950 case VMSTATE_RESETTING: 3951 case VMSTATE_RUNNING: 3952 { 3953 LogFlowFunc(("Suspending the VM...\n")); 3954 /* disable the callback to prevent Console-level state change */ 3955 pConsole->mVMStateChangeCallbackDisabled = true; 3956 int rc = VMR3Suspend(pUVM, VMSUSPENDREASON_RECONFIG); 3957 pConsole->mVMStateChangeCallbackDisabled = false; 3958 AssertRCReturn(rc, rc); 3959 fResume = true; 3960 break; 3961 } 3962 3963 case VMSTATE_SUSPENDED: 3964 case VMSTATE_CREATED: 3965 case VMSTATE_OFF: 3966 fResume = false; 3967 break; 3968 3969 case VMSTATE_RUNNING_LS: 3970 case VMSTATE_RUNNING_FT: 3971 return setErrorInternal(VBOX_E_INVALID_VM_STATE, 3972 COM_IIDOF(IConsole), 3973 getStaticComponentName(), 3974 (enmVMState == VMSTATE_RUNNING_LS) ? Utf8Str(tr("Cannot change drive during live migration")) : Utf8Str(tr("Cannot change drive during fault tolerant syncing")), 3975 false /*aWarning*/, 3976 true /*aLogIt*/); 3977 3978 default: 3979 AssertMsgFailedReturn(("enmVMState=%d\n", enmVMState), VERR_ACCESS_DENIED); 3980 } 3948 AssertReturn(enmVMState == VMSTATE_SUSPENDED, VERR_INVALID_STATE); 3981 3949 3982 3950 /* … … 3993 3961 AssertReturn(pCtlInst, VERR_INTERNAL_ERROR); 3994 3962 3995 int rc = VINF_SUCCESS; 3996 int rcRet = VINF_SUCCESS; 3997 3998 rcRet = pConsole->configMediumAttachment(pCtlInst, 3999 pcszDevice, 4000 uInstance, 4001 enmBus, 4002 fUseHostIOCache, 4003 false /* fSetupMerge */, 4004 false /* fBuiltinIOCache */, 4005 0 /* uMergeSource */, 4006 0 /* uMergeTarget */, 4007 aMediumAtt, 4008 pConsole->mMachineState, 4009 NULL /* phrc */, 4010 true /* fAttachDetach */, 4011 false /* fForceUnmount */, 4012 !fSilent /* fHotplug */, 4013 pUVM, 4014 NULL /* paLedDevType */); 4015 /** @todo this dumps everything attached to this device instance, which 4016 * is more than necessary. Dumping the changed LUN would be enough. */ 3963 PCFGMNODE pLunL0 = NULL; 3964 int rc = pThis->configMediumAttachment(pCtlInst, 3965 pcszDevice, 3966 uInstance, 3967 enmBus, 3968 fUseHostIOCache, 3969 false /* fSetupMerge */, 3970 false /* fBuiltinIOCache */, 3971 0 /* uMergeSource */, 3972 0 /* uMergeTarget */, 3973 aMediumAtt, 3974 pThis->mMachineState, 3975 NULL /* phrc */, 3976 true /* fAttachDetach */, 3977 false /* fForceUnmount */, 3978 !fSilent /* fHotplug */, 3979 pUVM, 3980 NULL /* paLedDevType */, 3981 &pLunL0); 3982 /* Dump the changed LUN if possible, dump the complete device otherwise */ 4017 3983 if (enmBus != StorageBus_USB) 4018 CFGMR3Dump(pCtlInst); 4019 4020 /* 4021 * Resume the VM if necessary. 4022 */ 4023 if (fResume) 4024 { 4025 LogFlowFunc(("Resuming the VM...\n")); 4026 /* disable the callback to prevent Console-level state change */ 4027 pConsole->mVMStateChangeCallbackDisabled = true; 4028 rc = VMR3Resume(pUVM, VMRESUMEREASON_RECONFIG); 4029 pConsole->mVMStateChangeCallbackDisabled = false; 4030 AssertRC(rc); 4031 if (RT_FAILURE(rc)) 4032 { 4033 /* too bad, we failed. try to sync the console state with the VMM state */ 4034 vmstateChangeCallback(pUVM, VMSTATE_SUSPENDED, enmVMState, pConsole); 4035 } 4036 /** @todo if we failed with drive mount, then the VMR3Resume 4037 * error (if any) will be hidden from the caller. For proper reporting 4038 * of such multiple errors to the caller we need to enhance the 4039 * IVirtualBoxError interface. For now, give the first error the higher 4040 * priority. 4041 */ 4042 if (RT_SUCCESS(rcRet)) 4043 rcRet = rc; 4044 } 4045 4046 LogFlowFunc(("Returning %Rrc\n", rcRet)); 4047 return rcRet; 3984 CFGMR3Dump(pLunL0 ? pLunL0 : pCtlInst); 3985 3986 LogFlowFunc(("Returning %Rrc\n", rc)); 3987 return rc; 4048 3988 } 4049 3989 … … 4113 4053 4114 4054 /* 4055 * Suspend the VM first. The VM must not be running since it might have 4056 * pending I/O to the drive which is being changed. 4057 */ 4058 bool fResume = false; 4059 int vrc = suspendBeforeConfigChange(pUVM, &alock, &fResume); 4060 if (RT_FAILURE(vrc)) 4061 return vrc; 4062 4063 /* 4115 4064 * Call worker in EMT, that's faster and safer than doing everything 4116 4065 * using VMR3ReqCall. Note that we separate VMR3ReqCall from VMR3ReqWait … … 4118 4067 */ 4119 4068 PVMREQ pReq; 4120 int vrc = VMR3ReqCallU(pUVM, 4121 VMCPUID_ANY, 4122 &pReq, 4123 0 /* no wait! */, 4124 VMREQFLAGS_VBOX_STATUS, 4125 (PFNRT)Console::detachStorageDevice, 4126 7, 4127 this, 4128 pUVM, 4129 pszDevice, 4130 uInstance, 4131 enmBus, 4132 aMediumAttachment, 4133 fSilent); 4069 vrc = VMR3ReqCallU(pUVM, VMCPUID_ANY, &pReq, 0 /* no wait! */, VMREQFLAGS_VBOX_STATUS, 4070 (PFNRT)detachStorageDevice, 7, 4071 this, pUVM, pszDevice, uInstance, enmBus, aMediumAttachment, fSilent); 4134 4072 4135 4073 /* release the lock before waiting for a result (EMT will call us back!) */ … … 4144 4082 } 4145 4083 VMR3ReqFree(pReq); 4084 4085 if (fResume) 4086 resumeAfterConfigChange(pUVM); 4146 4087 4147 4088 if (RT_SUCCESS(vrc)) … … 4173 4114 * 4174 4115 * @thread EMT 4116 * @note The VM must not be running since it might have pending I/O to the drive which is being changed. 4175 4117 */ 4176 DECLCALLBACK(int) Console::detachStorageDevice(Console *p Console,4118 DECLCALLBACK(int) Console::detachStorageDevice(Console *pThis, 4177 4119 PUVM pUVM, 4178 4120 const char *pcszDevice, … … 4182 4124 bool fSilent) 4183 4125 { 4184 LogFlowFunc(("p Console=%p uInstance=%u pszDevice=%p:{%s} enmBus=%u, pMediumAtt=%p\n",4185 p Console, uInstance, pcszDevice, pcszDevice, enmBus, pMediumAtt));4186 4187 AssertReturn(p Console, VERR_INVALID_PARAMETER);4188 4189 AutoCaller autoCaller(p Console);4126 LogFlowFunc(("pThis=%p uInstance=%u pszDevice=%p:{%s} enmBus=%u, pMediumAtt=%p\n", 4127 pThis, uInstance, pcszDevice, pcszDevice, enmBus, pMediumAtt)); 4128 4129 AssertReturn(pThis, VERR_INVALID_PARAMETER); 4130 4131 AutoCaller autoCaller(pThis); 4190 4132 AssertComRCReturn(autoCaller.rc(), VERR_ACCESS_DENIED); 4191 4133 4192 4134 /* 4193 * Suspend the VM first. 4194 * 4195 * The VM must not be running since it might have pending I/O to 4196 * the drive which is being changed. 4135 * Check the VM for correct state. 4197 4136 */ 4198 bool fResume;4199 4137 VMSTATE enmVMState = VMR3GetStateU(pUVM); 4200 switch (enmVMState) 4201 { 4202 case VMSTATE_RESETTING: 4203 case VMSTATE_RUNNING: 4204 { 4205 LogFlowFunc(("Suspending the VM...\n")); 4206 /* disable the callback to prevent Console-level state change */ 4207 pConsole->mVMStateChangeCallbackDisabled = true; 4208 int rc = VMR3Suspend(pUVM, VMSUSPENDREASON_RECONFIG); 4209 pConsole->mVMStateChangeCallbackDisabled = false; 4210 AssertRCReturn(rc, rc); 4211 fResume = true; 4212 break; 4213 } 4214 4215 case VMSTATE_SUSPENDED: 4216 case VMSTATE_CREATED: 4217 case VMSTATE_OFF: 4218 fResume = false; 4219 break; 4220 4221 case VMSTATE_RUNNING_LS: 4222 case VMSTATE_RUNNING_FT: 4223 return setErrorInternal(VBOX_E_INVALID_VM_STATE, 4224 COM_IIDOF(IConsole), 4225 getStaticComponentName(), 4226 (enmVMState == VMSTATE_RUNNING_LS) ? Utf8Str(tr("Cannot change drive during live migration")) : Utf8Str(tr("Cannot change drive during fault tolerant syncing")), 4227 false /*aWarning*/, 4228 true /*aLogIt*/); 4229 4230 default: 4231 AssertMsgFailedReturn(("enmVMState=%d\n", enmVMState), VERR_ACCESS_DENIED); 4232 } 4138 AssertReturn(enmVMState == VMSTATE_SUSPENDED, VERR_INVALID_STATE); 4233 4139 4234 4140 /* Determine the base path for the device instance. */ … … 4274 4180 4275 4181 Utf8Str devicePath = Utf8StrFmt("%s/%u/LUN#%u", pcszDevice, uInstance, uLUN); 4276 p Console->mapMediumAttachments.erase(devicePath);4182 pThis->mapMediumAttachments.erase(devicePath); 4277 4183 4278 4184 } … … 4286 4192 /* Find the correct USB device in the list. */ 4287 4193 USBStorageDeviceList::iterator it; 4288 for (it = p Console->mUSBStorageDevices.begin(); it != pConsole->mUSBStorageDevices.end(); it++)4194 for (it = pThis->mUSBStorageDevices.begin(); it != pThis->mUSBStorageDevices.end(); it++) 4289 4195 { 4290 4196 if (it->iPort == lPort) … … 4292 4198 } 4293 4199 4294 AssertReturn(it != p Console->mUSBStorageDevices.end(), VERR_INTERNAL_ERROR);4200 AssertReturn(it != pThis->mUSBStorageDevices.end(), VERR_INTERNAL_ERROR); 4295 4201 rc = PDMR3UsbDetachDevice(pUVM, &it->mUuid); 4296 4202 AssertRCReturn(rc, rc); 4297 pConsole->mUSBStorageDevices.erase(it); 4298 } 4299 4300 /* 4301 * Resume the VM if necessary. 4302 */ 4303 if (fResume) 4304 { 4305 LogFlowFunc(("Resuming the VM...\n")); 4306 /* disable the callback to prevent Console-level state change */ 4307 pConsole->mVMStateChangeCallbackDisabled = true; 4308 rc = VMR3Resume(pUVM, VMRESUMEREASON_RECONFIG); 4309 pConsole->mVMStateChangeCallbackDisabled = false; 4310 AssertRC(rc); 4311 if (RT_FAILURE(rc)) 4312 { 4313 /* too bad, we failed. try to sync the console state with the VMM state */ 4314 vmstateChangeCallback(pUVM, VMSTATE_SUSPENDED, enmVMState, pConsole); 4315 } 4316 /** @todo: if we failed with drive mount, then the VMR3Resume 4317 * error (if any) will be hidden from the caller. For proper reporting 4318 * of such multiple errors to the caller we need to enhance the 4319 * IVirtualBoxError interface. For now, give the first error the higher 4320 * priority. 4321 */ 4322 if (RT_SUCCESS(rcRet)) 4323 rcRet = rc; 4203 pThis->mUSBStorageDevices.erase(it); 4324 4204 } 4325 4205 … … 4563 4443 4564 4444 /* 4445 * Suspend the VM first. 4446 */ 4447 bool fResume = false; 4448 int vrc = suspendBeforeConfigChange(pUVM, NULL, &fResume); 4449 if (RT_FAILURE(vrc)) 4450 return vrc; 4451 4452 /* 4565 4453 * Call worker in EMT, that's faster and safer than doing everything 4566 4454 * using VM3ReqCall. Note that we separate VMR3ReqCall from VMR3ReqWait … … 4568 4456 */ 4569 4457 PVMREQ pReq; 4570 intvrc = VMR3ReqCallU(pUVM, 0 /*idDstCpu*/, &pReq, 0 /* no wait! */, VMREQFLAGS_VBOX_STATUS,4571 (PFNRT)Console::changeNetworkAttachment, 6,4572 4458 vrc = VMR3ReqCallU(pUVM, 0 /*idDstCpu*/, &pReq, 0 /* no wait! */, VMREQFLAGS_VBOX_STATUS, 4459 (PFNRT)changeNetworkAttachment, 6, 4460 this, pUVM, pszDevice, uInstance, uLun, aNetworkAdapter); 4573 4461 4574 4462 if (vrc == VERR_TIMEOUT || RT_SUCCESS(vrc)) … … 4580 4468 } 4581 4469 VMR3ReqFree(pReq); 4470 4471 if (fResume) 4472 resumeAfterConfigChange(pUVM); 4582 4473 4583 4474 if (RT_SUCCESS(vrc)) … … 4607 4498 * @thread EMT 4608 4499 * @note Locks the Console object for writing. 4500 * @note The VM must not be running. 4609 4501 */ 4610 4502 DECLCALLBACK(int) Console::changeNetworkAttachment(Console *pThis, … … 4642 4534 4643 4535 /* 4644 * Suspend the VM first. 4645 * 4646 * The VM must not be running since it might have pending I/O to 4647 * the drive which is being changed. 4536 * Check the VM for correct state. 4648 4537 */ 4649 bool fResume;4650 4538 VMSTATE enmVMState = VMR3GetStateU(pUVM); 4651 switch (enmVMState) 4652 { 4653 case VMSTATE_RESETTING: 4654 case VMSTATE_RUNNING: 4655 { 4656 LogFlowFunc(("Suspending the VM...\n")); 4657 /* disable the callback to prevent Console-level state change */ 4658 pThis->mVMStateChangeCallbackDisabled = true; 4659 int rc = VMR3Suspend(pUVM, VMSUSPENDREASON_RECONFIG); 4660 pThis->mVMStateChangeCallbackDisabled = false; 4661 AssertRCReturn(rc, rc); 4662 fResume = true; 4663 break; 4664 } 4665 4666 case VMSTATE_SUSPENDED: 4667 case VMSTATE_CREATED: 4668 case VMSTATE_OFF: 4669 fResume = false; 4670 break; 4671 4672 default: 4673 AssertLogRelMsgFailedReturn(("enmVMState=%d\n", enmVMState), VERR_ACCESS_DENIED); 4674 } 4675 4676 int rc = VINF_SUCCESS; 4677 int rcRet = VINF_SUCCESS; 4539 AssertReturn(enmVMState == VMSTATE_SUSPENDED, VERR_INVALID_STATE); 4678 4540 4679 4541 PCFGMNODE pCfg = NULL; /* /Devices/Dev/.../Config/ */ … … 4682 4544 AssertRelease(pInst); 4683 4545 4684 rcRet = pThis->configNetwork(pszDevice, uInstance, uLun, aNetworkAdapter, pCfg, pLunL0, pInst, 4685 true /*fAttachDetach*/, false /*fIgnoreConnectFailure*/); 4686 4687 /* 4688 * Resume the VM if necessary. 4689 */ 4690 if (fResume) 4691 { 4692 LogFlowFunc(("Resuming the VM...\n")); 4693 /* disable the callback to prevent Console-level state change */ 4694 pThis->mVMStateChangeCallbackDisabled = true; 4695 rc = VMR3Resume(pUVM, VMRESUMEREASON_RECONFIG); 4696 pThis->mVMStateChangeCallbackDisabled = false; 4697 AssertRC(rc); 4698 if (RT_FAILURE(rc)) 4699 { 4700 /* too bad, we failed. try to sync the console state with the VMM state */ 4701 vmstateChangeCallback(pUVM, VMSTATE_SUSPENDED, enmVMState, pThis); 4702 } 4703 /// @todo (r=dmik) if we failed with drive mount, then the VMR3Resume 4704 // error (if any) will be hidden from the caller. For proper reporting 4705 // of such multiple errors to the caller we need to enhance the 4706 // IVirtualBoxError interface. For now, give the first error the higher 4707 // priority. 4708 if (RT_SUCCESS(rcRet)) 4709 rcRet = rc; 4710 } 4711 4712 LogFlowFunc(("Returning %Rrc\n", rcRet)); 4713 return rcRet; 4546 int rc = pThis->configNetwork(pszDevice, uInstance, uLun, aNetworkAdapter, pCfg, pLunL0, pInst, 4547 true /*fAttachDetach*/, false /*fIgnoreConnectFailure*/); 4548 4549 LogFlowFunc(("Returning %Rrc\n", rc)); 4550 return rc; 4714 4551 } 4715 4552 … … 5760 5597 } 5761 5598 5762 vrc = VMR3ReqCallWaitU(ptrVM.rawUVM(), 5763 VMCPUID_ANY, 5764 (PFNRT)reconfigureMediumAttachment, 5765 13, 5766 this, 5767 ptrVM.rawUVM(), 5768 pcszDevice, 5769 uInstance, 5770 enmBus, 5771 fUseHostIOCache, 5772 fBuiltinIOCache, 5773 true /* fSetupMerge */, 5774 aSourceIdx, 5775 aTargetIdx, 5776 aMediumAttachment, 5777 mMachineState, 5778 &rc); 5599 vrc = VMR3ReqCallWaitU(ptrVM.rawUVM(), VMCPUID_ANY, 5600 (PFNRT)reconfigureMediumAttachment, 13, 5601 this, ptrVM.rawUVM(), pcszDevice, uInstance, enmBus, fUseHostIOCache, 5602 fBuiltinIOCache, true /* fSetupMerge */, aSourceIdx, aTargetIdx, 5603 aMediumAttachment, mMachineState, &rc); 5779 5604 /* error handling is after resuming the VM */ 5780 5605 … … 5834 5659 rc = mControl->FinishOnlineMergeMedium(); 5835 5660 5836 vrc = VMR3ReqCallWaitU(ptrVM.rawUVM(), 5837 VMCPUID_ANY, 5838 (PFNRT)reconfigureMediumAttachment, 5839 13, 5840 this, 5841 ptrVM.rawUVM(), 5842 pcszDevice, 5843 uInstance, 5844 enmBus, 5845 fUseHostIOCache, 5846 fBuiltinIOCache, 5847 false /* fSetupMerge */, 5848 0 /* uMergeSource */, 5849 0 /* uMergeTarget */, 5850 aMediumAttachment, 5851 mMachineState, 5852 &rc); 5661 vrc = VMR3ReqCallWaitU(ptrVM.rawUVM(), VMCPUID_ANY, 5662 (PFNRT)reconfigureMediumAttachment, 13, 5663 this, ptrVM.rawUVM(), pcszDevice, uInstance, enmBus, fUseHostIOCache, 5664 fBuiltinIOCache, false /* fSetupMerge */, 0 /* uMergeSource */, 5665 0 /* uMergeTarget */, aMediumAttachment, mMachineState, &rc); 5853 5666 /* error handling is after resuming the VM */ 5854 5667 … … 8293 8106 this, ptrVM.rawUVM(), aHostDevice, uuid.raw(), fRemote, 8294 8107 Address.c_str(), pvRemoteBackend, portVersion, aMaskedIfs); 8295 8296 8108 if (RT_SUCCESS(vrc)) 8297 8109 { … … 9518 9330 * Reconfigures a medium attachment (part of taking or deleting an online snapshot). 9519 9331 * 9520 * @param p ConsoleReference to the console object.9332 * @param pThis Reference to the console object. 9521 9333 * @param pUVM The VM handle. 9522 9334 * @param lInstance The instance of the controller. … … 9532 9344 */ 9533 9345 /* static */ 9534 DECLCALLBACK(int) Console::reconfigureMediumAttachment(Console *p Console,9346 DECLCALLBACK(int) Console::reconfigureMediumAttachment(Console *pThis, 9535 9347 PUVM pUVM, 9536 9348 const char *pcszDevice, … … 9548 9360 LogFlowFunc(("pUVM=%p aMediumAtt=%p phrc=%p\n", pUVM, aMediumAtt, phrc)); 9549 9361 9550 int rc;9551 9362 HRESULT hrc; 9552 9363 Bstr bstr; 9553 9364 *phrc = S_OK; 9554 #define RC_CHECK() do { if (RT_FAILURE(rc)) { AssertMsgFailed(("rc=%Rrc\n", rc)); return rc; } } while (0)9555 9365 #define H() do { if (FAILED(hrc)) { AssertMsgFailed(("hrc=%Rhrc (%#x)\n", hrc, hrc)); *phrc = hrc; return VERR_GENERAL_FAILURE; } } while (0) 9556 9366 … … 9573 9383 9574 9384 /* Update the device instance configuration. */ 9575 rc = pConsole->configMediumAttachment(pCtlInst, 9576 pcszDevice, 9577 uInstance, 9578 enmBus, 9579 fUseHostIOCache, 9580 fBuiltinIOCache, 9581 fSetupMerge, 9582 uMergeSource, 9583 uMergeTarget, 9584 aMediumAtt, 9585 aMachineState, 9586 phrc, 9587 true /* fAttachDetach */, 9588 false /* fForceUnmount */, 9589 false /* fHotplug */, 9590 pUVM, 9591 NULL /* paLedDevType */); 9592 /** @todo this dumps everything attached to this device instance, which 9593 * is more than necessary. Dumping the changed LUN would be enough. */ 9594 CFGMR3Dump(pCtlInst); 9595 RC_CHECK(); 9596 9597 #undef RC_CHECK 9385 PCFGMNODE pLunL0 = NULL; 9386 int rc = pThis->configMediumAttachment(pCtlInst, 9387 pcszDevice, 9388 uInstance, 9389 enmBus, 9390 fUseHostIOCache, 9391 fBuiltinIOCache, 9392 fSetupMerge, 9393 uMergeSource, 9394 uMergeTarget, 9395 aMediumAtt, 9396 aMachineState, 9397 phrc, 9398 true /* fAttachDetach */, 9399 false /* fForceUnmount */, 9400 false /* fHotplug */, 9401 pUVM, 9402 NULL /* paLedDevType */, 9403 &pLunL0); 9404 /* Dump the changed LUN if possible, dump the complete device otherwise */ 9405 CFGMR3Dump(pLunL0 ? pLunL0 : pCtlInst); 9406 if (RT_FAILURE(rc)) 9407 { 9408 AssertMsgFailed(("rc=%Rrc\n", rc)); 9409 return rc; 9410 } 9411 9598 9412 #undef H 9599 9413 … … 9777 9591 * isn't going to need the Console lock. 9778 9592 */ 9779 vrc = VMR3ReqCallWaitU(ptrVM.rawUVM(), 9780 VMCPUID_ANY, 9781 (PFNRT)reconfigureMediumAttachment, 9782 13, 9783 that, 9784 ptrVM.rawUVM(), 9785 pcszDevice, 9786 lInstance, 9787 enmBus, 9788 fUseHostIOCache, 9789 fBuiltinIOCache, 9790 false /* fSetupMerge */, 9791 0 /* uMergeSource */, 9792 0 /* uMergeTarget */, 9793 atts[i], 9794 that->mMachineState, 9795 &rc); 9593 vrc = VMR3ReqCallWaitU(ptrVM.rawUVM(), VMCPUID_ANY, 9594 (PFNRT)reconfigureMediumAttachment, 13, 9595 that, ptrVM.rawUVM(), pcszDevice, lInstance, enmBus, fUseHostIOCache, 9596 fBuiltinIOCache, false /* fSetupMerge */, 0 /* uMergeSource */, 9597 0 /* uMergeTarget */, atts[i], that->mMachineState, &rc); 9796 9598 if (RT_FAILURE(vrc)) 9797 9599 throw setErrorStatic(E_FAIL, Console::tr("%Rrc"), vrc); -
trunk/src/VBox/Main/src-client/ConsoleImpl2.cpp
r50721 r50723 2194 2194 false /* fHotplug */, 2195 2195 pUVM, 2196 paLedDevType); 2196 paLedDevType, 2197 NULL /* ppLunL0 */); 2197 2198 if (RT_FAILURE(rc)) 2198 2199 return rc; … … 3496 3497 bool fHotplug, 3497 3498 PUVM pUVM, 3498 DeviceType_T *paLedDevType) 3499 DeviceType_T *paLedDevType, 3500 PCFGMNODE *ppLunL0) 3499 3501 { 3500 3502 // InsertConfig* throws … … 3610 3612 3611 3613 InsertConfigNode(pCtlInst, Utf8StrFmt("LUN#%u", uLUN).c_str(), &pLunL0); 3614 if (ppLunL0) 3615 *ppLunL0 = pLunL0; 3612 3616 3613 3617 PCFGMNODE pCfg = CFGMR3GetChild(pCtlInst, "Config");
Note:
See TracChangeset
for help on using the changeset viewer.