VirtualBox

Changeset 44558 in vbox


Ignore:
Timestamp:
Feb 6, 2013 7:54:11 AM (12 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
83618
Message:

VBOXSF: use page list for read/write buffer.

Location:
trunk/src/VBox/Additions
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/WINNT/SharedFolders/driver/file.c

    r42154 r44558  
    77
    88/*
    9  * Copyright (C) 2012 Oracle Corporation
     9 * Copyright (C) 2012-2013 Oracle Corporation
    1010 *
    1111 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    2020#include "vbsf.h"
    2121#include <iprt/fs.h>
     22#include <iprt/mem.h>
     23
     24
     25/* How much data to transfer in one HGCM request. */
     26#define VBSF_MAX_READ_WRITE_PAGES 256
     27
     28
     29typedef int FNVBSFTRANSFERBUFFER(PVBSFCLIENT pClient, PVBSFMAP pMap, SHFLHANDLE hFile,
     30                                 uint64_t offset, uint32_t *pcbBuffer,
     31                                 uint8_t *pBuffer, bool fLocked);
     32typedef FNVBSFTRANSFERBUFFER *PFNVBSFTRANSFERBUFFER;
     33
     34typedef int FNVBSFTRANSFERPAGES(PVBSFCLIENT pClient, PVBSFMAP pMap, SHFLHANDLE hFile,
     35                                uint64_t offset, uint32_t *pcbBuffer,
     36                                uint16_t offFirstPage, uint16_t cPages, RTGCPHYS64 *paPages);
     37typedef FNVBSFTRANSFERPAGES *PFNVBSFTRANSFERPAGES;
     38
     39
     40static int vbsfTransferBufferRead(PVBSFCLIENT pClient, PVBSFMAP pMap, SHFLHANDLE hFile,
     41                                  uint64_t offset, uint32_t *pcbBuffer,
     42                                  uint8_t *pBuffer, bool fLocked)
     43{
     44    return vboxCallRead(pClient, pMap, hFile, offset, pcbBuffer, pBuffer, fLocked);
     45}
     46
     47static int vbsfTransferBufferWrite(PVBSFCLIENT pClient, PVBSFMAP pMap, SHFLHANDLE hFile,
     48                                   uint64_t offset, uint32_t *pcbBuffer,
     49                                   uint8_t *pBuffer, bool fLocked)
     50{
     51    return vboxCallWrite(pClient, pMap, hFile, offset, pcbBuffer, pBuffer, fLocked);
     52}
     53
     54static int vbsfTransferPagesRead(PVBSFCLIENT pClient, PVBSFMAP pMap, SHFLHANDLE hFile,
     55                                 uint64_t offset, uint32_t *pcbBuffer,
     56                                 uint16_t offFirstPage, uint16_t cPages, RTGCPHYS64 *paPages)
     57{
     58    return VbglR0SharedFolderReadPageList(pClient, pMap, hFile, offset, pcbBuffer, offFirstPage, cPages, paPages);
     59}
     60
     61static int vbsfTransferPagesWrite(PVBSFCLIENT pClient, PVBSFMAP pMap, SHFLHANDLE hFile,
     62                                  uint64_t offset, uint32_t *pcbBuffer,
     63                                  uint16_t offFirstPage, uint16_t cPages, RTGCPHYS64 *paPages)
     64{
     65    return VbglR0SharedFolderWritePageList(pClient, pMap, hFile, offset, pcbBuffer, offFirstPage, cPages, paPages);
     66}
     67
     68
     69typedef struct VBSFTRANSFERCTX
     70{
     71    PVBSFCLIENT pClient;
     72    PVBSFMAP pMap;
     73    SHFLHANDLE hFile;
     74    uint64_t offset;
     75    uint32_t cbData;
     76
     77    PMDL pMdl;
     78    uint8_t *pBuffer;
     79    bool fLocked;
     80
     81    PFNVBSFTRANSFERBUFFER pfnTransferBuffer;
     82    PFNVBSFTRANSFERPAGES pfnTransferPages;
     83} VBSFTRANSFERCTX;
     84
     85
     86static int vbsfTransferCommon(VBSFTRANSFERCTX *pCtx)
     87{
     88    int rc = VINF_SUCCESS;
     89    BOOLEAN fProcessed = FALSE;
     90
     91    uint32_t cbTransferred = 0;
     92
     93    uint32_t cbToTransfer;
     94    uint32_t cbIO;
     95
     96    if (VbglR0CanUsePhysPageList())
     97    {
     98        ULONG offFirstPage = MmGetMdlByteOffset(pCtx->pMdl);
     99        ULONG cPages = ADDRESS_AND_SIZE_TO_SPAN_PAGES(MmGetMdlVirtualAddress(pCtx->pMdl), pCtx->cbData);
     100        ULONG cPagesToTransfer = RT_MIN(cPages, VBSF_MAX_READ_WRITE_PAGES);
     101        RTGCPHYS64 *paPages = (RTGCPHYS64 *)RTMemTmpAlloc(cPagesToTransfer * sizeof(RTGCPHYS64));
     102
     103        Log(("VBOXSF: vbsfTransferCommon: using page list: %d pages, offset 0x%03X\n", cPages, offFirstPage));
     104
     105        if (paPages)
     106        {
     107            PPFN_NUMBER paPfns = MmGetMdlPfnArray(pCtx->pMdl);
     108            ULONG cPagesTransferred = 0;
     109            cbTransferred = 0;
     110
     111            while (cPagesToTransfer != 0)
     112            {
     113                ULONG iPage;
     114                cbToTransfer = cPagesToTransfer * PAGE_SIZE - offFirstPage;
     115
     116                if (cbToTransfer > pCtx->cbData - cbTransferred)
     117                {
     118                    cbToTransfer = pCtx->cbData - cbTransferred;
     119                }
     120
     121                if (cbToTransfer == 0)
     122                {
     123                    /* Nothing to transfer. */
     124                    break;
     125                }
     126
     127                cbIO = cbToTransfer;
     128
     129                Log(("VBOXSF: vbsfTransferCommon: transferring %d pages at %d; %d bytes at %d\n",
     130                     cPagesToTransfer, cPagesTransferred, cbToTransfer, cbTransferred));
     131
     132                for (iPage = 0; iPage < cPagesToTransfer; iPage++)
     133                {
     134                    paPages[iPage] = (RTGCPHYS64)paPfns[iPage + cPagesTransferred] << PAGE_SHIFT;
     135                }
     136
     137                rc = pCtx->pfnTransferPages(pCtx->pClient, pCtx->pMap, pCtx->hFile,
     138                                            pCtx->offset + cbTransferred, &cbIO,
     139                                            (uint16_t)offFirstPage, (uint16_t)cPagesToTransfer, paPages);
     140                if (RT_FAILURE(rc))
     141                {
     142                    Log(("VBOXSF: vbsfTransferCommon: pfnTransferPages %Rrc, cbTransferred %d\n", rc, cbTransferred));
     143
     144                    /* If some data was transferred, then it is no error. */
     145                    if (cbTransferred > 0)
     146                    {
     147                        rc = VINF_SUCCESS;
     148                    }
     149
     150                    break;
     151                }
     152
     153                cbTransferred += cbIO;
     154
     155                if (cbToTransfer < cbIO)
     156                {
     157                    /* Transferred less than requested, do not continue with the possibly remaining data. */
     158                    break;
     159                }
     160
     161                cPagesTransferred += cPagesToTransfer;
     162                offFirstPage = 0;
     163
     164                cPagesToTransfer = cPages - cPagesTransferred;
     165                if (cPagesToTransfer > VBSF_MAX_READ_WRITE_PAGES)
     166                {
     167                    cPagesToTransfer = VBSF_MAX_READ_WRITE_PAGES;
     168                }
     169            }
     170
     171            RTMemTmpFree(paPages);
     172
     173            fProcessed = TRUE;
     174        }
     175    }
     176
     177    if (fProcessed != TRUE)
     178    {
     179        /* Split large transfers. */
     180        cbTransferred = 0;
     181        cbToTransfer = RT_MIN(pCtx->cbData, VBSF_MAX_READ_WRITE_PAGES * PAGE_SIZE);
     182
     183        /* Page list not supported or a fallback. */
     184        Log(("VBOXSF: vbsfTransferCommon: using linear address\n"));
     185
     186        while (cbToTransfer != 0)
     187        {
     188            cbIO = cbToTransfer;
     189
     190            Log(("VBOXSF: vbsfTransferCommon: transferring %d bytes at %d\n",
     191                 cbToTransfer, cbTransferred));
     192
     193            rc = pCtx->pfnTransferBuffer(pCtx->pClient, pCtx->pMap, pCtx->hFile,
     194                                         pCtx->offset + cbTransferred, &cbIO,
     195                                         pCtx->pBuffer + cbTransferred, true /* locked */);
     196
     197            if (RT_FAILURE(rc))
     198            {
     199                Log(("VBOXSF: vbsfTransferCommon: pfnTransferBuffer %Rrc, cbTransferred %d\n", rc, cbTransferred));
     200
     201                /* If some data was transferred, then it is no error. */
     202                if (cbTransferred > 0)
     203                {
     204                    rc = VINF_SUCCESS;
     205                }
     206
     207                break;
     208            }
     209
     210            cbTransferred += cbIO;
     211
     212            if (cbToTransfer < cbIO)
     213            {
     214                /* Transferred less than requested, do not continue with the possibly remaining data. */
     215                break;
     216            }
     217
     218            cbToTransfer = pCtx->cbData - cbTransferred;
     219            if (cbToTransfer > VBSF_MAX_READ_WRITE_PAGES * PAGE_SIZE)
     220            {
     221                cbToTransfer = VBSF_MAX_READ_WRITE_PAGES * PAGE_SIZE;
     222            }
     223        }
     224    }
     225
     226    pCtx->cbData = cbTransferred;
     227
     228    return rc;
     229}
    22230
    23231static NTSTATUS vbsfReadInternal(IN PRX_CONTEXT RxContext)
    24232{
    25233    NTSTATUS Status = STATUS_SUCCESS;
     234    VBSFTRANSFERCTX ctx;
    26235
    27236    RxCaptureFcb;
     
    81290    }
    82291
    83     /* @todo Split large reads. */
    84     vboxRC = vboxCallRead(&pDeviceExtension->hgcmClient, &pNetRootExtension->map, pVBoxFobx->hFile,
    85                           ByteOffset, &ByteCount, (uint8_t *)pbUserBuffer, true /* locked */);
     292    ctx.pClient = &pDeviceExtension->hgcmClient;
     293    ctx.pMap    = &pNetRootExtension->map;
     294    ctx.hFile   = pVBoxFobx->hFile;
     295    ctx.offset  = (uint64_t)ByteOffset;
     296    ctx.cbData  = ByteCount;
     297    ctx.pMdl    = BufferMdl;
     298    ctx.pBuffer = (uint8_t *)pbUserBuffer;
     299    ctx.fLocked = true;
     300    ctx.pfnTransferBuffer = vbsfTransferBufferRead;
     301    ctx.pfnTransferPages = vbsfTransferPagesRead;
     302
     303    vboxRC = vbsfTransferCommon(&ctx);
     304
     305    ByteCount = ctx.cbData;
    86306
    87307    Status = VBoxErrorToNTStatus(vboxRC);
     
    137357{
    138358    NTSTATUS Status = STATUS_SUCCESS;
     359    VBSFTRANSFERCTX ctx;
    139360
    140361    RxCaptureFcb;
     
    175396    }
    176397
    177     /* @todo Split large writes. */
    178     vboxRC = vboxCallWrite(&pDeviceExtension->hgcmClient, &pNetRootExtension->map, pVBoxFobx->hFile,
    179                            ByteOffset, &ByteCount, (uint8_t *)pbUserBuffer, true /* locked */);
     398    ctx.pClient = &pDeviceExtension->hgcmClient;
     399    ctx.pMap    = &pNetRootExtension->map;
     400    ctx.hFile   = pVBoxFobx->hFile;
     401    ctx.offset  = (uint64_t)ByteOffset;
     402    ctx.cbData  = ByteCount;
     403    ctx.pMdl    = BufferMdl;
     404    ctx.pBuffer = (uint8_t *)pbUserBuffer;
     405    ctx.fLocked = true;
     406    ctx.pfnTransferBuffer = vbsfTransferBufferWrite;
     407    ctx.pfnTransferPages = vbsfTransferPagesWrite;
     408
     409    vboxRC = vbsfTransferCommon(&ctx);
     410
     411    ByteCount = ctx.cbData;
    180412
    181413    Status = VBoxErrorToNTStatus(vboxRC);
  • trunk/src/VBox/Additions/common/VBoxGuestLib/VBGLInternal.h

    r42316 r44558  
    55
    66/*
    7  * Copyright (C) 2006-2012 Oracle Corporation
     7 * Copyright (C) 2006-2013 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    139139 * @param   a_fLocked       For the windows shared folders workarounds.
    140140 *
    141  * @remarks Disable the PageList feature for 64-bit Windows, because shared
    142  *          folders do not work, if this is enabled. This should be reenabled
    143  *          again when the problem is fixed.
    144  * @remarks Disabled the PageList feature for 32-bit Windows, see xTracker
    145  *          ticket 6096 and public ticket 10290. Hopefully this is the same
    146  *          issue as on Windows/AMD64.
     141 * @remarks Disabled the PageList feature for locked memory on Windows,
     142 *          because a new MDL is created by VBGL to get the page addresses
     143 *          and the pages from the MDL are marked as dirty when they should not.
    147144 */
    148145#if defined(RT_OS_WINDOWS)
    149 # ifdef RT_ARCH_AMD64
    150 #  define VBGLR0_CAN_USE_PHYS_PAGE_LIST(a_fLocked)  ( 0 )
    151 # else
    152 #  define VBGLR0_CAN_USE_PHYS_PAGE_LIST(a_fLocked) \
    153      ( !(a_fLocked) && (g_vbgldata.hostVersion.features & VMMDEV_HVF_HGCM_PHYS_PAGE_LIST) )
    154 # endif
     146# define VBGLR0_CAN_USE_PHYS_PAGE_LIST(a_fLocked) \
     147    ( !(a_fLocked) && (g_vbgldata.hostVersion.features & VMMDEV_HVF_HGCM_PHYS_PAGE_LIST) )
    155148#else
    156149# define VBGLR0_CAN_USE_PHYS_PAGE_LIST(a_fLocked) \
  • trunk/src/VBox/Additions/common/VBoxGuestLib/VBoxGuestR0LibSharedFolders.c

    r44528 r44558  
    55
    66/*
    7  * Copyright (C) 2006-2012 Oracle Corporation
     7 * Copyright (C) 2006-2013 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    443443}
    444444
     445DECLVBGL(int) VbglR0SharedFolderReadPageList(PVBSFCLIENT pClient, PVBSFMAP pMap, SHFLHANDLE hFile,
     446                                             uint64_t offset, uint32_t *pcbBuffer,
     447                                             uint16_t offFirstPage, uint16_t cPages, RTGCPHYS64 *paPages)
     448{
     449    uint32_t            cbToRead  = *pcbBuffer;
     450    uint32_t            cbData    = sizeof(VBoxSFRead) + RT_UOFFSETOF(HGCMPageListInfo, aPages[cPages]);
     451    VBoxSFRead         *pData     = (VBoxSFRead *)RTMemTmpAlloc(cbData);
     452    HGCMPageListInfo   *pPgLst    = (HGCMPageListInfo *)(pData + 1);
     453    uint16_t            iPage;
     454    int                 rc;
     455
     456    if (RT_UNLIKELY(!pData))
     457        return VERR_NO_TMP_MEMORY;
     458
     459    VBOX_INIT_CALL(&pData->callInfo, READ, pClient);
     460
     461    pData->root.type                      = VMMDevHGCMParmType_32bit;
     462    pData->root.u.value32                 = pMap->root;
     463
     464    pData->handle.type                    = VMMDevHGCMParmType_64bit;
     465    pData->handle.u.value64               = hFile;
     466    pData->offset.type                    = VMMDevHGCMParmType_64bit;
     467    pData->offset.u.value64               = offset;
     468    pData->cb.type                        = VMMDevHGCMParmType_32bit;
     469    pData->cb.u.value32                   = cbToRead;
     470    pData->buffer.type                    = VMMDevHGCMParmType_PageList;
     471    pData->buffer.u.PageList.size         = cbToRead;
     472    pData->buffer.u.PageList.offset       = sizeof(VBoxSFRead);
     473
     474    pPgLst->flags = VBOX_HGCM_F_PARM_DIRECTION_FROM_HOST;
     475    pPgLst->offFirstPage = offFirstPage;
     476    pPgLst->cPages = cPages;
     477    for (iPage = 0; iPage < cPages; iPage++)
     478        pPgLst->aPages[iPage] = paPages[iPage];
     479
     480    rc = VbglHGCMCall(pClient->handle, &pData->callInfo, cbData);
     481    if (RT_SUCCESS (rc))
     482    {
     483        rc = pData->callInfo.result;
     484        *pcbBuffer = pData->cb.u.value32;
     485    }
     486
     487    RTMemTmpFree(pData);
     488    return rc;
     489}
     490
    445491DECLVBGL(int) vboxCallWrite(PVBSFCLIENT pClient, PVBSFMAP pMap, SHFLHANDLE hFile,
    446492                            uint64_t offset, uint32_t *pcbBuffer, uint8_t *pBuffer, bool fLocked)
     
    523569    return rc;
    524570
     571}
     572
     573DECLVBGL(int) VbglR0SharedFolderWritePageList(PVBSFCLIENT pClient, PVBSFMAP pMap, SHFLHANDLE hFile,
     574                                              uint64_t offset, uint32_t *pcbBuffer,
     575                                              uint16_t offFirstPage, uint16_t cPages, RTGCPHYS64 *paPages)
     576{
     577    uint32_t            cbToWrite = *pcbBuffer;
     578    uint32_t            cbData    = sizeof(VBoxSFWrite) + RT_UOFFSETOF(HGCMPageListInfo, aPages[cPages]);
     579    VBoxSFWrite        *pData     = (VBoxSFWrite *)RTMemTmpAlloc(cbData);
     580    HGCMPageListInfo   *pPgLst    = (HGCMPageListInfo *)(pData + 1);
     581    uint16_t            iPage;
     582    int                 rc;
     583
     584    if (RT_UNLIKELY(!pData))
     585        return VERR_NO_TMP_MEMORY;
     586
     587    VBOX_INIT_CALL(&pData->callInfo, WRITE, pClient);
     588
     589    pData->root.type                      = VMMDevHGCMParmType_32bit;
     590    pData->root.u.value32                 = pMap->root;
     591
     592    pData->handle.type                    = VMMDevHGCMParmType_64bit;
     593    pData->handle.u.value64               = hFile;
     594    pData->offset.type                    = VMMDevHGCMParmType_64bit;
     595    pData->offset.u.value64               = offset;
     596    pData->cb.type                        = VMMDevHGCMParmType_32bit;
     597    pData->cb.u.value32                   = cbToWrite;
     598    pData->buffer.type                    = VMMDevHGCMParmType_PageList;
     599    pData->buffer.u.PageList.size         = cbToWrite;
     600    pData->buffer.u.PageList.offset       = sizeof(VBoxSFWrite);
     601
     602    pPgLst->flags = VBOX_HGCM_F_PARM_DIRECTION_TO_HOST;
     603    pPgLst->offFirstPage = offFirstPage;
     604    pPgLst->cPages = cPages;
     605    for (iPage = 0; iPage < cPages; iPage++)
     606        pPgLst->aPages[iPage] = paPages[iPage];
     607
     608    rc = VbglHGCMCall (pClient->handle, &pData->callInfo, cbData);
     609    if (RT_SUCCESS (rc))
     610    {
     611        rc = pData->callInfo.result;
     612        *pcbBuffer = pData->cb.u.value32;
     613    }
     614
     615    RTMemTmpFree(pData);
     616    return rc;
    525617}
    526618
  • trunk/src/VBox/Additions/common/VBoxGuestLib/VBoxGuestR0LibSharedFolders.h

    r44528 r44558  
    44
    55/*
    6  * Copyright (C) 2006-2012 Oracle Corporation
     6 * Copyright (C) 2006-2013 Oracle Corporation
    77 *
    88 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    173173
    174174DECLVBGL(int) vboxCallRead (PVBSFCLIENT pClient, PVBSFMAP pMap, SHFLHANDLE hFile, uint64_t offset, uint32_t *pcbBuffer, uint8_t *pBuffer, bool fLocked);
     175DECLVBGL(int) VbglR0SharedFolderReadPageList(PVBSFCLIENT pClient, PVBSFMAP pMap, SHFLHANDLE hFile,
     176                                             uint64_t offset, uint32_t *pcbBuffer,
     177                                             uint16_t offFirstPage, uint16_t cPages, RTGCPHYS64 *paPages);
    175178DECLVBGL(int) vboxCallWrite (PVBSFCLIENT pClient, PVBSFMAP pMap, SHFLHANDLE hFile, uint64_t offset, uint32_t *pcbBuffer, uint8_t *pBuffer, bool fLocked);
    176179DECLVBGL(int) VbglR0SfWritePhysCont(PVBSFCLIENT pClient, PVBSFMAP pMap, SHFLHANDLE hFile, uint64_t offset, uint32_t *pcbBuffer, RTCCPHYS PhysBuffer);
     180DECLVBGL(int) VbglR0SharedFolderWritePageList(PVBSFCLIENT pClient, PVBSFMAP pMap, SHFLHANDLE hFile,
     181                                              uint64_t offset, uint32_t *pcbBuffer,
     182                                              uint16_t offFirstPage, uint16_t cPages, RTGCPHYS64 *paPages);
    177183
    178184DECLVBGL(int) vboxCallLock (PVBSFCLIENT pClient, PVBSFMAP pMap, SHFLHANDLE hFile, uint64_t offset, uint64_t cbSize, uint32_t fLock);
  • trunk/src/VBox/Additions/common/VBoxGuestLib/VbglR0CanUsePhysPageList.cpp

    r44528 r44558  
    55
    66/*
    7  * Copyright (C) 2006-2012 Oracle Corporation
     7 * Copyright (C) 2006-2013 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    3535DECLR0VBGL(bool) VbglR0CanUsePhysPageList(void)
    3636{
     37    /* a_fLocked is false, because the actual capability of the host is requested.
     38     * See VBGLR0_CAN_USE_PHYS_PAGE_LIST definition.
     39     */
    3740    int rc = vbglR0Enter();
    3841    return RT_SUCCESS(rc)
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