VirtualBox

Changeset 50723 in vbox


Ignore:
Timestamp:
Mar 7, 2014 10:11:38 AM (11 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
92694
Message:

Main/Console: when changing a medium or network attachment, suspend the VM before doing the actual VMR3Req* call. Doing this in the EM context has bad side effects, see @bugref{4744} and @bugref{7283}. Also, don't dump the complete device instance but dump only the affected LUN.

Location:
trunk/src/VBox/Main
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/include/ConsoleImpl.h

    r50686 r50723  
    55
    66/*
    7  * Copyright (C) 2005-2013 Oracle Corporation
     7 * Copyright (C) 2005-2014 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    570570    HRESULT removeSharedFolder(const Utf8Str &strName);
    571571
     572    int  suspendBeforeConfigChange(PUVM pUVM, AutoWriteLock *pAlock, bool *pfResume);
     573    void resumeAfterConfigChange(PUVM pUVM);
     574
    572575    static DECLCALLBACK(int) configConstructor(PUVM pUVM, PVM pVM, void *pvConsole);
    573576    int configConstructorInner(PUVM pUVM, PVM pVM, AutoWriteLock *pAlock);
     
    597600                               bool fHotplug,
    598601                               PUVM pUVM,
    599                                DeviceType_T *paLedDevType);
     602                               DeviceType_T *paLedDevType,
     603                               PCFGMNODE *ppLunL0);
    600604    int configMedium(PCFGMNODE pLunL0,
    601605                     bool fPassthrough,
     
    611615                     MachineState_T aMachineState,
    612616                     HRESULT *phrc);
    613     static DECLCALLBACK(int) reconfigureMediumAttachment(Console *pConsole,
     617    static DECLCALLBACK(int) reconfigureMediumAttachment(Console *pThis,
    614618                                                         PUVM pUVM,
    615619                                                         const char *pcszDevice,
  • trunk/src/VBox/Main/src-client/ConsoleImpl.cpp

    r50686 r50723  
    55
    66/*
    7  * Copyright (C) 2005-2013 Oracle Corporation
     7 * Copyright (C) 2005-2014 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    24122412        PVMREQ pReq;
    24132413        vrc = VMR3ReqCallU(pUVM, 0, &pReq, 0 /* no wait! */, VMREQFLAGS_VBOX_STATUS,
    2414                            (PFNRT)Console::unplugCpu, 3,
     2414                           (PFNRT)unplugCpu, 3,
    24152415                           this, pUVM, (VMCPUID)aCpu);
    24162416        if (vrc == VERR_TIMEOUT || RT_SUCCESS(vrc))
     
    25182518    PVMREQ pReq;
    25192519    int vrc = VMR3ReqCallU(pUVM, 0, &pReq, 0 /* no wait! */, VMREQFLAGS_VBOX_STATUS,
    2520                            (PFNRT)Console::plugCpu, 3,
     2520                           (PFNRT)plugCpu, 3,
    25212521                           this, pUVM, aCpu);
    25222522
     
    35343534// private methods
    35353535/////////////////////////////////////////////////////////////////////////////
     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 */
     3546int 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 */
     3583void 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}
    35363601
    35373602/**
     
    36033668
    36043669    /*
     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    /*
    36053679     * Call worker in EMT, that's faster and safer than doing everything
    36063680     * using VMR3ReqCall. Note that we separate VMR3ReqCall from VMR3ReqWait
     
    36083682     */
    36093683    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);
    36253687
    36263688    /* release the lock before waiting for a result (EMT will call us back!) */
     
    36353697    }
    36363698    VMR3ReqFree(pReq);
     3699
     3700    if (fResume)
     3701        resumeAfterConfigChange(pUVM);
    36373702
    36383703    if (RT_SUCCESS(vrc))
     
    36713736 *
    36723737 * @thread  EMT
     3738 * @note The VM must not be running since it might have pending I/O to the drive which is being changed.
    36733739 */
    3674 DECLCALLBACK(int) Console::changeRemovableMedium(Console *pConsole,
     3740DECLCALLBACK(int) Console::changeRemovableMedium(Console *pThis,
    36753741                                                 PUVM pUVM,
    36763742                                                 const char *pcszDevice,
     
    36813747                                                 bool fForce)
    36823748{
    3683     LogFlowFunc(("pConsole=%p uInstance=%u pszDevice=%p:{%s} enmBus=%u, aMediumAtt=%p, fForce=%d\n",
    3684                  pConsole, uInstance, pcszDevice, pcszDevice, enmBus, aMediumAtt, fForce));
    3685 
    3686     AssertReturn(pConsole, VERR_INVALID_PARAMETER);
    3687 
    3688     AutoCaller autoCaller(pConsole);
     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);
    36893755    AssertComRCReturn(autoCaller.rc(), VERR_ACCESS_DENIED);
    36903756
    36913757    /*
    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.
    36963759     */
    3697     bool fResume;
    36983760    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);
    37323762
    37333763    /* Determine the base path for the device instance. */
     
    37363766    AssertReturn(pCtlInst, VERR_INTERNAL_ERROR);
    37373767
    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;
    37893792}
    37903793
     
    38583861
    38593862    /*
     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    /*
    38603872     * Call worker in EMT, that's faster and safer than doing everything
    38613873     * using VMR3ReqCall. Note that we separate VMR3ReqCall from VMR3ReqWait
     
    38633875     */
    38643876    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);
    38803880
    38813881    /* release the lock before waiting for a result (EMT will call us back!) */
     
    38903890    }
    38913891    VMR3ReqFree(pReq);
     3892
     3893    if (fResume)
     3894        resumeAfterConfigChange(pUVM);
    38923895
    38933896    if (RT_SUCCESS(vrc))
     
    39203923 *
    39213924 * @thread  EMT
     3925 * @note The VM must not be running since it might have pending I/O to the drive which is being changed.
    39223926 */
    3923 DECLCALLBACK(int) Console::attachStorageDevice(Console *pConsole,
     3927DECLCALLBACK(int) Console::attachStorageDevice(Console *pThis,
    39243928                                               PUVM pUVM,
    39253929                                               const char *pcszDevice,
     
    39303934                                               bool fSilent)
    39313935{
    3932     LogFlowFunc(("pConsole=%p uInstance=%u pszDevice=%p:{%s} enmBus=%u, aMediumAtt=%p\n",
    3933                  pConsole, uInstance, pcszDevice, pcszDevice, enmBus, aMediumAtt));
    3934 
    3935     AssertReturn(pConsole, VERR_INVALID_PARAMETER);
    3936 
    3937     AutoCaller autoCaller(pConsole);
     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);
    39383942    AssertComRCReturn(autoCaller.rc(), VERR_ACCESS_DENIED);
    39393943
    39403944    /*
    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.
    39453946     */
    3946     bool fResume;
    39473947    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);
    39813949
    39823950    /*
     
    39933961    AssertReturn(pCtlInst, VERR_INTERNAL_ERROR);
    39943962
    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 */
    40173983    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;
    40483988}
    40493989
     
    41134053
    41144054    /*
     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    /*
    41154064     * Call worker in EMT, that's faster and safer than doing everything
    41164065     * using VMR3ReqCall. Note that we separate VMR3ReqCall from VMR3ReqWait
     
    41184067     */
    41194068    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);
    41344072
    41354073    /* release the lock before waiting for a result (EMT will call us back!) */
     
    41444082    }
    41454083    VMR3ReqFree(pReq);
     4084
     4085    if (fResume)
     4086        resumeAfterConfigChange(pUVM);
    41464087
    41474088    if (RT_SUCCESS(vrc))
     
    41734114 *
    41744115 * @thread  EMT
     4116 * @note The VM must not be running since it might have pending I/O to the drive which is being changed.
    41754117 */
    4176 DECLCALLBACK(int) Console::detachStorageDevice(Console *pConsole,
     4118DECLCALLBACK(int) Console::detachStorageDevice(Console *pThis,
    41774119                                               PUVM pUVM,
    41784120                                               const char *pcszDevice,
     
    41824124                                               bool fSilent)
    41834125{
    4184     LogFlowFunc(("pConsole=%p uInstance=%u pszDevice=%p:{%s} enmBus=%u, pMediumAtt=%p\n",
    4185                  pConsole, uInstance, pcszDevice, pcszDevice, enmBus, pMediumAtt));
    4186 
    4187     AssertReturn(pConsole, VERR_INVALID_PARAMETER);
    4188 
    4189     AutoCaller autoCaller(pConsole);
     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);
    41904132    AssertComRCReturn(autoCaller.rc(), VERR_ACCESS_DENIED);
    41914133
    41924134    /*
    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.
    41974136     */
    4198     bool fResume;
    41994137    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);
    42334139
    42344140    /* Determine the base path for the device instance. */
     
    42744180
    42754181            Utf8Str devicePath = Utf8StrFmt("%s/%u/LUN#%u", pcszDevice, uInstance, uLUN);
    4276             pConsole->mapMediumAttachments.erase(devicePath);
     4182            pThis->mapMediumAttachments.erase(devicePath);
    42774183
    42784184        }
     
    42864192        /* Find the correct USB device in the list. */
    42874193        USBStorageDeviceList::iterator it;
    4288         for (it = pConsole->mUSBStorageDevices.begin(); it != pConsole->mUSBStorageDevices.end(); it++)
     4194        for (it = pThis->mUSBStorageDevices.begin(); it != pThis->mUSBStorageDevices.end(); it++)
    42894195        {
    42904196            if (it->iPort == lPort)
     
    42924198        }
    42934199
    4294         AssertReturn(it != pConsole->mUSBStorageDevices.end(), VERR_INTERNAL_ERROR);
     4200        AssertReturn(it != pThis->mUSBStorageDevices.end(), VERR_INTERNAL_ERROR);
    42954201        rc = PDMR3UsbDetachDevice(pUVM, &it->mUuid);
    42964202        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);
    43244204    }
    43254205
     
    45634443
    45644444    /*
     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    /*
    45654453     * Call worker in EMT, that's faster and safer than doing everything
    45664454     * using VM3ReqCall. Note that we separate VMR3ReqCall from VMR3ReqWait
     
    45684456     */
    45694457    PVMREQ pReq;
    4570     int vrc = VMR3ReqCallU(pUVM, 0 /*idDstCpu*/, &pReq, 0 /* no wait! */, VMREQFLAGS_VBOX_STATUS,
    4571                            (PFNRT)Console::changeNetworkAttachment, 6,
    4572                            this, pUVM, pszDevice, uInstance, uLun, aNetworkAdapter);
     4458    vrc = VMR3ReqCallU(pUVM, 0 /*idDstCpu*/, &pReq, 0 /* no wait! */, VMREQFLAGS_VBOX_STATUS,
     4459                       (PFNRT)changeNetworkAttachment, 6,
     4460                       this, pUVM, pszDevice, uInstance, uLun, aNetworkAdapter);
    45734461
    45744462    if (vrc == VERR_TIMEOUT || RT_SUCCESS(vrc))
     
    45804468    }
    45814469    VMR3ReqFree(pReq);
     4470
     4471    if (fResume)
     4472        resumeAfterConfigChange(pUVM);
    45824473
    45834474    if (RT_SUCCESS(vrc))
     
    46074498 * @thread  EMT
    46084499 * @note Locks the Console object for writing.
     4500 * @note The VM must not be running.
    46094501 */
    46104502DECLCALLBACK(int) Console::changeNetworkAttachment(Console *pThis,
     
    46424534
    46434535    /*
    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.
    46484537     */
    4649     bool fResume;
    46504538    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);
    46784540
    46794541    PCFGMNODE pCfg = NULL;          /* /Devices/Dev/.../Config/ */
     
    46824544    AssertRelease(pInst);
    46834545
    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;
    47144551}
    47154552
     
    57605597    }
    57615598
    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);
    57795604    /* error handling is after resuming the VM */
    57805605
     
    58345659    rc = mControl->FinishOnlineMergeMedium();
    58355660
    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);
    58535666    /* error handling is after resuming the VM */
    58545667
     
    82938106                               this, ptrVM.rawUVM(), aHostDevice, uuid.raw(), fRemote,
    82948107                               Address.c_str(), pvRemoteBackend, portVersion, aMaskedIfs);
    8295 
    82968108    if (RT_SUCCESS(vrc))
    82978109    {
     
    95189330 * Reconfigures a medium attachment (part of taking or deleting an online snapshot).
    95199331 *
    9520  * @param   pConsole      Reference to the console object.
     9332 * @param   pThis         Reference to the console object.
    95219333 * @param   pUVM          The VM handle.
    95229334 * @param   lInstance     The instance of the controller.
     
    95329344 */
    95339345/* static */
    9534 DECLCALLBACK(int) Console::reconfigureMediumAttachment(Console *pConsole,
     9346DECLCALLBACK(int) Console::reconfigureMediumAttachment(Console *pThis,
    95359347                                                       PUVM pUVM,
    95369348                                                       const char *pcszDevice,
     
    95489360    LogFlowFunc(("pUVM=%p aMediumAtt=%p phrc=%p\n", pUVM, aMediumAtt, phrc));
    95499361
    9550     int             rc;
    95519362    HRESULT         hrc;
    95529363    Bstr            bstr;
    95539364    *phrc = S_OK;
    9554 #define RC_CHECK() do { if (RT_FAILURE(rc)) { AssertMsgFailed(("rc=%Rrc\n", rc)); return rc; } } while (0)
    95559365#define H() do { if (FAILED(hrc)) { AssertMsgFailed(("hrc=%Rhrc (%#x)\n", hrc, hrc)); *phrc = hrc; return VERR_GENERAL_FAILURE; } } while (0)
    95569366
     
    95739383
    95749384    /* 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
    95989412#undef H
    95999413
     
    97779591                 * isn't going to need the Console lock.
    97789592                 */
    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);
    97969598                if (RT_FAILURE(vrc))
    97979599                    throw setErrorStatic(E_FAIL, Console::tr("%Rrc"), vrc);
  • trunk/src/VBox/Main/src-client/ConsoleImpl2.cpp

    r50721 r50723  
    21942194                                            false /* fHotplug */,
    21952195                                            pUVM,
    2196                                             paLedDevType);
     2196                                            paLedDevType,
     2197                                            NULL /* ppLunL0 */);
    21972198                if (RT_FAILURE(rc))
    21982199                    return rc;
     
    34963497                                    bool fHotplug,
    34973498                                    PUVM pUVM,
    3498                                     DeviceType_T *paLedDevType)
     3499                                    DeviceType_T *paLedDevType,
     3500                                    PCFGMNODE *ppLunL0)
    34993501{
    35003502    // InsertConfig* throws
     
    36103612
    36113613        InsertConfigNode(pCtlInst, Utf8StrFmt("LUN#%u", uLUN).c_str(), &pLunL0);
     3614        if (ppLunL0)
     3615            *ppLunL0 = pLunL0;
    36123616
    36133617        PCFGMNODE pCfg = CFGMR3GetChild(pCtlInst, "Config");
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette