Changeset 40466 in vbox for trunk/src/VBox
- Timestamp:
- Mar 14, 2012 2:34:15 PM (13 years ago)
- svn:sync-xref-src-repo-rev:
- 76832
- Location:
- trunk/src/VBox/Main
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/include/MediumImpl.h
r40432 r40466 265 265 266 266 HRESULT queryInfo(bool fSetImageId, bool fSetParentId); 267 HRESULT lockRead(MediumState_T *aState, bool fWithinQueryInfo);268 HRESULT lockWrite(MediumState_T *aState, bool fWithinQueryInfo);269 267 270 268 HRESULT canClose(); -
trunk/src/VBox/Main/src-server/MediumImpl.cpp
r40432 r40466 2080 2080 if (FAILED(autoCaller.rc())) return autoCaller.rc(); 2081 2081 2082 return lockRead(aState, false /* fWithinQueryInfo */); 2082 /* Must not hold the object lock, as we need control over it below. */ 2083 Assert(!isWriteLockOnCurrentThread()); 2084 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 2085 2086 /* Wait for a concurrently running Medium::queryInfo to complete. */ 2087 if (m->queryInfoRunning) 2088 { 2089 /* Must not hold the media tree lock, as Medium::queryInfo needs this 2090 * lock and thus we would run into a deadlock here. */ 2091 Assert(!m->pVirtualBox->getMediaTreeLockHandle().isWriteLockOnCurrentThread()); 2092 while (m->queryInfoRunning) 2093 { 2094 alock.release(); 2095 { 2096 AutoReadLock qlock(m->queryInfoSem COMMA_LOCKVAL_SRC_POS); 2097 } 2098 alock.acquire(); 2099 } 2100 } 2101 2102 /* return the current state before */ 2103 if (aState) 2104 *aState = m->state; 2105 2106 HRESULT rc = S_OK; 2107 2108 switch (m->state) 2109 { 2110 case MediumState_Created: 2111 case MediumState_Inaccessible: 2112 case MediumState_LockedRead: 2113 { 2114 ++m->readers; 2115 2116 ComAssertMsgBreak(m->readers != 0, ("Counter overflow"), rc = E_FAIL); 2117 2118 /* Remember pre-lock state */ 2119 if (m->state != MediumState_LockedRead) 2120 m->preLockState = m->state; 2121 2122 LogFlowThisFunc(("Okay - prev state=%d readers=%d\n", m->state, m->readers)); 2123 m->state = MediumState_LockedRead; 2124 2125 break; 2126 } 2127 default: 2128 { 2129 LogFlowThisFunc(("Failing - state=%d\n", m->state)); 2130 rc = setStateError(); 2131 break; 2132 } 2133 } 2134 2135 return rc; 2083 2136 } 2084 2137 … … 2143 2196 if (FAILED(autoCaller.rc())) return autoCaller.rc(); 2144 2197 2145 return lockWrite(aState, false /* fWithinQueryInfo */); 2198 /* Must not hold the object lock, as we need control over it below. */ 2199 Assert(!isWriteLockOnCurrentThread()); 2200 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 2201 2202 /* Wait for a concurrently running Medium::queryInfo to complete. */ 2203 if (m->queryInfoRunning) 2204 { 2205 /* Must not hold the media tree lock, as Medium::queryInfo needs this 2206 * lock and thus we would run into a deadlock here. */ 2207 Assert(!m->pVirtualBox->getMediaTreeLockHandle().isWriteLockOnCurrentThread()); 2208 while (m->queryInfoRunning) 2209 { 2210 alock.release(); 2211 { 2212 AutoReadLock qlock(m->queryInfoSem COMMA_LOCKVAL_SRC_POS); 2213 } 2214 alock.acquire(); 2215 } 2216 } 2217 2218 /* return the current state before */ 2219 if (aState) 2220 *aState = m->state; 2221 2222 HRESULT rc = S_OK; 2223 2224 switch (m->state) 2225 { 2226 case MediumState_Created: 2227 case MediumState_Inaccessible: 2228 { 2229 m->preLockState = m->state; 2230 2231 LogFlowThisFunc(("Okay - prev state=%d locationFull=%s\n", m->state, getLocationFull().c_str())); 2232 m->state = MediumState_LockedWrite; 2233 break; 2234 } 2235 default: 2236 { 2237 LogFlowThisFunc(("Failing - state=%d locationFull=%s\n", m->state, getLocationFull().c_str())); 2238 rc = setStateError(); 2239 break; 2240 } 2241 } 2242 2243 return rc; 2146 2244 } 2147 2245 … … 5188 5286 5189 5287 /** 5190 * @note @a aState may be NULL if the state value is not needed (only for 5191 * in-process calls). 5192 */ 5193 HRESULT Medium::lockRead(MediumState_T *aState, bool fWithinQueryInfo) 5194 { 5195 /* Must not hold the object lock, as we need control over it below. */ 5288 * Queries information from the medium. 5289 * 5290 * As a result of this call, the accessibility state and data members such as 5291 * size and description will be updated with the current information. 5292 * 5293 * @note This method may block during a system I/O call that checks storage 5294 * accessibility. 5295 * 5296 * @note Caller MUST NOT hold the media tree or medium lock. 5297 * 5298 * @note Locks mParent for reading. Locks this object for writing. 5299 * 5300 * @param fSetImageId Whether to reset the UUID contained in the image file to the UUID in the medium instance data (see SetIDs()) 5301 * @param fSetParentId Whether to reset the parent UUID contained in the image file to the parent UUID in the medium instance data (see SetIDs()) 5302 * @return 5303 */ 5304 HRESULT Medium::queryInfo(bool fSetImageId, bool fSetParentId) 5305 { 5196 5306 Assert(!isWriteLockOnCurrentThread()); 5197 5307 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 5198 5308 5199 /* Wait for a concurrently running Medium::queryInfo to complete. */ 5309 if ( m->state != MediumState_Created 5310 && m->state != MediumState_Inaccessible 5311 && m->state != MediumState_LockedRead) 5312 return E_FAIL; 5313 5314 HRESULT rc = S_OK; 5315 5316 int vrc = VINF_SUCCESS; 5317 5318 /* check if a blocking queryInfo() call is in progress on some other thread, 5319 * and wait for it to finish if so instead of querying data ourselves */ 5200 5320 if (m->queryInfoRunning) 5201 5321 { 5202 /* Must not hold the media tree lock, as Medium::queryInfo needs this 5203 * lock and thus we would run into a deadlock here. */ 5204 if (!fWithinQueryInfo) 5205 Assert(!m->pVirtualBox->getMediaTreeLockHandle().isWriteLockOnCurrentThread()); 5322 Assert( m->state == MediumState_LockedRead 5323 || m->state == MediumState_LockedWrite); 5324 5206 5325 while (m->queryInfoRunning) 5207 5326 { … … 5212 5331 alock.acquire(); 5213 5332 } 5214 }5215 5216 /* return the current state before */5217 if (aState)5218 *aState = m->state;5219 5220 HRESULT rc = S_OK;5221 5222 switch (m->state)5223 {5224 case MediumState_Created:5225 case MediumState_Inaccessible:5226 case MediumState_LockedRead:5227 {5228 ++m->readers;5229 5230 ComAssertMsgBreak(m->readers != 0, ("Counter overflow"), rc = E_FAIL);5231 5232 /* Remember pre-lock state */5233 if (m->state != MediumState_LockedRead)5234 m->preLockState = m->state;5235 5236 LogFlowThisFunc(("Okay - prev state=%d readers=%d\n", m->state, m->readers));5237 m->state = MediumState_LockedRead;5238 5239 break;5240 }5241 default:5242 {5243 LogFlowThisFunc(("Failing - state=%d\n", m->state));5244 rc = setStateError();5245 break;5246 }5247 }5248 5249 return rc;5250 }5251 5252 /**5253 * @note @a aState may be NULL if the state value is not needed (only for5254 * in-process calls).5255 */5256 HRESULT Medium::lockWrite(MediumState_T *aState, bool fWithinQueryInfo)5257 {5258 /* Must not hold the object lock, as we need control over it below. */5259 Assert(!isWriteLockOnCurrentThread());5260 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);5261 5262 /* Wait for a concurrently running Medium::queryInfo to complete. */5263 if (m->queryInfoRunning)5264 {5265 /* Must not hold the media tree lock, as Medium::queryInfo needs this5266 * lock and thus we would run into a deadlock here. */5267 if (!fWithinQueryInfo)5268 Assert(!m->pVirtualBox->getMediaTreeLockHandle().isWriteLockOnCurrentThread());5269 while (m->queryInfoRunning)5270 {5271 alock.release();5272 {5273 AutoReadLock qlock(m->queryInfoSem COMMA_LOCKVAL_SRC_POS);5274 }5275 alock.acquire();5276 }5277 }5278 5279 /* return the current state before */5280 if (aState)5281 *aState = m->state;5282 5283 HRESULT rc = S_OK;5284 5285 switch (m->state)5286 {5287 case MediumState_Created:5288 case MediumState_Inaccessible:5289 {5290 m->preLockState = m->state;5291 5292 LogFlowThisFunc(("Okay - prev state=%d locationFull=%s\n", m->state, getLocationFull().c_str()));5293 m->state = MediumState_LockedWrite;5294 break;5295 }5296 default:5297 {5298 LogFlowThisFunc(("Failing - state=%d locationFull=%s\n", m->state, getLocationFull().c_str()));5299 rc = setStateError();5300 break;5301 }5302 }5303 5304 return rc;5305 }5306 5307 /**5308 * Queries information from the medium.5309 *5310 * As a result of this call, the accessibility state and data members such as5311 * size and description will be updated with the current information.5312 *5313 * @note This method may block during a system I/O call that checks storage5314 * accessibility.5315 *5316 * @note Caller MUST NOT hold the media tree or medium lock.5317 *5318 * @note Locks mParent for reading. Locks this object for writing.5319 *5320 * @param fSetImageId Whether to reset the UUID contained in the image file to the UUID in the medium instance data (see SetIDs())5321 * @param fSetParentId Whether to reset the parent UUID contained in the image file to the parent UUID in the medium instance data (see SetIDs())5322 * @return5323 */5324 HRESULT Medium::queryInfo(bool fSetImageId, bool fSetParentId)5325 {5326 Assert(!isWriteLockOnCurrentThread());5327 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);5328 5329 if ( m->state != MediumState_Created5330 && m->state != MediumState_Inaccessible5331 && m->state != MediumState_LockedRead)5332 return E_FAIL;5333 5334 HRESULT rc = S_OK;5335 5336 int vrc = VINF_SUCCESS;5337 5338 /* check if a blocking queryInfo() call is in progress on some other thread,5339 * and wait for it to finish if so instead of querying data ourselves */5340 if (m->queryInfoRunning)5341 {5342 Assert( m->state == MediumState_LockedRead5343 || m->state == MediumState_LockedWrite);5344 5345 while (m->queryInfoRunning)5346 {5347 alock.release();5348 {5349 AutoReadLock qlock(m->queryInfoSem COMMA_LOCKVAL_SRC_POS);5350 }5351 alock.acquire();5352 }5353 5333 5354 5334 return S_OK; 5355 5335 } 5356 5357 alock.release();5358 Assert(!isWriteLockOnCurrentThread());5359 Assert(!m->pVirtualBox->getMediaTreeLockHandle().isWriteLockOnCurrentThread());5360 AutoWriteLock treeLock(m->pVirtualBox->getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS);5361 alock.acquire();5362 5336 5363 5337 bool success = false; … … 5387 5361 alock.release(); 5388 5362 if (uOpenFlags & (VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_SHAREABLE)) 5389 rc = lockRead(NULL, true /* fWithinQueryInfo */);5363 rc = LockRead(NULL); 5390 5364 else 5391 rc = lockWrite(NULL, true /* fWithinQueryInfo */);5365 rc = LockWrite(NULL); 5392 5366 if (FAILED(rc)) return rc; 5393 5367 alock.acquire(); … … 5411 5385 bool fRepairImageZeroParentUuid = false; 5412 5386 5413 /* release the object lock before a lengthy operation */ 5387 /* release the object lock before a lengthy operation, and take the 5388 * opportunity to have a media tree lock, too, which isn't held initially */ 5414 5389 m->queryInfoRunning = true; 5415 5390 alock.release(); 5416 treeLock.release();5417 5391 Assert(!isWriteLockOnCurrentThread()); 5418 5392 Assert(!m->pVirtualBox->getMediaTreeLockHandle().isWriteLockOnCurrentThread()); 5393 AutoWriteLock treeLock(m->pVirtualBox->getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS); 5394 treeLock.release(); 5419 5395 5420 5396 /* Note that taking the queryInfoSem after leaving the object lock above … … 5422 5398 * complete. This is unavoidable since the other order causes a lock order 5423 5399 * violation: here it would be requesting the object lock (at the beginning 5424 * of the method), then SemRW, and below the other way round. */5400 * of the method), then queryInfoSem, and below the other way round. */ 5425 5401 AutoWriteLock qlock(m->queryInfoSem COMMA_LOCKVAL_SRC_POS); 5402 alock.acquire(); 5426 5403 5427 5404 try … … 5562 5539 5563 5540 /* we set mParent & children() */ 5541 alock.release(); 5564 5542 treeLock.acquire(); 5565 5543 … … 5569 5547 5570 5548 treeLock.release(); 5549 alock.acquire(); 5571 5550 } 5572 5551 else 5573 5552 { 5574 5553 /* we access mParent */ 5554 alock.release(); 5575 5555 treeLock.acquire(); 5576 5556 … … 5596 5576 location.c_str(), 5597 5577 m->pVirtualBox->settingsFilePath().c_str()); 5578 treeLock.release(); 5579 alock.acquire(); 5598 5580 throw S_OK; 5599 5581 #endif /* 0 */ 5600 5582 } 5601 5583 5602 AutoReadLock parentLock(m->pParent COMMA_LOCKVAL_SRC_POS);5603 if ( !fRepairImageZeroParentUuid5604 && m->pParent->getState() != MediumState_Inaccessible5605 && m->pParent->getId() != parentId)5606 5584 { 5607 /** @todo r=klaus this always refers to VirtualBox.xml as the medium registry, even for new VMs */ 5608 lastAccessError = Utf8StrFmt( 5609 tr("Parent UUID {%RTuuid} of the medium '%s' does not match UUID {%RTuuid} of its parent medium stored in the media registry ('%s')"), 5610 &parentId, location.c_str(), 5611 m->pParent->getId().raw(), 5612 m->pVirtualBox->settingsFilePath().c_str()); 5613 throw S_OK; 5585 AutoReadLock parentLock(m->pParent COMMA_LOCKVAL_SRC_POS); 5586 if ( !fRepairImageZeroParentUuid 5587 && m->pParent->getState() != MediumState_Inaccessible 5588 && m->pParent->getId() != parentId) 5589 { 5590 /** @todo r=klaus this always refers to VirtualBox.xml as the medium registry, even for new VMs */ 5591 lastAccessError = Utf8StrFmt( 5592 tr("Parent UUID {%RTuuid} of the medium '%s' does not match UUID {%RTuuid} of its parent medium stored in the media registry ('%s')"), 5593 &parentId, location.c_str(), 5594 m->pParent->getId().raw(), 5595 m->pVirtualBox->settingsFilePath().c_str()); 5596 parentLock.release(); 5597 treeLock.release(); 5598 alock.acquire(); 5599 throw S_OK; 5600 } 5614 5601 } 5615 5602 … … 5619 5606 5620 5607 treeLock.release(); 5608 alock.acquire(); 5621 5609 } 5622 5610 } … … 5646 5634 } 5647 5635 5636 alock.release(); 5648 5637 treeLock.acquire(); 5649 5638 alock.acquire(); … … 5730 5719 rc = aRC; 5731 5720 } 5732 5733 alock.acquire();5734 5721 5735 5722 rc = UnlockWrite(NULL);
Note:
See TracChangeset
for help on using the changeset viewer.