- Timestamp:
- Mar 10, 2009 10:27:08 PM (16 years ago)
- Location:
- trunk/src/VBox/Main
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/ConsoleImpl.cpp
r17553 r17651 189 189 , mSetVMErrorCallback (NULL), mConfigConstructor (NULL), mStartPaused (false) {} 190 190 191 ~VMPowerUpTask()192 {193 /* No null output parameters in IPC*/194 MediaState_T dummy;195 196 /* we may be holding important error info on the current thread;197 * preserve it */198 ErrorInfoKeeper eik;199 200 /* if the locked media list is not empty, treat as a failure and201 * unlock all */202 for (LockedMedia::const_iterator it = lockedMedia.begin();203 it != lockedMedia.end(); ++ it)204 {205 if (it->second)206 it->first->UnlockWrite (&dummy);207 else208 it->first->UnlockRead (&dummy);209 }210 }211 212 191 PFNVMATERROR mSetVMErrorCallback; 213 192 PFNCFGMCONSTRUCTOR mConfigConstructor; … … 216 195 bool mStartPaused; 217 196 218 /** 219 * Successfully locked media list. The 2nd value in the pair is true if the 220 * medium is locked for writing and false if locked for reading. 221 */ 222 typedef std::list <std::pair <ComPtr <IMedium>, bool > > LockedMedia; 223 LockedMedia lockedMedia; 224 225 /** Media that need an accessibility check */ 226 typedef std::list <ComPtr <IMedium> > Media; 227 Media mediaToCheck; 197 typedef std::list <ComPtr <IHardDisk> > HardDiskList; 198 HardDiskList hardDisks; 199 200 /* array of progress objects for hard disk reset operations */ 201 typedef std::list <ComPtr <IProgress> > ProgressList; 202 ProgressList hardDiskProgresses; 228 203 }; 229 204 … … 4382 4357 } 4383 4358 4384 /* create a n IProgress object to track progress of this operation */4385 ComObjPtr <Progress> p rogress;4386 p rogress.createObject();4359 /* create a progress object to track progress of this operation */ 4360 ComObjPtr <Progress> powerupProgress; 4361 powerupProgress.createObject(); 4387 4362 Bstr progressDesc; 4388 4363 if (mMachineState == MachineState_Saved) … … 4390 4365 else 4391 4366 progressDesc = tr ("Starting virtual machine"); 4392 rc = p rogress->init (static_cast <IConsole *> (this),4393 progressDesc, FALSE /* aCancelable */);4367 rc = powerupProgress->init (static_cast <IConsole *> (this), 4368 progressDesc, FALSE /* aCancelable */); 4394 4369 CheckComRCReturnRC (rc); 4395 4396 /* pass reference to caller if requested */4397 if (aProgress)4398 progress.queryInterfaceTo (aProgress);4399 4370 4400 4371 /* setup task object and thread to carry out the operation 4401 4372 * asynchronously */ 4402 4373 4403 std::auto_ptr <VMPowerUpTask> task (new VMPowerUpTask (this, p rogress));4374 std::auto_ptr <VMPowerUpTask> task (new VMPowerUpTask (this, powerupProgress)); 4404 4375 ComAssertComRCRetRC (task->rc()); 4405 4376 … … 4411 4382 task->mSavedStateFile = savedStateFile; 4412 4383 4413 /* Lock all attached media in necessary mode. Note that until 4414 * setMachineState() is called below, it is OUR responsibility to unlock 4415 * media on failure (and VMPowerUpTask::lockedMedia is used for that). After 4416 * the setMachineState() call, VBoxSVC (SessionMachine::setMachineState()) 4417 * will unlock all the media upon the appropriate state change. Note that 4418 * media accessibility checks are performed on the powerup thread because 4419 * they may block. */ 4420 4421 MediaState_T mediaState; 4422 4423 /* lock all hard disks for writing and their parents for reading */ 4384 /* Reset differencing hard disks for which autoReset is true */ 4424 4385 { 4425 4386 com::SafeIfaceArray <IHardDiskAttachment> atts; … … 4434 4395 CheckComRCReturnRC (rc); 4435 4396 4436 bool first = true; 4437 4438 while (!hardDisk.isNull()) 4397 /* save for later use on the powerup thread */ 4398 task->hardDisks.push_back (hardDisk); 4399 4400 /* needs autoreset? */ 4401 BOOL autoReset = FALSE; 4402 rc = hardDisk->COMGETTER(AutoReset)(&autoReset); 4403 CheckComRCReturnRC (rc); 4404 4405 if (autoReset) 4439 4406 { 4440 if (first) 4441 { 4442 rc = hardDisk->LockWrite (&mediaState); 4443 CheckComRCReturnRC (rc); 4444 4445 task->lockedMedia.push_back (VMPowerUpTask::LockedMedia:: 4446 value_type (hardDisk, true)); 4447 first = false; 4448 } 4449 else 4450 { 4451 rc = hardDisk->LockRead (&mediaState); 4452 CheckComRCReturnRC (rc); 4453 4454 task->lockedMedia.push_back (VMPowerUpTask::LockedMedia:: 4455 value_type (hardDisk, false)); 4456 } 4457 4458 if (mediaState == MediaState_Inaccessible) 4459 task->mediaToCheck.push_back (hardDisk); 4460 4461 ComPtr <IHardDisk> parent; 4462 rc = hardDisk->COMGETTER(Parent) (parent.asOutParam()); 4407 ComPtr <IProgress> resetProgress; 4408 rc = hardDisk->Reset (resetProgress.asOutParam()); 4463 4409 CheckComRCReturnRC (rc); 4464 hardDisk = parent; 4410 4411 /* save for later use on the powerup thread */ 4412 task->hardDiskProgresses.push_back (resetProgress); 4465 4413 } 4466 4414 } 4467 4415 } 4468 /* lock the DVD image for reading if mounted */4469 {4470 ComPtr <IDVDDrive> drive;4471 rc = mMachine->COMGETTER(DVDDrive) (drive.asOutParam());4472 CheckComRCReturnRC (rc);4473 4474 DriveState_T driveState;4475 rc = drive->COMGETTER(State) (&driveState);4476 CheckComRCReturnRC (rc);4477 4478 if (driveState == DriveState_ImageMounted)4479 {4480 ComPtr <IDVDImage> image;4481 rc = drive->GetImage (image.asOutParam());4482 CheckComRCReturnRC (rc);4483 4484 rc = image->LockRead (&mediaState);4485 CheckComRCReturnRC (rc);4486 4487 task->lockedMedia.push_back (VMPowerUpTask::LockedMedia::4488 value_type (image, false));4489 4490 if (mediaState == MediaState_Inaccessible)4491 task->mediaToCheck.push_back (image);4492 }4493 }4494 /* lock the floppy image for reading if mounted */4495 {4496 ComPtr <IFloppyDrive> drive;4497 rc = mMachine->COMGETTER(FloppyDrive) (drive.asOutParam());4498 CheckComRCReturnRC (rc);4499 4500 DriveState_T driveState;4501 rc = drive->COMGETTER(State) (&driveState);4502 CheckComRCReturnRC (rc);4503 4504 if (driveState == DriveState_ImageMounted)4505 {4506 ComPtr<IFloppyImage> image;4507 rc = drive->GetImage (image.asOutParam());4508 CheckComRCReturnRC (rc);4509 4510 rc = image->LockRead (&mediaState);4511 CheckComRCReturnRC (rc);4512 4513 task->lockedMedia.push_back (VMPowerUpTask::LockedMedia::4514 value_type (image, false));4515 4516 if (mediaState == MediaState_Inaccessible)4517 task->mediaToCheck.push_back (image);4518 }4519 }4520 /* SUCCEEDED locking all media */4521 4416 4522 4417 rc = consoleInitReleaseLog (mMachine); 4523 4418 CheckComRCReturnRC (rc); 4524 4419 4420 /* pass the progress object to the caller if requested */ 4421 if (aProgress) 4422 { 4423 if (task->hardDiskProgresses.size() == 0) 4424 { 4425 /* there are no other operations to track, return the powerup 4426 * progress only */ 4427 powerupProgress.queryInterfaceTo (aProgress); 4428 } 4429 else 4430 { 4431 /* create a combined progress object */ 4432 ComObjPtr <CombinedProgress> progress; 4433 progress.createObject(); 4434 VMPowerUpTask::ProgressList progresses (task->hardDiskProgresses); 4435 progresses.push_back (ComPtr <IProgress> (powerupProgress)); 4436 rc = progress->init (static_cast <IConsole *> (this), 4437 progressDesc, progresses.begin(), 4438 progresses.end()); 4439 AssertComRCReturnRC (rc); 4440 progress.queryInterfaceTo (aProgress); 4441 } 4442 } 4443 4525 4444 int vrc = RTThreadCreate (NULL, Console::powerUpThread, (void *) task.get(), 4526 4445 0, RTTHREADTYPE_MAIN_WORKER, 0, "VMPowerUp"); … … 4529 4448 E_FAIL); 4530 4449 4531 /* clear the locked media list to prevent unlocking on task destruction as4532 * we are not going to fail after this point */4533 task->lockedMedia.clear();4534 4535 4450 /* task is now owned by powerUpThread(), so release it */ 4536 4451 task.release(); 4537 4452 4538 /* finally, set the state: no right to fail in this method afterwards! */ 4453 /* finally, set the state: no right to fail in this method afterwards 4454 * since we've already started the thread and it is now responsible for 4455 * any error reporting and appropriate state change! */ 4539 4456 4540 4457 if (mMachineState == MachineState_Saved) … … 6334 6251 try 6335 6252 { 6336 { 6337 ErrorInfoKeeper eik (true /* aIsNull */); 6338 MultiResult mrc (S_OK); 6339 6340 /* perform a check of inaccessible media deferred in PowerUp() */ 6341 for (VMPowerUpTask::Media::const_iterator 6342 it = task->mediaToCheck.begin(); 6343 it != task->mediaToCheck.end(); ++ it) 6344 { 6345 MediaState_T mediaState; 6346 rc = (*it)->COMGETTER(State) (&mediaState); 6347 CheckComRCThrowRC (rc); 6348 6349 Assert (mediaState == MediaState_LockedRead || 6350 mediaState == MediaState_LockedWrite); 6351 6352 /* Note that we locked the medium already, so use the error 6353 * value to see if there was an accessibility failure */ 6354 6355 Bstr error; 6356 rc = (*it)->COMGETTER(LastAccessError) (error.asOutParam()); 6357 CheckComRCThrowRC (rc); 6358 6359 if (!error.isNull()) 6360 { 6361 Bstr loc; 6362 rc = (*it)->COMGETTER(Location) (loc.asOutParam()); 6363 CheckComRCThrowRC (rc); 6364 6365 /* collect multiple errors */ 6366 eik.restore(); 6367 6368 /* be in sync with MediumBase::setStateError() */ 6369 Assert (!error.isEmpty()); 6370 mrc = setError (E_FAIL, 6371 tr ("Medium '%ls' is not accessible. %ls"), 6372 loc.raw(), error.raw()); 6373 6374 eik.fetch(); 6375 } 6376 } 6377 6378 eik.restore(); 6379 CheckComRCThrowRC ((HRESULT) mrc); 6380 } 6253 /* wait for auto reset ops to complete so that we can successfully lock 6254 * the attached hard disks by calling LockMedia() below */ 6255 for (VMPowerUpTask::ProgressList::const_iterator 6256 it = task->hardDiskProgresses.begin(); 6257 it != task->hardDiskProgresses.end(); ++ it) 6258 { 6259 HRESULT rc2 = (*it)->WaitForCompletion (-1); 6260 AssertComRC (rc2); 6261 } 6262 6263 /* lock attached media. This method will also check their 6264 * accessibility. Note that the media will be unlocked automatically 6265 * by SessionMachine::setMachineState() when the VM is powered down. */ 6266 rc = console->mControl->LockMedia(); 6267 CheckComRCThrowRC (rc); 6381 6268 6382 6269 #ifdef VBOX_WITH_VRDP -
trunk/src/VBox/Main/MachineImpl.cpp
r17601 r17651 10368 10368 10369 10369 /** 10370 * Locks the attached media. 10371 * 10372 * All attached hard disks and DVD/floppy are locked for writing. Parents of 10373 * attached hard disks (if any) are locked for reading. 10374 * 10375 * This method also performs accessibility check of all media it locks: if some 10376 * media is inaccessible, the method will return a failure and a bunch of 10377 * extended error info objects per each inaccessible medium. 10378 * 10379 * Note that this method is atomic: if it returns a success, all media are 10380 * locked as described above; on failure no media is locked at all (all 10381 * succeeded individual locks will be undone). 10382 * 10383 * This method is intended to be called when the machine is in Starting or 10384 * Restoring state and asserts otherwise. 10385 * 10386 * The locks made by this method must be undone by calling #unlockMedia() when 10387 * no more needed. 10388 */ 10389 HRESULT SessionMachine::lockMedia() 10390 { 10391 AutoCaller autoCaller (this); 10392 AssertComRCReturn (autoCaller.rc(), autoCaller.rc()); 10393 10394 AutoWriteLock alock (this); 10395 10396 AssertReturn (mData->mMachineState == MachineState_Starting || 10397 mData->mMachineState == MachineState_Restoring, E_FAIL); 10398 10399 typedef std::list <ComPtr <IMedium> > MediaList; 10400 MediaList mediaToCheck; 10401 MediaState_T mediaState; 10402 10403 try 10404 { 10405 HRESULT rc = S_OK; 10406 10407 /* lock hard disks */ 10408 for (HDData::AttachmentList::const_iterator it = 10409 mHDData->mAttachments.begin(); 10410 it != mHDData->mAttachments.end(); ++ it) 10411 { 10412 ComObjPtr<HardDisk> hd = (*it)->hardDisk(); 10413 10414 bool first = true; 10415 10416 while (!hd.isNull()) 10417 { 10418 if (first) 10419 { 10420 rc = hd->LockWrite (&mediaState); 10421 CheckComRCThrowRC (rc); 10422 10423 mData->mSession.mLockedMedia.push_back ( 10424 Data::Session::LockedMedia::value_type ( 10425 ComPtr <IHardDisk> (hd), true)); 10426 10427 first = false; 10428 } 10429 else 10430 { 10431 rc = hd->LockRead (&mediaState); 10432 CheckComRCThrowRC (rc); 10433 10434 mData->mSession.mLockedMedia.push_back ( 10435 Data::Session::LockedMedia::value_type ( 10436 ComPtr <IHardDisk> (hd), false)); 10437 } 10438 10439 if (mediaState == MediaState_Inaccessible) 10440 mediaToCheck.push_back (ComPtr <IHardDisk> (hd)); 10441 10442 /* no locks or callers here since there should be no way to 10443 * change the hard disk parent at this point (as it is still 10444 * attached to the machine) */ 10445 hd = hd->parent(); 10446 } 10447 } 10448 10449 /* lock the DVD image for reading if mounted */ 10450 { 10451 AutoReadLock driveLock (mDVDDrive); 10452 if (mDVDDrive->data()->state == DriveState_ImageMounted) 10453 { 10454 ComObjPtr <DVDImage> image = mDVDDrive->data()->image; 10455 10456 rc = image->LockRead (&mediaState); 10457 CheckComRCThrowRC (rc); 10458 10459 mData->mSession.mLockedMedia.push_back ( 10460 Data::Session::LockedMedia::value_type ( 10461 ComPtr <IDVDImage> (image), false)); 10462 10463 if (mediaState == MediaState_Inaccessible) 10464 mediaToCheck.push_back (ComPtr <IDVDImage> (image)); 10465 } 10466 } 10467 10468 /* lock the floppy image for reading if mounted */ 10469 { 10470 AutoReadLock driveLock (mFloppyDrive); 10471 if (mFloppyDrive->data()->state == DriveState_ImageMounted) 10472 { 10473 ComObjPtr <FloppyImage> image = mFloppyDrive->data()->image; 10474 10475 rc = image->LockRead (&mediaState); 10476 CheckComRCThrowRC (rc); 10477 10478 mData->mSession.mLockedMedia.push_back ( 10479 Data::Session::LockedMedia::value_type ( 10480 ComPtr <IFloppyImage> (image), false)); 10481 10482 if (mediaState == MediaState_Inaccessible) 10483 mediaToCheck.push_back (ComPtr <IFloppyImage> (image)); 10484 } 10485 } 10486 10487 /* SUCCEEDED locking all media, now check accessibility */ 10488 10489 ErrorInfoKeeper eik (true /* aIsNull */); 10490 MultiResult mrc (S_OK); 10491 10492 /* perform a check of inaccessible media deferred above */ 10493 for (MediaList::const_iterator 10494 it = mediaToCheck.begin(); 10495 it != mediaToCheck.end(); ++ it) 10496 { 10497 MediaState_T mediaState; 10498 rc = (*it)->COMGETTER(State) (&mediaState); 10499 CheckComRCThrowRC (rc); 10500 10501 Assert (mediaState == MediaState_LockedRead || 10502 mediaState == MediaState_LockedWrite); 10503 10504 /* Note that we locked the medium already, so use the error 10505 * value to see if there was an accessibility failure */ 10506 10507 Bstr error; 10508 rc = (*it)->COMGETTER(LastAccessError) (error.asOutParam()); 10509 CheckComRCThrowRC (rc); 10510 10511 if (!error.isNull()) 10512 { 10513 Bstr loc; 10514 rc = (*it)->COMGETTER(Location) (loc.asOutParam()); 10515 CheckComRCThrowRC (rc); 10516 10517 /* collect multiple errors */ 10518 eik.restore(); 10519 10520 /* be in sync with MediumBase::setStateError() */ 10521 Assert (!error.isEmpty()); 10522 mrc = setError (E_FAIL, 10523 tr ("Medium '%ls' is not accessible. %ls"), 10524 loc.raw(), error.raw()); 10525 10526 eik.fetch(); 10527 } 10528 } 10529 10530 eik.restore(); 10531 CheckComRCThrowRC ((HRESULT) mrc); 10532 } 10533 catch (HRESULT aRC) 10534 { 10535 /* Unlock all locked media on failure */ 10536 unlockMedia(); 10537 return aRC; 10538 } 10539 10540 return S_OK; 10541 } 10542 10543 /** 10544 * Undoes the locks made by by #lockMedia(). 10545 */ 10546 void SessionMachine::unlockMedia() 10547 { 10548 AutoCaller autoCaller (this); 10549 AssertComRCReturnVoid (autoCaller.rc()); 10550 10551 AutoWriteLock alock (this); 10552 10553 /* we may be holding important error info on the current thread; 10554 * preserve it */ 10555 ErrorInfoKeeper eik; 10556 10557 HRESULT rc = S_OK; 10558 10559 for (Data::Session::LockedMedia::const_iterator 10560 it = mData->mSession.mLockedMedia.begin(); 10561 it != mData->mSession.mLockedMedia.end(); ++ it) 10562 { 10563 if (it->second) 10564 rc = it->first->UnlockWrite (NULL); 10565 else 10566 rc = it->first->UnlockRead (NULL); 10567 10568 AssertComRC (rc); 10569 } 10570 10571 mData->mSession.mLockedMedia.clear(); 10572 } 10573 10574 /** 10370 10575 * Helper to change the machine state (reimplementation). 10371 10576 * … … 10417 10622 mSnapshotData.mLastState >= MachineState_Running)) 10418 10623 { 10419 /* The EMT thread has just stopped, unlock attached media. Note that 10420 * opposed to locking, we do unlocking here because the VM process may 10421 * have just aborted before properly unlocking all media it locked. */ 10422 10423 for (HDData::AttachmentList::const_iterator it = 10424 mHDData->mAttachments.begin(); 10425 it != mHDData->mAttachments.end(); ++ it) 10426 { 10427 ComObjPtr<HardDisk> hd = (*it)->hardDisk(); 10428 10429 bool first = true; 10430 10431 while (!hd.isNull()) 10432 { 10433 if (first) 10434 { 10435 rc = hd->UnlockWrite (NULL); 10436 AssertComRC (rc); 10437 10438 first = false; 10439 } 10440 else 10441 { 10442 rc = hd->UnlockRead (NULL); 10443 AssertComRC (rc); 10444 } 10445 10446 /* no locks or callers here since there should be no way to 10447 * change the hard disk parent at this point (as it is still 10448 * attached to the machine) */ 10449 hd = hd->parent(); 10450 } 10451 } 10452 { 10453 AutoReadLock driveLock (mDVDDrive); 10454 if (mDVDDrive->data()->state == DriveState_ImageMounted) 10455 { 10456 rc = mDVDDrive->data()->image->UnlockRead (NULL); 10457 AssertComRC (rc); 10458 } 10459 } 10460 { 10461 AutoReadLock driveLock (mFloppyDrive); 10462 if (mFloppyDrive->data()->state == DriveState_ImageMounted) 10463 { 10464 rc = mFloppyDrive->data()->image->UnlockRead (NULL); 10465 AssertComRC (rc); 10466 } 10467 } 10624 /* The EMT thread has just stopped, unlock attached media. Note that as 10625 * opposed to locking that is done from Console, we do unlocking here 10626 * because the VM process may have aborted before having a chance to 10627 * properly unlock all media it locked. */ 10628 10629 unlockMedia(); 10468 10630 } 10469 10631 -
trunk/src/VBox/Main/idl/VirtualBox.xidl
r17648 r17651 3261 3261 <interface 3262 3262 name="IInternalMachineControl" extends="$unknown" 3263 uuid=" 4042ddf2-93d3-4749-8517-dde3f17ea630"3263 uuid="2c88b969-7a74-4ef3-b95f-8a209a1535f3" 3264 3264 internal="yes" 3265 3265 wsmap="suppress" … … 3612 3612 </desc> 3613 3613 </param> 3614 </method> 3615 3616 <method name="lockMedia"> 3617 <desc> 3618 Locks all media attached to the machine for writing and parents of 3619 attahced different hard disks (if any) for reading. This operation is 3620 atomic so that if it fails no media is actually locked. 3621 3622 This method is intended to be called when the machine is in Starting or 3623 Restoring state. The locked media will be automatically unlocked when 3624 the machine is powered off or crashed. 3625 </desc> 3614 3626 </method> 3615 3627 </interface> -
trunk/src/VBox/Main/include/MachineImpl.h
r17287 r17651 90 90 91 91 /** 92 * 93 * 94 * Only one instance of this data exists per every machine --95 * it is shared by the Machine, SessionMachine and all SnapshotMachine96 * instances associated with the given machine using the util::Shareable97 * templatethrough the mData variable.98 * 99 * 100 * 101 * 102 * 103 * 92 * Internal machine data. 93 * 94 * Only one instance of this data exists per every machine -- it is shared 95 * by the Machine, SessionMachine and all SnapshotMachine instances 96 * associated with the given machine using the util::Shareable template 97 * through the mData variable. 98 * 99 * @note |const| members are persistent during lifetime so can be 100 * accessed without locking. 101 * 102 * @note There is no need to lock anything inside init() or uninit() 103 * methods, because they are always serialized (see AutoCaller). 104 104 */ 105 105 struct Data 106 106 { 107 107 /** 108 * 109 * 108 * Data structure to hold information about sessions opened for the 109 * given machine. 110 110 */ 111 111 struct Session … … 123 123 124 124 /** 125 * PID of the session object that must be passed to openSession()126 * to finalize the openRemoteSession() request127 * (i.e., PID of theprocess created by openRemoteSession())125 * PID of the session object that must be passed to openSession() to 126 * finalize the openRemoteSession() request (i.e., PID of the 127 * process created by openRemoteSession()) 128 128 */ 129 129 RTPROCESS mPid; … … 137 137 /** Session machine object */ 138 138 ComObjPtr <SessionMachine> mMachine; 139 140 /** 141 * Successfully locked media list. The 2nd value in the pair is true 142 * if the medium is locked for writing and false if locked for 143 * reading. 144 */ 145 typedef std::list <std::pair <ComPtr <IMedium>, bool > > LockedMedia; 146 LockedMedia mLockedMedia; 139 147 }; 140 148 … … 904 912 STDMETHOD(PushGuestProperty) (IN_BSTR aName, IN_BSTR aValue, 905 913 ULONG64 aTimestamp, IN_BSTR aFlags); 914 STDMETHOD(LockMedia)() { return lockMedia(); } 906 915 907 916 // public methods only for internal purposes … … 967 976 void discardSnapshotHandler (DiscardSnapshotTask &aTask); 968 977 void discardCurrentStateHandler (DiscardCurrentStateTask &aTask); 978 979 HRESULT lockMedia(); 980 void unlockMedia(); 969 981 970 982 HRESULT setMachineState (MachineState_T aMachineState);
Note:
See TracChangeset
for help on using the changeset viewer.