VirtualBox

Changeset 23404 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Sep 29, 2009 10:18:37 AM (15 years ago)
Author:
vboxsync
Message:

AsyncCompletion: Handle out of resources case properly. Should fix assertion on Darwin

Location:
trunk/src/VBox/VMM
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/PDMAsyncCompletionFileInternal.h

    r22851 r23404  
    331331    /** Global cache data. */
    332332    PDMACFILECACHEGLOBAL                Cache;
     333    /** Flag whether the out of resources warning was printed already. */
     334    bool                                fOutOfResourcesWarningPrinted;
    333335} PDMASYNCCOMPLETIONEPCLASSFILE;
    334336/** Pointer to the endpoint class data. */
  • trunk/src/VBox/VMM/PDMAsyncCompletionFileNormal.cpp

    r23213 r23404  
    287287}
    288288
     289/**
     290 * Put a list of tasks in the pending request list of an endpoint.
     291 */
     292DECLINLINE(void) pdmacFileAioMgrEpAddTaskList(PPDMASYNCCOMPLETIONENDPOINTFILE pEndpoint, PPDMACTASKFILE pTaskHead)
     293{
     294    /* Add the rest of the tasks to the pending list */
     295    if (!pEndpoint->AioMgr.pReqsPendingHead)
     296    {
     297        Assert(!pEndpoint->AioMgr.pReqsPendingTail);
     298        pEndpoint->AioMgr.pReqsPendingHead = pTaskHead;
     299    }
     300    else
     301    {
     302        Assert(pEndpoint->AioMgr.pReqsPendingTail);
     303        pEndpoint->AioMgr.pReqsPendingTail->pNext = pTaskHead;
     304    }
     305
     306    /* Update the tail. */
     307    while (pTaskHead->pNext)
     308        pTaskHead = pTaskHead->pNext;
     309
     310    pEndpoint->AioMgr.pReqsPendingTail = pTaskHead;
     311}
     312
     313/**
     314 * Put one task in the pending request list of an endpoint.
     315 */
     316DECLINLINE(void) pdmacFileAioMgrEpAddTask(PPDMASYNCCOMPLETIONENDPOINTFILE pEndpoint, PPDMACTASKFILE pTask)
     317{
     318    /* Add the rest of the tasks to the pending list */
     319    if (!pEndpoint->AioMgr.pReqsPendingHead)
     320    {
     321        Assert(!pEndpoint->AioMgr.pReqsPendingTail);
     322        pEndpoint->AioMgr.pReqsPendingHead = pTask;
     323    }
     324    else
     325    {
     326        Assert(pEndpoint->AioMgr.pReqsPendingTail);
     327        pEndpoint->AioMgr.pReqsPendingTail->pNext = pTask;
     328    }
     329
     330    pEndpoint->AioMgr.pReqsPendingTail = pTask;
     331}
     332
     333/**
     334 * Wrapper around RTFIleAioCtxSubmit() which is also doing error handling.
     335 */
     336static int pdmacFileAioMgrNormalReqsEnqueue(PPDMACEPFILEMGR pAioMgr,
     337                                            PPDMASYNCCOMPLETIONENDPOINTFILE pEndpoint,
     338                                            PRTFILEAIOREQ pahReqs, size_t cReqs)
     339{
     340    int rc;
     341
     342    pAioMgr->cRequestsActive += cReqs;
     343    pEndpoint->AioMgr.cRequestsActive += cReqs;
     344
     345    rc = RTFileAioCtxSubmit(pAioMgr->hAioCtx, pahReqs, cReqs);
     346    if (RT_FAILURE(rc))
     347    {
     348        if (rc == VERR_FILE_AIO_INSUFFICIENT_RESSOURCES)
     349        {
     350            PPDMASYNCCOMPLETIONEPCLASSFILE pEpClass = (PPDMASYNCCOMPLETIONEPCLASSFILE)pEndpoint->Core.pEpClass;
     351
     352            /*
     353             * We run out of resources.
     354             * Need to check which requests got queued
     355             * and put the rest on the pending list again.
     356             */
     357            if (RT_UNLIKELY(!pEpClass->fOutOfResourcesWarningPrinted))
     358            {
     359                pEpClass->fOutOfResourcesWarningPrinted = true;
     360                LogRel(("AIOMgr: The operating system doesn't have enough resources "
     361                        "to handle the I/O load of the VM. Expect reduced I/O performance\n"));
     362            }
     363
     364            for (size_t i = 0; i < cReqs; i++)
     365            {
     366                int rcReq = RTFileAioReqGetRC(pahReqs[i], NULL);
     367
     368                if (rcReq != VERR_FILE_AIO_IN_PROGRESS)
     369                {
     370                    AssertMsg(rcReq == VERR_FILE_AIO_NOT_SUBMITTED,
     371                              ("Request returned unexpected return code: rc=%Rrc\n", rcReq));
     372
     373                    PPDMACTASKFILE pTask = (PPDMACTASKFILE)RTFileAioReqGetUser(pahReqs[i]);
     374
     375                    /* Put the entry on the free array */
     376                    pAioMgr->pahReqsFree[pAioMgr->iFreeEntryNext] = pahReqs[i];
     377                    pAioMgr->iFreeEntryNext = (pAioMgr->iFreeEntryNext + 1) % pAioMgr->cReqEntries;
     378
     379                    pdmacFileAioMgrEpAddTask(pEndpoint, pTask);
     380                    pAioMgr->cRequestsActive--;
     381                    pEndpoint->AioMgr.cRequestsActive--;
     382                }
     383            }
     384        }
     385        else
     386            AssertMsgFailed(("Unexpected return code rc=%Rrc\n", rc));
     387    }
     388
     389    return rc;
     390}
     391
    289392static int pdmacFileAioMgrNormalProcessTaskList(PPDMACTASKFILE pTaskHead,
    290393                                                PPDMACEPFILEMGR pAioMgr,
     
    307410        pTaskHead = pTaskHead->pNext;
    308411
     412        pCurr->pNext = NULL;
     413
    309414        AssertMsg(VALID_PTR(pCurr->pEndpoint) && (pCurr->pEndpoint == pEndpoint),
    310415                  ("Endpoints do not match\n"));
     
    324429                    pEndpoint->pFlushReq = pCurr;
    325430
    326                     if (pTaskHead)
    327                     {
    328                         /* Add the rest of the tasks to the pending list */
    329                         if (!pEndpoint->AioMgr.pReqsPendingHead)
    330                         {
    331                             Assert(!pEndpoint->AioMgr.pReqsPendingTail);
    332                             pEndpoint->AioMgr.pReqsPendingHead = pTaskHead;
    333                         }
    334                         else
    335                         {
    336                             Assert(pEndpoint->AioMgr.pReqsPendingTail);
    337                             pEndpoint->AioMgr.pReqsPendingTail->pNext = pTaskHead;
    338                         }
    339 
    340                         /* Update the tail. */
    341                         while (pTaskHead->pNext)
    342                             pTaskHead = pTaskHead->pNext;
    343 
    344                         pEndpoint->AioMgr.pReqsPendingTail = pTaskHead;
    345                     }
     431                    /* Do not process the task list further until the flush finished. */
     432                    pdmacFileAioMgrEpAddTaskList(pEndpoint, pTaskHead);
    346433                }
    347434                break;
     
    444531                if (cRequests == RT_ELEMENTS(apReqs))
    445532                {
    446                     pAioMgr->cRequestsActive += cRequests;
    447                     pEndpoint->AioMgr.cRequestsActive += cRequests;
    448                     rc = RTFileAioCtxSubmit(pAioMgr->hAioCtx, apReqs, cRequests);
     533                    rc = pdmacFileAioMgrNormalReqsEnqueue(pAioMgr, pEndpoint, apReqs, cRequests);
     534                    cRequests = 0;
    449535                    if (RT_FAILURE(rc))
    450536                    {
    451                         /* @todo implement */
    452                         AssertMsgFailed(("Implement\n"));
     537                        AssertMsg(rc == VERR_FILE_AIO_INSUFFICIENT_RESSOURCES, ("Unexpected return code\n"));
     538                        break;
    453539                    }
    454 
    455                     cRequests = 0;
    456540                }
    457541                break;
     
    464548    if (cRequests)
    465549    {
    466         pAioMgr->cRequestsActive += cRequests;
    467         pEndpoint->AioMgr.cRequestsActive += cRequests;
    468         rc = RTFileAioCtxSubmit(pAioMgr->hAioCtx, apReqs, cRequests);
    469         AssertMsgReturn(RT_SUCCESS(rc), ("Could not submit %u requests %Rrc\n", cRequests, rc), rc);
    470     }
    471 
    472     if (RT_UNLIKELY(!cMaxRequests && pTaskHead && !pEndpoint->pFlushReq))
    473     {
    474         /*
    475          * The I/O manager has no room left for more requests
    476          * but there are still requests to process.
    477          * Create a new I/O manager and let it handle some endpoints.
    478          */
    479 
    480         /* Add the rest of the tasks to the pending list first */
    481         if (!pEndpoint->AioMgr.pReqsPendingHead)
    482         {
    483             Assert(!pEndpoint->AioMgr.pReqsPendingTail);
    484             pEndpoint->AioMgr.pReqsPendingHead = pTaskHead;
    485         }
    486         else
    487         {
    488             Assert(pEndpoint->AioMgr.pReqsPendingTail);
    489             pEndpoint->AioMgr.pReqsPendingTail->pNext = pTaskHead;
    490         }
    491 
    492         /* Update the tail. */
    493         while (pTaskHead->pNext)
    494             pTaskHead = pTaskHead->pNext;
    495 
    496         pEndpoint->AioMgr.pReqsPendingTail = pTaskHead;
    497 
    498         pdmacFileAioMgrNormalBalanceLoad(pAioMgr);
    499     }
     550        rc = pdmacFileAioMgrNormalReqsEnqueue(pAioMgr, pEndpoint, apReqs, cRequests);
     551        AssertMsg(RT_SUCCESS(rc) || (rc == VERR_FILE_AIO_INSUFFICIENT_RESSOURCES),
     552                  ("Unexpected return code rc=%Rrc\n", rc));
     553    }
     554
     555    if (pTaskHead)
     556    {
     557        /* Add the rest of the tasks to the pending list */
     558        pdmacFileAioMgrEpAddTaskList(pEndpoint, pTaskHead);
     559
     560
     561        if (RT_UNLIKELY(!cMaxRequests && !pEndpoint->pFlushReq))
     562        {
     563            /*
     564             * The I/O manager has no room left for more requests
     565             * but there are still requests to process.
     566             * Create a new I/O manager and let it handle some endpoints.
     567             */
     568            pdmacFileAioMgrNormalBalanceLoad(pAioMgr);
     569        }
     570    }
     571
     572    /* Insufficient resources are not fatal. */
     573    if (rc == VERR_FILE_AIO_INSUFFICIENT_RESSOURCES)
     574        rc = VINF_SUCCESS;
    500575
    501576    return rc;
     
    536611    }
    537612
    538     if (!pEndpoint->pFlushReq)
     613    if (!pEndpoint->pFlushReq && !pEndpoint->AioMgr.pReqsPendingHead)
    539614    {
    540615        /* Now the request queue. */
     
    764839                        /* Put the entry on the free array */
    765840                        pAioMgr->pahReqsFree[pAioMgr->iFreeEntryNext] = apReqs[i];
    766                         pAioMgr->iFreeEntryNext = (pAioMgr->iFreeEntryNext + 1) %pAioMgr->cReqEntries;
     841                        pAioMgr->iFreeEntryNext = (pAioMgr->iFreeEntryNext + 1) % pAioMgr->cReqEntries;
    767842
    768843                        pAioMgr->cRequestsActive--;
  • trunk/src/VBox/VMM/testcase/tstPDMAsyncCompletion.cpp

    r20429 r23404  
    5555 */
    5656#define NR_TASKS      80
    57 #define BUFFER_SIZE 4096 /* 4K */
     57#define BUFFER_SIZE (64*_1K)
    5858
    5959/* Buffers to store data in .*/
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette