VirtualBox

Changeset 38877 in vbox for trunk/src/VBox/VMM/VMMR3


Ignore:
Timestamp:
Sep 27, 2011 9:04:46 AM (13 years ago)
Author:
vboxsync
Message:

VMM/PDMBlkCache: Add discard API

File:
1 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
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