summaryrefslogtreecommitdiff
path: root/src/VBox/VMM/VMMR3/PDMAsyncCompletionFileNormal.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/VBox/VMM/VMMR3/PDMAsyncCompletionFileNormal.cpp')
-rw-r--r--src/VBox/VMM/VMMR3/PDMAsyncCompletionFileNormal.cpp67
1 files changed, 43 insertions, 24 deletions
diff --git a/src/VBox/VMM/VMMR3/PDMAsyncCompletionFileNormal.cpp b/src/VBox/VMM/VMMR3/PDMAsyncCompletionFileNormal.cpp
index 2b37f009..44d31e7f 100644
--- a/src/VBox/VMM/VMMR3/PDMAsyncCompletionFileNormal.cpp
+++ b/src/VBox/VMM/VMMR3/PDMAsyncCompletionFileNormal.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2006-2011 Oracle Corporation
+ * Copyright (C) 2006-2013 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -54,9 +54,9 @@ int pdmacFileAioMgrNormalInit(PPDMACEPFILEMGR pAioMgr)
{
pAioMgr->cRequestsActiveMax = PDMACEPFILEMGR_REQS_STEP;
- int rc = RTFileAioCtxCreate(&pAioMgr->hAioCtx, RTFILEAIO_UNLIMITED_REQS);
+ int rc = RTFileAioCtxCreate(&pAioMgr->hAioCtx, RTFILEAIO_UNLIMITED_REQS, 0 /* fFlags */);
if (rc == VERR_OUT_OF_RANGE)
- rc = RTFileAioCtxCreate(&pAioMgr->hAioCtx, pAioMgr->cRequestsActiveMax);
+ rc = RTFileAioCtxCreate(&pAioMgr->hAioCtx, pAioMgr->cRequestsActiveMax, 0 /* fFlags */);
if (RT_SUCCESS(rc))
{
@@ -354,9 +354,9 @@ static int pdmacFileAioMgrNormalGrow(PPDMACEPFILEMGR pAioMgr)
pAioMgr->cRequestsActiveMax += PDMACEPFILEMGR_REQS_STEP;
RTFILEAIOCTX hAioCtxNew = NIL_RTFILEAIOCTX;
- int rc = RTFileAioCtxCreate(&hAioCtxNew, RTFILEAIO_UNLIMITED_REQS);
+ int rc = RTFileAioCtxCreate(&hAioCtxNew, RTFILEAIO_UNLIMITED_REQS, 0 /* fFlags */);
if (rc == VERR_OUT_OF_RANGE)
- rc = RTFileAioCtxCreate(&hAioCtxNew, pAioMgr->cRequestsActiveMax);
+ rc = RTFileAioCtxCreate(&hAioCtxNew, pAioMgr->cRequestsActiveMax, 0 /* fFlags */);
if (RT_SUCCESS(rc))
{
@@ -637,12 +637,19 @@ static int pdmacFileAioMgrNormalReqsEnqueue(PPDMACEPFILEMGR pAioMgr,
static bool pdmacFileAioMgrNormalIsRangeLocked(PPDMASYNCCOMPLETIONENDPOINTFILE pEndpoint,
RTFOFF offStart, size_t cbRange,
- PPDMACTASKFILE pTask)
+ PPDMACTASKFILE pTask, bool fAlignedReq)
{
AssertMsg( pTask->enmTransferType == PDMACTASKFILETRANSFER_WRITE
|| pTask->enmTransferType == PDMACTASKFILETRANSFER_READ,
("Invalid task type %d\n", pTask->enmTransferType));
+ /*
+ * If there is no unaligned request active and the current one is aligned
+ * just pass it through.
+ */
+ if (!pEndpoint->AioMgr.cLockedReqsActive && fAlignedReq)
+ return false;
+
PPDMACFILERANGELOCK pRangeLock;
pRangeLock = (PPDMACFILERANGELOCK)RTAvlrFileOffsetRangeGet(pEndpoint->AioMgr.pTreeRangesLocked, offStart);
if (!pRangeLock)
@@ -658,12 +665,7 @@ static bool pdmacFileAioMgrNormalIsRangeLocked(PPDMASYNCCOMPLETIONENDPOINTFILE p
}
/* Check whether we have one of the situations explained below */
- if ( pRangeLock
-#if 0 /** @todo later. For now we will just block all requests if they interfere */
- && ( (pRangeLock->fReadLock && pTask->enmTransferType == PDMACTASKFILETRANSFER_WRITE)
- || (!pRangeLock->fReadLock)
-#endif
- )
+ if (pRangeLock)
{
/* Add to the list. */
pTask->pNext = NULL;
@@ -689,15 +691,25 @@ static bool pdmacFileAioMgrNormalIsRangeLocked(PPDMASYNCCOMPLETIONENDPOINTFILE p
static int pdmacFileAioMgrNormalRangeLock(PPDMACEPFILEMGR pAioMgr,
PPDMASYNCCOMPLETIONENDPOINTFILE pEndpoint,
RTFOFF offStart, size_t cbRange,
- PPDMACTASKFILE pTask)
+ PPDMACTASKFILE pTask, bool fAlignedReq)
{
LogFlowFunc(("pAioMgr=%#p pEndpoint=%#p offStart=%RTfoff cbRange=%zu pTask=%#p\n",
pAioMgr, pEndpoint, offStart, cbRange, pTask));
- AssertMsg(!pdmacFileAioMgrNormalIsRangeLocked(pEndpoint, offStart, cbRange, pTask),
+ AssertMsg(!pdmacFileAioMgrNormalIsRangeLocked(pEndpoint, offStart, cbRange, pTask, fAlignedReq),
("Range is already locked offStart=%RTfoff cbRange=%u\n",
offStart, cbRange));
+ /*
+ * If there is no unaligned request active and the current one is aligned
+ * just don't use the lock.
+ */
+ if (!pEndpoint->AioMgr.cLockedReqsActive && fAlignedReq)
+ {
+ pTask->pRangeLock = NULL;
+ return VINF_SUCCESS;
+ }
+
PPDMACFILERANGELOCK pRangeLock = (PPDMACFILERANGELOCK)RTMemCacheAlloc(pAioMgr->hMemCacheRangeLocks);
if (!pRangeLock)
return VERR_NO_MEMORY;
@@ -715,6 +727,7 @@ static int pdmacFileAioMgrNormalRangeLock(PPDMACEPFILEMGR pAioMgr,
/* Let the task point to its lock. */
pTask->pRangeLock = pRangeLock;
+ pEndpoint->AioMgr.cLockedReqsActive++;
return VINF_SUCCESS;
}
@@ -728,7 +741,10 @@ static PPDMACTASKFILE pdmacFileAioMgrNormalRangeLockFree(PPDMACEPFILEMGR pAioMgr
LogFlowFunc(("pAioMgr=%#p pEndpoint=%#p pRangeLock=%#p\n",
pAioMgr, pEndpoint, pRangeLock));
- AssertPtr(pRangeLock);
+ /* pRangeLock can be NULL if there was no lock assigned with the task. */
+ if (!pRangeLock)
+ return NULL;
+
Assert(pRangeLock->cRefs == 1);
RTAvlrFileOffsetRemove(pEndpoint->AioMgr.pTreeRangesLocked, pRangeLock->Core.Key);
@@ -736,6 +752,7 @@ static PPDMACTASKFILE pdmacFileAioMgrNormalRangeLockFree(PPDMACEPFILEMGR pAioMgr
pRangeLock->pWaitingTasksHead = NULL;
pRangeLock->pWaitingTasksTail = NULL;
RTMemCacheFree(pAioMgr->hMemCacheRangeLocks, pRangeLock);
+ pEndpoint->AioMgr.cLockedReqsActive--;
return pTasksWaitingHead;
}
@@ -771,7 +788,8 @@ static int pdmacFileAioMgrNormalTaskPrepareBuffered(PPDMACEPFILEMGR pAioMgr,
* the same range. This will result in data corruption if both are executed concurrently.
*/
int rc = VINF_SUCCESS;
- bool fLocked = pdmacFileAioMgrNormalIsRangeLocked(pEndpoint, pTask->Off, pTask->DataSeg.cbSeg, pTask);
+ bool fLocked = pdmacFileAioMgrNormalIsRangeLocked(pEndpoint, pTask->Off, pTask->DataSeg.cbSeg, pTask,
+ true /* fAlignedReq */);
if (!fLocked)
{
/* Get a request handle. */
@@ -799,7 +817,7 @@ static int pdmacFileAioMgrNormalTaskPrepareBuffered(PPDMACEPFILEMGR pAioMgr,
rc = pdmacFileAioMgrNormalRangeLock(pAioMgr, pEndpoint, pTask->Off,
pTask->DataSeg.cbSeg,
- pTask);
+ pTask, true /* fAlignedReq */);
if (RT_SUCCESS(rc))
{
@@ -825,6 +843,8 @@ static int pdmacFileAioMgrNormalTaskPrepareNonBuffered(PPDMACEPFILEMGR pAioMgr,
RTFOFF offStart = pTask->Off & ~(RTFOFF)(512-1);
size_t cbToTransfer = RT_ALIGN_Z(pTask->DataSeg.cbSeg + (pTask->Off - offStart), 512);
PDMACTASKFILETRANSFER enmTransferType = pTask->enmTransferType;
+ bool fAlignedReq = cbToTransfer == pTask->DataSeg.cbSeg
+ && offStart == pTask->Off;
AssertMsg( pTask->enmTransferType == PDMACTASKFILETRANSFER_WRITE
|| (uint64_t)(offStart + cbToTransfer) <= pEndpoint->cbFile,
@@ -852,7 +872,7 @@ static int pdmacFileAioMgrNormalTaskPrepareNonBuffered(PPDMACEPFILEMGR pAioMgr,
* the same range. This will result in data corruption if both are executed concurrently.
*/
int rc = VINF_SUCCESS;
- bool fLocked = pdmacFileAioMgrNormalIsRangeLocked(pEndpoint, offStart, cbToTransfer, pTask);
+ bool fLocked = pdmacFileAioMgrNormalIsRangeLocked(pEndpoint, offStart, cbToTransfer, pTask, fAlignedReq);
if (!fLocked)
{
PPDMASYNCCOMPLETIONEPCLASSFILE pEpClassFile = (PPDMASYNCCOMPLETIONEPCLASSFILE)pEndpoint->Core.pEpClass;
@@ -862,8 +882,7 @@ static int pdmacFileAioMgrNormalTaskPrepareNonBuffered(PPDMACEPFILEMGR pAioMgr,
RTFILEAIOREQ hReq = pdmacFileAioMgrNormalRequestAlloc(pAioMgr);
AssertMsg(hReq != NIL_RTFILEAIOREQ, ("Out of request handles\n"));
- if ( RT_UNLIKELY(cbToTransfer != pTask->DataSeg.cbSeg)
- || RT_UNLIKELY(offStart != pTask->Off)
+ if ( !fAlignedReq
|| ((pEpClassFile->uBitmaskAlignment & (RTR3UINTPTR)pvBuf) != (RTR3UINTPTR)pvBuf))
{
LogFlow(("Using bounce buffer for task %#p cbToTransfer=%zd cbSeg=%zd offStart=%RTfoff off=%RTfoff\n",
@@ -928,8 +947,7 @@ static int pdmacFileAioMgrNormalTaskPrepareNonBuffered(PPDMACEPFILEMGR pAioMgr,
offStart, pvBuf, cbToTransfer, pTask);
AssertRC(rc);
- rc = pdmacFileAioMgrNormalRangeLock(pAioMgr, pEndpoint, offStart, cbToTransfer, pTask);
-
+ rc = pdmacFileAioMgrNormalRangeLock(pAioMgr, pEndpoint, offStart, cbToTransfer, pTask, fAlignedReq);
if (RT_SUCCESS(rc))
{
pTask->hReq = hReq;
@@ -998,6 +1016,7 @@ static int pdmacFileAioMgrNormalProcessTaskList(PPDMACTASKFILE pTaskHead,
rc = RTFileAioReqPrepareFlush(hReq, pEndpoint->hFile, pCurr);
if (RT_FAILURE(rc))
{
+ LogRel(("AIOMgr: Preparing flush failed with %Rrc, disabling async flushes\n", rc));
pEndpoint->fAsyncFlushSupported = false;
pdmacFileAioMgrNormalRequestFree(pAioMgr, hReq);
rc = VINF_SUCCESS; /* Fake success */
@@ -1349,7 +1368,7 @@ static void pdmacFileAioMgrNormalReqCompleteRc(PPDMACEPFILEMGR pAioMgr, RTFILEAI
if (pTask->enmTransferType == PDMACTASKFILETRANSFER_FLUSH)
{
- LogFlow(("Async flushes are not supported for this endpoint, disabling\n"));
+ LogRel(("AIOMgr: Flush failed with %Rrc, disabling async flushes\n", rcReq));
pEndpoint->fAsyncFlushSupported = false;
AssertMsg(pEndpoint->pFlushReq == pTask, ("Failed flush request doesn't match active one\n"));
/* The other method will take over now. */
@@ -1497,8 +1516,8 @@ static void pdmacFileAioMgrNormalReqCompleteRc(PPDMACEPFILEMGR pAioMgr, RTFILEAI
/* Write it now. */
pTask->fPrefetch = false;
- size_t cbToTransfer = RT_ALIGN_Z(pTask->DataSeg.cbSeg, 512);
RTFOFF offStart = pTask->Off & ~(RTFOFF)(512-1);
+ size_t cbToTransfer = RT_ALIGN_Z(pTask->DataSeg.cbSeg + (pTask->Off - offStart), 512);
/* Grow the file if needed. */
if (RT_UNLIKELY((uint64_t)(pTask->Off + pTask->DataSeg.cbSeg) > pEndpoint->cbFile))