VirtualBox

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


Ignore:
Timestamp:
Sep 26, 2016 3:11:22 PM (9 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
110931
Message:

AHCI: Remove trim related structures from the request structure and convert the ranges on the fly when told so

File:
1 edited

Legend:

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

    r64009 r64015  
    306306            PFNAHCIPOSTPROCESS pfnPostProcess;
    307307        } Io;
    308         /** Data for a trim request. */
    309         struct
    310         {
    311             /** Pointer to the array of ranges to trim. */
    312             PRTRANGE           paRanges;
    313             /** Number of entries in the array. */
    314             unsigned           cRanges;
    315         } Trim;
    316308    } u;
    317309} AHCIREQ;
     
    57875779 *
    57885780 * @returns VBox status code.
    5789  * @param   pAhciPort    AHCI port state.
    5790  * @param   pAhciReq     The request handling the TRIM request.
    5791  */
    5792 static int ahciTrimRangesCreate(PAHCIPort pAhciPort, PAHCIREQ pAhciReq)
     5781 * @param   pAhciPort     AHCI port state.
     5782 * @param   pAhciReq      The request handling the TRIM request.
     5783 * @param   idxRangeStart Index of the first range to start copying.
     5784 * @param   paRanges      Where to store the ranges.
     5785 * @param   cRanges       Number of ranges fitting into the array.
     5786 * @param   pcRanges      Where to store the amount of ranges actually copied on success.
     5787 */
     5788static int ahciTrimRangesCreate(PAHCIPort pAhciPort, PAHCIREQ pAhciReq, uint32_t idxRangeStart,
     5789                                PRTRANGE paRanges, uint32_t cRanges, uint32_t *pcRanges)
    57935790{
    57945791    SGLEntry aPrdtlEntries[32];
    57955792    uint64_t aRanges[64];
    5796     unsigned cRangesMax;
    5797     unsigned cRanges = 0;
    57985793    uint32_t cPrdtlEntries = pAhciReq->cPrdtlEntries;
    57995794    RTGCPHYS GCPhysPrdtl   = pAhciReq->GCPhysPrdtl;
    58005795    PPDMDEVINS pDevIns     = pAhciPort->CTX_SUFF(pDevIns);
    5801     int rc = VINF_SUCCESS;
     5796    int rc = VERR_PDM_MEDIAEX_IOBUF_OVERFLOW;
     5797    uint32_t idxRange = 0;
    58025798
    58035799    LogFlowFunc(("pAhciPort=%#p pAhciReq=%#p\n", pAhciPort, pAhciReq));
     
    58055801    AssertMsgReturn(pAhciReq->enmType == PDMMEDIAEXIOREQTYPE_DISCARD, ("This is not a trim request\n"), VERR_INVALID_PARAMETER);
    58065802
    5807     /* The data buffer contains LBA range entries. Each range is 8 bytes big. */
    5808     if (!pAhciReq->cmdFis[AHCI_CMDFIS_SECTC] && !pAhciReq->cmdFis[AHCI_CMDFIS_SECTCEXP])
    5809         cRangesMax = 65536 * 512 / 8;
    5810     else
    5811         cRangesMax = pAhciReq->cmdFis[AHCI_CMDFIS_SECTC] * 512 / 8;
    5812 
    58135803    if (!cPrdtlEntries)
    5814     {
    58155804        pAhciReq->fFlags |= AHCI_REQ_OVERFLOW;
    5816         return VINF_SUCCESS;
    5817     }
    5818 
    5819     do
    5820     {
    5821         uint32_t cPrdtlEntriesRead =   (cPrdtlEntries < RT_ELEMENTS(aPrdtlEntries))
    5822                                      ? cPrdtlEntries
    5823                                      : RT_ELEMENTS(aPrdtlEntries);
    5824 
     5805
     5806    /* Convert the ranges from ATA to our format. */
     5807    while (   cPrdtlEntries
     5808           && idxRange < cRanges)
     5809    {
     5810        uint32_t cPrdtlEntriesRead = RT_MIN(cPrdtlEntries, RT_ELEMENTS(aPrdtlEntries));
     5811
     5812        rc = VINF_SUCCESS;
    58255813        PDMDevHlpPhysRead(pDevIns, GCPhysPrdtl, &aPrdtlEntries[0], cPrdtlEntriesRead * sizeof(SGLEntry));
    58265814
    5827         for (uint32_t i = 0; i < cPrdtlEntriesRead; i++)
     5815        for (uint32_t i = 0; i < cPrdtlEntriesRead && idxRange < cRanges; i++)
    58285816        {
    58295817            RTGCPHYS GCPhysAddrDataBase = AHCI_RTGCPHYS_FROM_U32(aPrdtlEntries[i].u32DBAUp, aPrdtlEntries[i].u32DBA);
     
    58355823            PDMDevHlpPhysRead(pDevIns, GCPhysAddrDataBase, aRanges, cbThisCopy);
    58365824
    5837             for (unsigned idxRange = 0; idxRange < RT_ELEMENTS(aRanges); idxRange++)
     5825            for (unsigned idxRangeSrc = 0; idxRangeSrc < RT_ELEMENTS(aRanges) && idxRange < cRanges; idxRangeSrc++)
    58385826            {
    5839                 aRanges[idxRange] = RT_H2LE_U64(aRanges[idxRange]);
    5840                 if (AHCI_RANGE_LENGTH_GET(aRanges[idxRange]) != 0)
    5841                     cRanges++;
    5842                 else
    5843                     break;
    5844             }
    5845         }
    5846 
    5847         GCPhysPrdtl   += cPrdtlEntriesRead * sizeof(SGLEntry);
    5848         cPrdtlEntries -= cPrdtlEntriesRead;
    5849     } while (cPrdtlEntries);
    5850 
    5851     if (RT_UNLIKELY(!cRanges))
    5852     {
    5853         return VERR_BUFFER_OVERFLOW;
    5854     }
    5855 
    5856     pAhciReq->u.Trim.cRanges = cRanges;
    5857     pAhciReq->u.Trim.paRanges = (PRTRANGE)RTMemAllocZ(sizeof(RTRANGE) * cRanges);
    5858     if (pAhciReq->u.Trim.paRanges)
    5859     {
    5860         uint32_t idxRange = 0;
    5861 
    5862         cPrdtlEntries = pAhciReq->cPrdtlEntries;
    5863         GCPhysPrdtl   = pAhciReq->GCPhysPrdtl;
    5864 
    5865         /* Convert the ranges from the guest to our format. */
    5866         do
    5867         {
    5868             uint32_t cPrdtlEntriesRead =   (cPrdtlEntries < RT_ELEMENTS(aPrdtlEntries))
    5869                                          ? cPrdtlEntries
    5870                                          : RT_ELEMENTS(aPrdtlEntries);
    5871 
    5872             PDMDevHlpPhysRead(pDevIns, GCPhysPrdtl, &aPrdtlEntries[0], cPrdtlEntriesRead * sizeof(SGLEntry));
    5873 
    5874             for (uint32_t i = 0; i < cPrdtlEntriesRead; i++)
    5875             {
    5876                 RTGCPHYS GCPhysAddrDataBase = AHCI_RTGCPHYS_FROM_U32(aPrdtlEntries[i].u32DBAUp, aPrdtlEntries[i].u32DBA);
    5877                 uint32_t cbThisCopy = (aPrdtlEntries[i].u32DescInf & SGLENTRY_DESCINF_DBC) + 1;
    5878 
    5879                 cbThisCopy = RT_MIN(cbThisCopy, sizeof(aRanges));
    5880 
    5881                 /* Copy into buffer. */
    5882                 PDMDevHlpPhysRead(pDevIns, GCPhysAddrDataBase, aRanges, cbThisCopy);
    5883 
    5884                 for (unsigned idxRangeSrc = 0; idxRangeSrc < RT_ELEMENTS(aRanges); idxRangeSrc++)
     5827                /* Skip range if told to do so. */
     5828                if (!idxRangeStart)
    58855829                {
    58865830                    aRanges[idxRangeSrc] = RT_H2LE_U64(aRanges[idxRangeSrc]);
    58875831                    if (AHCI_RANGE_LENGTH_GET(aRanges[idxRangeSrc]) != 0)
    58885832                    {
    5889                         pAhciReq->u.Trim.paRanges[idxRange].offStart = (aRanges[idxRangeSrc] & AHCI_RANGE_LBA_MASK) * pAhciPort->cbSector;
    5890                         pAhciReq->u.Trim.paRanges[idxRange].cbRange = AHCI_RANGE_LENGTH_GET(aRanges[idxRangeSrc]) * pAhciPort->cbSector;
     5833                        paRanges[idxRange].offStart = (aRanges[idxRangeSrc] & AHCI_RANGE_LBA_MASK) * pAhciPort->cbSector;
     5834                        paRanges[idxRange].cbRange = AHCI_RANGE_LENGTH_GET(aRanges[idxRangeSrc]) * pAhciPort->cbSector;
    58915835                        idxRange++;
    58925836                    }
     
    58945838                        break;
    58955839                }
     5840                else
     5841                    idxRangeStart--;
    58965842            }
    5897 
    5898             GCPhysPrdtl   += cPrdtlEntriesRead * sizeof(SGLEntry);
    5899             cPrdtlEntries -= cPrdtlEntriesRead;
    5900         } while (idxRange < cRanges);
    5901     }
    5902     else
    5903         rc = VERR_NO_MEMORY;
     5843        }
     5844
     5845        GCPhysPrdtl   += cPrdtlEntriesRead * sizeof(SGLEntry);
     5846        cPrdtlEntries -= cPrdtlEntriesRead;
     5847    }
     5848
     5849    *pcRanges = idxRange;
    59045850
    59055851    LogFlowFunc(("returns rc=%Rrc\n", rc));
    59065852    return rc;
    5907 }
    5908 
    5909 /**
    5910  * Destroy the trim range list.
    5911  *
    5912  * @returns nothing.
    5913  * @param   pAhciReq    The task state.
    5914  */
    5915 static void ahciTrimRangesDestroy(PAHCIREQ pAhciReq)
    5916 {
    5917     AssertReturnVoid(pAhciReq->enmType == PDMMEDIAEXIOREQTYPE_DISCARD);
    5918     RTMemFree(pAhciReq->u.Trim.paRanges);
    59195853}
    59205854
     
    60275961        }
    60285962        else if (pAhciReq->enmType == PDMMEDIAEXIOREQTYPE_DISCARD)
    6029         {
    6030             ahciTrimRangesDestroy(pAhciReq);
    60315963            pAhciPort->Led.Actual.s.fWriting = 0;
    6032         }
    60335964
    60345965        if (RT_FAILURE(rcReq))
     
    61206051        fCanceled = true;
    61216052
    6122         if (pAhciReq->enmType == PDMMEDIAEXIOREQTYPE_DISCARD)
    6123             ahciTrimRangesDestroy(pAhciReq);
    6124         else if (pAhciReq->enmType != PDMMEDIAEXIOREQTYPE_FLUSH)
     6053        if (pAhciReq->enmType != PDMMEDIAEXIOREQTYPE_FLUSH)
    61256054            ahciIoBufFree(pAhciPort, pAhciReq, false /* fCopyToGuest */);
    61266055
     
    62186147                                                       uint32_t *pcRanges)
    62196148{
    6220     RT_NOREF2(pInterface, hIoReq);
     6149    RT_NOREF1(hIoReq);
     6150    PAHCIPort pAhciPort = RT_FROM_MEMBER(pInterface, AHCIPort, IMediaExPort);
    62216151    PAHCIREQ pIoReq = (PAHCIREQ)pvIoReqAlloc;
    6222     uint32_t cRangesCopy = RT_MIN(pIoReq->u.Trim.cRanges - idxRangeStart, cRanges);
    6223     Assert(   idxRangeStart < pIoReq->u.Trim.cRanges
    6224            && (idxRangeStart + cRanges) <= pIoReq->u.Trim.cRanges);
    6225 
    6226     memcpy(paRanges, &pIoReq->u.Trim.paRanges[idxRangeStart], cRangesCopy * sizeof(RTRANGE));
    6227     *pcRanges = cRangesCopy;
    6228 
    6229     return VINF_SUCCESS;
     6152
     6153    return ahciTrimRangesCreate(pAhciPort, pIoReq, idxRangeStart, paRanges, cRanges, pcRanges);
    62306154}
    62316155
     
    66386562    else if (enmType == PDMMEDIAEXIOREQTYPE_DISCARD)
    66396563    {
    6640         rc = ahciTrimRangesCreate(pAhciPort, pAhciReq);
    6641         if (RT_SUCCESS(rc))
    6642         {
    6643             pAhciPort->Led.Asserted.s.fWriting = pAhciPort->Led.Actual.s.fWriting = 1;
    6644             rc = pAhciPort->pDrvMediaEx->pfnIoReqDiscard(pAhciPort->pDrvMediaEx, pAhciReq->hIoReq,
    6645                                                          pAhciReq->u.Trim.cRanges);
    6646         }
     6564        uint32_t cRangesMax;
     6565
     6566        /* The data buffer contains LBA range entries. Each range is 8 bytes big. */
     6567        if (!pAhciReq->cmdFis[AHCI_CMDFIS_SECTC] && !pAhciReq->cmdFis[AHCI_CMDFIS_SECTCEXP])
     6568            cRangesMax = 65536 * 512 / 8;
     6569        else
     6570            cRangesMax = pAhciReq->cmdFis[AHCI_CMDFIS_SECTC] * 512 / 8;
     6571
     6572        pAhciPort->Led.Asserted.s.fWriting = pAhciPort->Led.Actual.s.fWriting = 1;
     6573        rc = pAhciPort->pDrvMediaEx->pfnIoReqDiscard(pAhciPort->pDrvMediaEx, pAhciReq->hIoReq,
     6574                                                     cRangesMax);
    66476575    }
    66486576    else if (enmType == PDMMEDIAEXIOREQTYPE_READ)
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