VirtualBox

Changeset 33094 in vbox for trunk/src/VBox/Devices/Storage


Ignore:
Timestamp:
Oct 13, 2010 10:51:49 AM (14 years ago)
Author:
vboxsync
Message:

VD: Fix an assertion when queuing a flush while an expanding write request is still active. Rename variables.

File:
1 edited

Legend:

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

    r33088 r33094  
    201201    /** Critical section protecting the disk against concurrent access. */
    202202    RTCRITSECT          CritSect;
    203     /** Flag whether the last image is currently written to and needs to grow.
    204      * Other write requests which will grow the image too need to be deferred to
    205      * prevent data corruption. - Protected by the critical section.
     203    /** Flag whether the disk is currently locked by growing write or a flush
     204     * request. Other flush or growing write requests need to wait until
     205     * the current one completes.
    206206     */
    207     volatile bool       fGrowing;
     207    volatile bool       fLocked;
    208208    /** List of waiting requests. - Protected by the critical section. */
    209     RTLISTNODE          ListWriteGrowing;
     209    RTLISTNODE          ListWriteLocked;
    210210
    211211    /** Pointer to the L2 disk cache if any. */
     
    10651065}
    10661066
     1067DECLINLINE(int) vdIoCtxDefer(PVBOXHDD pDisk, PVDIOCTX pIoCtx)
     1068{
     1069    PVDIOCTXDEFERRED pDeferred = (PVDIOCTXDEFERRED)RTMemAllocZ(sizeof(VDIOCTXDEFERRED));
     1070
     1071    if (!pDeferred)
     1072        return VERR_NO_MEMORY;
     1073
     1074    LogFlowFunc(("Deferring write pIoCtx=%#p\n", pIoCtx));
     1075
     1076    Assert(!pIoCtx->pIoCtxParent && !pIoCtx->fBlocked);
     1077
     1078    RTListInit(&pDeferred->NodeDeferred);
     1079    pDeferred->pIoCtx = pIoCtx;
     1080    RTListAppend(&pDisk->ListWriteLocked, &pDeferred->NodeDeferred);
     1081    pIoCtx->fBlocked = true;
     1082    return VINF_SUCCESS;
     1083}
     1084
    10671085static size_t vdIoCtxCopy(PVDIOCTX pIoCtxDst, PVDIOCTX pIoCtxSrc, size_t cbData)
    10681086{
     
    11781196
    11791197    return rc;
     1198}
     1199
     1200static int vdIoCtxLockDisk(PVBOXHDD pDisk, PVDIOCTX pIoCtx)
     1201{
     1202    int rc = VINF_SUCCESS;
     1203
     1204    if (!ASMAtomicCmpXchgBool(&pDisk->fLocked, true, false))
     1205    {
     1206        rc = vdIoCtxDefer(pDisk, pIoCtx);
     1207        if (RT_SUCCESS(rc))
     1208            rc = VERR_VD_ASYNC_IO_IN_PROGRESS;
     1209    }
     1210
     1211    return rc;
     1212}
     1213
     1214static void vdIoCtxUnlockDisk(PVBOXHDD pDisk, PVDIOCTX pIoCtx)
     1215{
     1216    Assert(pDisk->fLocked);
     1217    ASMAtomicXchgBool(&pDisk->fLocked, false);
     1218
     1219    /* Process any pending writes if the current request didn't caused another growing. */
     1220    RTCritSectEnter(&pDisk->CritSect);
     1221
     1222    if (!RTListIsEmpty(&pDisk->ListWriteLocked))
     1223    {
     1224        RTLISTNODE ListTmp;
     1225
     1226        RTListMove(&ListTmp, &pDisk->ListWriteLocked);
     1227        RTCritSectLeave(&pDisk->CritSect);
     1228
     1229        /* Process the list. */
     1230        do
     1231        {
     1232            int rc;
     1233            PVDIOCTXDEFERRED pDeferred = RTListNodeGetFirst(&ListTmp, VDIOCTXDEFERRED, NodeDeferred);
     1234            PVDIOCTX pIoCtxWait = pDeferred->pIoCtx;
     1235
     1236            AssertPtr(pIoCtxWait);
     1237
     1238            RTListNodeRemove(&pDeferred->NodeDeferred);
     1239            RTMemFree(pDeferred);
     1240
     1241            Assert(!pIoCtxWait->pIoCtxParent);
     1242
     1243            pIoCtxWait->fBlocked = false;
     1244            LogFlowFunc(("Processing waiting I/O context pIoCtxWait=%#p\n", pIoCtxWait));
     1245
     1246            rc = vdIoCtxProcess(pIoCtxWait);
     1247            if (   rc == VINF_VD_ASYNC_IO_FINISHED
     1248                && ASMAtomicCmpXchgBool(&pIoCtxWait->fComplete, true, false))
     1249            {
     1250                LogFlowFunc(("Waiting I/O context completed pIoCtxWait=%#p\n", pIoCtxWait));
     1251                vdThreadFinishWrite(pDisk);
     1252                pIoCtxWait->Type.Root.pfnComplete(pIoCtxWait->Type.Root.pvUser1,
     1253                                                  pIoCtxWait->Type.Root.pvUser2,
     1254                                                  pIoCtxWait->rcReq);
     1255                vdIoCtxFree(pDisk, pIoCtxWait);
     1256            }
     1257        } while (!RTListIsEmpty(&ListTmp));
     1258    }
     1259    else
     1260        RTCritSectLeave(&pDisk->CritSect);
    11801261}
    11811262
     
    18471928        if (rc == VERR_VD_BLOCK_FREE)
    18481929        {
    1849             /*
    1850              * If there is a growing request already put this one onto the waiting list.
    1851              * It will be restarted if the current request completes.
    1852              */
    1853             if (ASMAtomicReadBool(&pDisk->fGrowing))
    1854             {
    1855                 PVDIOCTXDEFERRED pDeferred = (PVDIOCTXDEFERRED)RTMemAllocZ(sizeof(VDIOCTXDEFERRED));
    1856                 AssertPtr(pDeferred);
    1857 
    1858                 LogFlowFunc(("Deferring write pIoCtx=%#p\n", pIoCtx));
    1859 
    1860                 Assert(!pIoCtx->pIoCtxParent && !pIoCtx->fBlocked);
    1861 
    1862                 RTListInit(&pDeferred->NodeDeferred);
    1863                 pDeferred->pIoCtx = pIoCtx;
    1864                 RTListAppend(&pDisk->ListWriteGrowing, &pDeferred->NodeDeferred);
    1865                 pIoCtx->fBlocked = true;
    1866                 rc = VERR_VD_ASYNC_IO_IN_PROGRESS;
    1867                 break;
    1868             }
    1869             else
     1930            /* Lock the disk .*/
     1931            rc = vdIoCtxLockDisk(pDisk, pIoCtx);
     1932            if (RT_SUCCESS(rc))
    18701933            {
    18711934                /*
     
    18951958                }
    18961959
    1897                 /* Set the state to growing. */
    18981960                LogFlowFunc(("Disk is growing because of pIoCtx=%#p pIoCtxWrite=%#p\n",
    1899 
    19001961                             pIoCtx, pIoCtxWrite));
    1901                 ASMAtomicWriteBool(&pDisk->fGrowing, true);
    19021962
    19031963                pIoCtxWrite->pImage                = pImage;
     
    19191979                    Assert(pIoCtx->cbTransferLeft >= cbThisWrite);
    19201980                    ASMAtomicSubU32(&pIoCtx->cbTransferLeft, cbThisWrite);
    1921                     ASMAtomicWriteBool(&pDisk->fGrowing, false);
     1981                    ASMAtomicWriteBool(&pDisk->fLocked, false);
    19221982                    vdIoCtxFree(pDisk, pIoCtxWrite);
    19231983
     
    19341994                }
    19351995            }
     1996            else
     1997            {
     1998                rc = VERR_VD_ASYNC_IO_IN_PROGRESS;
     1999                break;
     2000            }
    19362001        }
    19372002
     
    19772042    PVDIMAGE pImage = pIoCtx->pImage;
    19782043
    1979     vdResetModifiedFlag(pDisk);
    1980     rc = pImage->Backend->pfnAsyncFlush(pImage->pBackendData, pIoCtx);
    1981     if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS)
    1982         rc = VINF_SUCCESS;
     2044    rc = vdIoCtxLockDisk(pDisk, pIoCtx);
     2045    if (RT_SUCCESS(rc))
     2046    {
     2047        vdResetModifiedFlag(pDisk);
     2048        rc = pImage->Backend->pfnAsyncFlush(pImage->pBackendData, pIoCtx);
     2049        if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS)
     2050            rc = VINF_SUCCESS;
     2051    }
    19832052
    19842053    return rc;
     
    24122481                 * We have to process any pending writes now.
    24132482                 */
    2414                 Assert(pDisk->fGrowing);
    2415                 ASMAtomicWriteBool(&pDisk->fGrowing, false);
     2483                Assert(pDisk->fLocked);
     2484                ASMAtomicWriteBool(&pDisk->fLocked, false);
    24162485
    24172486                /* Unblock the parent */
     
    24342503                RTCritSectEnter(&pDisk->CritSect);
    24352504
    2436                 if (!RTListIsEmpty(&pDisk->ListWriteGrowing) && !pDisk->fGrowing)
     2505                if (!RTListIsEmpty(&pDisk->ListWriteLocked) && !pDisk->fLocked)
    24372506                {
    24382507                    RTLISTNODE ListTmp;
    24392508
    2440                     LogFlowFunc(("Before: pNext=%#p pPrev=%#p\n", pDisk->ListWriteGrowing.pNext,
    2441                                  pDisk->ListWriteGrowing.pPrev));
    2442 
    2443                     RTListMove(&ListTmp, &pDisk->ListWriteGrowing);
    2444 
    2445                     LogFlowFunc(("After: pNext=%#p pPrev=%#p\n", pDisk->ListWriteGrowing.pNext,
    2446                                  pDisk->ListWriteGrowing.pPrev));
     2509                    LogFlowFunc(("Before: pNext=%#p pPrev=%#p\n", pDisk->ListWriteLocked.pNext,
     2510                                 pDisk->ListWriteLocked.pPrev));
     2511
     2512                    RTListMove(&ListTmp, &pDisk->ListWriteLocked);
     2513
     2514                    LogFlowFunc(("After: pNext=%#p pPrev=%#p\n", pDisk->ListWriteLocked.pNext,
     2515                                 pDisk->ListWriteLocked.pPrev));
    24472516
    24482517                    RTCritSectLeave(&pDisk->CritSect);
     
    24822551            else
    24832552            {
    2484                 if (pIoCtx->enmTxDir != VDIOCTXTXDIR_READ)
     2553                if (pIoCtx->enmTxDir == VDIOCTXTXDIR_FLUSH)
    24852554                {
    2486                     AssertMsg(   pIoCtx->enmTxDir == VDIOCTXTXDIR_WRITE
    2487                               || pIoCtx->enmTxDir == VDIOCTXTXDIR_FLUSH,
    2488                               ("Invalid transfer direction\n"));
     2555                    vdIoCtxUnlockDisk(pDisk, pIoCtx);
    24892556                    vdThreadFinishWrite(pDisk);
    24902557                }
     2558                else if (pIoCtx->enmTxDir == VDIOCTXTXDIR_WRITE)
     2559                    vdThreadFinishWrite(pDisk);
    24912560                else
     2561                {
     2562                    Assert(pIoCtx->enmTxDir == VDIOCTXTXDIR_READ);
    24922563                    vdThreadFinishRead(pDisk);
     2564                }
    24932565
    24942566                LogFlowFunc(("I/O context completed pIoCtx=%#p rcReq=%Rrc\n", pIoCtx, pIoCtx->rcReq));
     
    35893661            pDisk->pInterfaceThreadSync = NULL;
    35903662            pDisk->pInterfaceThreadSyncCallbacks = NULL;
    3591             pDisk->fGrowing = false;
    3592             RTListInit(&pDisk->ListWriteGrowing);
     3663            pDisk->fLocked = false;
     3664            RTListInit(&pDisk->ListWriteLocked);
    35933665
    35943666            /* Create the I/O ctx cache */
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