VirtualBox

Ignore:
Timestamp:
Nov 18, 2018 4:53:44 AM (6 years ago)
Author:
vboxsync
Message:

os2/VBoxSF: Make use of the embedded buffer feature. Also tried out and measured a few other approaches, see comments.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/os2/VBoxSF/VBoxSFFile.cpp

    r75543 r75550  
    464464}
    465465
     466#include <VBox/VBoxGuest.h>
     467
     468
     469
     470
     471DECLVBGL(int) VbglR0SfFastPhysFsInfo(PVBGLSFCLIENT pClient, PVBGLSFMAP pMap, SHFLHANDLE hFile,
     472                                     uint32_t flags, uint32_t *pcbBuffer, PSHFLDIRINFO pBuffer)
     473{
     474    struct FsInfoReq
     475    {
     476        VBGLIOCIDCHGCMFASTCALL  Hdr;
     477        VMMDevHGCMCall          Call;
     478        VBoxSFParmInformation   Parms;
     479        HGCMPageListInfo        PgLst;
     480        RTGCPHYS64              PageTwo;
     481    } *pReq;
     482    AssertCompileMemberOffset(struct FsInfoReq, Call, 52);
     483    AssertCompileMemberOffset(struct FsInfoReq, Parms, 0x60);
     484
     485    pReq = (struct FsInfoReq *)VbglR0PhysHeapAlloc(sizeof(*pReq));
     486    if (!pReq)
     487        return VERR_NO_MEMORY;
     488
     489    VBGLIOCIDCHGCMFASTCALL_INIT(&pReq->Hdr, VbglR0PhysHeapGetPhysAddr(pReq), &pReq->Call, pClient->idClient,
     490                                SHFL_FN_INFORMATION, SHFL_CPARMS_INFORMATION, sizeof(*pReq));
     491#if 0
     492    VBGLREQHDR_INIT_EX(&pReq->Hdr.Hdr, sizeof(*pReq), sizeof(*pReq));
     493    pReq->Hdr.GCPhysReq      = VbglR0PhysHeapGetPhysAddr(pReq) + sizeof(pReq->Hdr);
     494    pReq->Hdr.fInterruptible = false;
     495
     496    pReq->Call.header.header.size       = sizeof(*pReq) - sizeof(pReq->Hdr);
     497    pReq->Call.header.header.version    = VBGLREQHDR_VERSION;
     498    pReq->Call.header.header.requestType= VMMDevReq_HGCMCall32;
     499    pReq->Call.header.header.rc         = VERR_INTERNAL_ERROR;
     500    pReq->Call.header.header.reserved1  = 0;
     501    pReq->Call.header.header.fRequestor = VMMDEV_REQUESTOR_KERNEL        | VMMDEV_REQUESTOR_USR_DRV_OTHER
     502                                        | VMMDEV_REQUESTOR_CON_DONT_KNOW | VMMDEV_REQUESTOR_TRUST_NOT_GIVEN;
     503    pReq->Call.header.fu32Flags         = 0;
     504    pReq->Call.header.result            = VERR_INTERNAL_ERROR;
     505    pReq->Call.u32ClientID              = pClient->idClient;
     506    pReq->Call.u32Function              = SHFL_FN_INFORMATION;
     507    pReq->Call.cParms                   = SHFL_CPARMS_INFORMATION;
     508#endif
     509    uint32_t const cbBuffer = *pcbBuffer;
     510    pReq->Parms.id32Root.type           = VMMDevHGCMParmType_32bit;
     511    pReq->Parms.id32Root.u.value32      = pMap->root;
     512    pReq->Parms.u64Handle.type          = VMMDevHGCMParmType_64bit;
     513    pReq->Parms.u64Handle.u.value64     = hFile;
     514    pReq->Parms.f32Flags.type           = VMMDevHGCMParmType_32bit;
     515    pReq->Parms.f32Flags.u.value32      = flags;
     516    pReq->Parms.cb32.type               = VMMDevHGCMParmType_32bit;
     517    pReq->Parms.cb32.u.value32          = cbBuffer;
     518    pReq->Parms.pInfo.type              = VMMDevHGCMParmType_PageList;
     519    pReq->Parms.pInfo.u.PageList.size   = cbBuffer;
     520    pReq->Parms.pInfo.u.PageList.offset = RT_UOFFSETOF(struct FsInfoReq, PgLst) - RT_UOFFSETOF(struct FsInfoReq, Call);
     521
     522    Assert(cbBuffer < _1K);
     523    pReq->PgLst.flags                   = VBOX_HGCM_F_PARM_DIRECTION_FROM_HOST;
     524    pReq->PgLst.cPages                  = cbBuffer <= (PAGE_SIZE - ((uintptr_t)pBuffer & PAGE_OFFSET_MASK)) ? 1 : 2;
     525    pReq->PgLst.offFirstPage            = (uint16_t)((uintptr_t)pBuffer & PAGE_OFFSET_MASK);
     526    pReq->PgLst.aPages[0]               = VbglR0PhysHeapGetPhysAddr(pBuffer) & ~(RTGCPHYS64)PAGE_OFFSET_MASK;
     527    if (pReq->PgLst.cPages == 1)
     528        pReq->PageTwo                   = NIL_RTGCPHYS64;
     529    else
     530        pReq->PageTwo                   = pReq->PgLst.aPages[0] + PAGE_SIZE;
     531
     532    int rc = VbglR0HGCMFastCall(pClient->handle, &pReq->Hdr, sizeof(*pReq));
     533    if (RT_SUCCESS(rc))
     534    {
     535        rc = pReq->Call.header.result;
     536        *pcbBuffer = pReq->Parms.cb32.u.value32;
     537    }
     538    VbglR0PhysHeapFree(pReq);
     539    return rc;
     540}
     541
     542
     543DECLVBGL(int) VbglR0SfPhysFsInfo(PVBGLSFCLIENT pClient, PVBGLSFMAP pMap, SHFLHANDLE hFile,
     544                                 uint32_t flags, uint32_t *pcbBuffer, PSHFLDIRINFO pBuffer)
     545{
     546    uint32_t const cbBuffer = *pcbBuffer;
     547
     548    struct
     549    {
     550        VBoxSFInformation   Core;
     551        HGCMPageListInfo    PgLst;
     552        RTGCPHYS64          PageTwo;
     553    } Req;
     554
     555    VBGL_HGCM_HDR_INIT_EX(&Req.Core.callInfo, pClient->idClient, SHFL_FN_INFORMATION, SHFL_CPARMS_INFORMATION, sizeof(Req));
     556    Req.Core.callInfo.fInterruptible = false;
     557
     558    Req.Core.root.type                      = VMMDevHGCMParmType_32bit;
     559    Req.Core.root.u.value32                 = pMap->root;
     560
     561    Req.Core.handle.type                    = VMMDevHGCMParmType_64bit;
     562    Req.Core.handle.u.value64               = hFile;
     563    Req.Core.flags.type                     = VMMDevHGCMParmType_32bit;
     564    Req.Core.flags.u.value32                = flags;
     565    Req.Core.cb.type                        = VMMDevHGCMParmType_32bit;
     566    Req.Core.cb.u.value32                   = cbBuffer;
     567    Req.Core.info.type                      = VMMDevHGCMParmType_PageList;
     568    Req.Core.info.u.PageList.size           = cbBuffer;
     569    Req.Core.info.u.PageList.offset         = sizeof(Req.Core);
     570
     571    Assert(cbBuffer < _1K);
     572    Req.PgLst.flags                         = VBOX_HGCM_F_PARM_DIRECTION_FROM_HOST;
     573    Req.PgLst.cPages                        = cbBuffer <= (PAGE_SIZE - ((uintptr_t)pBuffer & PAGE_OFFSET_MASK)) ? 1 : 2;
     574    Req.PgLst.offFirstPage                  = (uint16_t)((uintptr_t)pBuffer & PAGE_OFFSET_MASK);
     575    Req.PgLst.aPages[0]                     = VbglR0PhysHeapGetPhysAddr(pBuffer) & ~(RTGCPHYS64)PAGE_OFFSET_MASK;
     576    if (Req.PgLst.cPages == 1)
     577        Req.PageTwo                         = NIL_RTGCPHYS64;
     578    else
     579        Req.PageTwo                         = Req.PgLst.aPages[0] + PAGE_SIZE;
     580
     581    int rc = VbglR0HGCMCallRaw(pClient->handle, &Req.Core.callInfo, sizeof(Req));
     582    //Log(("VBOXSF: VbglR0SfFsInfo: VbglR0HGCMCall rc = %#x, result = %#x\n", rc, data.callInfo.Hdr.rc));
     583    if (RT_SUCCESS(rc))
     584    {
     585        rc = Req.Core.callInfo.Hdr.rc;
     586        *pcbBuffer = Req.Core.cb.u.value32;
     587    }
     588    return rc;
     589}
     590
    466591
    467592/**
     
    480605vboxSfOs2QueryFileInfo(PVBOXSFFOLDER pFolder, PSFFSI pSfFsi, PVBOXSFSYFI pSfFsd, ULONG uLevel, PBYTE pbData, ULONG cbData)
    481606{
     607    /*
     608     * Performance notes:
     609     *
     610     * This function was used for some performance hacking in an attempt at
     611     * squeezing more performance out of the HGCM and shared folders code.
     612     *
     613     * 0. Skip calling the host and returning zeros:
     614     *       906 ns / 3653 ticks
     615     *
     616     *    This is comparable to JFS (859 ns) and HPFS (1107 ns) and give an
     617     *    idea what we're up against compared to a "local" file system.
     618     *
     619     * 1. Having shortcircuted the host side processing by faking a success when
     620     *    VMMDevHGCM.cpp is about to do pThis->pHGCMDrv->pfnCall, then measuring
     621     *    various guest side changes in the request and request submission path:
     622     *
     623     *     - Wasted on virtual address vs page list buffer:
     624     *         4095 ns / 16253 ticks
     625     *
     626     *       Suspect this is due to expensive memory locking on the guest side and
     627     *       the host doing extra virtual address conversion.
     628     *
     629     *     - Wasted repackaging the HGCM request:
     630     *         450 ns / 1941 ticks
     631     *
     632     *     - Embedding the SHFLFSOBJINFO into the buffer may save a little as well:
     633     *         286 ns / 1086 ticks
     634     *
     635     *    Raw data:
     636     *        11843ns / 47469 ticks - VbglR0SfFsInfo
     637     *         7748ns / 31216 ticks - VbglR0SfPhysFsInfo
     638     *         7298ns / 29275 ticks - VbglR0SfFastPhysFsInfo
     639     *         7012ns / 28189 ticks - Embedded buffer.
     640     *
     641     * 2. should've done measurements of the host side optimizations too...
     642     *
     643     */
     644#if 0
    482645    APIRET rc;
    483646    PSHFLFSOBJINFO pObjInfo = (PSHFLFSOBJINFO)VbglR0PhysHeapAlloc(sizeof(*pObjInfo));
     
    487650        uint32_t cbObjInfo = sizeof(*pObjInfo);
    488651
    489         int vrc = VbglR0SfFsInfo(&g_SfClient, &pFolder->hHostFolder, pSfFsd->hHostFile,
    490                                  SHFL_INFO_FILE | SHFL_INFO_GET, &cbObjInfo, (PSHFLDIRINFO)pObjInfo);
     652        int vrc = VbglR0SfFastPhysFsInfo(&g_SfClient, &pFolder->hHostFolder, pSfFsd->hHostFile,
     653                                         SHFL_INFO_FILE | SHFL_INFO_GET, &cbObjInfo, (PSHFLDIRINFO)pObjInfo);
    491654        if (RT_SUCCESS(vrc))
    492655        {
     
    513676    else
    514677        rc = ERROR_NOT_ENOUGH_MEMORY;
     678#else
     679    APIRET rc;
     680    struct MyEmbReq
     681    {
     682        VBGLIOCIDCHGCMFASTCALL  Hdr;
     683        VMMDevHGCMCall          Call;
     684        VBoxSFParmInformation   Parms;
     685        SHFLFSOBJINFO           ObjInfo;
     686    } *pReq = (struct MyEmbReq *)VbglR0PhysHeapAlloc(sizeof(*pReq));
     687    if (pReq)
     688    {
     689        RT_ZERO(pReq->ObjInfo);
     690
     691        VBGLIOCIDCHGCMFASTCALL_INIT(&pReq->Hdr, VbglR0PhysHeapGetPhysAddr(pReq), &pReq->Call, g_SfClient.idClient,
     692                                    SHFL_FN_INFORMATION, SHFL_CPARMS_INFORMATION, sizeof(*pReq));
     693        pReq->Parms.id32Root.type               = VMMDevHGCMParmType_32bit;
     694        pReq->Parms.id32Root.u.value32          = pFolder->hHostFolder.root;
     695        pReq->Parms.u64Handle.type              = VMMDevHGCMParmType_64bit;
     696        pReq->Parms.u64Handle.u.value64         = pSfFsd->hHostFile;
     697        pReq->Parms.f32Flags.type               = VMMDevHGCMParmType_32bit;
     698        pReq->Parms.f32Flags.u.value32          = SHFL_INFO_FILE | SHFL_INFO_GET;
     699        pReq->Parms.cb32.type                   = VMMDevHGCMParmType_32bit;
     700        pReq->Parms.cb32.u.value32              = sizeof(pReq->ObjInfo);
     701        pReq->Parms.pInfo.type                  = VMMDevHGCMParmType_Embedded;
     702        pReq->Parms.pInfo.u.Embedded.cbData     = sizeof(pReq->ObjInfo);
     703        pReq->Parms.pInfo.u.Embedded.offData    = RT_UOFFSETOF(struct MyEmbReq, ObjInfo) - sizeof(VBGLIOCIDCHGCMFASTCALL);
     704        pReq->Parms.pInfo.u.Embedded.fFlags     = VBOX_HGCM_F_PARM_DIRECTION_FROM_HOST;
     705
     706        int vrc = VbglR0HGCMFastCall(g_SfClient.handle, &pReq->Hdr, sizeof(*pReq));
     707        if (RT_SUCCESS(vrc))
     708            vrc = pReq->Call.header.result;
     709        if (RT_SUCCESS(vrc))
     710        {
     711            rc = vboxSfOs2FileStatusFromObjInfo(pbData, cbData, uLevel, &pReq->ObjInfo);
     712            if (rc == NO_ERROR)
     713            {
     714                /* Update the timestamps in the independent file data: */
     715                int16_t cMinLocalTimeDelta = vboxSfOs2GetLocalTimeDelta();
     716                vboxSfOs2DateTimeFromTimeSpec(&pSfFsi->sfi_cdate, &pSfFsi->sfi_ctime, pReq->ObjInfo.BirthTime,        cMinLocalTimeDelta);
     717                vboxSfOs2DateTimeFromTimeSpec(&pSfFsi->sfi_adate, &pSfFsi->sfi_atime, pReq->ObjInfo.AccessTime,       cMinLocalTimeDelta);
     718                vboxSfOs2DateTimeFromTimeSpec(&pSfFsi->sfi_mdate, &pSfFsi->sfi_mtime, pReq->ObjInfo.ModificationTime, cMinLocalTimeDelta);
     719
     720                /* And the size field as we're at it: */
     721                pSfFsi->sfi_sizel = pReq->ObjInfo.cbObject;
     722            }
     723        }
     724        else
     725        {
     726            Log(("vboxSfOs2QueryFileInfo: VbglR0SfFsInfo failed: %Rrc\n", vrc));
     727            rc = vboxSfOs2ConvertStatusToOs2(vrc, ERROR_GEN_FAILURE);
     728        }
     729
     730        VbglR0PhysHeapFree(pReq);
     731    }
     732    else
     733        rc = ERROR_NOT_ENOUGH_MEMORY;
     734#endif
    515735    return rc;
    516736}
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