Changeset 52324 in vbox
- Timestamp:
- Aug 8, 2014 12:41:32 PM (10 years ago)
- Location:
- trunk/src/VBox/Main
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/idl/VirtualBox.xidl
r52319 r52324 13867 13867 </attribute> 13868 13868 13869 <method name="setIds" >13869 <method name="setIds" wrap-hint-server="passcaller"> 13870 13870 <desc> 13871 13871 Changes the UUID and parent UUID for a hard disk medium. … … 13903 13903 </method> 13904 13904 13905 <method name="refreshState" >13905 <method name="refreshState" wrap-hint-server="passcaller"> 13906 13906 <desc> 13907 13907 If the current medium state (see <link to="MediumState"/>) is one of -
trunk/src/VBox/Main/include/MediumImpl.h
r52096 r52324 230 230 231 231 // wrapped IMedium methods 232 HRESULT setIds(BOOL aSetImageId, 232 HRESULT setIds(AutoCaller &aAutoCaller, 233 BOOL aSetImageId, 233 234 const com::Guid &aImageId, 234 235 BOOL aSetParentId, 235 236 const com::Guid &aParentId); 236 HRESULT refreshState(MediumState_T *aState); 237 HRESULT refreshState(AutoCaller &aAutoCaller, 238 MediumState_T *aState); 237 239 HRESULT getSnapshotIds(const com::Guid &aMachineId, 238 240 std::vector<com::Guid> &aSnapshotIds); … … 273 275 274 276 // Private internal nmethods 275 HRESULT i_queryInfo(bool fSetImageId, bool fSetParentId );277 HRESULT i_queryInfo(bool fSetImageId, bool fSetParentId, AutoCaller &autoCaller); 276 278 HRESULT i_canClose(); 277 279 HRESULT i_unregisterWithVirtualBox(); -
trunk/src/VBox/Main/src-server/MediumImpl.cpp
r52168 r52324 131 131 132 132 /** Special synchronization for operations which must wait for 133 * Medium:: queryInfo in another thread to complete. Using a SemRW is133 * Medium::i_queryInfo in another thread to complete. Using a SemRW is 134 134 * not quite ideal, but at least it is subject to the lock validator, 135 135 * unlike the SemEventMulti which we had here for many years. Catching … … 149 149 bool autoReset : 1; 150 150 151 /** New UUID to be set on the next Medium:: queryInfo call. */151 /** New UUID to be set on the next Medium::i_queryInfo call. */ 152 152 const Guid uuidImage; 153 /** New parent UUID to be set on the next Medium:: queryInfo call. */153 /** New parent UUID to be set on the next Medium::i_queryInfo call. */ 154 154 const Guid uuidParentImage; 155 155 … … 926 926 m->hostDrive = false; 927 927 928 /* No storage unit is created yet, no need to call Medium:: queryInfo */928 /* No storage unit is created yet, no need to call Medium::i_queryInfo */ 929 929 930 930 rc = i_setFormat(aFormat); … … 1051 1051 m->strLastAccessError = tr("Accessibility check was not yet performed"); 1052 1052 1053 /* Confirm a successful initialization before the call to queryInfo.1053 /* Confirm a successful initialization before the call to i_queryInfo. 1054 1054 * Otherwise we can end up with a AutoCaller deadlock because the 1055 1055 * medium becomes visible but is not marked as initialized. Causes … … 1064 1064 return autoCaller.rc(); 1065 1065 1066 /* need to call queryInfo immediately to correctly place the medium in1066 /* need to call i_queryInfo immediately to correctly place the medium in 1067 1067 * the respective media tree and update other information such as uuid */ 1068 rc = i_queryInfo(fForceNewUuid /* fSetImageId */, false /* fSetParentId */); 1068 rc = i_queryInfo(fForceNewUuid /* fSetImageId */, false /* fSetParentId */, 1069 autoCaller); 1069 1070 if (SUCCEEDED(rc)) 1070 1071 { … … 1086 1087 alock.release(); autoCaller.release(); uninit(); return E_FAIL); 1087 1088 1088 /* storage format must be detected by Medium:: queryInfo if the1089 /* storage format must be detected by Medium::i_queryInfo if the 1089 1090 * medium is accessible */ 1090 1091 AssertStmt(!m->strFormat.isEmpty(), … … 1153 1154 } 1154 1155 1155 /* see below why we don't call Medium:: queryInfo (and therefore treat1156 /* see below why we don't call Medium::i_queryInfo (and therefore treat 1156 1157 * the medium as inaccessible for now */ 1157 1158 m->state = MediumState_Inaccessible; … … 1260 1261 m->strLocationFull.c_str(), m->strFormat.c_str(), m->id.raw())); 1261 1262 1262 /* Don't call Medium:: queryInfo for registered media to prevent the calling1263 /* Don't call Medium::i_queryInfo for registered media to prevent the calling 1263 1264 * thread (i.e. the VirtualBox server startup thread) from an unexpected 1264 1265 * freeze but mark it as initially inaccessible instead. The vital UUID, … … 1855 1856 } 1856 1857 1857 HRESULT Medium::setIds(BOOL aSetImageId, 1858 HRESULT Medium::setIds(AutoCaller &autoCaller, 1859 BOOL aSetImageId, 1858 1860 const com::Guid &aImageId, 1859 1861 BOOL aSetParentId, … … 1893 1895 unconst(m->uuidParentImage) = parentId; 1894 1896 1895 // must not hold any locks before calling Medium:: queryInfo1897 // must not hold any locks before calling Medium::i_queryInfo 1896 1898 alock.release(); 1897 1899 1898 1900 HRESULT rc = i_queryInfo(!!aSetImageId /* fSetImageId */, 1899 !!aSetParentId /* fSetParentId */); 1901 !!aSetParentId /* fSetParentId */, 1902 autoCaller); 1900 1903 1901 1904 return rc; 1902 1905 } 1903 1906 1904 HRESULT Medium::refreshState( MediumState_T *aState)1907 HRESULT Medium::refreshState(AutoCaller &autoCaller, MediumState_T *aState) 1905 1908 { 1906 1909 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); … … 1914 1917 case MediumState_LockedRead: 1915 1918 { 1916 // must not hold any locks before calling Medium:: queryInfo1919 // must not hold any locks before calling Medium::i_queryInfo 1917 1920 alock.release(); 1918 1921 1919 rc = i_queryInfo(false /* fSetImageId */, false /* fSetParentId */); 1922 rc = i_queryInfo(false /* fSetImageId */, false /* fSetParentId */, 1923 autoCaller); 1920 1924 1921 1925 alock.acquire(); … … 1969 1973 HRESULT Medium::lockRead(ComPtr<IToken> &aToken) 1970 1974 { 1971 /* Must not hold the object lock, as we need control over it below. */1972 Assert(!isWriteLockOnCurrentThread());1973 1975 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 1974 1976 1975 /* Wait for a concurrently running Medium:: queryInfo to complete. */1977 /* Wait for a concurrently running Medium::i_queryInfo to complete. */ 1976 1978 if (m->queryInfoRunning) 1977 1979 { 1978 /* Must not hold the media tree lock, as Medium:: queryInfo needs this1980 /* Must not hold the media tree lock, as Medium::i_queryInfo needs this 1979 1981 * lock and thus we would run into a deadlock here. */ 1980 1982 Assert(!m->pVirtualBox->i_getMediaTreeLockHandle().isWriteLockOnCurrentThread()); … … 1982 1984 { 1983 1985 alock.release(); 1986 /* must not hold the object lock now */ 1987 Assert(!isWriteLockOnCurrentThread()); 1984 1988 { 1985 1989 AutoReadLock qlock(m->queryInfoSem COMMA_LOCKVAL_SRC_POS); … … 2086 2090 HRESULT Medium::lockWrite(ComPtr<IToken> &aToken) 2087 2091 { 2088 /* Must not hold the object lock, as we need control over it below. */2089 Assert(!isWriteLockOnCurrentThread());2090 2092 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 2091 2093 2092 /* Wait for a concurrently running Medium:: queryInfo to complete. */2094 /* Wait for a concurrently running Medium::i_queryInfo to complete. */ 2093 2095 if (m->queryInfoRunning) 2094 2096 { 2095 /* Must not hold the media tree lock, as Medium:: queryInfo needs this2097 /* Must not hold the media tree lock, as Medium::i_queryInfo needs this 2096 2098 * lock and thus we would run into a deadlock here. */ 2097 2099 Assert(!m->pVirtualBox->i_getMediaTreeLockHandle().isWriteLockOnCurrentThread()); … … 2099 2101 { 2100 2102 alock.release(); 2103 /* must not hold the object lock now */ 2104 Assert(!isWriteLockOnCurrentThread()); 2101 2105 { 2102 2106 AutoReadLock qlock(m->queryInfoSem COMMA_LOCKVAL_SRC_POS); … … 3794 3798 { 3795 3799 alock.release(); 3796 rc = pMedium->i_queryInfo(false /* fSetImageId */, false /* fSetParentId */); 3800 rc = pMedium->i_queryInfo(false /* fSetImageId */, false /* fSetParentId */, 3801 autoCaller); 3797 3802 alock.acquire(); 3798 3803 if (FAILED(rc)) return rc; … … 5411 5416 * @return 5412 5417 */ 5413 HRESULT Medium::i_queryInfo(bool fSetImageId, bool fSetParentId )5418 HRESULT Medium::i_queryInfo(bool fSetImageId, bool fSetParentId, AutoCaller &autoCaller) 5414 5419 { 5415 5420 Assert(!isWriteLockOnCurrentThread()); … … 5425 5430 int vrc = VINF_SUCCESS; 5426 5431 5427 /* check if a blocking queryInfo() call is in progress on some other thread,5432 /* check if a blocking i_queryInfo() call is in progress on some other thread, 5428 5433 * and wait for it to finish if so instead of querying data ourselves */ 5429 5434 if (m->queryInfoRunning) … … 5435 5440 { 5436 5441 alock.release(); 5442 /* must not hold the object lock now */ 5443 Assert(!isWriteLockOnCurrentThread()); 5437 5444 { 5438 5445 AutoReadLock qlock(m->queryInfoSem COMMA_LOCKVAL_SRC_POS); … … 5467 5474 uOpenFlags |= VD_OPEN_FLAGS_SHAREABLE; 5468 5475 5469 /* Lock the medium, which makes the behavior much more consistent */5470 alock.release();5476 /* Lock the medium, which makes the behavior much more consistent, must be 5477 * done before dropping the object lock and setting queryInfoRunning. */ 5471 5478 ComPtr<IToken> pToken; 5472 5479 if (uOpenFlags & (VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_SHAREABLE)) … … 5475 5482 rc = LockWrite(pToken.asOutParam()); 5476 5483 if (FAILED(rc)) return rc; 5477 alock.acquire();5478 5484 5479 5485 /* Copies of the input state fields which are not read-only, … … 5495 5501 bool fRepairImageZeroParentUuid = false; 5496 5502 5497 /* release the object lock before a lengthy operation, and take the 5498 * opportunity to have a media tree lock, too, which isn't held initially */ 5503 ComObjPtr<VirtualBox> pVirtualBox = m->pVirtualBox; 5504 5505 /* must be set before leaving the object lock the first time */ 5499 5506 m->queryInfoRunning = true; 5507 5508 /* must leave object lock now, because a lock from a higher lock class 5509 * is needed and also a lengthy operation is coming */ 5500 5510 alock.release(); 5501 Assert(!isWriteLockOnCurrentThread()); 5502 Assert(!m->pVirtualBox->i_getMediaTreeLockHandle().isWriteLockOnCurrentThread()); 5503 AutoWriteLock treeLock(m->pVirtualBox->i_getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS); 5504 treeLock.release(); 5511 autoCaller.release(); 5505 5512 5506 5513 /* Note that taking the queryInfoSem after leaving the object lock above 5507 * can lead to short spinning of the loops waiting for queryInfo() to5514 * can lead to short spinning of the loops waiting for i_queryInfo() to 5508 5515 * complete. This is unavoidable since the other order causes a lock order 5509 5516 * violation: here it would be requesting the object lock (at the beginning 5510 5517 * of the method), then queryInfoSem, and below the other way round. */ 5511 5518 AutoWriteLock qlock(m->queryInfoSem COMMA_LOCKVAL_SRC_POS); 5519 5520 /* take the opportunity to have a media tree lock, released initially */ 5521 Assert(!isWriteLockOnCurrentThread()); 5522 Assert(!pVirtualBox->i_getMediaTreeLockHandle().isWriteLockOnCurrentThread()); 5523 AutoWriteLock treeLock(pVirtualBox->i_getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS); 5524 treeLock.release(); 5525 5526 /* re-take the caller, but not the object lock, to keep uninit away */ 5527 autoCaller.add(); 5528 if (FAILED(autoCaller.rc())) 5529 { 5530 m->queryInfoRunning = false; 5531 return autoCaller.rc(); 5532 } 5512 5533 5513 5534 try … … 5601 5622 location.c_str(), 5602 5623 mediumId.raw(), 5603 m->pVirtualBox->i_settingsFilePath().c_str());5624 pVirtualBox->i_settingsFilePath().c_str()); 5604 5625 throw S_OK; 5605 5626 } … … 5667 5688 rc = VBOX_E_OBJECT_NOT_FOUND; 5668 5689 else 5669 rc = m->pVirtualBox->i_findHardDiskById(Guid(parentId), false /* aSetError */, &pParent);5690 rc = pVirtualBox->i_findHardDiskById(Guid(parentId), false /* aSetError */, &pParent); 5670 5691 if (FAILED(rc)) 5671 5692 { … … 5689 5710 lastAccessError = Utf8StrFmt(tr("Parent medium with UUID {%RTuuid} of the medium '%s' is not found in the media registry ('%s')"), 5690 5711 &parentId, location.c_str(), 5691 m->pVirtualBox->i_settingsFilePath().c_str());5712 pVirtualBox->i_settingsFilePath().c_str()); 5692 5713 throw S_OK; 5693 5714 } 5694 5715 } 5695 5716 5717 /* must drop the caller before taking the tree lock */ 5718 autoCaller.release(); 5696 5719 /* we set mParent & children() */ 5697 5720 treeLock.acquire(); 5721 autoCaller.add(); 5722 if (FAILED(autoCaller.rc())) 5723 throw autoCaller.rc(); 5698 5724 5699 5725 if (m->pParent) … … 5705 5731 else 5706 5732 { 5733 /* must drop the caller before taking the tree lock */ 5734 autoCaller.release(); 5707 5735 /* we access mParent */ 5708 5736 treeLock.acquire(); 5737 autoCaller.add(); 5738 if (FAILED(autoCaller.rc())) 5739 throw autoCaller.rc(); 5709 5740 5710 5741 /* check that parent UUIDs match. Note that there's no need … … 5728 5759 tr("Medium type of '%s' is differencing but it is not associated with any parent medium in the media registry ('%s')"), 5729 5760 location.c_str(), 5730 m->pVirtualBox->settingsFilePath().c_str());5761 pVirtualBox->settingsFilePath().c_str()); 5731 5762 treeLock.release(); 5732 5763 throw S_OK; … … 5735 5766 5736 5767 { 5768 autoCaller.release(); 5737 5769 AutoReadLock parentLock(m->pParent COMMA_LOCKVAL_SRC_POS); 5770 autoCaller.add(); 5771 if (FAILED(autoCaller.rc())) 5772 throw autoCaller.rc(); 5773 5738 5774 if ( !fRepairImageZeroParentUuid 5739 5775 && m->pParent->i_getState() != MediumState_Inaccessible … … 5745 5781 &parentId, location.c_str(), 5746 5782 m->pParent->i_getId().raw(), 5747 m->pVirtualBox->i_settingsFilePath().c_str());5783 pVirtualBox->i_settingsFilePath().c_str()); 5748 5784 parentLock.release(); 5749 5785 treeLock.release(); … … 5784 5820 } 5785 5821 5822 autoCaller.release(); 5786 5823 treeLock.acquire(); 5824 autoCaller.add(); 5825 if (FAILED(autoCaller.rc())) 5826 { 5827 m->queryInfoRunning = false; 5828 return autoCaller.rc(); 5829 } 5787 5830 alock.acquire(); 5788 5831 … … 5800 5843 rc, vrc)); 5801 5844 } 5802 5803 /* unblock anyone waiting for the queryInfo results */5804 qlock.release();5805 m->queryInfoRunning = false;5806 5845 5807 5846 /* Set the proper state according to the result of the check */ … … 5810 5849 else 5811 5850 m->preLockState = MediumState_Inaccessible; 5851 5852 /* unblock anyone waiting for the i_queryInfo results */ 5853 qlock.release(); 5854 m->queryInfoRunning = false; 5812 5855 5813 5856 pToken->Abandon();
Note:
See TracChangeset
for help on using the changeset viewer.