Changeset 23956 in vbox for trunk/src/VBox/VMM
- Timestamp:
- Oct 21, 2009 10:18:40 PM (16 years ago)
- svn:sync-xref-src-repo-rev:
- 53775
- Location:
- trunk/src/VBox/VMM
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/PDMAsyncCompletionFile.cpp
r23952 r23956 25 25 *******************************************************************************/ 26 26 #define LOG_GROUP LOG_GROUP_PDM_ASYNC_COMPLETION 27 #define RT_STRICT 27 28 #include "PDMInternal.h" 28 29 #include <VBox/pdm.h> … … 381 382 * @param pEpClass Pointer to the endpoint class data. 382 383 * @param ppAioMgr Where to store the pointer to the new async I/O manager on success. 384 * @param fFailsafe Flag to force a failsafe manager even if the global flag is not set. 383 385 */ 384 int pdmacFileAioMgrCreate(PPDMASYNCCOMPLETIONEPCLASSFILE pEpClass, PPPDMACEPFILEMGR ppAioMgr )386 int pdmacFileAioMgrCreate(PPDMASYNCCOMPLETIONEPCLASSFILE pEpClass, PPPDMACEPFILEMGR ppAioMgr, bool fFailsafe) 385 387 { 386 388 int rc = VINF_SUCCESS; … … 392 394 if (RT_SUCCESS(rc)) 393 395 { 394 pAioMgrNew->fFailsafe = pEpClass->fFailsafe;396 pAioMgrNew->fFailsafe = fFailsafe ? true : pEpClass->fFailsafe; 395 397 396 398 rc = RTSemEventCreate(&pAioMgrNew->EventSem); … … 637 639 { 638 640 /* Safe mode. Every file has its own async I/O manager. */ 639 rc = pdmacFileAioMgrCreate(pEpClassFile, &pAioMgr );641 rc = pdmacFileAioMgrCreate(pEpClassFile, &pAioMgr, false); 640 642 AssertRC(rc); 641 643 } … … 656 658 if (!pEpClassFile->pAioMgrHead) 657 659 { 658 rc = pdmacFileAioMgrCreate(pEpClassFile, &pAioMgr );660 rc = pdmacFileAioMgrCreate(pEpClassFile, &pAioMgr, false); 659 661 AssertRC(rc); 660 662 } -
trunk/src/VBox/VMM/PDMAsyncCompletionFileFailsafe.cpp
r22979 r23956 21 21 */ 22 22 #define LOG_GROUP LOG_GROUP_PDM_ASYNC_COMPLETION 23 #define RT_STRICT 23 24 #include <iprt/types.h> 25 #include <iprt/assert.h> 24 26 #include <VBox/log.h> 25 27 26 28 #include "PDMAsyncCompletionFileInternal.h" 27 29 28 static int pdmacFileAioMgrFailsafeProcessEndpoint(PPDMASYNCCOMPLETIONENDPOINTFILE pEndpoint) 30 static int pdmacFileAioMgrFailsafeProcessEndpointTaskList(PPDMASYNCCOMPLETIONENDPOINTFILE pEndpoint, 31 PPDMACTASKFILE pTasks) 29 32 { 30 33 int rc = VINF_SUCCESS; 31 PPDMACTASKFILE pTasks = pdmacFileEpGetNewTasks(pEndpoint);32 34 33 35 while (pTasks) … … 83 85 } 84 86 87 static int pdmacFileAioMgrFailsafeProcessEndpoint(PPDMASYNCCOMPLETIONENDPOINTFILE pEndpoint) 88 { 89 int rc = VINF_SUCCESS; 90 PPDMACTASKFILE pTasks = pEndpoint->AioMgr.pReqsPendingHead; 91 92 pEndpoint->AioMgr.pReqsPendingHead = NULL; 93 pEndpoint->AioMgr.pReqsPendingTail = NULL; 94 95 /* Process the request pending list first in case the endpoint was migrated due to an error. */ 96 if (pTasks) 97 rc = pdmacFileAioMgrFailsafeProcessEndpointTaskList(pEndpoint, pTasks); 98 99 if (RT_SUCCESS(rc)) 100 { 101 pTasks = pdmacFileEpGetNewTasks(pEndpoint); 102 103 if (pTasks); 104 rc = pdmacFileAioMgrFailsafeProcessEndpointTaskList(pEndpoint, pTasks); 105 } 106 107 return rc; 108 } 109 85 110 /** 86 111 * A fallback method in case something goes wrong with the normal -
trunk/src/VBox/VMM/PDMAsyncCompletionFileInternal.h
r23404 r23956 528 528 void pdmacFileAioMgrNormalDestroy(PPDMACEPFILEMGR pAioMgr); 529 529 530 int pdmacFileAioMgrCreate(PPDMASYNCCOMPLETIONEPCLASSFILE pEpClass, PPPDMACEPFILEMGR ppAioMgr );530 int pdmacFileAioMgrCreate(PPDMASYNCCOMPLETIONEPCLASSFILE pEpClass, PPPDMACEPFILEMGR ppAioMgr, bool fFailsafe); 531 531 532 532 int pdmacFileAioMgrAddEndpoint(PPDMACEPFILEMGR pAioMgr, PPDMASYNCCOMPLETIONENDPOINTFILE pEndpoint); -
trunk/src/VBox/VMM/PDMAsyncCompletionFileNormal.cpp
r23812 r23956 21 21 */ 22 22 #define LOG_GROUP LOG_GROUP_PDM_ASYNC_COMPLETION 23 #define RT_STRICT 23 24 #include <iprt/types.h> 24 25 #include <iprt/asm.h> … … 26 27 #include <iprt/mem.h> 27 28 #include <iprt/string.h> 29 #include <iprt/assert.h> 28 30 #include <VBox/log.h> 29 31 … … 206 208 { 207 209 rc = pdmacFileAioMgrCreate((PPDMASYNCCOMPLETIONEPCLASSFILE)pAioMgr->pEndpointsHead->Core.pEpClass, 208 &pAioMgrNew );210 &pAioMgrNew, false); 209 211 if (RT_SUCCESS(rc)) 210 212 { … … 850 852 pEndpoint = pTask->pEndpoint; 851 853 852 AssertMsg( RT_SUCCESS(rcReq) 853 && ( (cbTransfered == pTask->DataSeg.cbSeg) 854 || (pTask->fBounceBuffer)), 855 ("Task didn't completed successfully (rc=%Rrc) or was incomplete (cbTransfered=%u)\n", rcReq, cbTransfered)); 856 857 if (pTask->fPrefetch) 854 /* 855 * It is possible that the request failed on Linux with kernels < 2.6.23 856 * if the passed buffer was allocated with remap_pfn_range or if the file 857 * is on an NFS endpoint which does not support async and direct I/O at the same time. 858 * The endpoint will be migrated to a failsafe manager in case a request fails. 859 */ 860 if (RT_FAILURE(rcReq)) 858 861 { 859 Assert(pTask->enmTransferType == PDMACTASKFILETRANSFER_WRITE); 860 Assert(pTask->fBounceBuffer); 861 862 memcpy(((uint8_t *)pTask->pvBounceBuffer) + pTask->uBounceBufOffset, 863 pTask->DataSeg.pvSeg, 864 pTask->DataSeg.cbSeg); 865 866 /* Write it now. */ 867 pTask->fPrefetch = false; 868 size_t cbToTransfer = RT_ALIGN_Z(pTask->DataSeg.cbSeg, 512); 869 RTFOFF offStart = pTask->Off & ~(RTFOFF)(512-1); 870 871 /* Grow the file if needed. */ 872 if (RT_UNLIKELY((uint64_t)(pTask->Off + pTask->DataSeg.cbSeg) > pEndpoint->cbFile)) 862 /* Free bounce buffers and the IPRT request. */ 863 pAioMgr->pahReqsFree[pAioMgr->iFreeEntryNext] = apReqs[i]; 864 pAioMgr->iFreeEntryNext = (pAioMgr->iFreeEntryNext + 1) % pAioMgr->cReqEntries; 865 866 pAioMgr->cRequestsActive--; 867 pEndpoint->AioMgr.cRequestsActive--; 868 pEndpoint->AioMgr.cReqsProcessed++; 869 870 if (pTask->fBounceBuffer) 871 RTMemFree(pTask->pvBounceBuffer); 872 873 /* Queue the request on the pending list. */ 874 pTask->pNext = pEndpoint->AioMgr.pReqsPendingHead; 875 pEndpoint->AioMgr.pReqsPendingHead = pTask; 876 877 /* Create a new failsafe manager if neccessary. */ 878 if (!pEndpoint->AioMgr.fMoving) 873 879 { 874 ASMAtomicWriteU64(&pEndpoint->cbFile, pTask->Off + pTask->DataSeg.cbSeg); 875 RTFileSetSize(pEndpoint->File, pTask->Off + pTask->DataSeg.cbSeg); 880 PPDMACEPFILEMGR pAioMgrFailsafe; 881 882 pEndpoint->AioMgr.fMoving = true; 883 884 rc = pdmacFileAioMgrCreate((PPDMASYNCCOMPLETIONEPCLASSFILE)pEndpoint->Core.pEpClass, 885 &pAioMgrFailsafe, true); 886 AssertRC(rc); 887 888 pEndpoint->AioMgr.pAioMgrDst = pAioMgrFailsafe; 876 889 } 877 890 878 rc = RTFileAioReqPrepareWrite(apReqs[i], pEndpoint->File, 879 offStart, pTask->pvBounceBuffer, cbToTransfer, pTask); 880 AssertRC(rc); 881 rc = RTFileAioCtxSubmit(pAioMgr->hAioCtx, &apReqs[i], 1); 882 AssertRC(rc); 891 /* If this was the last request for the endpoint migrate it to the new manager. */ 892 if (!pEndpoint->AioMgr.cRequestsActive) 893 { 894 bool fReqsPending = pdmacFileAioMgrNormalRemoveEndpoint(pEndpoint); 895 Assert(!fReqsPending); 896 897 rc = pdmacFileAioMgrAddEndpoint(pEndpoint->AioMgr.pAioMgrDst, pEndpoint); 898 AssertRC(rc); 899 } 883 900 } 884 901 else 885 902 { 886 if (pTask->fBounceBuffer) 903 AssertMsg(( (cbTransfered == pTask->DataSeg.cbSeg) 904 || (pTask->fBounceBuffer && (cbTransfered >= pTask->DataSeg.cbSeg))), 905 ("Task didn't completed successfully (rc=%Rrc) or was incomplete (cbTransfered=%u)\n", rcReq, cbTransfered)); 906 907 if (pTask->fPrefetch) 887 908 { 888 if (pTask->enmTransferType == PDMACTASKFILETRANSFER_READ) 889 memcpy(pTask->DataSeg.pvSeg, 890 ((uint8_t *)pTask->pvBounceBuffer) + pTask->uBounceBufOffset, 891 pTask->DataSeg.cbSeg); 892 893 RTMemPageFree(pTask->pvBounceBuffer); 909 Assert(pTask->enmTransferType == PDMACTASKFILETRANSFER_WRITE); 910 Assert(pTask->fBounceBuffer); 911 912 memcpy(((uint8_t *)pTask->pvBounceBuffer) + pTask->uBounceBufOffset, 913 pTask->DataSeg.pvSeg, 914 pTask->DataSeg.cbSeg); 915 916 /* Write it now. */ 917 pTask->fPrefetch = false; 918 size_t cbToTransfer = RT_ALIGN_Z(pTask->DataSeg.cbSeg, 512); 919 RTFOFF offStart = pTask->Off & ~(RTFOFF)(512-1); 920 921 /* Grow the file if needed. */ 922 if (RT_UNLIKELY((uint64_t)(pTask->Off + pTask->DataSeg.cbSeg) > pEndpoint->cbFile)) 923 { 924 ASMAtomicWriteU64(&pEndpoint->cbFile, pTask->Off + pTask->DataSeg.cbSeg); 925 RTFileSetSize(pEndpoint->File, pTask->Off + pTask->DataSeg.cbSeg); 926 } 927 928 rc = RTFileAioReqPrepareWrite(apReqs[i], pEndpoint->File, 929 offStart, pTask->pvBounceBuffer, cbToTransfer, pTask); 930 AssertRC(rc); 931 rc = RTFileAioCtxSubmit(pAioMgr->hAioCtx, &apReqs[i], 1); 932 AssertRC(rc); 894 933 } 895 896 /* Put the entry on the free array */ 897 pAioMgr->pahReqsFree[pAioMgr->iFreeEntryNext] = apReqs[i]; 898 pAioMgr->iFreeEntryNext = (pAioMgr->iFreeEntryNext + 1) % pAioMgr->cReqEntries; 899 900 pAioMgr->cRequestsActive--; 901 pEndpoint->AioMgr.cRequestsActive--; 902 pEndpoint->AioMgr.cReqsProcessed++; 903 904 /* Call completion callback */ 905 pTask->pfnCompleted(pTask, pTask->pvUser); 906 pdmacFileTaskFree(pEndpoint, pTask); 907 908 /* 909 * If there is no request left on the endpoint but a flush request is set 910 * it completed now and we notify the owner. 911 * Furthermore we look for new requests and continue. 912 */ 913 if (!pEndpoint->AioMgr.cRequestsActive && pEndpoint->pFlushReq) 934 else 914 935 { 936 if (pTask->fBounceBuffer) 937 { 938 if (pTask->enmTransferType == PDMACTASKFILETRANSFER_READ) 939 memcpy(pTask->DataSeg.pvSeg, 940 ((uint8_t *)pTask->pvBounceBuffer) + pTask->uBounceBufOffset, 941 pTask->DataSeg.cbSeg); 942 943 RTMemPageFree(pTask->pvBounceBuffer); 944 } 945 946 /* Put the entry on the free array */ 947 pAioMgr->pahReqsFree[pAioMgr->iFreeEntryNext] = apReqs[i]; 948 pAioMgr->iFreeEntryNext = (pAioMgr->iFreeEntryNext + 1) % pAioMgr->cReqEntries; 949 950 pAioMgr->cRequestsActive--; 951 pEndpoint->AioMgr.cRequestsActive--; 952 pEndpoint->AioMgr.cReqsProcessed++; 953 915 954 /* Call completion callback */ 916 pTask = pEndpoint->pFlushReq;917 pEndpoint->pFlushReq = NULL;918 919 AssertMsg(pTask->pEndpoint == pEndpoint, ("Endpoint of the flush request does not match assigned one\n"));920 921 955 pTask->pfnCompleted(pTask, pTask->pvUser); 922 956 pdmacFileTaskFree(pEndpoint, pTask); 957 958 /* 959 * If there is no request left on the endpoint but a flush request is set 960 * it completed now and we notify the owner. 961 * Furthermore we look for new requests and continue. 962 */ 963 if (!pEndpoint->AioMgr.cRequestsActive && pEndpoint->pFlushReq) 964 { 965 /* Call completion callback */ 966 pTask = pEndpoint->pFlushReq; 967 pEndpoint->pFlushReq = NULL; 968 969 AssertMsg(pTask->pEndpoint == pEndpoint, ("Endpoint of the flush request does not match assigned one\n")); 970 971 pTask->pfnCompleted(pTask, pTask->pvUser); 972 pdmacFileTaskFree(pEndpoint, pTask); 973 } 974 else if (RT_UNLIKELY(!pEndpoint->AioMgr.cRequestsActive && pEndpoint->AioMgr.fMoving)) 975 { 976 /* If we the endpoint is about to be migrated do it now. */ 977 bool fReqsPending = pdmacFileAioMgrNormalRemoveEndpoint(pEndpoint); 978 Assert(!fReqsPending); 979 980 rc = pdmacFileAioMgrAddEndpoint(pEndpoint->AioMgr.pAioMgrDst, pEndpoint); 981 AssertRC(rc); 982 } 923 983 } 924 } 925 } 984 } /* request completed successfully */ 985 } /* for every completed request */ 926 986 927 987 /* Check for an external blocking event before we go to sleep again. */
Note:
See TracChangeset
for help on using the changeset viewer.