- Timestamp:
- Jun 16, 2014 7:09:13 PM (11 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Storage/VD.cpp
r51102 r51623 278 278 * the current one completes. - NIL_VDIOCTX if unlocked. */ 279 279 volatile PVDIOCTX pIoCtxLockOwner; 280 /** If the disk was locked by a growing write, flush or discard request this 281 * contains the start offset to check for interfering I/O while it is in progress. */ 282 uint64_t uOffsetStartLocked; 283 /** If the disk was locked by a growing write, flush or discard request this contains 284 * the first non affected offset to check for interfering I/O while it is in progress. */ 285 uint64_t uOffsetEndLocked; 280 286 281 287 /** Pointer to the L2 disk cache if any. */ … … 1550 1556 DECLINLINE(void) vdIoCtxDefer(PVBOXHDD pDisk, PVDIOCTX pIoCtx) 1551 1557 { 1552 LogFlowFunc(("Deferring writepIoCtx=%#p\n", pIoCtx));1558 LogFlowFunc(("Deferring I/O context pIoCtx=%#p\n", pIoCtx)); 1553 1559 1554 1560 Assert(!pIoCtx->pIoCtxParent && !(pIoCtx->fFlags & VDIOCTX_FLAGS_BLOCKED)); … … 1646 1652 if ( RT_SUCCESS(rc) 1647 1653 && !pIoCtx->cMetaTransfersPending 1648 && !pIoCtx->cDataTransfersPending) 1654 && !pIoCtx->cDataTransfersPending 1655 && !(pIoCtx->fFlags & VDIOCTX_FLAGS_BLOCKED)) 1649 1656 rc = VINF_VD_ASYNC_IO_FINISHED; 1650 1657 else if ( RT_SUCCESS(rc) … … 1973 1980 size_t cbThisRead; 1974 1981 1982 /* 1983 * Check whether there is a full block write in progress which was not allocated. 1984 * Defer I/O if the range interferes but only if it does not belong to the 1985 * write doing the allocation. 1986 */ 1987 if ( pDisk->pIoCtxLockOwner != NIL_VDIOCTX 1988 && uOffset >= pDisk->uOffsetStartLocked 1989 && uOffset < pDisk->uOffsetEndLocked 1990 && ( !pIoCtx->pIoCtxParent 1991 || pIoCtx->pIoCtxParent != pDisk->pIoCtxLockOwner)) 1992 { 1993 Log(("Interferring read while allocating a new block => deferring read\n")); 1994 vdIoCtxDefer(pDisk, pIoCtx); 1995 return VINF_SUCCESS; 1996 } 1997 1975 1998 /* Loop until all reads started or we have a backend which needs to read metadata. */ 1976 1999 do … … 2002 2025 else 2003 2026 { 2004 2005 2027 /* 2006 2028 * Try to read from the given image. … … 2921 2943 * unwanted expanding of images. VMDK is an example. */ 2922 2944 cbThisWrite = cbWrite; 2945 2946 /* 2947 * Check whether there is a full block write in progress which was not allocated. 2948 * Defer I/O if the range interferes. 2949 */ 2950 if ( pDisk->pIoCtxLockOwner != NIL_VDIOCTX 2951 && uOffset >= pDisk->uOffsetStartLocked 2952 && uOffset < pDisk->uOffsetEndLocked) 2953 { 2954 Log(("Interferring write while allocating a new block => deferring write\n")); 2955 vdIoCtxDefer(pDisk, pIoCtx); 2956 rc = VERR_VD_ASYNC_IO_IN_PROGRESS; 2957 break; 2958 } 2959 2923 2960 fWrite = (pImage->uOpenFlags & VD_OPEN_FLAGS_HONOR_SAME) 2924 2961 ? 0 : VD_WRITE_NO_ALLOC; 2925 rc = pImage->Backend->pfnWrite(pImage->pBackendData, uOffset, 2926 cbThisWrite, pIoCtx, 2927 &cbThisWrite, &cbPreRead, 2928 &cbPostRead, fWrite); 2962 rc = pImage->Backend->pfnWrite(pImage->pBackendData, uOffset, cbThisWrite, 2963 pIoCtx, &cbThisWrite, &cbPreRead, &cbPostRead, 2964 fWrite); 2929 2965 if (rc == VERR_VD_BLOCK_FREE) 2930 2966 { … … 2963 2999 LogFlowFunc(("Disk is growing because of pIoCtx=%#p pIoCtxWrite=%#p\n", 2964 3000 pIoCtx, pIoCtxWrite)); 3001 3002 /* Save the current range for the growing operation to check for intersecting requests later. */ 3003 pDisk->uOffsetStartLocked = uOffset - cbPreRead; 3004 pDisk->uOffsetEndLocked = uOffset + cbThisWrite + cbPostRead; 2965 3005 2966 3006 pIoCtxWrite->Type.Child.cbPreRead = cbPreRead; … … 3050 3090 if (RT_SUCCESS(rc)) 3051 3091 { 3092 /* Mark the whole disk as locked. */ 3093 pDisk->uOffsetStartLocked = 0; 3094 pDisk->uOffsetEndLocked = UINT64_C(0xffffffffffffffff); 3095 3052 3096 vdResetModifiedFlag(pDisk); 3053 3097 rc = pImage->Backend->pfnFlush(pImage->pBackendData, pIoCtx); … … 3319 3363 size_t cbDiscardLeft = pIoCtx->Req.Discard.cbDiscardLeft; 3320 3364 size_t cbThisDiscard; 3365 3366 pDisk->uOffsetStartLocked = offStart; 3367 pDisk->uOffsetEndLocked = offStart + cbDiscardLeft; 3321 3368 3322 3369 if (RT_UNLIKELY(!pDiscard))
Note:
See TracChangeset
for help on using the changeset viewer.