VirtualBox

Changeset 36132 in vbox for trunk/src


Ignore:
Timestamp:
Mar 2, 2011 9:58:40 PM (14 years ago)
Author:
vboxsync
Message:

VD: Update the modification UUID during async I/O

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Storage/VD.cpp

    r35781 r36132  
    213213    /** List of waiting requests. - Protected by the critical section. */
    214214    RTLISTNODE          ListWriteLocked;
     215    /** I/O context which locked the disk. */
     216    PVDIOCTX            pIoCtxLockOwner;
    215217
    216218    /** Pointer to the L2 disk cache if any. */
     
    12001202}
    12011203
     1204DECLINLINE(bool) vdIoCtxIsDiskLockOwner(PVBOXHDD pDisk, PVDIOCTX pIoCtx)
     1205{
     1206    return    pDisk->fLocked
     1207           && pDisk->pIoCtxLockOwner == pIoCtx;
     1208}
     1209
    12021210static int vdIoCtxLockDisk(PVBOXHDD pDisk, PVDIOCTX pIoCtx)
    12031211{
     
    12061214    if (!ASMAtomicCmpXchgBool(&pDisk->fLocked, true, false))
    12071215    {
     1216        Assert(pDisk->pIoCtxLockOwner != pIoCtx); /* No nesting allowed. */
     1217
    12081218        rc = vdIoCtxDefer(pDisk, pIoCtx);
    12091219        if (RT_SUCCESS(rc))
    12101220            rc = VERR_VD_ASYNC_IO_IN_PROGRESS;
    12111221    }
     1222    else
     1223    {
     1224        Assert(!pDisk->pIoCtxLockOwner);
     1225        pDisk->pIoCtxLockOwner = pIoCtx;
     1226    }
    12121227
    12131228    return rc;
    12141229}
    12151230
    1216 static void vdIoCtxUnlockDisk(PVBOXHDD pDisk, PVDIOCTX pIoCtx)
     1231static void vdIoCtxUnlockDisk(PVBOXHDD pDisk, PVDIOCTX pIoCtx, bool fProcessDeferredReqs)
    12171232{
    12181233    Assert(pDisk->fLocked);
     1234    Assert(pDisk->pIoCtxLockOwner == pIoCtx);
     1235    pDisk->pIoCtxLockOwner = NULL;
    12191236    ASMAtomicXchgBool(&pDisk->fLocked, false);
    12201237
    1221     /* Process any pending writes if the current request didn't caused another growing. */
    1222     RTCritSectEnter(&pDisk->CritSect);
    1223 
    1224     if (!RTListIsEmpty(&pDisk->ListWriteLocked))
    1225     {
    1226         RTLISTNODE ListTmp;
    1227 
    1228         RTListMove(&ListTmp, &pDisk->ListWriteLocked);
    1229         RTCritSectLeave(&pDisk->CritSect);
    1230 
    1231         /* Process the list. */
    1232         do
    1233         {
    1234             int rc;
    1235             PVDIOCTXDEFERRED pDeferred = RTListGetFirst(&ListTmp, VDIOCTXDEFERRED, NodeDeferred);
    1236             PVDIOCTX pIoCtxWait = pDeferred->pIoCtx;
    1237 
    1238             AssertPtr(pIoCtxWait);
    1239 
    1240             RTListNodeRemove(&pDeferred->NodeDeferred);
    1241             RTMemFree(pDeferred);
    1242 
    1243             Assert(!pIoCtxWait->pIoCtxParent);
    1244 
    1245             pIoCtxWait->fBlocked = false;
    1246             LogFlowFunc(("Processing waiting I/O context pIoCtxWait=%#p\n", pIoCtxWait));
    1247 
    1248             rc = vdIoCtxProcess(pIoCtxWait);
    1249             if (   rc == VINF_VD_ASYNC_IO_FINISHED
    1250                 && ASMAtomicCmpXchgBool(&pIoCtxWait->fComplete, true, false))
     1238    if (fProcessDeferredReqs)
     1239    {
     1240        /* Process any pending writes if the current request didn't caused another growing. */
     1241        RTCritSectEnter(&pDisk->CritSect);
     1242
     1243        if (!RTListIsEmpty(&pDisk->ListWriteLocked))
     1244        {
     1245            RTLISTNODE ListTmp;
     1246
     1247            RTListMove(&ListTmp, &pDisk->ListWriteLocked);
     1248            RTCritSectLeave(&pDisk->CritSect);
     1249
     1250            /* Process the list. */
     1251            do
    12511252            {
    1252                 LogFlowFunc(("Waiting I/O context completed pIoCtxWait=%#p\n", pIoCtxWait));
    1253                 vdThreadFinishWrite(pDisk);
    1254                 pIoCtxWait->Type.Root.pfnComplete(pIoCtxWait->Type.Root.pvUser1,
    1255                                                   pIoCtxWait->Type.Root.pvUser2,
    1256                                                   pIoCtxWait->rcReq);
    1257                 vdIoCtxFree(pDisk, pIoCtxWait);
    1258             }
    1259         } while (!RTListIsEmpty(&ListTmp));
    1260     }
    1261     else
    1262         RTCritSectLeave(&pDisk->CritSect);
     1253                int rc;
     1254                PVDIOCTXDEFERRED pDeferred = RTListGetFirst(&ListTmp, VDIOCTXDEFERRED, NodeDeferred);
     1255                PVDIOCTX pIoCtxWait = pDeferred->pIoCtx;
     1256
     1257                AssertPtr(pIoCtxWait);
     1258
     1259                RTListNodeRemove(&pDeferred->NodeDeferred);
     1260                RTMemFree(pDeferred);
     1261
     1262                Assert(!pIoCtxWait->pIoCtxParent);
     1263
     1264                pIoCtxWait->fBlocked = false;
     1265                LogFlowFunc(("Processing waiting I/O context pIoCtxWait=%#p\n", pIoCtxWait));
     1266
     1267                rc = vdIoCtxProcess(pIoCtxWait);
     1268                if (   rc == VINF_VD_ASYNC_IO_FINISHED
     1269                    && ASMAtomicCmpXchgBool(&pIoCtxWait->fComplete, true, false))
     1270                {
     1271                    LogFlowFunc(("Waiting I/O context completed pIoCtxWait=%#p\n", pIoCtxWait));
     1272                    vdThreadFinishWrite(pDisk);
     1273                    pIoCtxWait->Type.Root.pfnComplete(pIoCtxWait->Type.Root.pvUser1,
     1274                                                      pIoCtxWait->Type.Root.pvUser2,
     1275                                                      pIoCtxWait->rcReq);
     1276                    vdIoCtxFree(pDisk, pIoCtxWait);
     1277                }
     1278            } while (!RTListIsEmpty(&ListTmp));
     1279        }
     1280        else
     1281            RTCritSectLeave(&pDisk->CritSect);
     1282    }
    12631283}
    12641284
     
    16401660
    16411661/**
     1662 * Flush helper async version.
     1663 */
     1664static int vdSetModifiedHelperAsync(PVDIOCTX pIoCtx)
     1665{
     1666    int rc = VINF_SUCCESS;
     1667    PVBOXHDD pDisk = pIoCtx->pDisk;
     1668    PVDIMAGE pImage = pIoCtx->pImageCur;
     1669
     1670    rc = pImage->Backend->pfnAsyncFlush(pImage->pBackendData, pIoCtx);
     1671    if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS)
     1672        rc = VINF_SUCCESS;
     1673
     1674    return rc;
     1675}
     1676
     1677/**
     1678 * internal: mark the disk as modified - async version.
     1679 */
     1680static int vdSetModifiedFlagAsync(PVBOXHDD pDisk, PVDIOCTX pIoCtx)
     1681{
     1682    int rc = VINF_SUCCESS;
     1683
     1684    pDisk->uModified |= VD_IMAGE_MODIFIED_FLAG;
     1685    if (pDisk->uModified & VD_IMAGE_MODIFIED_FIRST)
     1686    {
     1687        rc = vdIoCtxLockDisk(pDisk, pIoCtx);
     1688        if (RT_SUCCESS(rc))
     1689        {
     1690            pDisk->uModified &= ~VD_IMAGE_MODIFIED_FIRST;
     1691
     1692            /* First modify, so create a UUID and ensure it's written to disk. */
     1693            vdResetModifiedFlag(pDisk);
     1694
     1695            if (!(pDisk->uModified & VD_IMAGE_MODIFIED_DISABLE_UUID_UPDATE))
     1696            {
     1697                PVDIOCTX pIoCtxFlush = vdIoCtxChildAlloc(pDisk, VDIOCTXTXDIR_FLUSH,
     1698                                                         0, 0, pDisk->pLast,
     1699                                                         NULL, pIoCtx, 0, 0, NULL,
     1700                                                         vdSetModifiedHelperAsync);
     1701
     1702                if (pIoCtxFlush)
     1703                {
     1704                    rc = vdIoCtxProcess(pIoCtxFlush);
     1705                    if (rc == VINF_VD_ASYNC_IO_FINISHED)
     1706                    {
     1707                        vdIoCtxUnlockDisk(pDisk, pIoCtxFlush, false /* fProcessDeferredReqs */);
     1708                        vdIoCtxFree(pDisk, pIoCtxFlush);
     1709                    }
     1710                    else if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS)
     1711                    {
     1712                        pIoCtx->fBlocked = true;
     1713                    }
     1714                    else /* Another error */
     1715                        vdIoCtxFree(pDisk, pIoCtxFlush);
     1716                }
     1717                else
     1718                    rc = VERR_NO_MEMORY;
     1719            }
     1720        }
     1721    }
     1722
     1723    return rc;
     1724}
     1725
     1726/**
    16421727 * internal: write a complete block (only used for diff images), taking the
    16431728 * remaining data from parent images. This implementation does not optimize
     
    19282013    size_t cbPreRead, cbPostRead;
    19292014
     2015    rc = vdSetModifiedFlagAsync(pDisk, pIoCtx);
     2016    if (RT_FAILURE(rc)) /* Includes I/O in progress. */
     2017        return rc;
     2018
    19302019    /* Loop until all written. */
    19312020    do
     
    24892578                PVDIOCTX pIoCtxParent = pIoCtx->pIoCtxParent;
    24902579
    2491                 LogFlowFunc(("I/O context transferred %u bytes for the parent pIoCtxParent=%p\n",
    2492                              pIoCtx->Type.Child.cbTransferParent, pIoCtxParent));
    2493 
    2494                 /* Update the parent state. */
    24952580                Assert(!pIoCtxParent->pIoCtxParent);
    2496                 Assert(pIoCtx->enmTxDir == VDIOCTXTXDIR_WRITE);
    2497                 Assert(pIoCtxParent->cbTransferLeft >= pIoCtx->Type.Child.cbTransferParent);
    2498                 ASMAtomicSubU32(&pIoCtxParent->cbTransferLeft, pIoCtx->Type.Child.cbTransferParent);
    2499 
    25002581                if (RT_FAILURE(pIoCtx->rcReq))
    25012582                    ASMAtomicCmpXchgS32(&pIoCtxParent->rcReq, pIoCtx->rcReq, VINF_SUCCESS);
     2583
     2584                if (pIoCtx->enmTxDir == VDIOCTXTXDIR_WRITE)
     2585                {
     2586                    LogFlowFunc(("I/O context transferred %u bytes for the parent pIoCtxParent=%p\n",
     2587                                 pIoCtx->Type.Child.cbTransferParent, pIoCtxParent));
     2588
     2589                    /* Update the parent state. */
     2590                    Assert(pIoCtxParent->cbTransferLeft >= pIoCtx->Type.Child.cbTransferParent);
     2591                    ASMAtomicSubU32(&pIoCtxParent->cbTransferLeft, pIoCtx->Type.Child.cbTransferParent);
     2592                }
     2593                else
     2594                    Assert(pIoCtx->enmTxDir == VDIOCTXTXDIR_FLUSH);
    25022595
    25032596                /*
     
    25052598                 * We have to process any pending writes now.
    25062599                 */
    2507                 Assert(pDisk->fLocked);
    2508                 ASMAtomicWriteBool(&pDisk->fLocked, false);
     2600                vdIoCtxUnlockDisk(pDisk, pIoCtxParent, false /* fProcessDeferredReqs */);
    25092601
    25102602                /* Unblock the parent */
     
    25272619                RTCritSectEnter(&pDisk->CritSect);
    25282620
    2529                 if (!RTListIsEmpty(&pDisk->ListWriteLocked) && !pDisk->fLocked)
     2621                if (   !RTListIsEmpty(&pDisk->ListWriteLocked)
     2622                    && !vdIoCtxIsDiskLockOwner(pDisk, pIoCtx))
    25302623                {
    25312624                    RTLISTNODE ListTmp;
     
    25772670                if (pIoCtx->enmTxDir == VDIOCTXTXDIR_FLUSH)
    25782671                {
    2579                     vdIoCtxUnlockDisk(pDisk, pIoCtx);
     2672                    vdIoCtxUnlockDisk(pDisk, pIoCtx, true /* fProcessDerredReqs */);
    25802673                    vdThreadFinishWrite(pDisk);
    25812674                }
     
    37393832            pDisk->pInterfaceThreadSyncCallbacks = NULL;
    37403833            pDisk->fLocked = false;
     3834            pDisk->pIoCtxLockOwner = NULL;
    37413835            RTListInit(&pDisk->ListWriteLocked);
    37423836
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