Changeset 36991 in vbox for trunk/src/VBox/Main
- Timestamp:
- May 6, 2011 7:16:50 PM (14 years ago)
- Location:
- trunk/src/VBox/Main
- Files:
-
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/idl/VirtualBox.xidl
r36954 r36991 13549 13549 <interface 13550 13550 name="IInternalSessionControl" extends="$unknown" 13551 uuid=" a2fbf834-149d-41da-ae52-0dc3b0f032b3"13551 uuid="3a975b65-27e7-42fa-9176-d097d7bd78d4" 13552 13552 internal="yes" 13553 13553 wsmap="suppress" … … 13715 13715 <param name="mediumAttachment" type="IMediumAttachment" dir="in"/> 13716 13716 <param name="force" type="boolean" dir="in"/> 13717 </method> 13718 13719 <method name="onStorageDeviceChange"> 13720 <desc> 13721 Triggered when attached storage devices of the 13722 associated virtual machine have changed. 13723 13724 <result name="VBOX_E_INVALID_VM_STATE"> 13725 Session state prevents operation. 13726 </result> 13727 <result name="VBOX_E_INVALID_OBJECT_STATE"> 13728 Session type prevents operation. 13729 </result> 13730 13731 </desc> 13732 13733 <param name="mediumAttachment" type="IMediumAttachment" dir="in"/> 13734 <param name="remove" type="boolean" dir="in"> 13735 <desc>TRUE if the device is removed, FALSE if it was added.</desc> 13736 </param> 13717 13737 </method> 13718 13738 … … 15437 15457 <enum 15438 15458 name="VBoxEventType" 15439 uuid=" e71c487f-755e-46e9-a476-dd6a5d134597"15459 uuid="cce48db6-8561-479d-8d46-1358bab45d4e" 15440 15460 > 15441 15461 … … 15690 15710 </desc> 15691 15711 </const> 15712 <const name="OnStorageDeviceChanged" value="71"> 15713 <desc> 15714 See <link to="IStorageDeviceChangedEvent">IStorageDeviceChangedEvent</link>. 15715 </desc> 15716 </const> 15692 15717 15693 15718 <!-- Last event marker --> 15694 <const name="Last" value="7 1">15719 <const name="Last" value="72"> 15695 15720 <desc> 15696 15721 Must be last event, used for iterations and structures relying on numerical event values. … … 17088 17113 </interface> 17089 17114 17115 <interface 17116 name="IStorageDeviceChangedEvent" extends="IEvent" 17117 uuid="8a5c2dce-e341-49d4-afce-c95979f7d70c" 17118 wsmap="managed" autogen="VBoxEvent" id="OnStorageDeviceChanged" 17119 > 17120 <desc> 17121 Notification when a 17122 <link to="IMachine::mediumAttachments">storage device</link> 17123 is attached or removed. 17124 </desc> 17125 <attribute name="storageDevice" type="IMediumAttachment" readonly="yes"> 17126 <desc> 17127 Storage device that is subject to change. 17128 </desc> 17129 </attribute> 17130 <attribute name="removed" type="boolean" readonly="yes"> 17131 <desc> 17132 Flag whether the device was removed or added to the VM. 17133 </desc> 17134 </attribute> 17135 </interface> 17136 17090 17137 <module name="VBoxSVC" context="LocalServer"> 17091 17138 <class name="VirtualBox" uuid="B1A7A4F2-47B9-4A1E-82B2-07CCD5323C3F" -
trunk/src/VBox/Main/include/ConsoleImpl.h
r36439 r36991 191 191 HRESULT onUSBDeviceDetach(IN_BSTR aId, IVirtualBoxErrorInfo *aError); 192 192 HRESULT onBandwidthGroupChange(IBandwidthGroup *aBandwidthGroup); 193 HRESULT onStorageDeviceChange(IMediumAttachment *aMediumAttachment, BOOL aRemove); 193 194 HRESULT getGuestProperty(IN_BSTR aKey, BSTR *aValue, LONG64 *aTimestamp, BSTR *aFlags); 194 195 HRESULT setGuestProperty(IN_BSTR aKey, IN_BSTR aValue, IN_BSTR aFlags); … … 505 506 bool fAttachDetach, 506 507 bool fForceUnmount, 508 bool fHotplug, 507 509 PVM pVM, 508 510 DeviceType_T *paLedDevType); … … 571 573 #endif 572 574 575 static DECLCALLBACK(int) attachStorageDevice(Console *pThis, 576 PVM pVM, 577 const char *pcszDevice, 578 unsigned uInstance, 579 StorageBus_T enmBus, 580 bool fUseHostIOCache, 581 IMediumAttachment *aMediumAtt); 582 static DECLCALLBACK(int) detachStorageDevice(Console *pThis, 583 PVM pVM, 584 const char *pcszDevice, 585 unsigned uInstance, 586 StorageBus_T enmBus, 587 IMediumAttachment *aMediumAtt); 588 HRESULT doStorageDeviceAttach(IMediumAttachment *aMediumAttachment, PVM pVM); 589 HRESULT doStorageDeviceDetach(IMediumAttachment *aMediumAttachment, PVM pVM); 590 573 591 static DECLCALLBACK(int) fntTakeSnapshotWorker(RTTHREAD Thread, void *pvUser); 574 592 -
trunk/src/VBox/Main/include/MachineImpl.h
r36898 r36991 638 638 virtual HRESULT onSharedFolderChange() { return S_OK; } 639 639 virtual HRESULT onBandwidthGroupChange(IBandwidthGroup * /* aBandwidthGroup */) { return S_OK; } 640 virtual HRESULT onStorageDeviceChange(IMediumAttachment * /* mediumAttachment */, BOOL /* remove */) { return S_OK; } 640 641 641 642 HRESULT saveRegistryEntry(settings::MachineRegistryEntry &data); … … 833 834 void commit(); 834 835 void copyFrom(Machine *aThat); 836 bool isControllerHotplugCapable(StorageControllerType_T enmCtrlType); 835 837 836 838 struct DeleteTask; … … 1005 1007 HRESULT onSharedFolderChange(); 1006 1008 HRESULT onBandwidthGroupChange(IBandwidthGroup *aBandwidthGroup); 1009 HRESULT onStorageDeviceChange(IMediumAttachment *aMediumAttachment, BOOL aRemove); 1007 1010 1008 1011 bool hasMatchingUSBFilter(const ComObjPtr<HostUSBDevice> &aDevice, ULONG *aMaskedIfs); -
trunk/src/VBox/Main/include/SessionImpl.h
r35638 r36991 99 99 STDMETHOD(OnShowWindow)(BOOL aCheck, BOOL *aCanShow, LONG64 *aWinId); 100 100 STDMETHOD(OnBandwidthGroupChange)(IBandwidthGroup *aBandwidthGroup); 101 STDMETHOD(OnStorageDeviceChange)(IMediumAttachment *aMediumAttachment, BOOL aRemove); 101 102 STDMETHOD(AccessGuestProperty)(IN_BSTR aName, IN_BSTR aValue, IN_BSTR aFlags, 102 103 BOOL aIsSetter, BSTR *aRetValue, LONG64 *aRetTimestamp, BSTR *aRetFlags); -
trunk/src/VBox/Main/src-client/ConsoleImpl.cpp
r36976 r36991 3556 3556 true /* fAttachDetach */, 3557 3557 fForce /* fForceUnmount */, 3558 false /* fHotplug */, 3558 3559 pVM, 3559 3560 NULL /* paLedDevType */); … … 3591 3592 } 3592 3593 3594 3595 /** 3596 * Attach a new storage device to the VM. 3597 * 3598 * @param aMediumAttachment The medium attachmentwhich is added. 3599 * @param pVM Safe VM handle. 3600 * 3601 * @note Locks this object for writing. 3602 */ 3603 HRESULT Console::doStorageDeviceAttach(IMediumAttachment *aMediumAttachment, PVM pVM) 3604 { 3605 AutoCaller autoCaller(this); 3606 AssertComRCReturnRC(autoCaller.rc()); 3607 3608 /* We will need to release the write lock before calling EMT */ 3609 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 3610 3611 HRESULT rc = S_OK; 3612 const char *pszDevice = NULL; 3613 3614 SafeIfaceArray<IStorageController> ctrls; 3615 rc = mMachine->COMGETTER(StorageControllers)(ComSafeArrayAsOutParam(ctrls)); 3616 AssertComRC(rc); 3617 IMedium *pMedium; 3618 rc = aMediumAttachment->COMGETTER(Medium)(&pMedium); 3619 AssertComRC(rc); 3620 Bstr mediumLocation; 3621 if (pMedium) 3622 { 3623 rc = pMedium->COMGETTER(Location)(mediumLocation.asOutParam()); 3624 AssertComRC(rc); 3625 } 3626 3627 Bstr attCtrlName; 3628 rc = aMediumAttachment->COMGETTER(Controller)(attCtrlName.asOutParam()); 3629 AssertComRC(rc); 3630 ComPtr<IStorageController> pStorageController; 3631 for (size_t i = 0; i < ctrls.size(); ++i) 3632 { 3633 Bstr ctrlName; 3634 rc = ctrls[i]->COMGETTER(Name)(ctrlName.asOutParam()); 3635 AssertComRC(rc); 3636 if (attCtrlName == ctrlName) 3637 { 3638 pStorageController = ctrls[i]; 3639 break; 3640 } 3641 } 3642 if (pStorageController.isNull()) 3643 return setError(E_FAIL, 3644 tr("Could not find storage controller '%ls'"), attCtrlName.raw()); 3645 3646 StorageControllerType_T enmCtrlType; 3647 rc = pStorageController->COMGETTER(ControllerType)(&enmCtrlType); 3648 AssertComRC(rc); 3649 pszDevice = convertControllerTypeToDev(enmCtrlType); 3650 3651 StorageBus_T enmBus; 3652 rc = pStorageController->COMGETTER(Bus)(&enmBus); 3653 AssertComRC(rc); 3654 ULONG uInstance; 3655 rc = pStorageController->COMGETTER(Instance)(&uInstance); 3656 AssertComRC(rc); 3657 BOOL fUseHostIOCache; 3658 rc = pStorageController->COMGETTER(UseHostIOCache)(&fUseHostIOCache); 3659 AssertComRC(rc); 3660 3661 /* 3662 * Call worker in EMT, that's faster and safer than doing everything 3663 * using VMR3ReqCall. Note that we separate VMR3ReqCall from VMR3ReqWait 3664 * here to make requests from under the lock in order to serialize them. 3665 */ 3666 PVMREQ pReq; 3667 int vrc = VMR3ReqCall(pVM, 3668 VMCPUID_ANY, 3669 &pReq, 3670 0 /* no wait! */, 3671 VMREQFLAGS_VBOX_STATUS, 3672 (PFNRT)Console::attachStorageDevice, 3673 7, 3674 this, 3675 pVM, 3676 pszDevice, 3677 uInstance, 3678 enmBus, 3679 fUseHostIOCache, 3680 aMediumAttachment); 3681 3682 /* leave the lock before waiting for a result (EMT will call us back!) */ 3683 alock.leave(); 3684 3685 if (vrc == VERR_TIMEOUT || RT_SUCCESS(vrc)) 3686 { 3687 vrc = VMR3ReqWait(pReq, RT_INDEFINITE_WAIT); 3688 AssertRC(vrc); 3689 if (RT_SUCCESS(vrc)) 3690 vrc = pReq->iStatus; 3691 } 3692 VMR3ReqFree(pReq); 3693 3694 if (RT_SUCCESS(vrc)) 3695 { 3696 LogFlowThisFunc(("Returns S_OK\n")); 3697 return S_OK; 3698 } 3699 3700 if (!pMedium) 3701 return setError(E_FAIL, 3702 tr("Could not mount the media/drive '%ls' (%Rrc)"), 3703 mediumLocation.raw(), vrc); 3704 3705 return setError(E_FAIL, 3706 tr("Could not unmount the currently mounted media/drive (%Rrc)"), 3707 vrc); 3708 } 3709 3710 3711 /** 3712 * Performs the storage attach operation in EMT. 3713 * 3714 * @returns VBox status code. 3715 * 3716 * @param pThis Pointer to the Console object. 3717 * @param pVM The VM handle. 3718 * @param pcszDevice The PDM device name. 3719 * @param uInstance The PDM device instance. 3720 * 3721 * @thread EMT 3722 */ 3723 DECLCALLBACK(int) Console::attachStorageDevice(Console *pConsole, 3724 PVM pVM, 3725 const char *pcszDevice, 3726 unsigned uInstance, 3727 StorageBus_T enmBus, 3728 bool fUseHostIOCache, 3729 IMediumAttachment *aMediumAtt) 3730 { 3731 LogFlowFunc(("pConsole=%p uInstance=%u pszDevice=%p:{%s} enmBus=%u, aMediumAtt=%p\n", 3732 pConsole, uInstance, pcszDevice, pcszDevice, enmBus, aMediumAtt)); 3733 3734 AssertReturn(pConsole, VERR_INVALID_PARAMETER); 3735 3736 AutoCaller autoCaller(pConsole); 3737 AssertComRCReturn(autoCaller.rc(), VERR_ACCESS_DENIED); 3738 3739 /* 3740 * Suspend the VM first. 3741 * 3742 * The VM must not be running since it might have pending I/O to 3743 * the drive which is being changed. 3744 */ 3745 bool fResume; 3746 VMSTATE enmVMState = VMR3GetState(pVM); 3747 switch (enmVMState) 3748 { 3749 case VMSTATE_RESETTING: 3750 case VMSTATE_RUNNING: 3751 { 3752 LogFlowFunc(("Suspending the VM...\n")); 3753 /* disable the callback to prevent Console-level state change */ 3754 pConsole->mVMStateChangeCallbackDisabled = true; 3755 int rc = VMR3Suspend(pVM); 3756 pConsole->mVMStateChangeCallbackDisabled = false; 3757 AssertRCReturn(rc, rc); 3758 fResume = true; 3759 break; 3760 } 3761 3762 case VMSTATE_SUSPENDED: 3763 case VMSTATE_CREATED: 3764 case VMSTATE_OFF: 3765 fResume = false; 3766 break; 3767 3768 case VMSTATE_RUNNING_LS: 3769 case VMSTATE_RUNNING_FT: 3770 return setErrorInternal(VBOX_E_INVALID_VM_STATE, 3771 COM_IIDOF(IConsole), 3772 getStaticComponentName(), 3773 (enmVMState == VMSTATE_RUNNING_LS) ? Utf8Str(tr("Cannot change drive during live migration")) : Utf8Str(tr("Cannot change drive during fault tolerant syncing")), 3774 false /*aWarning*/, 3775 true /*aLogIt*/); 3776 3777 default: 3778 AssertMsgFailedReturn(("enmVMState=%d\n", enmVMState), VERR_ACCESS_DENIED); 3779 } 3780 3781 /* Determine the base path for the device instance. */ 3782 PCFGMNODE pCtlInst; 3783 pCtlInst = CFGMR3GetChildF(CFGMR3GetRoot(pVM), "Devices/%s/%u/", pcszDevice, uInstance); 3784 AssertReturn(pCtlInst, VERR_INTERNAL_ERROR); 3785 3786 int rc = VINF_SUCCESS; 3787 int rcRet = VINF_SUCCESS; 3788 3789 rcRet = pConsole->configMediumAttachment(pCtlInst, 3790 pcszDevice, 3791 uInstance, 3792 enmBus, 3793 fUseHostIOCache, 3794 false /* fSetupMerge */, 3795 false /* fBuiltinIoCache */, 3796 0 /* uMergeSource */, 3797 0 /* uMergeTarget */, 3798 aMediumAtt, 3799 pConsole->mMachineState, 3800 NULL /* phrc */, 3801 true /* fAttachDetach */, 3802 false /* fForceUnmount */, 3803 true /* fHotplug */, 3804 pVM, 3805 NULL /* paLedDevType */); 3806 /** @todo this dumps everything attached to this device instance, which 3807 * is more than necessary. Dumping the changed LUN would be enough. */ 3808 CFGMR3Dump(pCtlInst); 3809 3810 /* 3811 * Resume the VM if necessary. 3812 */ 3813 if (fResume) 3814 { 3815 LogFlowFunc(("Resuming the VM...\n")); 3816 /* disable the callback to prevent Console-level state change */ 3817 pConsole->mVMStateChangeCallbackDisabled = true; 3818 rc = VMR3Resume(pVM); 3819 pConsole->mVMStateChangeCallbackDisabled = false; 3820 AssertRC(rc); 3821 if (RT_FAILURE(rc)) 3822 { 3823 /* too bad, we failed. try to sync the console state with the VMM state */ 3824 vmstateChangeCallback(pVM, VMSTATE_SUSPENDED, enmVMState, pConsole); 3825 } 3826 /** @todo: if we failed with drive mount, then the VMR3Resume 3827 * error (if any) will be hidden from the caller. For proper reporting 3828 * of such multiple errors to the caller we need to enhance the 3829 * IVirtualBoxError interface. For now, give the first error the higher 3830 * priority. 3831 */ 3832 if (RT_SUCCESS(rcRet)) 3833 rcRet = rc; 3834 } 3835 3836 LogFlowFunc(("Returning %Rrc\n", rcRet)); 3837 return rcRet; 3838 } 3839 3840 /** 3841 * Attach a new storage device to the VM. 3842 * 3843 * @param aMediumAttachment The medium attachmentwhich is added. 3844 * @param pVM Safe VM handle. 3845 * 3846 * @note Locks this object for writing. 3847 */ 3848 HRESULT Console::doStorageDeviceDetach(IMediumAttachment *aMediumAttachment, PVM pVM) 3849 { 3850 AutoCaller autoCaller(this); 3851 AssertComRCReturnRC(autoCaller.rc()); 3852 3853 /* We will need to release the write lock before calling EMT */ 3854 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 3855 3856 HRESULT rc = S_OK; 3857 const char *pszDevice = NULL; 3858 3859 SafeIfaceArray<IStorageController> ctrls; 3860 rc = mMachine->COMGETTER(StorageControllers)(ComSafeArrayAsOutParam(ctrls)); 3861 AssertComRC(rc); 3862 IMedium *pMedium; 3863 rc = aMediumAttachment->COMGETTER(Medium)(&pMedium); 3864 AssertComRC(rc); 3865 Bstr mediumLocation; 3866 if (pMedium) 3867 { 3868 rc = pMedium->COMGETTER(Location)(mediumLocation.asOutParam()); 3869 AssertComRC(rc); 3870 } 3871 3872 Bstr attCtrlName; 3873 rc = aMediumAttachment->COMGETTER(Controller)(attCtrlName.asOutParam()); 3874 AssertComRC(rc); 3875 ComPtr<IStorageController> pStorageController; 3876 for (size_t i = 0; i < ctrls.size(); ++i) 3877 { 3878 Bstr ctrlName; 3879 rc = ctrls[i]->COMGETTER(Name)(ctrlName.asOutParam()); 3880 AssertComRC(rc); 3881 if (attCtrlName == ctrlName) 3882 { 3883 pStorageController = ctrls[i]; 3884 break; 3885 } 3886 } 3887 if (pStorageController.isNull()) 3888 return setError(E_FAIL, 3889 tr("Could not find storage controller '%ls'"), attCtrlName.raw()); 3890 3891 StorageControllerType_T enmCtrlType; 3892 rc = pStorageController->COMGETTER(ControllerType)(&enmCtrlType); 3893 AssertComRC(rc); 3894 pszDevice = convertControllerTypeToDev(enmCtrlType); 3895 3896 StorageBus_T enmBus; 3897 rc = pStorageController->COMGETTER(Bus)(&enmBus); 3898 AssertComRC(rc); 3899 ULONG uInstance; 3900 rc = pStorageController->COMGETTER(Instance)(&uInstance); 3901 AssertComRC(rc); 3902 3903 /* 3904 * Call worker in EMT, that's faster and safer than doing everything 3905 * using VMR3ReqCall. Note that we separate VMR3ReqCall from VMR3ReqWait 3906 * here to make requests from under the lock in order to serialize them. 3907 */ 3908 PVMREQ pReq; 3909 int vrc = VMR3ReqCall(pVM, 3910 VMCPUID_ANY, 3911 &pReq, 3912 0 /* no wait! */, 3913 VMREQFLAGS_VBOX_STATUS, 3914 (PFNRT)Console::detachStorageDevice, 3915 6, 3916 this, 3917 pVM, 3918 pszDevice, 3919 uInstance, 3920 enmBus, 3921 aMediumAttachment); 3922 3923 /* leave the lock before waiting for a result (EMT will call us back!) */ 3924 alock.leave(); 3925 3926 if (vrc == VERR_TIMEOUT || RT_SUCCESS(vrc)) 3927 { 3928 vrc = VMR3ReqWait(pReq, RT_INDEFINITE_WAIT); 3929 AssertRC(vrc); 3930 if (RT_SUCCESS(vrc)) 3931 vrc = pReq->iStatus; 3932 } 3933 VMR3ReqFree(pReq); 3934 3935 if (RT_SUCCESS(vrc)) 3936 { 3937 LogFlowThisFunc(("Returns S_OK\n")); 3938 return S_OK; 3939 } 3940 3941 if (!pMedium) 3942 return setError(E_FAIL, 3943 tr("Could not mount the media/drive '%ls' (%Rrc)"), 3944 mediumLocation.raw(), vrc); 3945 3946 return setError(E_FAIL, 3947 tr("Could not unmount the currently mounted media/drive (%Rrc)"), 3948 vrc); 3949 } 3950 3951 /** 3952 * Performs the storage detach operation in EMT. 3953 * 3954 * @returns VBox status code. 3955 * 3956 * @param pThis Pointer to the Console object. 3957 * @param pVM The VM handle. 3958 * @param pcszDevice The PDM device name. 3959 * @param uInstance The PDM device instance. 3960 * 3961 * @thread EMT 3962 */ 3963 DECLCALLBACK(int) Console::detachStorageDevice(Console *pConsole, 3964 PVM pVM, 3965 const char *pcszDevice, 3966 unsigned uInstance, 3967 StorageBus_T enmBus, 3968 IMediumAttachment *pMediumAtt) 3969 { 3970 LogFlowFunc(("pConsole=%p uInstance=%u pszDevice=%p:{%s} enmBus=%u, pMediumAtt=%p\n", 3971 pConsole, uInstance, pcszDevice, pcszDevice, enmBus, pMediumAtt)); 3972 3973 AssertReturn(pConsole, VERR_INVALID_PARAMETER); 3974 3975 AutoCaller autoCaller(pConsole); 3976 AssertComRCReturn(autoCaller.rc(), VERR_ACCESS_DENIED); 3977 3978 /* 3979 * Suspend the VM first. 3980 * 3981 * The VM must not be running since it might have pending I/O to 3982 * the drive which is being changed. 3983 */ 3984 bool fResume; 3985 VMSTATE enmVMState = VMR3GetState(pVM); 3986 switch (enmVMState) 3987 { 3988 case VMSTATE_RESETTING: 3989 case VMSTATE_RUNNING: 3990 { 3991 LogFlowFunc(("Suspending the VM...\n")); 3992 /* disable the callback to prevent Console-level state change */ 3993 pConsole->mVMStateChangeCallbackDisabled = true; 3994 int rc = VMR3Suspend(pVM); 3995 pConsole->mVMStateChangeCallbackDisabled = false; 3996 AssertRCReturn(rc, rc); 3997 fResume = true; 3998 break; 3999 } 4000 4001 case VMSTATE_SUSPENDED: 4002 case VMSTATE_CREATED: 4003 case VMSTATE_OFF: 4004 fResume = false; 4005 break; 4006 4007 case VMSTATE_RUNNING_LS: 4008 case VMSTATE_RUNNING_FT: 4009 return setErrorInternal(VBOX_E_INVALID_VM_STATE, 4010 COM_IIDOF(IConsole), 4011 getStaticComponentName(), 4012 (enmVMState == VMSTATE_RUNNING_LS) ? Utf8Str(tr("Cannot change drive during live migration")) : Utf8Str(tr("Cannot change drive during fault tolerant syncing")), 4013 false /*aWarning*/, 4014 true /*aLogIt*/); 4015 4016 default: 4017 AssertMsgFailedReturn(("enmVMState=%d\n", enmVMState), VERR_ACCESS_DENIED); 4018 } 4019 4020 /* Determine the base path for the device instance. */ 4021 PCFGMNODE pCtlInst; 4022 pCtlInst = CFGMR3GetChildF(CFGMR3GetRoot(pVM), "Devices/%s/%u/", pcszDevice, uInstance); 4023 AssertReturn(pCtlInst, VERR_INTERNAL_ERROR); 4024 4025 #define H() AssertMsgReturn(!FAILED(hrc), ("hrc=%Rhrc\n", hrc), VERR_GENERAL_FAILURE) 4026 4027 HRESULT hrc; 4028 int rc = VINF_SUCCESS; 4029 int rcRet = VINF_SUCCESS; 4030 unsigned uLUN; 4031 LONG lDev; 4032 LONG lPort; 4033 DeviceType_T lType; 4034 PCFGMNODE pLunL0 = NULL; 4035 PCFGMNODE pCfg = NULL; 4036 4037 hrc = pMediumAtt->COMGETTER(Device)(&lDev); H(); 4038 hrc = pMediumAtt->COMGETTER(Port)(&lPort); H(); 4039 hrc = pMediumAtt->COMGETTER(Type)(&lType); H(); 4040 hrc = Console::convertBusPortDeviceToLun(enmBus, lPort, lDev, uLUN); H(); 4041 4042 #undef H 4043 4044 /* First check if the LUN really exists. */ 4045 pLunL0 = CFGMR3GetChildF(pCtlInst, "LUN#%u", uLUN); 4046 if (pLunL0) 4047 { 4048 rc = PDMR3DeviceDetach(pVM, pcszDevice, uInstance, uLUN, 0); 4049 if (rc == VERR_PDM_NO_DRIVER_ATTACHED_TO_LUN) 4050 rc = VINF_SUCCESS; 4051 AssertRCReturn(rc, rc); 4052 CFGMR3RemoveNode(pLunL0); 4053 } 4054 else 4055 AssertFailedReturn(VERR_INTERNAL_ERROR); 4056 4057 CFGMR3Dump(pCtlInst); 4058 4059 /* 4060 * Resume the VM if necessary. 4061 */ 4062 if (fResume) 4063 { 4064 LogFlowFunc(("Resuming the VM...\n")); 4065 /* disable the callback to prevent Console-level state change */ 4066 pConsole->mVMStateChangeCallbackDisabled = true; 4067 rc = VMR3Resume(pVM); 4068 pConsole->mVMStateChangeCallbackDisabled = false; 4069 AssertRC(rc); 4070 if (RT_FAILURE(rc)) 4071 { 4072 /* too bad, we failed. try to sync the console state with the VMM state */ 4073 vmstateChangeCallback(pVM, VMSTATE_SUSPENDED, enmVMState, pConsole); 4074 } 4075 /** @todo: if we failed with drive mount, then the VMR3Resume 4076 * error (if any) will be hidden from the caller. For proper reporting 4077 * of such multiple errors to the caller we need to enhance the 4078 * IVirtualBoxError interface. For now, give the first error the higher 4079 * priority. 4080 */ 4081 if (RT_SUCCESS(rcRet)) 4082 rcRet = rc; 4083 } 4084 4085 LogFlowFunc(("Returning %Rrc\n", rcRet)); 4086 return rcRet; 4087 } 3593 4088 3594 4089 /** … … 4513 5008 4514 5009 /** 5010 * Called by IInternalSessionControl::OnStorageDeviceChange(). 5011 * 5012 * @note Locks this object for writing. 5013 */ 5014 HRESULT Console::onStorageDeviceChange(IMediumAttachment *aMediumAttachment, BOOL aRemove) 5015 { 5016 LogFlowThisFunc(("\n")); 5017 5018 AutoCaller autoCaller(this); 5019 AssertComRCReturnRC(autoCaller.rc()); 5020 5021 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 5022 5023 HRESULT rc = S_OK; 5024 5025 /* don't trigger medium change if the VM isn't running */ 5026 SafeVMPtrQuiet ptrVM(this); 5027 if (ptrVM.isOk()) 5028 { 5029 if (aRemove) 5030 rc = doStorageDeviceDetach(aMediumAttachment, ptrVM); 5031 else 5032 rc = doStorageDeviceAttach(aMediumAttachment, ptrVM); 5033 ptrVM.release(); 5034 } 5035 5036 /* notify console callbacks on success */ 5037 if (SUCCEEDED(rc)) 5038 fireStorageDeviceChangedEvent(mEventSource, aMediumAttachment, aRemove); 5039 5040 LogFlowThisFunc(("Leaving rc=%#x\n", rc)); 5041 return rc; 5042 } 5043 5044 /** 4515 5045 * @note Temporarily locks this object for writing. 4516 5046 */ … … 8332 8862 true /* fAttachDetach */, 8333 8863 false /* fForceUnmount */, 8864 false /* fHotplug */, 8334 8865 pVM, 8335 8866 NULL /* paLedDevType */); -
trunk/src/VBox/Main/src-client/ConsoleImpl2.cpp
r36837 r36991 1651 1651 false /* fAttachDetach */, 1652 1652 false /* fForceUnmount */, 1653 false /* fHotplug */, 1653 1654 pVM, 1654 1655 paLedDevType); … … 2813 2814 bool fAttachDetach, 2814 2815 bool fForceUnmount, 2816 bool fHotplug, 2815 2817 PVM pVM, 2816 2818 DeviceType_T *paLedDevType) … … 2870 2872 } 2871 2873 2872 rc = PDMR3DeviceDetach(pVM, pcszDevice, uInstance, uLUN, PDM_TACH_FLAGS_NOT_HOT_PLUG);2874 rc = PDMR3DeviceDetach(pVM, pcszDevice, uInstance, uLUN, fHotplug ? 0 : PDM_TACH_FLAGS_NOT_HOT_PLUG); 2873 2875 if (rc == VERR_PDM_NO_DRIVER_ATTACHED_TO_LUN) 2874 2876 rc = VINF_SUCCESS; … … 3109 3111 /* Attach the new driver. */ 3110 3112 rc = PDMR3DeviceAttach(pVM, pcszDevice, uInstance, uLUN, 3111 PDM_TACH_FLAGS_NOT_HOT_PLUG, NULL /*ppBase*/);3113 fHotplug ? 0 : PDM_TACH_FLAGS_NOT_HOT_PLUG, NULL /*ppBase*/); 3112 3114 AssertRCReturn(rc, rc); 3113 3115 -
trunk/src/VBox/Main/src-client/SessionImpl.cpp
r35638 r36991 725 725 726 726 return mConsole->onBandwidthGroupChange(aBandwidthGroup); 727 } 728 729 STDMETHODIMP Session::OnStorageDeviceChange(IMediumAttachment *aMediumAttachment, BOOL aRemove) 730 { 731 LogFlowThisFunc(("\n")); 732 733 AutoCaller autoCaller(this); 734 AssertComRCReturn(autoCaller.rc(), autoCaller.rc()); 735 736 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 737 AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE); 738 AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE); 739 740 return mConsole->onStorageDeviceChange(aMediumAttachment, aRemove); 727 741 } 728 742 -
trunk/src/VBox/Main/src-server/MachineImpl.cpp
r36898 r36991 3404 3404 AssertReturn(mData->mMachineState != MachineState_Saved, E_FAIL); 3405 3405 3406 if (Global::IsOnlineOrTransient(mData->mMachineState))3407 return setError(VBOX_E_INVALID_VM_STATE,3408 tr("Invalid machine state: %s"),3409 Global::stringifyMachineState(mData->mMachineState));3410 3411 3406 /* Check for an existing controller. */ 3412 3407 ComObjPtr<StorageController> ctl; 3413 3408 rc = getStorageControllerByName(aControllerName, ctl, true /* aSetError */); 3414 3409 if (FAILED(rc)) return rc; 3410 3411 StorageControllerType_T ctrlType; 3412 rc = ctl->COMGETTER(ControllerType)(&ctrlType); 3413 if (FAILED(rc)) 3414 return setError(E_FAIL, 3415 tr("Could not get type of controller '%ls'"), 3416 aControllerName); 3417 3418 /* Check that the controller can do hotplugging if we detach the device while the VM is running. */ 3419 bool fHotplug = false; 3420 if (Global::IsOnlineOrTransient(mData->mMachineState)) 3421 fHotplug = true; 3422 3423 if (fHotplug && !isControllerHotplugCapable(ctrlType)) 3424 return setError(VBOX_E_INVALID_VM_STATE, 3425 tr("Invalid machine state: %s"), 3426 Global::stringifyMachineState(mData->mMachineState)); 3415 3427 3416 3428 // check that the port and device are not out of range … … 3784 3796 alock.release(); 3785 3797 3798 if (fHotplug) 3799 rc = onStorageDeviceChange(attachment, FALSE /* aRemove */); 3800 3786 3801 mParent->saveRegistries(llRegistriesThatNeedSaving); 3787 3802 … … 3809 3824 AssertReturn(mData->mMachineState != MachineState_Saved, E_FAIL); 3810 3825 3826 /* Check for an existing controller. */ 3827 ComObjPtr<StorageController> ctl; 3828 rc = getStorageControllerByName(aControllerName, ctl, true /* aSetError */); 3829 if (FAILED(rc)) return rc; 3830 3831 StorageControllerType_T ctrlType; 3832 rc = ctl->COMGETTER(ControllerType)(&ctrlType); 3833 if (FAILED(rc)) 3834 return setError(E_FAIL, 3835 tr("Could not get type of controller '%ls'"), 3836 aControllerName); 3837 3838 /* Check that the controller can do hotplugging if we detach the device while the VM is running. */ 3839 bool fHotplug = false; 3811 3840 if (Global::IsOnlineOrTransient(mData->mMachineState)) 3841 fHotplug = true; 3842 3843 if (fHotplug && !isControllerHotplugCapable(ctrlType)) 3812 3844 return setError(VBOX_E_INVALID_VM_STATE, 3813 3845 tr("Invalid machine state: %s"), … … 3823 3855 aDevice, aControllerPort, aControllerName); 3824 3856 3857 /* 3858 * The VM has to detach the device before we delete any implicit diffs. 3859 * If this fails we can roll back without loosing data. 3860 */ 3861 if (fHotplug) 3862 { 3863 alock.leave(); 3864 rc = onStorageDeviceChange(pAttach, TRUE /* aRemove */); 3865 alock.enter(); 3866 } 3867 if (FAILED(rc)) return rc; 3868 3869 /* If we are here everything went well and we can delete the implicit now. */ 3825 3870 rc = detachDevice(pAttach, alock, NULL /* pSnapshot */, &llRegistriesThatNeedSaving); 3826 3871 … … 10116 10161 for (ULONG slot = 0; slot < RT_ELEMENTS(mParallelPorts); slot++) 10117 10162 mParallelPorts[slot]->copyFrom(aThat->mParallelPorts[slot]); 10163 } 10164 10165 /** 10166 * Returns whether the given storage controller is hotplug capable. 10167 * 10168 * @returns true if the controller supports hotplugging 10169 * false otherwise. 10170 * @param enmCtrlType The controller type to check for. 10171 */ 10172 bool Machine::isControllerHotplugCapable(StorageControllerType_T enmCtrlType) 10173 { 10174 switch (enmCtrlType) 10175 { 10176 case StorageControllerType_IntelAhci: 10177 return true; 10178 case StorageControllerType_LsiLogic: 10179 case StorageControllerType_LsiLogicSas: 10180 case StorageControllerType_BusLogic: 10181 case StorageControllerType_PIIX3: 10182 case StorageControllerType_PIIX4: 10183 case StorageControllerType_ICH6: 10184 case StorageControllerType_I82078: 10185 default: 10186 return false; 10187 } 10118 10188 } 10119 10189 … … 11836 11906 11837 11907 /** 11908 * @note Locks this object for reading. 11909 */ 11910 HRESULT SessionMachine::onStorageDeviceChange(IMediumAttachment *aAttachment, BOOL aRemove) 11911 { 11912 LogFlowThisFunc(("\n")); 11913 11914 AutoCaller autoCaller(this); 11915 AssertComRCReturn(autoCaller.rc(), autoCaller.rc()); 11916 11917 ComPtr<IInternalSessionControl> directControl; 11918 { 11919 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 11920 directControl = mData->mSession.mDirectControl; 11921 } 11922 11923 /* ignore notifications sent after #OnSessionEnd() is called */ 11924 if (!directControl) 11925 return S_OK; 11926 11927 return directControl->OnStorageDeviceChange(aAttachment, aRemove); 11928 } 11929 11930 /** 11838 11931 * Returns @c true if this machine's USB controller reports it has a matching 11839 11932 * filter for the given USB device and @c false otherwise.
Note:
See TracChangeset
for help on using the changeset viewer.