Changeset 33094 in vbox for trunk/src/VBox/Devices/Storage
- Timestamp:
- Oct 13, 2010 10:51:49 AM (14 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Storage/VBoxHDD.cpp
r33088 r33094 201 201 /** Critical section protecting the disk against concurrent access. */ 202 202 RTCRITSECT CritSect; 203 /** Flag whether the last image is currently written to and needs to grow.204 * Other write requests which will grow the image too need to be deferred to205 * prevent data corruption. - Protected by the critical section.203 /** Flag whether the disk is currently locked by growing write or a flush 204 * request. Other flush or growing write requests need to wait until 205 * the current one completes. 206 206 */ 207 volatile bool f Growing;207 volatile bool fLocked; 208 208 /** List of waiting requests. - Protected by the critical section. */ 209 RTLISTNODE ListWrite Growing;209 RTLISTNODE ListWriteLocked; 210 210 211 211 /** Pointer to the L2 disk cache if any. */ … … 1065 1065 } 1066 1066 1067 DECLINLINE(int) vdIoCtxDefer(PVBOXHDD pDisk, PVDIOCTX pIoCtx) 1068 { 1069 PVDIOCTXDEFERRED pDeferred = (PVDIOCTXDEFERRED)RTMemAllocZ(sizeof(VDIOCTXDEFERRED)); 1070 1071 if (!pDeferred) 1072 return VERR_NO_MEMORY; 1073 1074 LogFlowFunc(("Deferring write pIoCtx=%#p\n", pIoCtx)); 1075 1076 Assert(!pIoCtx->pIoCtxParent && !pIoCtx->fBlocked); 1077 1078 RTListInit(&pDeferred->NodeDeferred); 1079 pDeferred->pIoCtx = pIoCtx; 1080 RTListAppend(&pDisk->ListWriteLocked, &pDeferred->NodeDeferred); 1081 pIoCtx->fBlocked = true; 1082 return VINF_SUCCESS; 1083 } 1084 1067 1085 static size_t vdIoCtxCopy(PVDIOCTX pIoCtxDst, PVDIOCTX pIoCtxSrc, size_t cbData) 1068 1086 { … … 1178 1196 1179 1197 return rc; 1198 } 1199 1200 static int vdIoCtxLockDisk(PVBOXHDD pDisk, PVDIOCTX pIoCtx) 1201 { 1202 int rc = VINF_SUCCESS; 1203 1204 if (!ASMAtomicCmpXchgBool(&pDisk->fLocked, true, false)) 1205 { 1206 rc = vdIoCtxDefer(pDisk, pIoCtx); 1207 if (RT_SUCCESS(rc)) 1208 rc = VERR_VD_ASYNC_IO_IN_PROGRESS; 1209 } 1210 1211 return rc; 1212 } 1213 1214 static void vdIoCtxUnlockDisk(PVBOXHDD pDisk, PVDIOCTX pIoCtx) 1215 { 1216 Assert(pDisk->fLocked); 1217 ASMAtomicXchgBool(&pDisk->fLocked, false); 1218 1219 /* Process any pending writes if the current request didn't caused another growing. */ 1220 RTCritSectEnter(&pDisk->CritSect); 1221 1222 if (!RTListIsEmpty(&pDisk->ListWriteLocked)) 1223 { 1224 RTLISTNODE ListTmp; 1225 1226 RTListMove(&ListTmp, &pDisk->ListWriteLocked); 1227 RTCritSectLeave(&pDisk->CritSect); 1228 1229 /* Process the list. */ 1230 do 1231 { 1232 int rc; 1233 PVDIOCTXDEFERRED pDeferred = RTListNodeGetFirst(&ListTmp, VDIOCTXDEFERRED, NodeDeferred); 1234 PVDIOCTX pIoCtxWait = pDeferred->pIoCtx; 1235 1236 AssertPtr(pIoCtxWait); 1237 1238 RTListNodeRemove(&pDeferred->NodeDeferred); 1239 RTMemFree(pDeferred); 1240 1241 Assert(!pIoCtxWait->pIoCtxParent); 1242 1243 pIoCtxWait->fBlocked = false; 1244 LogFlowFunc(("Processing waiting I/O context pIoCtxWait=%#p\n", pIoCtxWait)); 1245 1246 rc = vdIoCtxProcess(pIoCtxWait); 1247 if ( rc == VINF_VD_ASYNC_IO_FINISHED 1248 && ASMAtomicCmpXchgBool(&pIoCtxWait->fComplete, true, false)) 1249 { 1250 LogFlowFunc(("Waiting I/O context completed pIoCtxWait=%#p\n", pIoCtxWait)); 1251 vdThreadFinishWrite(pDisk); 1252 pIoCtxWait->Type.Root.pfnComplete(pIoCtxWait->Type.Root.pvUser1, 1253 pIoCtxWait->Type.Root.pvUser2, 1254 pIoCtxWait->rcReq); 1255 vdIoCtxFree(pDisk, pIoCtxWait); 1256 } 1257 } while (!RTListIsEmpty(&ListTmp)); 1258 } 1259 else 1260 RTCritSectLeave(&pDisk->CritSect); 1180 1261 } 1181 1262 … … 1847 1928 if (rc == VERR_VD_BLOCK_FREE) 1848 1929 { 1849 /* 1850 * If there is a growing request already put this one onto the waiting list. 1851 * It will be restarted if the current request completes. 1852 */ 1853 if (ASMAtomicReadBool(&pDisk->fGrowing)) 1854 { 1855 PVDIOCTXDEFERRED pDeferred = (PVDIOCTXDEFERRED)RTMemAllocZ(sizeof(VDIOCTXDEFERRED)); 1856 AssertPtr(pDeferred); 1857 1858 LogFlowFunc(("Deferring write pIoCtx=%#p\n", pIoCtx)); 1859 1860 Assert(!pIoCtx->pIoCtxParent && !pIoCtx->fBlocked); 1861 1862 RTListInit(&pDeferred->NodeDeferred); 1863 pDeferred->pIoCtx = pIoCtx; 1864 RTListAppend(&pDisk->ListWriteGrowing, &pDeferred->NodeDeferred); 1865 pIoCtx->fBlocked = true; 1866 rc = VERR_VD_ASYNC_IO_IN_PROGRESS; 1867 break; 1868 } 1869 else 1930 /* Lock the disk .*/ 1931 rc = vdIoCtxLockDisk(pDisk, pIoCtx); 1932 if (RT_SUCCESS(rc)) 1870 1933 { 1871 1934 /* … … 1895 1958 } 1896 1959 1897 /* Set the state to growing. */1898 1960 LogFlowFunc(("Disk is growing because of pIoCtx=%#p pIoCtxWrite=%#p\n", 1899 1900 1961 pIoCtx, pIoCtxWrite)); 1901 ASMAtomicWriteBool(&pDisk->fGrowing, true);1902 1962 1903 1963 pIoCtxWrite->pImage = pImage; … … 1919 1979 Assert(pIoCtx->cbTransferLeft >= cbThisWrite); 1920 1980 ASMAtomicSubU32(&pIoCtx->cbTransferLeft, cbThisWrite); 1921 ASMAtomicWriteBool(&pDisk->f Growing, false);1981 ASMAtomicWriteBool(&pDisk->fLocked, false); 1922 1982 vdIoCtxFree(pDisk, pIoCtxWrite); 1923 1983 … … 1934 1994 } 1935 1995 } 1996 else 1997 { 1998 rc = VERR_VD_ASYNC_IO_IN_PROGRESS; 1999 break; 2000 } 1936 2001 } 1937 2002 … … 1977 2042 PVDIMAGE pImage = pIoCtx->pImage; 1978 2043 1979 vdResetModifiedFlag(pDisk); 1980 rc = pImage->Backend->pfnAsyncFlush(pImage->pBackendData, pIoCtx); 1981 if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS) 1982 rc = VINF_SUCCESS; 2044 rc = vdIoCtxLockDisk(pDisk, pIoCtx); 2045 if (RT_SUCCESS(rc)) 2046 { 2047 vdResetModifiedFlag(pDisk); 2048 rc = pImage->Backend->pfnAsyncFlush(pImage->pBackendData, pIoCtx); 2049 if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS) 2050 rc = VINF_SUCCESS; 2051 } 1983 2052 1984 2053 return rc; … … 2412 2481 * We have to process any pending writes now. 2413 2482 */ 2414 Assert(pDisk->f Growing);2415 ASMAtomicWriteBool(&pDisk->f Growing, false);2483 Assert(pDisk->fLocked); 2484 ASMAtomicWriteBool(&pDisk->fLocked, false); 2416 2485 2417 2486 /* Unblock the parent */ … … 2434 2503 RTCritSectEnter(&pDisk->CritSect); 2435 2504 2436 if (!RTListIsEmpty(&pDisk->ListWrite Growing) && !pDisk->fGrowing)2505 if (!RTListIsEmpty(&pDisk->ListWriteLocked) && !pDisk->fLocked) 2437 2506 { 2438 2507 RTLISTNODE ListTmp; 2439 2508 2440 LogFlowFunc(("Before: pNext=%#p pPrev=%#p\n", pDisk->ListWrite Growing.pNext,2441 pDisk->ListWrite Growing.pPrev));2442 2443 RTListMove(&ListTmp, &pDisk->ListWrite Growing);2444 2445 LogFlowFunc(("After: pNext=%#p pPrev=%#p\n", pDisk->ListWrite Growing.pNext,2446 pDisk->ListWrite Growing.pPrev));2509 LogFlowFunc(("Before: pNext=%#p pPrev=%#p\n", pDisk->ListWriteLocked.pNext, 2510 pDisk->ListWriteLocked.pPrev)); 2511 2512 RTListMove(&ListTmp, &pDisk->ListWriteLocked); 2513 2514 LogFlowFunc(("After: pNext=%#p pPrev=%#p\n", pDisk->ListWriteLocked.pNext, 2515 pDisk->ListWriteLocked.pPrev)); 2447 2516 2448 2517 RTCritSectLeave(&pDisk->CritSect); … … 2482 2551 else 2483 2552 { 2484 if (pIoCtx->enmTxDir != VDIOCTXTXDIR_READ)2553 if (pIoCtx->enmTxDir == VDIOCTXTXDIR_FLUSH) 2485 2554 { 2486 AssertMsg( pIoCtx->enmTxDir == VDIOCTXTXDIR_WRITE 2487 || pIoCtx->enmTxDir == VDIOCTXTXDIR_FLUSH, 2488 ("Invalid transfer direction\n")); 2555 vdIoCtxUnlockDisk(pDisk, pIoCtx); 2489 2556 vdThreadFinishWrite(pDisk); 2490 2557 } 2558 else if (pIoCtx->enmTxDir == VDIOCTXTXDIR_WRITE) 2559 vdThreadFinishWrite(pDisk); 2491 2560 else 2561 { 2562 Assert(pIoCtx->enmTxDir == VDIOCTXTXDIR_READ); 2492 2563 vdThreadFinishRead(pDisk); 2564 } 2493 2565 2494 2566 LogFlowFunc(("I/O context completed pIoCtx=%#p rcReq=%Rrc\n", pIoCtx, pIoCtx->rcReq)); … … 3589 3661 pDisk->pInterfaceThreadSync = NULL; 3590 3662 pDisk->pInterfaceThreadSyncCallbacks = NULL; 3591 pDisk->f Growing= false;3592 RTListInit(&pDisk->ListWrite Growing);3663 pDisk->fLocked = false; 3664 RTListInit(&pDisk->ListWriteLocked); 3593 3665 3594 3666 /* Create the I/O ctx cache */
Note:
See TracChangeset
for help on using the changeset viewer.