VirtualBox

Changeset 28902 in vbox


Ignore:
Timestamp:
Apr 29, 2010 2:54:08 PM (15 years ago)
Author:
vboxsync
Message:

DiskIntegrity: Add possibility to check for hanging requests

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Storage/DrvDiskIntegrity.cpp

    r28800 r28902  
    2929#include <iprt/message.h>
    3030#include <iprt/sg.h>
     31#include <iprt/time.h>
     32#include <iprt/semaphore.h>
    3133
    3234#include "Builtins.h"
     
    5456    /** User argument */
    5557    void     *pvUser;
     58    /** Slot in the array. */
     59    unsigned  iSlot;
    5660} DRVDISKAIOREQ, *PDRVDISKAIOREQ;
    5761
     
    8791
    8892/**
     93 * Active requests list entry.
     94 */
     95typedef struct DRVDISKAIOREQACTIVE
     96{
     97    /** Pointer to the request. */
     98    volatile PDRVDISKAIOREQ pIoReq;
     99    /** Start timestamp. */
     100    uint64_t  tsStart;
     101} DRVDISKAIOREQACTIVE, *PDRVDISKAIOREQACTIVE;
     102
     103/**
    89104 * Disk integrity driver instance data.
    90105 *
     
    112127    PDMIMEDIAASYNCPORT      IMediaAsyncPort;
    113128
     129    /** Flag whether consistency checks are enabled. */
     130    bool                    fCheckConsistency;
    114131    /** AVL tree containing the disk blocks to check. */
    115132    PAVLRFOFFTREE           pTreeSegments;
     133
     134    /** Flag whether async request tracing is enabled. */
     135    bool                    fTraceRequests;
     136    /** Interval the thread should check for expired requests (milliseconds). */
     137    uint32_t                uCheckIntervalMs;
     138    /** Expire timeout for a request (milliseconds). */
     139    uint32_t                uExpireIntervalMs;
     140    /** Thread which checks for lost requests. */
     141    RTTHREAD                hThread;
     142    /** Event semaphore */
     143    RTSEMEVENT              SemEvent;
     144    /** Flag whether the thread should run. */
     145    bool                    fRunning;
     146    /** Array containing active requests. */
     147    DRVDISKAIOREQACTIVE     apReqActive[128];
     148    /** Next free slot in the array */
     149    volatile unsigned       iNextFreeSlot;
    116150} DRVDISKINTEGRITY, *PDRVDISKINTEGRITY;
    117151
     
    354388}
    355389
     390/**
     391 * Adds a request to the active list.
     392 *
     393 * @returns nothing.
     394 * @param   pThis    The driver instance data.
     395 * @param   pIoReq   The request to add.
     396 */
     397static void drvdiskintIoReqAdd(PDRVDISKINTEGRITY pThis, PDRVDISKAIOREQ pIoReq)
     398{
     399    PDRVDISKAIOREQACTIVE pReqActive = &pThis->apReqActive[pThis->iNextFreeSlot];
     400
     401    Assert(!pReqActive->pIoReq);
     402    pReqActive->tsStart = RTTimeSystemMilliTS();
     403    pReqActive->pIoReq  = pIoReq;
     404    pIoReq->iSlot = pThis->iNextFreeSlot;
     405
     406    /* Search for the next one. */
     407    pThis->iNextFreeSlot++;
     408    while (pThis->apReqActive[pThis->iNextFreeSlot].pIoReq)
     409        pThis->iNextFreeSlot = pThis->iNextFreeSlot++ % RT_ELEMENTS(pThis->apReqActive);
     410}
     411
     412/**
     413 * Removes a request from the active list.
     414 *
     415 * @returns nothing.
     416 * @param   pThis    The driver instance data.
     417 * @param   pIoReq   The request to remove.
     418 */
     419static void drvdiskintIoReqRemove(PDRVDISKINTEGRITY pThis, PDRVDISKAIOREQ pIoReq)
     420{
     421    PDRVDISKAIOREQACTIVE pReqActive = &pThis->apReqActive[pIoReq->iSlot];
     422
     423    Assert(pReqActive->pIoReq == pIoReq);
     424
     425    ASMAtomicXchgPtr((void * volatile *)&pReqActive->pIoReq, NULL);
     426}
     427
     428/**
     429 * Thread checking for expired requests.
     430 *
     431 * @returns IPRT status code.
     432 * @param   pThread    Thread handle.
     433 * @param   pvUser     Opaque user data.
     434 */
     435static int drvdiskIntIoReqExpiredCheck(RTTHREAD pThread, void *pvUser)
     436{
     437    PDRVDISKINTEGRITY pThis = (PDRVDISKINTEGRITY)pvUser;
     438
     439    while (pThis->fRunning)
     440    {
     441        int rc = RTSemEventWait(pThis->SemEvent, pThis->uCheckIntervalMs);
     442
     443        if (!pThis->fRunning)
     444            break;
     445
     446        Assert(rc == VERR_TIMEOUT);
     447
     448        /* Get current timestamp for comparison. */
     449        uint64_t tsCurr = RTTimeSystemMilliTS();
     450
     451        /* Go through the array and check for expired requests. */
     452        for (unsigned i = 0; i < RT_ELEMENTS(pThis->apReqActive); i++)
     453        {
     454            PDRVDISKAIOREQACTIVE pReqActive = &pThis->apReqActive[i];
     455            PDRVDISKAIOREQ pIoReq = (PDRVDISKAIOREQ)ASMAtomicReadPtr((void * volatile *)&pReqActive->pIoReq);
     456
     457            if (   pIoReq
     458                && (tsCurr - pReqActive->tsStart) >= pThis->uExpireIntervalMs)
     459            {
     460                RTMsgError("Request %#p expired (active for %llu ms already)\n",
     461                           pIoReq, tsCurr - pReqActive->tsStart);
     462                RTAssertDebugBreak();
     463            }
     464        }
     465    }
     466
     467    return VINF_SUCCESS;
     468}
     469
    356470/* -=-=-=-=- IMedia -=-=-=-=- */
    357471
     
    374488        return rc;
    375489
    376     /* Verify the read. */
    377     RTSGSEG Seg;
    378     Seg.cbSeg = cbRead;
    379     Seg.pvSeg = pvBuf;
    380     return drvdiskintReadVerify(pThis, &Seg, 1, off, cbRead);
     490    if (pThis->fCheckConsistency)
     491    {
     492        /* Verify the read. */
     493        RTSGSEG Seg;
     494        Seg.cbSeg = cbRead;
     495        Seg.pvSeg = pvBuf;
     496        rc = drvdiskintReadVerify(pThis, &Seg, 1, off, cbRead);
     497    }
     498
     499    return rc;
    381500}
    382501
     
    391510        return rc;
    392511
    393     /* Record the write. */
    394     RTSGSEG Seg;
    395     Seg.cbSeg = cbWrite;
    396     Seg.pvSeg = (void *)pvBuf;
    397     return drvdiskintWriteRecord(pThis, &Seg, 1, off, cbWrite);
     512    if (pThis->fCheckConsistency)
     513    {
     514        /* Record the write. */
     515        RTSGSEG Seg;
     516        Seg.cbSeg = cbWrite;
     517        Seg.pvSeg = (void *)pvBuf;
     518        rc = drvdiskintWriteRecord(pThis, &Seg, 1, off, cbWrite);
     519    }
     520
     521    return rc;
    398522}
    399523
     
    408532    AssertPtr(pIoReq);
    409533
     534    if (pThis->fTraceRequests)
     535        drvdiskintIoReqAdd(pThis, pIoReq);
     536
    410537    int rc = pThis->pDrvMediaAsync->pfnStartRead(pThis->pDrvMediaAsync, uOffset, paSeg, cSeg,
    411538                                                 cbRead, pIoReq);
     
    413540    {
    414541        /* Verify the read now. */
    415         int rc2 = drvdiskintReadVerify(pThis, paSeg, cSeg, uOffset, cbRead);
    416         AssertRC(rc2);
     542        if (pThis->fCheckConsistency)
     543        {
     544            int rc2 = drvdiskintReadVerify(pThis, paSeg, cSeg, uOffset, cbRead);
     545            AssertRC(rc2);
     546        }
     547
     548        if (pThis->fTraceRequests)
     549            drvdiskintIoReqRemove(pThis, pIoReq);
    417550        RTMemFree(pIoReq);
    418551    }
     
    434567    AssertPtr(pIoReq);
    435568
     569    if (pThis->fTraceRequests)
     570        drvdiskintIoReqAdd(pThis, pIoReq);
     571
    436572    int rc = pThis->pDrvMediaAsync->pfnStartWrite(pThis->pDrvMediaAsync, uOffset, paSeg, cSeg,
    437573                                                  cbWrite, pIoReq);
     
    439575    {
    440576        /* Verify the read now. */
    441         int rc2 = drvdiskintWriteRecord(pThis, paSeg, cSeg, uOffset, cbWrite);
    442         AssertRC(rc2);
     577        if  (pThis->fCheckConsistency)
     578        {
     579            int rc2 = drvdiskintWriteRecord(pThis, paSeg, cSeg, uOffset, cbWrite);
     580            AssertRC(rc2);
     581        }
     582
     583        if (pThis->fTraceRequests)
     584            drvdiskintIoReqRemove(pThis, pIoReq);
     585
    443586        RTMemFree(pIoReq);
    444587    }
     
    523666    LogFlowFunc(("pIoReq=%#p\n", pIoReq));
    524667
    525     if (RT_SUCCESS(rcReq))
     668    /* Remove from the active list. */
     669    if (pThis->fTraceRequests)
     670        drvdiskintIoReqRemove(pThis, pIoReq);
     671
     672    if (RT_SUCCESS(rcReq) && pThis->fCheckConsistency)
    526673    {
    527674        if (pIoReq->fRead)
     
    580727        RTMemFree(pThis->pTreeSegments);
    581728    }
     729
     730    if (pThis->fTraceRequests)
     731    {
     732        pThis->fRunning = false;
     733        RTSemEventSignal(pThis->SemEvent);
     734        RTSemEventDestroy(pThis->SemEvent);
     735    }
    582736}
    583737
     
    589743static DECLCALLBACK(int) drvdiskintConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags)
    590744{
     745    int rc = VINF_SUCCESS;
    591746    PDRVDISKINTEGRITY pThis = PDMINS_2_DATA(pDrvIns, PDRVDISKINTEGRITY);
    592747    LogFlow(("drvdiskintConstruct: iInstance=%d\n", pDrvIns->iInstance));
     
    596751     * Validate configuration.
    597752     */
    598     if (!CFGMR3AreValuesValid(pCfg, ""))
     753    if (!CFGMR3AreValuesValid(pCfg, "CheckConsistency\0"
     754                                    "TraceRequests\0"
     755                                    "CheckIntervalMs\0"
     756                                    "ExpireIntervalMs\0"))
    599757        return VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES;
     758
     759    rc = CFGMR3QueryBoolDef(pCfg, "CheckConsistency", &pThis->fCheckConsistency, false);
     760    AssertRC(rc);
     761    rc = CFGMR3QueryBoolDef(pCfg, "TraceRequests", &pThis->fTraceRequests, false);
     762    AssertRC(rc);
     763    rc = CFGMR3QueryU32Def(pCfg, "CheckIntervalMs", &pThis->uCheckIntervalMs, 5000); /* 5 seconds */
     764    AssertRC(rc);
     765    rc = CFGMR3QueryU32Def(pCfg, "ExpireIntervalMs", &pThis->uExpireIntervalMs, 20000); /* 20 seconds */
     766    AssertRC(rc);
    600767
    601768    /*
     
    630797     */
    631798    PPDMIBASE pBase;
    632     int rc = PDMDrvHlpAttach(pDrvIns, fFlags, &pBase);
     799    rc = PDMDrvHlpAttach(pDrvIns, fFlags, &pBase);
    633800    if (RT_FAILURE(rc))
    634801        return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS,
    635                                    N_("Failed to attach driver below us! %Rrf"), rc);
     802                                   N_("Failed to attach driver below us! %Rrc"), rc);
    636803
    637804    pThis->pDrvMedia = PDMIBASE_QUERY_INTERFACE(pBase, PDMIMEDIA);
     
    645812    pThis->pDrvMediaAsyncPort = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMIMEDIAASYNCPORT);
    646813
    647     /* Create the AVL tree. */
    648     pThis->pTreeSegments = (PAVLRFOFFTREE)RTMemAllocZ(sizeof(AVLRFOFFTREE));
    649     if (!pThis->pTreeSegments)
    650         rc = VERR_NO_MEMORY;
     814    if (pThis->fCheckConsistency)
     815    {
     816        /* Create the AVL tree. */
     817        pThis->pTreeSegments = (PAVLRFOFFTREE)RTMemAllocZ(sizeof(AVLRFOFFTREE));
     818        if (!pThis->pTreeSegments)
     819            rc = VERR_NO_MEMORY;
     820    }
     821
     822    if (pThis->fTraceRequests)
     823    {
     824        for (unsigned i = 0; i < RT_ELEMENTS(pThis->apReqActive); i++)
     825        {
     826            pThis->apReqActive[i].pIoReq  = NULL;
     827            pThis->apReqActive[i].tsStart = 0;
     828        }
     829
     830        pThis->iNextFreeSlot = 0;
     831
     832        /* Init event semaphore. */
     833        rc = RTSemEventCreate(&pThis->SemEvent);
     834        AssertRC(rc);
     835        pThis->fRunning = true;
     836        rc = RTThreadCreate(&pThis->hThread, drvdiskIntIoReqExpiredCheck, pThis,
     837                            0, RTTHREADTYPE_INFREQUENT_POLLER, 0, "DiskIntegrity");
     838        AssertRC(rc);
     839    }
    651840
    652841    return rc;
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