VirtualBox

Changeset 63741 in vbox


Ignore:
Timestamp:
Sep 7, 2016 7:53:09 AM (8 years ago)
Author:
vboxsync
Message:

Storage/QED,QCOW: Always write the complete L1 and L2 table when allocating a new cluster instead of just the updated entry

Location:
trunk/src/VBox/Storage
Files:
2 edited

Legend:

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

    r63635 r63741  
    888888}
    889889
     890/**
     891 * Write the given table to image converting to the image endianess if required.
     892 *
     893 * @returns VBox status code.
     894 * @param   pImage        The image instance data.
     895 * @param   pIoCtx        The I/O context.
     896 * @param   offTbl        The offset the table should be written to.
     897 * @param   paTbl         The table to write.
     898 * @param   pfnComplete   Callback called when the write completes.
     899 * @param   pvUser        Opaque user data to pass in the completion callback.
     900 */
     901static int qcowTblWrite(PQCOWIMAGE pImage, PVDIOCTX pIoCtx, uint64_t offTbl, uint64_t *paTbl,
     902                        size_t cbTbl, unsigned cTblEntries,
     903                        PFNVDXFERCOMPLETED pfnComplete, void *pvUser)
     904{
     905    int rc = VINF_SUCCESS;
     906
     907#if defined(RT_LITTLE_ENDIAN)
     908    uint64_t *paTblImg = (uint64_t *)RTMemAllocZ(cbTbl);
     909    if (paTblImg)
     910    {
     911        qcowTableConvertFromHostEndianess(paTblImg, paTbl, cTblEntries);
     912        rc = vdIfIoIntFileWriteMeta(pImage->pIfIo, pImage->pStorage,
     913                                    offTbl, paTblImg, cbTbl,
     914                                    pIoCtx, pfnComplete, pvUser);
     915        RTMemFree(paTblImg);
     916    }
     917    else
     918        rc = VERR_NO_MEMORY;
     919#else
     920    /* Write table directly. */
     921    RT_NOREF(cTblEntries);
     922    rc = vdIfIoIntFileWriteMeta(pImage->pIfIo, pImage->pStorage,
     923                                offTbl, paTbl, cbTbl, pIoCtx,
     924                                pfnComplete, pvUser);
     925#endif
     926
     927    return rc;
     928}
    890929
    891930/**
     
    951990        QCowHeader Header;
    952991
    953 #if defined(RT_LITTLE_ENDIAN)
    954         uint64_t *paL1TblImg = (uint64_t *)RTMemAllocZ(pImage->cbL1Table);
    955         if (paL1TblImg)
    956         {
    957             qcowTableConvertFromHostEndianess(paL1TblImg, pImage->paL1Table,
    958                                              pImage->cL1TableEntries);
    959             rc = vdIfIoIntFileWriteMeta(pImage->pIfIo, pImage->pStorage,
    960                                         pImage->offL1Table, paL1TblImg,
    961                                         pImage->cbL1Table, pIoCtx, NULL, NULL);
    962             RTMemFree(paL1TblImg);
    963         }
    964         else
    965             rc = VERR_NO_MEMORY;
    966 #else
    967         /* Write L1 table directly. */
    968         rc = vdIfIoIntFileWriteMeta(pImage->pIfIo, pImage->pStorage,
    969                                     pImage->offL1Table, pImage->paL1Table,
    970                                     pImage->cbL1Table, pIoCtx, NULL, NULL);
    971 #endif
     992        rc = qcowTblWrite(pImage, pIoCtx, pImage->offL1Table, pImage->paL1Table,
     993                          pImage->cbL1Table, pImage->cL1TableEntries, NULL, NULL);
    972994        if (RT_SUCCESS(rc) || rc == VERR_VD_ASYNC_IO_IN_PROGRESS)
    973995        {
     
    13811403        case QCOWCLUSTERASYNCALLOCSTATE_L2_LINK:
    13821404        {
    1383             /* Assumption right now is that the L1 table is not modified if the link fails. */
     1405            /* Revert the L1 table entry */
     1406            pImage->paL1Table[pClusterAlloc->idxL1] = 0;
     1407
     1408            /* Assumption right now is that the L1 table is not modified on storage if the link fails. */
    13841409            rc = vdIfIoIntFileSetSize(pImage->pIfIo, pImage->pStorage, pClusterAlloc->offNextClusterOld);
    13851410            qcowL2TblCacheEntryRelease(pClusterAlloc->pL2Entry); /* Release L2 cache entry. */
     
    13911416        {
    13921417            /* Assumption right now is that the L2 table is not modified if the link fails. */
     1418            pClusterAlloc->pL2Entry->paL2Tbl[pClusterAlloc->idxL2] = 0;
    13931419            rc = vdIfIoIntFileSetSize(pImage->pIfIo, pImage->pStorage, pClusterAlloc->offNextClusterOld);
    13941420            qcowL2TblCacheEntryRelease(pClusterAlloc->pL2Entry); /* Release L2 cache entry. */
     
    14281454        case QCOWCLUSTERASYNCALLOCSTATE_L2_ALLOC:
    14291455        {
    1430             uint64_t offUpdateLe = RT_H2BE_U64(pClusterAlloc->pL2Entry->offL2Tbl);
     1456            /* Update the link in the in memory L1 table now. */
     1457            pImage->paL1Table[pClusterAlloc->idxL1] = pClusterAlloc->pL2Entry->offL2Tbl;
    14311458
    14321459            /* Update the link in the on disk L1 table now. */
    14331460            pClusterAlloc->enmAllocState = QCOWCLUSTERASYNCALLOCSTATE_L2_LINK;
    1434             rc = vdIfIoIntFileWriteMeta(pImage->pIfIo, pImage->pStorage,
    1435                                         pImage->offL1Table + pClusterAlloc->idxL1*sizeof(uint64_t),
    1436                                         &offUpdateLe, sizeof(uint64_t), pIoCtx,
    1437                                         qcowAsyncClusterAllocUpdate, pClusterAlloc);
     1461            rc = qcowTblWrite(pImage, pIoCtx, pImage->offL1Table, pImage->paL1Table,
     1462                              pImage->cbL1Table, pImage->cL1TableEntries,
     1463                              qcowAsyncClusterAllocUpdate, pClusterAlloc);
    14381464            if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS)
    14391465                break;
     
    14511477            uint64_t offData = qcowClusterAllocate(pImage, 1);
    14521478
    1453             /* Update the link in the in memory L1 table now. */
    1454             pImage->paL1Table[pClusterAlloc->idxL1] = pClusterAlloc->pL2Entry->offL2Tbl;
    14551479            qcowL2TblCacheEntryInsert(pImage, pClusterAlloc->pL2Entry);
    14561480
     
    14741498        case QCOWCLUSTERASYNCALLOCSTATE_USER_ALLOC:
    14751499        {
    1476             uint64_t offUpdateLe = RT_H2BE_U64(pClusterAlloc->offClusterNew);
    1477 
    14781500            pClusterAlloc->enmAllocState = QCOWCLUSTERASYNCALLOCSTATE_USER_LINK;
     1501            pClusterAlloc->pL2Entry->paL2Tbl[pClusterAlloc->idxL2] = pClusterAlloc->offClusterNew;
    14791502
    14801503            /* Link L2 table and update it. */
    1481             rc = vdIfIoIntFileWriteMeta(pImage->pIfIo, pImage->pStorage,
    1482                                         pImage->paL1Table[pClusterAlloc->idxL1] + pClusterAlloc->idxL2*sizeof(uint64_t),
    1483                                         &offUpdateLe, sizeof(uint64_t), pIoCtx,
    1484                                         qcowAsyncClusterAllocUpdate, pClusterAlloc);
     1504            rc = qcowTblWrite(pImage, pIoCtx, pImage->paL1Table[pClusterAlloc->idxL1],
     1505                              pClusterAlloc->pL2Entry->paL2Tbl,
     1506                              pImage->cbL2Table, pImage->cL2TableEntries,
     1507                              qcowAsyncClusterAllocUpdate, pClusterAlloc);
    14851508            if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS)
    14861509                break;
     
    14951518        {
    14961519            /* Everything done without errors, signal completion. */
    1497             pClusterAlloc->pL2Entry->paL2Tbl[pClusterAlloc->idxL2] = pClusterAlloc->offClusterNew;
    14981520            qcowL2TblCacheEntryRelease(pClusterAlloc->pL2Entry);
    14991521            RTMemFree(pClusterAlloc);
  • trunk/src/VBox/Storage/QED.cpp

    r63636 r63741  
    566566}
    567567
    568 #if 0 /* unused */
    569 /**
    570  * Fetches the L2 from the given offset trying the LRU cache first and
    571  * reading it from the image after a cache miss.
    572  *
    573  * @returns VBox status code.
    574  * @param   pImage    Image instance data.
    575  * @param   offL2Tbl  The offset of the L2 table in the image.
    576  * @param   ppL2Entry Where to store the L2 table on success.
    577  */
    578 static int qedL2TblCacheFetch(PQEDIMAGE pImage, uint64_t offL2Tbl, PQEDL2CACHEENTRY *ppL2Entry)
    579 {
    580     int rc = VINF_SUCCESS;
    581 
    582     LogFlowFunc(("pImage=%#p offL2Tbl=%llu ppL2Entry=%#p\n", pImage, offL2Tbl, ppL2Entry));
    583 
    584     /* Try to fetch the L2 table from the cache first. */
    585     PQEDL2CACHEENTRY pL2Entry = qedL2TblCacheRetain(pImage, offL2Tbl);
    586     if (!pL2Entry)
    587     {
    588         LogFlowFunc(("Reading L2 table from image\n"));
    589         pL2Entry = qedL2TblCacheEntryAlloc(pImage);
    590 
    591         if (pL2Entry)
    592         {
    593             /* Read from the image. */
    594             pL2Entry->offL2Tbl = offL2Tbl;
    595             rc = vdIfIoIntFileReadSync(pImage->pIfIo, pImage->pStorage, offL2Tbl,
    596                                        pL2Entry->paL2Tbl, pImage->cbTable);
    597             if (RT_SUCCESS(rc))
    598             {
    599 #if defined(RT_BIG_ENDIAN)
    600                 qedTableConvertToHostEndianess(pL2Entry->paL2Tbl, pImage->cTableEntries);
    601 #endif
    602                 qedL2TblCacheEntryInsert(pImage, pL2Entry);
    603             }
    604             else
    605             {
    606                 qedL2TblCacheEntryRelease(pL2Entry);
    607                 qedL2TblCacheEntryFree(pImage, pL2Entry);
    608             }
    609         }
    610         else
    611             rc = VERR_NO_MEMORY;
    612     }
    613 
    614     if (RT_SUCCESS(rc))
    615         *ppL2Entry = pL2Entry;
    616 
    617     LogFlowFunc(("returns rc=%Rrc\n", rc));
    618     return rc;
    619 }
    620 #endif
    621 
    622568/**
    623569 * Fetches the L2 from the given offset trying the LRU cache first and
     
    822768}
    823769
     770/**
     771 * Write the given table to image converting to the image endianess if required.
     772 *
     773 * @returns VBox status code.
     774 * @param   pImage        The image instance data.
     775 * @param   pIoCtx        The I/O context.
     776 * @param   offTbl        The offset the table should be written to.
     777 * @param   paTbl         The table to write.
     778 * @param   pfnComplete   Callback called when the write completes.
     779 * @param   pvUser        Opaque user data to pass in the completion callback.
     780 */
     781static int qedTblWrite(PQEDIMAGE pImage, PVDIOCTX pIoCtx, uint64_t offTbl, uint64_t *paTbl,
     782                       PFNVDXFERCOMPLETED pfnComplete, void *pvUser)
     783{
     784    int rc = VINF_SUCCESS;
     785
     786#if defined(RT_BIG_ENDIAN)
     787    uint64_t *paTblImg = (uint64_t *)RTMemAllocZ(pImage->cbTable);
     788    if (paTblImg)
     789    {
     790        qedTableConvertFromHostEndianess(paTblImg, paTbl,
     791                                         pImage->cTableEntries);
     792        rc = vdIfIoIntFileWriteMeta(pImage->pIfIo, pImage->pStorage,
     793                                    offTbl, paTblImg, pImage->cbTable,
     794                                    pIoCtx, pfnComplete, pvUser);
     795        RTMemFree(paTblImg);
     796    }
     797    else
     798        rc = VERR_NO_MEMORY;
     799#else
     800    /* Write table directly. */
     801    rc = vdIfIoIntFileWriteMeta(pImage->pIfIo, pImage->pStorage,
     802                                offTbl, paTbl, pImage->cbTable, pIoCtx,
     803                                pfnComplete, pvUser);
     804#endif
     805
     806    return rc;
     807}
    824808
    825809/**
     
    885869
    886870        Assert(!(pImage->cbTable % pImage->cbCluster));
    887 #if defined(RT_BIG_ENDIAN)
    888         uint64_t *paL1TblImg = (uint64_t *)RTMemAllocZ(pImage->cbTable);
    889         if (paL1TblImg)
    890         {
    891             qedTableConvertFromHostEndianess(paL1TblImg, pImage->paL1Table,
    892                                              pImage->cTableEntries);
    893             rc = vdIfIoIntFileWriteMeta(pImage->pIfIo, pImage->pStorage,
    894                                         pImage->offL1Table, paL1TblImg,
    895                                         pImage->cbTable, pIoCtx, NULL, NULL);
    896             RTMemFree(paL1TblImg);
    897         }
    898         else
    899             rc = VERR_NO_MEMORY;
    900 #else
    901         /* Write L1 table directly. */
    902         rc = vdIfIoIntFileWriteMeta(pImage->pIfIo, pImage->pStorage,
    903                                     pImage->offL1Table, pImage->paL1Table,
    904                                     pImage->cbTable, pIoCtx, NULL, NULL);
    905 #endif
     871        rc = qedTblWrite(pImage, pIoCtx, pImage->offL1Table, pImage->paL1Table,
     872                         NULL, NULL);
    906873        if (RT_SUCCESS(rc) || rc == VERR_VD_ASYNC_IO_IN_PROGRESS)
    907874        {
     
    14141381        case QEDCLUSTERASYNCALLOCSTATE_L2_LINK:
    14151382        {
    1416             /* Assumption right now is that the L1 table is not modified if the link fails. */
     1383            /* Revert the L1 table entry */
     1384            pImage->paL1Table[pClusterAlloc->idxL1] = 0;
     1385
     1386            /* Assumption right now is that the L1 table is not modified on storage if the link fails. */
    14171387            rc = vdIfIoIntFileSetSize(pImage->pIfIo, pImage->pStorage, pClusterAlloc->cbImageOld);
    14181388            qedL2TblCacheEntryRelease(pClusterAlloc->pL2Entry); /* Release L2 cache entry. */
     
    14241394        {
    14251395            /* Assumption right now is that the L2 table is not modified if the link fails. */
     1396            pClusterAlloc->pL2Entry->paL2Tbl[pClusterAlloc->idxL2] = 0;
    14261397            rc = vdIfIoIntFileSetSize(pImage->pIfIo, pImage->pStorage, pClusterAlloc->cbImageOld);
    14271398            qedL2TblCacheEntryRelease(pClusterAlloc->pL2Entry); /* Release L2 cache entry. */
     
    14611432        case QEDCLUSTERASYNCALLOCSTATE_L2_ALLOC:
    14621433        {
    1463             uint64_t offUpdateLe = RT_H2LE_U64(pClusterAlloc->pL2Entry->offL2Tbl);
     1434            /* Update the link in the in memory L1 table now. */
     1435            pImage->paL1Table[pClusterAlloc->idxL1] = pClusterAlloc->pL2Entry->offL2Tbl;
    14641436
    14651437            /* Update the link in the on disk L1 table now. */
    14661438            pClusterAlloc->enmAllocState = QEDCLUSTERASYNCALLOCSTATE_L2_LINK;
    1467             rc = vdIfIoIntFileWriteMeta(pImage->pIfIo, pImage->pStorage,
    1468                                         pImage->offL1Table + pClusterAlloc->idxL1*sizeof(uint64_t),
    1469                                         &offUpdateLe, sizeof(uint64_t), pIoCtx,
    1470                                         qedAsyncClusterAllocUpdate, pClusterAlloc);
     1439            rc = qedTblWrite(pImage, pIoCtx, pImage->offL1Table, pImage->paL1Table,
     1440                             qedAsyncClusterAllocUpdate, pClusterAlloc);
    14711441            if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS)
    14721442                break;
     
    14841454            uint64_t offData = qedClusterAllocate(pImage, 1);
    14851455
    1486             /* Update the link in the in memory L1 table now. */
    1487             pImage->paL1Table[pClusterAlloc->idxL1] = pClusterAlloc->pL2Entry->offL2Tbl;
    14881456            qedL2TblCacheEntryInsert(pImage, pClusterAlloc->pL2Entry);
    14891457
     
    15071475        case QEDCLUSTERASYNCALLOCSTATE_USER_ALLOC:
    15081476        {
    1509             uint64_t offUpdateLe = RT_H2LE_U64(pClusterAlloc->offClusterNew);
    1510 
    15111477            pClusterAlloc->enmAllocState = QEDCLUSTERASYNCALLOCSTATE_USER_LINK;
     1478            pClusterAlloc->pL2Entry->paL2Tbl[pClusterAlloc->idxL2] = pClusterAlloc->offClusterNew;
    15121479
    15131480            /* Link L2 table and update it. */
    1514             rc = vdIfIoIntFileWriteMeta(pImage->pIfIo, pImage->pStorage,
    1515                                         pImage->paL1Table[pClusterAlloc->idxL1] + pClusterAlloc->idxL2*sizeof(uint64_t),
    1516                                         &offUpdateLe, sizeof(uint64_t), pIoCtx,
    1517                                         qedAsyncClusterAllocUpdate, pClusterAlloc);
     1481            rc = qedTblWrite(pImage, pIoCtx, pImage->paL1Table[pClusterAlloc->idxL1],
     1482                             pClusterAlloc->pL2Entry->paL2Tbl,
     1483                             qedAsyncClusterAllocUpdate, pClusterAlloc);
    15181484            if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS)
    15191485                break;
     
    15281494        {
    15291495            /* Everything done without errors, signal completion. */
    1530             pClusterAlloc->pL2Entry->paL2Tbl[pClusterAlloc->idxL2] = pClusterAlloc->offClusterNew;
    15311496            qedL2TblCacheEntryRelease(pClusterAlloc->pL2Entry);
    15321497            RTMemFree(pClusterAlloc);
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