- Timestamp:
- Mar 2, 2011 9:58:40 PM (14 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Storage/VD.cpp
r35781 r36132 213 213 /** List of waiting requests. - Protected by the critical section. */ 214 214 RTLISTNODE ListWriteLocked; 215 /** I/O context which locked the disk. */ 216 PVDIOCTX pIoCtxLockOwner; 215 217 216 218 /** Pointer to the L2 disk cache if any. */ … … 1200 1202 } 1201 1203 1204 DECLINLINE(bool) vdIoCtxIsDiskLockOwner(PVBOXHDD pDisk, PVDIOCTX pIoCtx) 1205 { 1206 return pDisk->fLocked 1207 && pDisk->pIoCtxLockOwner == pIoCtx; 1208 } 1209 1202 1210 static int vdIoCtxLockDisk(PVBOXHDD pDisk, PVDIOCTX pIoCtx) 1203 1211 { … … 1206 1214 if (!ASMAtomicCmpXchgBool(&pDisk->fLocked, true, false)) 1207 1215 { 1216 Assert(pDisk->pIoCtxLockOwner != pIoCtx); /* No nesting allowed. */ 1217 1208 1218 rc = vdIoCtxDefer(pDisk, pIoCtx); 1209 1219 if (RT_SUCCESS(rc)) 1210 1220 rc = VERR_VD_ASYNC_IO_IN_PROGRESS; 1211 1221 } 1222 else 1223 { 1224 Assert(!pDisk->pIoCtxLockOwner); 1225 pDisk->pIoCtxLockOwner = pIoCtx; 1226 } 1212 1227 1213 1228 return rc; 1214 1229 } 1215 1230 1216 static void vdIoCtxUnlockDisk(PVBOXHDD pDisk, PVDIOCTX pIoCtx )1231 static void vdIoCtxUnlockDisk(PVBOXHDD pDisk, PVDIOCTX pIoCtx, bool fProcessDeferredReqs) 1217 1232 { 1218 1233 Assert(pDisk->fLocked); 1234 Assert(pDisk->pIoCtxLockOwner == pIoCtx); 1235 pDisk->pIoCtxLockOwner = NULL; 1219 1236 ASMAtomicXchgBool(&pDisk->fLocked, false); 1220 1237 1221 /* Process any pending writes if the current request didn't caused another growing. */ 1222 RTCritSectEnter(&pDisk->CritSect); 1223 1224 if (!RTListIsEmpty(&pDisk->ListWriteLocked)) 1225 { 1226 RTLISTNODE ListTmp; 1227 1228 RTListMove(&ListTmp, &pDisk->ListWriteLocked); 1229 RTCritSectLeave(&pDisk->CritSect); 1230 1231 /* Process the list. */ 1232 do 1233 { 1234 int rc; 1235 PVDIOCTXDEFERRED pDeferred = RTListGetFirst(&ListTmp, VDIOCTXDEFERRED, NodeDeferred); 1236 PVDIOCTX pIoCtxWait = pDeferred->pIoCtx; 1237 1238 AssertPtr(pIoCtxWait); 1239 1240 RTListNodeRemove(&pDeferred->NodeDeferred); 1241 RTMemFree(pDeferred); 1242 1243 Assert(!pIoCtxWait->pIoCtxParent); 1244 1245 pIoCtxWait->fBlocked = false; 1246 LogFlowFunc(("Processing waiting I/O context pIoCtxWait=%#p\n", pIoCtxWait)); 1247 1248 rc = vdIoCtxProcess(pIoCtxWait); 1249 if ( rc == VINF_VD_ASYNC_IO_FINISHED 1250 && ASMAtomicCmpXchgBool(&pIoCtxWait->fComplete, true, false)) 1238 if (fProcessDeferredReqs) 1239 { 1240 /* Process any pending writes if the current request didn't caused another growing. */ 1241 RTCritSectEnter(&pDisk->CritSect); 1242 1243 if (!RTListIsEmpty(&pDisk->ListWriteLocked)) 1244 { 1245 RTLISTNODE ListTmp; 1246 1247 RTListMove(&ListTmp, &pDisk->ListWriteLocked); 1248 RTCritSectLeave(&pDisk->CritSect); 1249 1250 /* Process the list. */ 1251 do 1251 1252 { 1252 LogFlowFunc(("Waiting I/O context completed pIoCtxWait=%#p\n", pIoCtxWait)); 1253 vdThreadFinishWrite(pDisk); 1254 pIoCtxWait->Type.Root.pfnComplete(pIoCtxWait->Type.Root.pvUser1, 1255 pIoCtxWait->Type.Root.pvUser2, 1256 pIoCtxWait->rcReq); 1257 vdIoCtxFree(pDisk, pIoCtxWait); 1258 } 1259 } while (!RTListIsEmpty(&ListTmp)); 1260 } 1261 else 1262 RTCritSectLeave(&pDisk->CritSect); 1253 int rc; 1254 PVDIOCTXDEFERRED pDeferred = RTListGetFirst(&ListTmp, VDIOCTXDEFERRED, NodeDeferred); 1255 PVDIOCTX pIoCtxWait = pDeferred->pIoCtx; 1256 1257 AssertPtr(pIoCtxWait); 1258 1259 RTListNodeRemove(&pDeferred->NodeDeferred); 1260 RTMemFree(pDeferred); 1261 1262 Assert(!pIoCtxWait->pIoCtxParent); 1263 1264 pIoCtxWait->fBlocked = false; 1265 LogFlowFunc(("Processing waiting I/O context pIoCtxWait=%#p\n", pIoCtxWait)); 1266 1267 rc = vdIoCtxProcess(pIoCtxWait); 1268 if ( rc == VINF_VD_ASYNC_IO_FINISHED 1269 && ASMAtomicCmpXchgBool(&pIoCtxWait->fComplete, true, false)) 1270 { 1271 LogFlowFunc(("Waiting I/O context completed pIoCtxWait=%#p\n", pIoCtxWait)); 1272 vdThreadFinishWrite(pDisk); 1273 pIoCtxWait->Type.Root.pfnComplete(pIoCtxWait->Type.Root.pvUser1, 1274 pIoCtxWait->Type.Root.pvUser2, 1275 pIoCtxWait->rcReq); 1276 vdIoCtxFree(pDisk, pIoCtxWait); 1277 } 1278 } while (!RTListIsEmpty(&ListTmp)); 1279 } 1280 else 1281 RTCritSectLeave(&pDisk->CritSect); 1282 } 1263 1283 } 1264 1284 … … 1640 1660 1641 1661 /** 1662 * Flush helper async version. 1663 */ 1664 static int vdSetModifiedHelperAsync(PVDIOCTX pIoCtx) 1665 { 1666 int rc = VINF_SUCCESS; 1667 PVBOXHDD pDisk = pIoCtx->pDisk; 1668 PVDIMAGE pImage = pIoCtx->pImageCur; 1669 1670 rc = pImage->Backend->pfnAsyncFlush(pImage->pBackendData, pIoCtx); 1671 if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS) 1672 rc = VINF_SUCCESS; 1673 1674 return rc; 1675 } 1676 1677 /** 1678 * internal: mark the disk as modified - async version. 1679 */ 1680 static int vdSetModifiedFlagAsync(PVBOXHDD pDisk, PVDIOCTX pIoCtx) 1681 { 1682 int rc = VINF_SUCCESS; 1683 1684 pDisk->uModified |= VD_IMAGE_MODIFIED_FLAG; 1685 if (pDisk->uModified & VD_IMAGE_MODIFIED_FIRST) 1686 { 1687 rc = vdIoCtxLockDisk(pDisk, pIoCtx); 1688 if (RT_SUCCESS(rc)) 1689 { 1690 pDisk->uModified &= ~VD_IMAGE_MODIFIED_FIRST; 1691 1692 /* First modify, so create a UUID and ensure it's written to disk. */ 1693 vdResetModifiedFlag(pDisk); 1694 1695 if (!(pDisk->uModified & VD_IMAGE_MODIFIED_DISABLE_UUID_UPDATE)) 1696 { 1697 PVDIOCTX pIoCtxFlush = vdIoCtxChildAlloc(pDisk, VDIOCTXTXDIR_FLUSH, 1698 0, 0, pDisk->pLast, 1699 NULL, pIoCtx, 0, 0, NULL, 1700 vdSetModifiedHelperAsync); 1701 1702 if (pIoCtxFlush) 1703 { 1704 rc = vdIoCtxProcess(pIoCtxFlush); 1705 if (rc == VINF_VD_ASYNC_IO_FINISHED) 1706 { 1707 vdIoCtxUnlockDisk(pDisk, pIoCtxFlush, false /* fProcessDeferredReqs */); 1708 vdIoCtxFree(pDisk, pIoCtxFlush); 1709 } 1710 else if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS) 1711 { 1712 pIoCtx->fBlocked = true; 1713 } 1714 else /* Another error */ 1715 vdIoCtxFree(pDisk, pIoCtxFlush); 1716 } 1717 else 1718 rc = VERR_NO_MEMORY; 1719 } 1720 } 1721 } 1722 1723 return rc; 1724 } 1725 1726 /** 1642 1727 * internal: write a complete block (only used for diff images), taking the 1643 1728 * remaining data from parent images. This implementation does not optimize … … 1928 2013 size_t cbPreRead, cbPostRead; 1929 2014 2015 rc = vdSetModifiedFlagAsync(pDisk, pIoCtx); 2016 if (RT_FAILURE(rc)) /* Includes I/O in progress. */ 2017 return rc; 2018 1930 2019 /* Loop until all written. */ 1931 2020 do … … 2489 2578 PVDIOCTX pIoCtxParent = pIoCtx->pIoCtxParent; 2490 2579 2491 LogFlowFunc(("I/O context transferred %u bytes for the parent pIoCtxParent=%p\n",2492 pIoCtx->Type.Child.cbTransferParent, pIoCtxParent));2493 2494 /* Update the parent state. */2495 2580 Assert(!pIoCtxParent->pIoCtxParent); 2496 Assert(pIoCtx->enmTxDir == VDIOCTXTXDIR_WRITE);2497 Assert(pIoCtxParent->cbTransferLeft >= pIoCtx->Type.Child.cbTransferParent);2498 ASMAtomicSubU32(&pIoCtxParent->cbTransferLeft, pIoCtx->Type.Child.cbTransferParent);2499 2500 2581 if (RT_FAILURE(pIoCtx->rcReq)) 2501 2582 ASMAtomicCmpXchgS32(&pIoCtxParent->rcReq, pIoCtx->rcReq, VINF_SUCCESS); 2583 2584 if (pIoCtx->enmTxDir == VDIOCTXTXDIR_WRITE) 2585 { 2586 LogFlowFunc(("I/O context transferred %u bytes for the parent pIoCtxParent=%p\n", 2587 pIoCtx->Type.Child.cbTransferParent, pIoCtxParent)); 2588 2589 /* Update the parent state. */ 2590 Assert(pIoCtxParent->cbTransferLeft >= pIoCtx->Type.Child.cbTransferParent); 2591 ASMAtomicSubU32(&pIoCtxParent->cbTransferLeft, pIoCtx->Type.Child.cbTransferParent); 2592 } 2593 else 2594 Assert(pIoCtx->enmTxDir == VDIOCTXTXDIR_FLUSH); 2502 2595 2503 2596 /* … … 2505 2598 * We have to process any pending writes now. 2506 2599 */ 2507 Assert(pDisk->fLocked); 2508 ASMAtomicWriteBool(&pDisk->fLocked, false); 2600 vdIoCtxUnlockDisk(pDisk, pIoCtxParent, false /* fProcessDeferredReqs */); 2509 2601 2510 2602 /* Unblock the parent */ … … 2527 2619 RTCritSectEnter(&pDisk->CritSect); 2528 2620 2529 if (!RTListIsEmpty(&pDisk->ListWriteLocked) && !pDisk->fLocked) 2621 if ( !RTListIsEmpty(&pDisk->ListWriteLocked) 2622 && !vdIoCtxIsDiskLockOwner(pDisk, pIoCtx)) 2530 2623 { 2531 2624 RTLISTNODE ListTmp; … … 2577 2670 if (pIoCtx->enmTxDir == VDIOCTXTXDIR_FLUSH) 2578 2671 { 2579 vdIoCtxUnlockDisk(pDisk, pIoCtx );2672 vdIoCtxUnlockDisk(pDisk, pIoCtx, true /* fProcessDerredReqs */); 2580 2673 vdThreadFinishWrite(pDisk); 2581 2674 } … … 3739 3832 pDisk->pInterfaceThreadSyncCallbacks = NULL; 3740 3833 pDisk->fLocked = false; 3834 pDisk->pIoCtxLockOwner = NULL; 3741 3835 RTListInit(&pDisk->ListWriteLocked); 3742 3836
Note:
See TracChangeset
for help on using the changeset viewer.