Changeset 17651 in vbox for trunk/src/VBox/Main/MachineImpl.cpp
- Timestamp:
- Mar 10, 2009 10:27:08 PM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
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
Note:
See TracChangeset
for help on using the changeset viewer.