Changeset 35162 in vbox
- Timestamp:
- Dec 15, 2010 7:39:54 PM (14 years ago)
- Location:
- trunk
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/pdmblkcache.h
r34219 r35162 310 310 */ 311 311 VMMR3DECL(void) PDMR3BlkCacheIoXferComplete(PPDMBLKCACHE pBlkCache, PPDMBLKCACHEIOXFER hIoXfer, int rcIoXfer); 312 313 /** 314 * Suspends the block cache. The cache waits until all I/O transfers completed 315 * and stops to enqueue new requests after the call returned but will not accept 316 * reads, write or flushes either. 317 * 318 * @returns VBox status code. 319 * @param pBlkCache The cache instance. 320 */ 321 VMMR3DECL(int) PDMR3BlkCacheSuspend(PPDMBLKCACHE pBlkCache); 322 323 /** 324 * Resumes operation of the block cache. 325 * 326 * @returns VBox status code. 327 * @param pBlkCache The cache instance. 328 */ 329 VMMR3DECL(int) PDMR3BlkCacheResume(PPDMBLKCACHE pBlkCache); 330 312 331 /** @} */ 313 332 -
trunk/src/VBox/Devices/Storage/DrvVD.cpp
r35072 r35162 1897 1897 LogFlowFunc(("\n")); 1898 1898 PVBOXDISK pThis = PDMINS_2_DATA(pDrvIns, PVBOXDISK); 1899 1899 1900 drvvdSetWritable(pThis); 1900 1901 pThis->fErrorUseRuntime = true; 1902 1903 if (pThis->pBlkCache) 1904 { 1905 int rc = PDMR3BlkCacheResume(pThis->pBlkCache); 1906 AssertRC(rc); 1907 } 1901 1908 } 1902 1909 … … 1920 1927 LogFlowFunc(("\n")); 1921 1928 PVBOXDISK pThis = PDMINS_2_DATA(pDrvIns, PVBOXDISK); 1929 1930 if (pThis->pBlkCache) 1931 { 1932 int rc = PDMR3BlkCacheSuspend(pThis->pBlkCache); 1933 AssertRC(rc); 1934 } 1935 1922 1936 drvvdSetReadonly(pThis); 1923 1937 } -
trunk/src/VBox/VMM/PDMBlkCache.cpp
r34658 r35162 647 647 { 648 648 uint32_t cbCommitted = 0; 649 650 /* Return if the cache was suspended. */ 651 if (pBlkCache->fSuspended) 652 return; 653 649 654 RTSemRWRequestWrite(pBlkCache->SemRWEntries, RT_INDEFINITE_WAIT); 650 655 … … 683 688 AssertMsg(pBlkCache->pCache->cbDirty >= cbCommitted, 684 689 ("Number of committed bytes exceeds number of dirty bytes\n")); 685 ASMAtomicSubU32(&pBlkCache->pCache->cbDirty, cbCommitted); 690 uint32_t cbDirtyOld = ASMAtomicSubU32(&pBlkCache->pCache->cbDirty, cbCommitted); 691 692 /* Reset the commit timer if we don't have any dirty bits. */ 693 if ( !(cbDirtyOld - cbCommitted) 694 && pBlkCache->pCache->u32CommitTimeoutMs != 0) 695 TMTimerStop(pBlkCache->pCache->pTimerCommit); 686 696 } 687 697 … … 752 762 /* Prevent committing if the VM was suspended. */ 753 763 if (RT_LIKELY(!ASMAtomicReadBool(&pCache->fIoErrorVmSuspended))) 754 fDirtyBytesExceeded = (cbDirty >= pCache->cbCommitDirtyThreshold); 764 fDirtyBytesExceeded = (cbDirty + pEntry->cbData >= pCache->cbCommitDirtyThreshold); 765 else if (!cbDirty && pCache->u32CommitTimeoutMs > 0) 766 { 767 /* Arm the commit timer. */ 768 TMTimerSetMillies(pCache->pTimerCommit, pCache->u32CommitTimeoutMs); 769 } 755 770 } 756 771 … … 788 803 pdmBlkCacheCommitDirtyEntries(pCache); 789 804 790 TMTimerSetMillies(pTimer, pCache->u32CommitTimeoutMs);791 805 LogFlowFunc(("Entries committed, going to sleep\n")); 792 806 } … … 1191 1205 && pBlkCache->pszId) 1192 1206 { 1207 pBlkCache->fSuspended = false; 1193 1208 pBlkCache->pCache = pBlkCacheGlobal; 1194 1209 RTListInit(&pBlkCache->ListDirtyNotCommitted); … … 1203 1218 if (pBlkCache->pTree) 1204 1219 { 1205 /* Arm the timer if this is the first endpoint. */1206 if ( !pBlkCacheGlobal->cRefs1207 && pBlkCacheGlobal->u32CommitTimeoutMs > 0)1208 rc = TMTimerSetMillies(pBlkCacheGlobal->pTimerCommit, pBlkCacheGlobal->u32CommitTimeoutMs);1209 1210 if (RT_SUCCESS(rc))1211 {1212 1220 #ifdef VBOX_WITH_STATISTICS 1213 1214 1215 1216 1221 STAMR3RegisterF(pBlkCacheGlobal->pVM, &pBlkCache->StatWriteDeferred, 1222 STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, 1223 STAMUNIT_COUNT, "Number of deferred writes", 1224 "/PDM/BlkCache/%s/Cache/DeferredWrites", pBlkCache->pszId); 1217 1225 #endif 1218 1226 1219 /* Add to the list of users. */ 1220 pBlkCacheGlobal->cRefs++; 1221 RTListAppend(&pBlkCacheGlobal->ListUsers, &pBlkCache->NodeCacheUser); 1222 pdmBlkCacheLockLeave(pBlkCacheGlobal); 1223 1224 *ppBlkCache = pBlkCache; 1225 LogFlowFunc(("returns success\n")); 1226 return VINF_SUCCESS; 1227 } 1227 /* Add to the list of users. */ 1228 pBlkCacheGlobal->cRefs++; 1229 RTListAppend(&pBlkCacheGlobal->ListUsers, &pBlkCache->NodeCacheUser); 1230 pdmBlkCacheLockLeave(pBlkCacheGlobal); 1231 1232 *ppBlkCache = pBlkCache; 1233 LogFlowFunc(("returns success\n")); 1234 return VINF_SUCCESS; 1228 1235 } 1229 1236 else … … 1417 1424 pCache->cRefs--; 1418 1425 RTListNodeRemove(&pBlkCache->NodeCacheUser); 1419 1420 if ( !pCache->cRefs1421 && pCache->u32CommitTimeoutMs > 0)1422 TMTimerStop(pCache->pTimerCommit);1423 1426 1424 1427 pdmBlkCacheLockLeave(pCache); … … 1934 1937 LogFlowFunc((": pBlkCache=%#p{%s} off=%llu pcSgBuf=%#p cbRead=%u pvUser=%#p\n", 1935 1938 pBlkCache, pBlkCache->pszId, off, pcSgBuf, cbRead, pvUser)); 1939 1940 AssertPtrReturn(pBlkCache, VERR_INVALID_POINTER); 1941 AssertReturn(!pBlkCache->fSuspended, VERR_INVALID_STATE); 1936 1942 1937 1943 RTSGBUF SgBuf; … … 2149 2155 LogFlowFunc((": pBlkCache=%#p{%s} off=%llu pcSgBuf=%#p cbWrite=%u pvUser=%#p\n", 2150 2156 pBlkCache, pBlkCache->pszId, off, pcSgBuf, cbWrite, pvUser)); 2157 2158 AssertPtrReturn(pBlkCache, VERR_INVALID_POINTER); 2159 AssertReturn(!pBlkCache->fSuspended, VERR_INVALID_STATE); 2151 2160 2152 2161 RTSGBUF SgBuf; … … 2378 2387 LogFlowFunc((": pBlkCache=%#p{%s}\n", pBlkCache, pBlkCache->pszId)); 2379 2388 2389 AssertPtrReturn(pBlkCache, VERR_INVALID_POINTER); 2390 AssertReturn(!pBlkCache->fSuspended, VERR_INVALID_STATE); 2391 2380 2392 /* Commit dirty entries in the cache. */ 2381 2393 pdmBlkCacheCommit(pBlkCache); … … 2539 2551 } 2540 2552 2553 /** 2554 * Callback for the AVL do with all routine. Waits for a cachen entry to finish any pending I/O. 2555 * 2556 * @returns IPRT status code. 2557 * @param pNode The node to destroy. 2558 * @param pvUser Opaque user data. 2559 */ 2560 static int pdmBlkCacheEntryQuiesce(PAVLRU64NODECORE pNode, void *pvUser) 2561 { 2562 PPDMBLKCACHEENTRY pEntry = (PPDMBLKCACHEENTRY)pNode; 2563 PPDMBLKCACHE pBlkCache = pEntry->pBlkCache; 2564 2565 while (ASMAtomicReadU32(&pEntry->fFlags) & PDMBLKCACHE_ENTRY_IO_IN_PROGRESS) 2566 { 2567 /* Leave the locks to let the I/O thread make progress but reference the entry to prevent eviction. */ 2568 pdmBlkCacheEntryRef(pEntry); 2569 RTSemRWReleaseWrite(pBlkCache->SemRWEntries); 2570 2571 RTThreadSleep(1); 2572 2573 /* Re-enter all locks and drop the reference. */ 2574 RTSemRWRequestWrite(pBlkCache->SemRWEntries, RT_INDEFINITE_WAIT); 2575 pdmBlkCacheEntryRelease(pEntry); 2576 } 2577 2578 AssertMsg(!(pEntry->fFlags & PDMBLKCACHE_ENTRY_IO_IN_PROGRESS), 2579 ("Entry is dirty and/or still in progress fFlags=%#x\n", pEntry->fFlags)); 2580 2581 return VINF_SUCCESS; 2582 } 2583 2584 VMMR3DECL(int) PDMR3BlkCacheSuspend(PPDMBLKCACHE pBlkCache) 2585 { 2586 int rc = VINF_SUCCESS; 2587 LogFlowFunc(("pBlkCache=%#p\n", pBlkCache)); 2588 2589 AssertPtrReturn(pBlkCache, VERR_INVALID_POINTER); 2590 2591 ASMAtomicXchgBool(&pBlkCache->fSuspended, true); 2592 2593 /* Wait for all I/O to complete. */ 2594 RTSemRWRequestWrite(pBlkCache->SemRWEntries, RT_INDEFINITE_WAIT); 2595 rc = RTAvlrU64DoWithAll(pBlkCache->pTree, true, pdmBlkCacheEntryQuiesce, NULL); 2596 AssertRC(rc); 2597 RTSemRWReleaseWrite(pBlkCache->SemRWEntries); 2598 2599 return rc; 2600 } 2601 2602 VMMR3DECL(int) PDMR3BlkCacheResume(PPDMBLKCACHE pBlkCache) 2603 { 2604 LogFlowFunc(("pBlkCache=%#p\n", pBlkCache)); 2605 2606 AssertPtrReturn(pBlkCache, VERR_INVALID_POINTER); 2607 2608 ASMAtomicXchgBool(&pBlkCache->fSuspended, false); 2609 2610 return VINF_SUCCESS; 2611 } 2612 -
trunk/src/VBox/VMM/PDMBlkCacheInternal.h
r34347 r35162 247 247 STAMCOUNTER StatWriteDeferred; 248 248 #endif 249 250 /** Flag whether the cache was suspended. */ 251 volatile bool fSuspended; 252 249 253 } PDMBLKCACHE, *PPDMBLKCACHE; 250 254 #ifdef VBOX_WITH_STATISTICS
Note:
See TracChangeset
for help on using the changeset viewer.