VirtualBox

Changeset 38877 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Sep 27, 2011 9:04:46 AM (13 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
74199
Message:

VMM/PDMBlkCache: Add discard API

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

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMR3/PDMBlkCache.cpp

    r37933 r38877  
    12711271                                         PFNPDMBLKCACHEXFERCOMPLETEDRV pfnXferComplete,
    12721272                                         PFNPDMBLKCACHEXFERENQUEUEDRV pfnXferEnqueue,
     1273                                         PFNPDMBLKCACHEXFERENQUEUEDISCARDDRV pfnXferEnqueueDiscard,
    12731274                                         const char *pcszId)
    12741275{
     
    12791280    if (RT_SUCCESS(rc))
    12801281    {
    1281         pBlkCache->enmType = PDMBLKCACHETYPE_DRV;
    1282         pBlkCache->u.Drv.pfnXferComplete = pfnXferComplete;
    1283         pBlkCache->u.Drv.pfnXferEnqueue  = pfnXferEnqueue;
    1284         pBlkCache->u.Drv.pDrvIns         = pDrvIns;
     1282        pBlkCache->enmType                      = PDMBLKCACHETYPE_DRV;
     1283        pBlkCache->u.Drv.pfnXferComplete        = pfnXferComplete;
     1284        pBlkCache->u.Drv.pfnXferEnqueue         = pfnXferEnqueue;
     1285        pBlkCache->u.Drv.pfnXferEnqueueDiscard  = pfnXferEnqueueDiscard;
     1286        pBlkCache->u.Drv.pDrvIns                = pDrvIns;
    12851287        *ppBlkCache = pBlkCache;
    12861288    }
     
    12931295                                         PFNPDMBLKCACHEXFERCOMPLETEDEV pfnXferComplete,
    12941296                                         PFNPDMBLKCACHEXFERENQUEUEDEV pfnXferEnqueue,
     1297                                         PFNPDMBLKCACHEXFERENQUEUEDISCARDDEV pfnXferEnqueueDiscard,
    12951298                                         const char *pcszId)
    12961299{
     
    13011304    if (RT_SUCCESS(rc))
    13021305    {
    1303         pBlkCache->enmType = PDMBLKCACHETYPE_DEV;
    1304         pBlkCache->u.Dev.pfnXferComplete = pfnXferComplete;
    1305         pBlkCache->u.Dev.pfnXferEnqueue  = pfnXferEnqueue;
    1306         pBlkCache->u.Dev.pDevIns         = pDevIns;
     1306        pBlkCache->enmType                      = PDMBLKCACHETYPE_DEV;
     1307        pBlkCache->u.Dev.pfnXferComplete        = pfnXferComplete;
     1308        pBlkCache->u.Dev.pfnXferEnqueue         = pfnXferEnqueue;
     1309        pBlkCache->u.Dev.pfnXferEnqueueDiscard  = pfnXferEnqueueDiscard;
     1310        pBlkCache->u.Dev.pDevIns                = pDevIns;
    13071311        *ppBlkCache = pBlkCache;
    13081312    }
     
    13161320                                      PFNPDMBLKCACHEXFERCOMPLETEUSB pfnXferComplete,
    13171321                                      PFNPDMBLKCACHEXFERENQUEUEUSB pfnXferEnqueue,
     1322                                      PFNPDMBLKCACHEXFERENQUEUEDISCARDUSB pfnXferEnqueueDiscard,
    13181323                                      const char *pcszId)
    13191324{
     
    13241329    if (RT_SUCCESS(rc))
    13251330    {
    1326         pBlkCache->enmType = PDMBLKCACHETYPE_USB;
    1327         pBlkCache->u.Usb.pfnXferComplete = pfnXferComplete;
    1328         pBlkCache->u.Usb.pfnXferEnqueue  = pfnXferEnqueue;
    1329         pBlkCache->u.Usb.pUsbIns         = pUsbIns;
     1331        pBlkCache->enmType                      = PDMBLKCACHETYPE_USB;
     1332        pBlkCache->u.Usb.pfnXferComplete        = pfnXferComplete;
     1333        pBlkCache->u.Usb.pfnXferEnqueue         = pfnXferEnqueue;
     1334        pBlkCache->u.Usb.pfnXferEnqueueDiscard  = pfnXferEnqueueDiscard;
     1335        pBlkCache->u.Usb.pUsbIns                = pUsbIns;
    13301336        *ppBlkCache = pBlkCache;
    13311337    }
     
    13391345                                      PFNPDMBLKCACHEXFERCOMPLETEINT pfnXferComplete,
    13401346                                      PFNPDMBLKCACHEXFERENQUEUEINT pfnXferEnqueue,
     1347                                      PFNPDMBLKCACHEXFERENQUEUEDISCARDINT pfnXferEnqueueDiscard,
    13411348                                      const char *pcszId)
    13421349{
     
    13471354    if (RT_SUCCESS(rc))
    13481355    {
    1349         pBlkCache->enmType = PDMBLKCACHETYPE_INTERNAL;
    1350         pBlkCache->u.Int.pfnXferComplete = pfnXferComplete;
    1351         pBlkCache->u.Int.pfnXferEnqueue  = pfnXferEnqueue;
    1352         pBlkCache->u.Int.pvUser          = pvUser;
     1356        pBlkCache->enmType                      = PDMBLKCACHETYPE_INTERNAL;
     1357        pBlkCache->u.Int.pfnXferComplete        = pfnXferComplete;
     1358        pBlkCache->u.Int.pfnXferEnqueue         = pfnXferEnqueue;
     1359        pBlkCache->u.Int.pfnXferEnqueueDiscard  = pfnXferEnqueueDiscard;
     1360        pBlkCache->u.Int.pvUser                 = pvUser;
    13531361        *ppBlkCache = pBlkCache;
    13541362    }
     
    24082416}
    24092417
     2418VMMR3DECL(int) PDMR3BlkCacheDiscard(PPDMBLKCACHE pBlkCache, PCRTRANGE paRanges,
     2419                                    unsigned cRanges, void *pvUser)
     2420{
     2421    int rc = VINF_SUCCESS;
     2422    PPDMBLKCACHEGLOBAL pCache = pBlkCache->pCache;
     2423    PPDMBLKCACHEENTRY pEntry;
     2424    PPDMBLKCACHEREQ pReq;
     2425
     2426    LogFlowFunc((": pBlkCache=%#p{%s} paRanges=%#p cRanges=%u pvUser=%#p\n",
     2427                 pBlkCache, pBlkCache->pszId, paRanges, cRanges, pvUser));
     2428
     2429    AssertPtrReturn(pBlkCache, VERR_INVALID_POINTER);
     2430    AssertReturn(!pBlkCache->fSuspended, VERR_INVALID_STATE);
     2431
     2432    /* Allocate new request structure. */
     2433    pReq = pdmBlkCacheReqAlloc(pvUser);
     2434    if (RT_UNLIKELY(!pReq))
     2435        return VERR_NO_MEMORY;
     2436
     2437    /* Increment data transfer counter to keep the request valid while we access it. */
     2438    ASMAtomicIncU32(&pReq->cXfersPending);
     2439
     2440    for (unsigned i = 0; i < cRanges; i++)
     2441    {
     2442        uint64_t offCur = paRanges[i].offStart;
     2443        size_t cbLeft = paRanges[i].cbRange;
     2444
     2445        while (cbLeft)
     2446        {
     2447            size_t cbThisDiscard;
     2448
     2449            pEntry = pdmBlkCacheGetCacheEntryByOffset(pBlkCache, offCur);
     2450
     2451            if (pEntry)
     2452            {
     2453                /* Write the data into the entry and mark it as dirty */
     2454                AssertPtr(pEntry->pList);
     2455
     2456                uint64_t offDiff = offCur - pEntry->Core.Key;
     2457
     2458                AssertMsg(offCur >= pEntry->Core.Key,
     2459                          ("Overflow in calculation offCur=%llu OffsetAligned=%llu\n",
     2460                          offCur, pEntry->Core.Key));
     2461
     2462                cbThisDiscard = RT_MIN(pEntry->cbData - offDiff, cbLeft);
     2463
     2464                /* Ghost lists contain no data. */
     2465                if (   (pEntry->pList == &pCache->LruRecentlyUsedIn)
     2466                    || (pEntry->pList == &pCache->LruFrequentlyUsed))
     2467                {
     2468                    /* Check if the entry is dirty. */
     2469                    if (pdmBlkCacheEntryFlagIsSetClearAcquireLock(pBlkCache, pEntry,
     2470                                                                  PDMBLKCACHE_ENTRY_IS_DIRTY,
     2471                                                                  0))
     2472                    {
     2473                        /* If it is dirty but not yet in progress remove it. */
     2474                        if (!(pEntry->fFlags & PDMBLKCACHE_ENTRY_IO_IN_PROGRESS))
     2475                        {
     2476                            pdmBlkCacheLockEnter(pCache);
     2477                            pdmBlkCacheEntryRemoveFromList(pEntry);
     2478
     2479                            STAM_PROFILE_ADV_START(&pCache->StatTreeRemove, Cache);
     2480                            RTAvlrU64Remove(pBlkCache->pTree, pEntry->Core.Key);
     2481                            STAM_PROFILE_ADV_STOP(&pCache->StatTreeRemove, Cache);
     2482
     2483                            pdmBlkCacheLockLeave(pCache);
     2484
     2485                            RTMemFree(pEntry);
     2486                        }
     2487                        else
     2488                        {
     2489#if 0
     2490                            /* The data isn't written to the file yet */
     2491                            pdmBlkCacheEntryWaitersAdd(pEntry, pReq,
     2492                                                       &SgBuf, offDiff, cbToWrite,
     2493                                                       true /* fWrite */);
     2494                            STAM_COUNTER_INC(&pBlkCache->StatWriteDeferred);
     2495#endif
     2496                        }
     2497
     2498                        RTSemRWReleaseWrite(pBlkCache->SemRWEntries);
     2499                        pdmBlkCacheEntryRelease(pEntry);
     2500                    }
     2501                    else /* Dirty bit not set */
     2502                    {
     2503                        /*
     2504                         * Check if a read is in progress for this entry.
     2505                         * We have to defer processing in that case.
     2506                         */
     2507                        if(pdmBlkCacheEntryFlagIsSetClearAcquireLock(pBlkCache, pEntry,
     2508                                                                     PDMBLKCACHE_ENTRY_IO_IN_PROGRESS,
     2509                                                                     0))
     2510                        {
     2511#if 0
     2512                            pdmBlkCacheEntryWaitersAdd(pEntry, pReq,
     2513                                                       &SgBuf, offDiff, cbToWrite,
     2514                                                       true /* fWrite */);
     2515#endif
     2516                            STAM_COUNTER_INC(&pBlkCache->StatWriteDeferred);
     2517                            RTSemRWReleaseWrite(pBlkCache->SemRWEntries);
     2518                            pdmBlkCacheEntryRelease(pEntry);
     2519                        }
     2520                        else /* I/O in progress flag not set */
     2521                        {
     2522                            pdmBlkCacheLockEnter(pCache);
     2523                            pdmBlkCacheEntryRemoveFromList(pEntry);
     2524
     2525                            RTSemRWRequestWrite(pBlkCache->SemRWEntries, RT_INDEFINITE_WAIT);
     2526                            STAM_PROFILE_ADV_START(&pCache->StatTreeRemove, Cache);
     2527                            RTAvlrU64Remove(pBlkCache->pTree, pEntry->Core.Key);
     2528                            STAM_PROFILE_ADV_STOP(&pCache->StatTreeRemove, Cache);
     2529                            RTSemRWReleaseWrite(pBlkCache->SemRWEntries);
     2530
     2531                            pdmBlkCacheLockLeave(pCache);
     2532
     2533                            RTMemFree(pEntry);
     2534                        }
     2535                    } /* Dirty bit not set */
     2536                }
     2537                else /* Entry is on the ghost list just remove cache entry. */
     2538                {
     2539                    pdmBlkCacheLockEnter(pCache);
     2540                    pdmBlkCacheEntryRemoveFromList(pEntry);
     2541
     2542                    RTSemRWRequestWrite(pBlkCache->SemRWEntries, RT_INDEFINITE_WAIT);
     2543                    STAM_PROFILE_ADV_START(&pCache->StatTreeRemove, Cache);
     2544                    RTAvlrU64Remove(pBlkCache->pTree, pEntry->Core.Key);
     2545                    STAM_PROFILE_ADV_STOP(&pCache->StatTreeRemove, Cache);
     2546                    RTSemRWReleaseWrite(pBlkCache->SemRWEntries);
     2547
     2548                    pdmBlkCacheLockLeave(pCache);
     2549
     2550                    RTMemFree(pEntry);
     2551                }
     2552            }
     2553            /* else: no entry found. */
     2554
     2555            offCur += cbThisDiscard;
     2556            cbLeft -= cbThisDiscard;
     2557        }
     2558    }
     2559
     2560    if (!pdmBlkCacheReqUpdate(pBlkCache, pReq, rc, false))
     2561        rc = VINF_AIO_TASK_PENDING;
     2562
     2563    LogFlowFunc((": Leave rc=%Rrc\n", rc));
     2564
     2565    return rc;
     2566}
     2567
    24102568/**
    24112569 * Completes a task segment freeing all resources and completes the task handle
  • trunk/src/VBox/VMM/include/PDMBlkCacheInternal.h

    r37935 r38877  
    204204        {
    205205            /** Pointer to the device instance owning the block cache. */
    206             R3PTRTYPE(PPDMDEVINS)                     pDevIns;
     206            R3PTRTYPE(PPDMDEVINS)                            pDevIns;
    207207            /** Complete callback to the user. */
    208             R3PTRTYPE(PFNPDMBLKCACHEXFERCOMPLETEDEV)  pfnXferComplete;
     208            R3PTRTYPE(PFNPDMBLKCACHEXFERCOMPLETEDEV)         pfnXferComplete;
    209209            /** I/O enqueue callback. */
    210             R3PTRTYPE(PFNPDMBLKCACHEXFERENQUEUEDEV)   pfnXferEnqueue;
     210            R3PTRTYPE(PFNPDMBLKCACHEXFERENQUEUEDEV)          pfnXferEnqueue;
     211            /** Discard enqueue callback. */
     212            R3PTRTYPE(PFNPDMBLKCACHEXFERENQUEUEDISCARDDEV)   pfnXferEnqueueDiscard;
    211213        } Dev;
    212214        /** PDMASYNCCOMPLETIONTEMPLATETYPE_DRV */
     
    214216        {
    215217            /** Pointer to the driver instance owning the block cache. */
    216             R3PTRTYPE(PPDMDRVINS)                     pDrvIns;
     218            R3PTRTYPE(PPDMDRVINS)                            pDrvIns;
    217219            /** Complete callback to the user. */
    218             R3PTRTYPE(PFNPDMBLKCACHEXFERCOMPLETEDRV)  pfnXferComplete;
     220            R3PTRTYPE(PFNPDMBLKCACHEXFERCOMPLETEDRV)         pfnXferComplete;
    219221            /** I/O enqueue callback. */
    220             R3PTRTYPE(PFNPDMBLKCACHEXFERENQUEUEDRV)   pfnXferEnqueue;
     222            R3PTRTYPE(PFNPDMBLKCACHEXFERENQUEUEDRV)          pfnXferEnqueue;
     223            /** Discard enqueue callback. */
     224            R3PTRTYPE(PFNPDMBLKCACHEXFERENQUEUEDISCARDDRV)   pfnXferEnqueueDiscard;
    221225        } Drv;
    222226        /** PDMASYNCCOMPLETIONTEMPLATETYPE_INTERNAL */
     
    224228        {
    225229            /** Pointer to user data. */
    226             R3PTRTYPE(void *)                         pvUser;
     230            R3PTRTYPE(void *)                                pvUser;
    227231            /** Complete callback to the user. */
    228             R3PTRTYPE(PFNPDMBLKCACHEXFERCOMPLETEINT)  pfnXferComplete;
     232            R3PTRTYPE(PFNPDMBLKCACHEXFERCOMPLETEINT)         pfnXferComplete;
    229233            /** I/O enqueue callback. */
    230             R3PTRTYPE(PFNPDMBLKCACHEXFERENQUEUEINT)   pfnXferEnqueue;
     234            R3PTRTYPE(PFNPDMBLKCACHEXFERENQUEUEINT)          pfnXferEnqueue;
     235            /** Discard enqueue callback. */
     236            R3PTRTYPE(PFNPDMBLKCACHEXFERENQUEUEDISCARDINT)   pfnXferEnqueueDiscard;
    231237        } Int;
    232238        /** PDMASYNCCOMPLETIONTEMPLATETYPE_USB */
     
    234240        {
    235241            /** Pointer to the usb instance owning the template. */
    236             R3PTRTYPE(PPDMUSBINS)                     pUsbIns;
     242            R3PTRTYPE(PPDMUSBINS)                            pUsbIns;
    237243            /** Complete callback to the user. */
    238             R3PTRTYPE(PFNPDMBLKCACHEXFERCOMPLETEUSB)  pfnXferComplete;
     244            R3PTRTYPE(PFNPDMBLKCACHEXFERCOMPLETEUSB)         pfnXferComplete;
    239245            /** I/O enqueue callback. */
    240             R3PTRTYPE(PFNPDMBLKCACHEXFERENQUEUEUSB)   pfnXferEnqueue;
     246            R3PTRTYPE(PFNPDMBLKCACHEXFERENQUEUEUSB)          pfnXferEnqueue;
     247            /** Discard enqueue callback. */
     248            R3PTRTYPE(PFNPDMBLKCACHEXFERENQUEUEDISCARDUSB)   pfnXferEnqueueDiscard;
    241249        } Usb;
    242250    } u;
    243251
    244252#ifdef VBOX_WITH_STATISTICS
    245     uint32_t    u32Alignment;
     253    uint32_t                      u32Alignment;
    246254    /** Number of times a write was deferred because the cache entry was still in progress */
    247     STAMCOUNTER StatWriteDeferred;
     255    STAMCOUNTER                   StatWriteDeferred;
    248256#endif
    249257
     
    274282typedef struct PDMBLKCACHEIOXFER
    275283{
    276     /** Flag whether the I/O xfer updates a cache entry or updates the request directl. */
    277     bool fIoCache;
     284    /** Flag whether the I/O xfer updates a cache entry or updates the request directly. */
     285    bool                  fIoCache;
    278286    /** Type dependent data. */
    279287    union
     
    281289        /** Pointer to the entry the transfer updates. */
    282290        PPDMBLKCACHEENTRY pEntry;
    283         /** Pointer to the request the ztransfer updates. */
     291        /** Pointer to the request the transfer updates. */
    284292        PPDMBLKCACHEREQ   pReq;
    285293    };
     294    /** Transfer direction. */
     295    PDMBLKCACHEXFERDIR    enmXferDir;
    286296    /** Segment used if a cache entry is updated. */
    287     RTSGSEG SgSeg;
     297    RTSGSEG               SgSeg;
    288298    /** S/G buffer. */
    289     RTSGBUF SgBuf;
    290     /** Transfer direction. */
    291     PDMBLKCACHEXFERDIR enmXferDir;
     299    RTSGBUF               SgBuf;
    292300} PDMBLKCACHEIOXFER;
    293301
Note: See TracChangeset for help on using the changeset viewer.

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