VirtualBox

Changeset 77243 in vbox


Ignore:
Timestamp:
Feb 10, 2019 10:44:00 PM (6 years ago)
Author:
vboxsync
Message:

HGCM,SharedFolders: Added new variation on the HGCM page list type that does not use a bounce buffer. bugref:9172

  • Added VMMDevHGCMParmType_NoBouncePageList.
  • Made VMMDevHGCMParmType_Embedded
Location:
trunk
Files:
12 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/VBoxGuestLibSharedFoldersInline.h

    r77054 r77243  
    779779    pReq->Parms.cb32Read.u.value32          = cbToRead;
    780780
    781     pReq->Parms.pBuf.type                   = VMMDevHGCMParmType_PageList;
     781    pReq->Parms.pBuf.type                   = g_fHostFeatures & VMMDEV_HVF_HGCM_NO_BOUNCE_PAGE_LIST
     782                                            ? VMMDevHGCMParmType_NoBouncePageList : VMMDevHGCMParmType_PageList;
    782783    pReq->Parms.pBuf.u.PageList.size        = cbToRead;
    783784    pReq->Parms.pBuf.u.PageList.offset      = RT_UOFFSETOF(VBOXSFREADPGLSTREQ, PgLst) - sizeof(VBGLIOCIDCHGCMFASTCALL);
     
    925926    pReq->Parms.cb32Write.u.value32         = cbToWrite;
    926927
    927     pReq->Parms.pBuf.type                   = VMMDevHGCMParmType_PageList;
     928    pReq->Parms.pBuf.type                   = g_fHostFeatures & VMMDEV_HVF_HGCM_NO_BOUNCE_PAGE_LIST
     929                                            ? VMMDevHGCMParmType_NoBouncePageList : VMMDevHGCMParmType_PageList;;
    928930    pReq->Parms.pBuf.u.PageList.size        = cbToWrite;
    929931    pReq->Parms.pBuf.u.PageList.offset      = RT_UOFFSETOF(VBOXSFWRITEPGLSTREQ, PgLst) - sizeof(VBGLIOCIDCHGCMFASTCALL);
  • trunk/include/VBox/VMMDev.h

    r77056 r77243  
    532532/** HGCM supports the contiguous page list parameter type. */
    533533#define VMMDEV_HVF_HGCM_CONTIGUOUS_PAGE_LIST    RT_BIT_32(2)
     534/** HGCM supports the no-bounce page list parameter type. */
     535#define VMMDEV_HVF_HGCM_NO_BOUNCE_PAGE_LIST     RT_BIT_32(3)
    534536/** VMMDev supports fast IRQ acknowledgements. */
    535537#define VMMDEV_HVF_FAST_IRQ_ACK                 RT_BIT_32(31)
     
    16321634#define VBOX_HGCM_F_PARM_DIRECTION_FROM_HOST UINT32_C(0x00000002)
    16331635#define VBOX_HGCM_F_PARM_DIRECTION_BOTH      UINT32_C(0x00000003)
     1636#define VBOX_HGCM_F_PARM_DIRECTION_MASK      UINT32_C(0x00000003)
    16341637/** Macro for validating that the specified flags are valid. */
    16351638#define VBOX_HGCM_F_PARM_ARE_VALID(fFlags) \
    1636     (   (fFlags) > VBOX_HGCM_F_PARM_DIRECTION_NONE \
    1637      && (fFlags) <= VBOX_HGCM_F_PARM_DIRECTION_BOTH )
     1639    (   ((fFlags) & VBOX_HGCM_F_PARM_DIRECTION_MASK) \
     1640     && !((fFlags) & ~VBOX_HGCM_F_PARM_DIRECTION_MASK) )
    16381641/** @} */
    16391642
  • trunk/include/VBox/VMMDevCoreTypes.h

    r76693 r77243  
    279279    VMMDevHGCMParmType_Embedded           = 11, /**< Small buffer embedded in request. */
    280280    VMMDevHGCMParmType_ContiguousPageList = 12, /**< Like PageList but with physically contiguous memory, so only one page entry. */
     281    VMMDevHGCMParmType_NoBouncePageList   = 13, /**< Like PageList but host function requires no bounce buffering. */
    281282    VMMDevHGCMParmType_SizeHack           = 0x7fffffff
    282283} HGCMFunctionParameterType;
  • trunk/include/VBox/hgcmsvc.h

    r76585 r77243  
    205205
    206206#define VBOX_HGCM_SVC_PARM_INVALID (0U)
    207 #define VBOX_HGCM_SVC_PARM_32BIT (1U)
    208 #define VBOX_HGCM_SVC_PARM_64BIT (2U)
    209 #define VBOX_HGCM_SVC_PARM_PTR   (3U)
     207#define VBOX_HGCM_SVC_PARM_32BIT   (1U)
     208#define VBOX_HGCM_SVC_PARM_64BIT   (2U)
     209#define VBOX_HGCM_SVC_PARM_PTR     (3U)
     210#define VBOX_HGCM_SVC_PARM_PAGES   (4U)
     211
     212/** VBOX_HGCM_SVC_PARM_PAGES specific data. */
     213typedef struct VBOXHGCMSVCPARMPAGES
     214{
     215    uint32_t    cb;
     216    uint16_t    cPages;
     217    uint16_t    u16Padding;
     218    void      **papvPages;
     219} VBOXHGCMSVCPARMPAGES;
     220typedef VBOXHGCMSVCPARMPAGES *PVBOXHGCMSVCPARMPAGES;
    210221
    211222typedef struct VBOXHGCMSVCPARM
     
    223234            void *addr;
    224235        } pointer;
     236        /** VBOX_HGCM_SVC_PARM_PAGES */
     237        VBOXHGCMSVCPARMPAGES Pages;
    225238    } u;
    226239} VBOXHGCMSVCPARM;
  • trunk/include/VBox/shflsvc.h

    r76665 r77243  
    13491349    /** value64, in: SHFLHANDLE of object to write to. */
    13501350    HGCMFunctionParameter u64Handle;
    1351     /** value64, in: Offset to start writing at. */
     1351    /** value64, in/out: Offset to start writing at / New offset.
     1352     * @note The new offset isn't necessarily off + cb for files opened with
     1353     *       SHFL_CF_ACCESS_APPEND since other parties (host programs, other VMs,
     1354     *       other computers) could have extended the file since the last time the
     1355     *       guest got a fresh size statistic.  So, this helps the guest avoiding
     1356     *       a stat call to check the actual size. */
    13521357    HGCMFunctionParameter off64Write;
    13531358    /** value32, in/out: How much to try write / Actually written. */
     
    13721377    HGCMFunctionParameter handle;
    13731378
    1374     /** value64, in:
    1375      * Offset to write to.
     1379    /** value64, in/out:
     1380     * Offset to write to/New offset.
     1381     * @note The new offset isn't necessarily off + cb for files opened with
     1382     *       SHFL_CF_ACCESS_APPEND since other parties (host programs, other VMs,
     1383     *       other computers) could have extended the file since the last time the
     1384     *       guest got a fresh size statistic.  So, this helps the guest avoiding
     1385     *       a stat call to check the actual size.
    13761386     */
    13771387    HGCMFunctionParameter offset;
  • trunk/src/VBox/Devices/VMMDev/VMMDev.cpp

    r77056 r77243  
    23022302                    | VMMDEV_HVF_HGCM_EMBEDDED_BUFFERS
    23032303                    | VMMDEV_HVF_HGCM_CONTIGUOUS_PAGE_LIST
     2304                    | VMMDEV_HVF_HGCM_NO_BOUNCE_PAGE_LIST
    23042305                    | VMMDEV_HVF_FAST_IRQ_ACK;
    23052306    return VINF_SUCCESS;
     
    47364737    PDMDevHlpSTAMRegisterF(pDevIns, &pThis->StatHgcmLargeCmdAllocs,STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
    47374738                           "Times the allocation cache could not be used.", "/HGCM/LargeCmdAllocs");
     4739    PDMDevHlpSTAMRegisterF(pDevIns, &pThis->StatHgcmFailedPageListLocking,STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
     4740                           "Times no-bounce page list locking failed.", "/HGCM/FailedPageListLocking");
    47384741#endif
    47394742
  • trunk/src/VBox/Devices/VMMDev/VMMDevHGCM.cpp

    r77126 r77243  
    8484    uint32_t cbData;
    8585
     86/** @todo save 8 bytes here by putting offFirstPage, cPages, and f32Direction
     87 *        into a bitfields like in VBOXHGCMPARMPAGES. */
    8688    /** Offset in the first physical page of the region. */
    8789    uint32_t offFirstPage;
     
    103105} VBOXHGCMPARMPTR;
    104106
     107
     108/**
     109 * Pages w/o bounce buffering.
     110 */
     111typedef struct VBOXHGCMPARMPAGES
     112{
     113    /** The buffer size. */
     114    uint32_t        cbData;
     115    /** Start of buffer offset into the first page. */
     116    uint32_t        offFirstPage : 12;
     117    /** VBOX_HGCM_F_PARM_XXX flags. */
     118    uint32_t        fFlags : 3;
     119    /** Set if we've locked all the pages. */
     120    uint32_t        fLocked : 1;
     121    /** Number of pages. */
     122    uint32_t        cPages : 16;
     123    /**< Array of page locks followed by array of page pointers, the first page
     124     * pointer is adjusted by offFirstPage. */
     125    PPGMPAGEMAPLOCK paPgLocks;
     126} VBOXHGCMPARMPAGES;
     127
    105128/**
    106129 * Information about a guest HGCM parameter.
     
    115138        VBOXHGCMPARMVAL       val;
    116139        VBOXHGCMPARMPTR       ptr;
     140        VBOXHGCMPARMPAGES     Pages;
    117141    } u;
    118142
     
    130154    bool                fCancelled;
    131155
    132     /** Whether the command was restored from saved state. */
    133     bool                fRestored;
    134 
    135156    /** Set if allocated from the memory cache, clear if heap. */
    136157    bool                fMemCache;
     158
     159    /** Whether the command was restored from saved state. */
     160    bool                fRestored : 1;
     161    /** Whether this command has a no-bounce page list and needs to be restored
     162     *  from guest memory the old fashioned way. */
     163    bool                fRestoreFromGuestMem : 1;
    137164
    138165    /** Copy of VMMDevRequestHeader::fRequestor.
     
    331358                    || pGuestParm->enmType == VMMDevHGCMParmType_PageList
    332359                    || pGuestParm->enmType == VMMDevHGCMParmType_ContiguousPageList)
     360                {
    333361                    if (pGuestParm->u.ptr.paPages != &pGuestParm->u.ptr.GCPhysSinglePage)
    334362                        RTMemFree(pGuestParm->u.ptr.paPages);
     363                }
     364                else if (pGuestParm->enmType == VMMDevHGCMParmType_NoBouncePageList)
     365                {
     366                    if (pGuestParm->u.Pages.paPgLocks)
     367                    {
     368                        if (pGuestParm->u.Pages.fLocked)
     369                            PDMDevHlpPhysBulkReleasePageMappingLocks(pThis->pDevInsR3, pGuestParm->u.Pages.cPages,
     370                                                                     pGuestParm->u.Pages.paPgLocks);
     371                        RTMemFree(pGuestParm->u.Pages.paPgLocks);
     372                        pGuestParm->u.Pages.paPgLocks = NULL;
     373                    }
     374                }
    335375            }
    336376        }
     
    663703            }
    664704
     705            case VMMDevHGCMParmType_PageList:
     706                RT_FALL_THRU();
    665707            case VMMDevHGCMParmType_LinAddr_In:
    666708            case VMMDevHGCMParmType_LinAddr_Out:
    667709            case VMMDevHGCMParmType_LinAddr:
    668             case VMMDevHGCMParmType_PageList:
    669710            case VMMDevHGCMParmType_Embedded:
    670711            case VMMDevHGCMParmType_ContiguousPageList:
     
    716757            }
    717758
     759            case VMMDevHGCMParmType_NoBouncePageList:
     760            {
     761                pHostParm->type = VBOX_HGCM_SVC_PARM_PAGES;
     762                pHostParm->u.Pages.cb        = pGuestParm->u.Pages.cbData;
     763                pHostParm->u.Pages.cPages    = pGuestParm->u.Pages.cPages;
     764                pHostParm->u.Pages.papvPages = (void **)&pGuestParm->u.Pages.paPgLocks[pGuestParm->u.Pages.cPages];
     765
     766                break;
     767            }
     768
    718769            default:
    719770                ASSERT_GUEST_FAILED_RETURN(VERR_INVALID_PARAMETER);
     
    912963            case VMMDevHGCMParmType_PageList:
    913964            case VMMDevHGCMParmType_ContiguousPageList:
     965            case VMMDevHGCMParmType_NoBouncePageList:
    914966            {
    915967#ifdef VBOX_WITH_64_BITS_GUESTS
     
    944996                                    VERR_INVALID_PARAMETER);
    945997
    946                 /* Contiguous page lists only ever have a single page. */
    947                 ASSERT_GUEST_RETURN(   pPageListInfo->cPages == 1
    948                                     || pGuestParm->enmType == VMMDevHGCMParmType_PageList, VERR_INVALID_PARAMETER);
    949 
    950                 /* Other fields of PageListInfo. */
    951                 ASSERT_GUEST_RETURN(   (pPageListInfo->flags & ~VBOX_HGCM_F_PARM_DIRECTION_BOTH) == 0
    952                                     && pPageListInfo->offFirstPage < PAGE_SIZE,
    953                                     VERR_INVALID_PARAMETER);
     998                /* Flags. */
     999                ASSERT_GUEST_MSG_RETURN(VBOX_HGCM_F_PARM_ARE_VALID(pPageListInfo->flags),
     1000                                        ("%#x\n", pPageListInfo->flags), VERR_INVALID_FLAGS);
     1001                /* First page offset. */
     1002                ASSERT_GUEST_MSG_RETURN(pPageListInfo->offFirstPage < PAGE_SIZE,
     1003                                        ("%#x\n", pPageListInfo->offFirstPage), VERR_INVALID_PARAMETER);
     1004
     1005                /* Contiguous page lists only ever have a single page and
     1006                   no-bounce page list requires cPages to match the size exactly.
     1007                   Plain page list does not impose any restrictions on cPages currently. */
     1008                ASSERT_GUEST_MSG_RETURN(      pPageListInfo->cPages
     1009                                           == (pGuestParm->enmType == VMMDevHGCMParmType_ContiguousPageList ? 1
     1010                                               : RT_ALIGN_32(pPageListInfo->offFirstPage + cbData, PAGE_SIZE) >> PAGE_SHIFT)
     1011                                        || pGuestParm->enmType == VMMDevHGCMParmType_PageList,
     1012                                        ("offFirstPage=%#x cbData=%#x cPages=%#x enmType=%d\n",
     1013                                         pPageListInfo->offFirstPage, cbData, pPageListInfo->cPages, pGuestParm->enmType),
     1014                                        VERR_INVALID_PARAMETER);
     1015
    9541016                RT_UNTRUSTED_VALIDATED_FENCE();
    9551017
    956                 /* cbData is not checked to fit into the pages, because the host code does not access
    957                  * more than the provided number of pages.
     1018                /*
     1019                 * Deal with no-bounce buffers first, as
     1020                 * VMMDevHGCMParmType_PageList is the fallback.
    9581021                 */
    959 
     1022                if (pGuestParm->enmType == VMMDevHGCMParmType_NoBouncePageList)
     1023                {
     1024                    /* Validate page offsets */
     1025                    ASSERT_GUEST_MSG_RETURN(   !(pPageListInfo->aPages[0] & PAGE_OFFSET_MASK)
     1026                                            || (pPageListInfo->aPages[0] & PAGE_OFFSET_MASK) == pPageListInfo->offFirstPage,
     1027                                            ("%#RX64 offFirstPage=%#x\n", pPageListInfo->aPages[0], pPageListInfo->offFirstPage),
     1028                                            VERR_INVALID_POINTER);
     1029                    uint32_t const cPages = pPageListInfo->cPages;
     1030                    for (uint32_t iPage = 1; iPage < cPages; iPage++)
     1031                        ASSERT_GUEST_MSG_RETURN(!(pPageListInfo->aPages[iPage] & PAGE_OFFSET_MASK),
     1032                                                ("[%#zx]=%#RX64\n", iPage, pPageListInfo->aPages[iPage]), VERR_INVALID_POINTER);
     1033                    RT_UNTRUSTED_VALIDATED_FENCE();
     1034
     1035                    pGuestParm->u.Pages.cbData       = cbData;
     1036                    pGuestParm->u.Pages.offFirstPage = pPageListInfo->offFirstPage;
     1037                    pGuestParm->u.Pages.fFlags       = pPageListInfo->flags;
     1038                    pGuestParm->u.Pages.cPages       = (uint16_t)cPages;
     1039                    pGuestParm->u.Pages.fLocked      = false;
     1040                    pGuestParm->u.Pages.paPgLocks    = (PPGMPAGEMAPLOCK)RTMemAllocZ(  (sizeof(PGMPAGEMAPLOCK) + sizeof(void *))
     1041                                                                                    * cPages);
     1042                    AssertReturn(pGuestParm->u.Pages.paPgLocks, VERR_NO_MEMORY);
     1043
     1044                    /* Make sure the page offsets are sensible. */
     1045                    int rc = VINF_SUCCESS;
     1046                    void **papvPages = (void **)&pGuestParm->u.Pages.paPgLocks[cPages];
     1047                    if (pPageListInfo->flags & VBOX_HGCM_F_PARM_DIRECTION_FROM_HOST)
     1048                        rc = PDMDevHlpPhysBulkGCPhys2CCPtr(pThis->pDevInsR3, cPages, pPageListInfo->aPages, 0 /*fFlags*/,
     1049                                                           papvPages, pGuestParm->u.Pages.paPgLocks);
     1050                    else
     1051                        rc = PDMDevHlpPhysBulkGCPhys2CCPtrReadOnly(pThis->pDevInsR3, cPages, pPageListInfo->aPages, 0 /*fFlags*/,
     1052                                                                   (void const **)papvPages, pGuestParm->u.Pages.paPgLocks);
     1053                    if (RT_SUCCESS(rc))
     1054                    {
     1055                        papvPages[0] = (void *)((uintptr_t)papvPages[0] | pPageListInfo->offFirstPage);
     1056                        pGuestParm->u.Pages.fLocked = true;
     1057                        break;
     1058                    }
     1059
     1060                    /* Locking failed, bail out.  In case of MMIO we fall back on regular page list handling. */
     1061                    RTMemFree(pGuestParm->u.Pages.paPgLocks);
     1062                    pGuestParm->u.Pages.paPgLocks = NULL;
     1063                    STAM_REL_COUNTER_INC(&pThis->StatHgcmFailedPageListLocking);
     1064                    ASSERT_GUEST_MSG_RETURN(rc == VERR_PGM_PHYS_PAGE_RESERVED, ("cPages=%u %Rrc\n", cPages, rc), rc);
     1065                    pGuestParm->enmType = VMMDevHGCMParmType_PageList;
     1066                }
     1067
     1068                /*
     1069                 * Regular page list or contiguous page list.
     1070                 */
    9601071                pGuestParm->u.ptr.cbData        = cbData;
    9611072                pGuestParm->u.ptr.offFirstPage  = pPageListInfo->offFirstPage;
     
    12191330     * Go over parameter descriptions saved in pCmd.
    12201331     */
    1221     uint32_t i;
    1222     for (i = 0; i < pCmd->u.call.cParms; ++i)
     1332#ifdef VBOX_WITH_64_BITS_GUESTS
     1333    HGCMFunctionParameter64 *pReqParm         = (HGCMFunctionParameter64 *)(pbReq + sizeof(VMMDevHGCMCall));
     1334    size_t const             cbHGCMParmStruct = pCmd->enmRequestType == VMMDevReq_HGCMCall64
     1335                                              ? sizeof(HGCMFunctionParameter64) : sizeof(HGCMFunctionParameter32);
     1336#else
     1337    HGCMFunctionParameter   *pReqParm         = (HGCMFunctionParameter   *)(pbReq + sizeof(VMMDevHGCMCall));
     1338    size_t const             cbHGCMParmStruct = sizeof(HGCMFunctionParameter);
     1339#endif
     1340    for (uint32_t i = 0;
     1341         i < pCmd->u.call.cParms;
     1342#ifdef VBOX_WITH_64_BITS_GUESTS
     1343         ++i, pReqParm = (HGCMFunctionParameter64 *)((uint8_t *)pReqParm + cbHGCMParmStruct)
     1344#else
     1345         ++i, pReqParm = (HGCMFunctionParameter   *)((uint8_t *)pReqParm + cbHGCMParmStruct)
     1346#endif
     1347        )
    12231348    {
    12241349        VBOXHGCMGUESTPARM * const pGuestParm = &pCmd->u.call.paGuestParms[i];
     
    12341359                const void *pvSrc = enmType == VMMDevHGCMParmType_32bit ? (void *)&pHostParm->u.uint32
    12351360                                                                        : (void *)&pHostParm->u.uint64;
     1361/** @todo optimize memcpy away here. */
    12361362                memcpy((uint8_t *)pHGCMCall + pVal->offValue, pvSrc, pVal->cbValue);
    12371363                break;
     
    12431369            case VMMDevHGCMParmType_PageList:
    12441370            {
    1245 /** @todo Update the return buffer size. */
     1371/** @todo Update the return buffer size? */
    12461372                const VBOXHGCMPARMPTR * const pPtr = &pGuestParm->u.ptr;
    12471373                if (   pPtr->cbData > 0
     
    12591385            case VMMDevHGCMParmType_Embedded:
    12601386            {
    1261 /** @todo Update the return buffer size!  */
    12621387                const VBOXHGCMPARMPTR * const pPtr = &pGuestParm->u.ptr;
     1388
     1389                /* Update size. */
     1390#ifdef VBOX_WITH_64_BITS_GUESTS
     1391                AssertCompileMembersSameSizeAndOffset(HGCMFunctionParameter64, u.Embedded.cbData, HGCMFunctionParameter32, u.Embedded.cbData);
     1392#endif
     1393                pReqParm->u.Embedded.cbData = pHostParm->u.pointer.size;
     1394
     1395                /* Copy out data. */
    12631396                if (   pPtr->cbData > 0
    12641397                    && (pPtr->fu32Direction & VBOX_HGCM_F_PARM_DIRECTION_FROM_HOST))
     
    12741407            case VMMDevHGCMParmType_ContiguousPageList:
    12751408            {
    1276 /** @todo Update the return buffer size.  */
    12771409                const VBOXHGCMPARMPTR * const pPtr = &pGuestParm->u.ptr;
     1410
     1411                /* Update size. */
     1412#ifdef VBOX_WITH_64_BITS_GUESTS
     1413                AssertCompileMembersSameSizeAndOffset(HGCMFunctionParameter64, u.PageList.size, HGCMFunctionParameter32, u.PageList.size);
     1414#endif
     1415                pReqParm->u.PageList.size = pHostParm->u.pointer.size;
     1416
     1417                /* Copy out data. */
    12781418                if (   pPtr->cbData > 0
    12791419                    && (pPtr->fu32Direction & VBOX_HGCM_F_PARM_DIRECTION_FROM_HOST))
     
    12861426                    if (RT_FAILURE(rc))
    12871427                        break;
     1428                }
     1429                break;
     1430            }
     1431
     1432            case VMMDevHGCMParmType_NoBouncePageList:
     1433            {
     1434                /* Update size. */
     1435#ifdef VBOX_WITH_64_BITS_GUESTS
     1436                AssertCompileMembersSameSizeAndOffset(HGCMFunctionParameter64, u.PageList.size, HGCMFunctionParameter32, u.PageList.size);
     1437#endif
     1438                pReqParm->u.PageList.size = pHostParm->u.Pages.cb;
     1439
     1440                /* unlock early. */
     1441                if (pGuestParm->u.Pages.fLocked)
     1442                {
     1443                    PDMDevHlpPhysBulkReleasePageMappingLocks(pThis->pDevInsR3, pGuestParm->u.Pages.cPages,
     1444                                                             pGuestParm->u.Pages.paPgLocks);
     1445                    pGuestParm->u.Pages.fLocked = false;
    12881446                }
    12891447                break;
     
    16811839
    16821840                        uint32_t iPage;
    1683                         for (iPage = 0; iPage < pPtr->cPages; ++iPage)
     1841                        for (iPage = 0; RT_SUCCESS(rc) && iPage < pPtr->cPages; ++iPage)
    16841842                            rc = SSMR3PutGCPhys(pSSM, pPtr->paPages[iPage]);
     1843                    }
     1844                    else if (pGuestParm->enmType == VMMDevHGCMParmType_NoBouncePageList)
     1845                    {
     1846                        /* We don't have the page addresses here, so it will need to be
     1847                           restored from guest memory.  This isn't an issue as it is only
     1848                           use with services which won't survive a save/restore anyway. */
    16851849                    }
    16861850                    else
     
    18341998                        }
    18351999                    }
     2000                    else if (pGuestParm->enmType == VMMDevHGCMParmType_NoBouncePageList)
     2001                    {
     2002                        /* This request type can only be stored from guest memory for now. */
     2003                        pCmd->fRestoreFromGuestMem = true;
     2004                    }
    18362005                    else
    18372006                    {
     
    22612430             * Reconstruct legacy commands.
    22622431             */
    2263             if (RT_LIKELY(pThis->u32SSMVersion >= VMMDEV_SAVED_STATE_VERSION_HGCM_PARAMS))
     2432            if (RT_LIKELY(   pThis->u32SSMVersion >= VMMDEV_SAVED_STATE_VERSION_HGCM_PARAMS
     2433                          && !pCmd->fRestoreFromGuestMem))
    22642434            { /* likely */ }
    22652435            else
  • trunk/src/VBox/Devices/VMMDev/VMMDevState.h

    r76565 r77243  
    319319    STAMPROFILE StatHgcmCmdTotal;
    320320    STAMCOUNTER StatHgcmLargeCmdAllocs;
     321    STAMCOUNTER StatHgcmFailedPageListLocking;
    321322#endif /* VBOX_WITH_HGCM */
    322323    STAMCOUNTER StatReqBufAllocs;
  • trunk/src/VBox/HostServices/SharedFolders/VBoxSharedFoldersSvc.cpp

    r76971 r77243  
    643643        }
    644644
    645         /** Read object content. */
     645        /* Read object content. */
    646646        case SHFL_FN_READ:
     647        {
    647648            pStat     = &g_StatRead;
    648649            pStatFail = &g_StatReadFail;
     
    650651
    651652            /* Verify parameter count and types. */
    652             if (cParms != SHFL_CPARMS_READ)
    653             {
    654                 rc = VERR_INVALID_PARAMETER;
    655             }
    656             else
    657             if (   paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT   /* root */
    658                 || paParms[1].type != VBOX_HGCM_SVC_PARM_64BIT   /* handle */
    659                 || paParms[2].type != VBOX_HGCM_SVC_PARM_64BIT   /* offset */
    660                 || paParms[3].type != VBOX_HGCM_SVC_PARM_32BIT   /* count */
    661                 || paParms[4].type != VBOX_HGCM_SVC_PARM_PTR     /* buffer */
    662                     )
    663             {
    664                 rc = VERR_INVALID_PARAMETER;
    665             }
    666             else
    667             {
    668                 /* Fetch parameters. */
    669                 SHFLROOT   root    = (SHFLROOT)paParms[0].u.uint32;
    670                 SHFLHANDLE Handle  = paParms[1].u.uint64;
    671                 uint64_t   offset  = paParms[2].u.uint64;
    672                 uint32_t   count   = paParms[3].u.uint32;
    673                 uint8_t   *pBuffer = (uint8_t *)paParms[4].u.pointer.addr;
    674 
    675                 /* Verify parameters values. */
    676                 if (   Handle == SHFL_HANDLE_ROOT
    677                     || count > paParms[4].u.pointer.size
    678                    )
    679                 {
    680                     rc = VERR_INVALID_PARAMETER;
    681                 }
    682                 else
    683                 if (Handle == SHFL_HANDLE_NIL)
    684                 {
    685                     AssertMsgFailed(("Invalid handle!\n"));
    686                     rc = VERR_INVALID_HANDLE;
    687                 }
    688                 else
    689                 {
    690                     /* Execute the function. */
    691                     if (g_pStatusLed)
    692                     {
    693                         Assert(g_pStatusLed->u32Magic == PDMLED_MAGIC);
    694                         g_pStatusLed->Asserted.s.fReading = g_pStatusLed->Actual.s.fReading = 1;
    695                     }
    696 
    697                     rc = vbsfRead (pClient, root, Handle, offset, &count, pBuffer);
    698                     if (g_pStatusLed)
    699                         g_pStatusLed->Actual.s.fReading = 0;
    700 
    701                     if (RT_SUCCESS(rc))
    702                     {
    703                         /* Update parameters.*/
    704                         paParms[3].u.uint32 = count;
    705                     }
    706                     else
    707                     {
    708                         paParms[3].u.uint32 = 0;   /* nothing read */
    709                     }
    710                 }
    711             }
    712             break;
    713 
    714         /** Write new object content. */
     653            ASSERT_GUEST_STMT_BREAK(cParms == SHFL_CPARMS_READ, rc = VERR_WRONG_PARAMETER_COUNT);
     654            ASSERT_GUEST_STMT_BREAK(paParms[0].type == VBOX_HGCM_SVC_PARM_32BIT, rc = VERR_WRONG_PARAMETER_TYPE); /* root */
     655            ASSERT_GUEST_STMT_BREAK(paParms[1].type == VBOX_HGCM_SVC_PARM_64BIT, rc = VERR_WRONG_PARAMETER_TYPE); /* handle */
     656            ASSERT_GUEST_STMT_BREAK(paParms[2].type == VBOX_HGCM_SVC_PARM_64BIT, rc = VERR_WRONG_PARAMETER_TYPE); /* offset */
     657            ASSERT_GUEST_STMT_BREAK(paParms[3].type == VBOX_HGCM_SVC_PARM_32BIT, rc = VERR_WRONG_PARAMETER_TYPE); /* count */
     658            ASSERT_GUEST_STMT_BREAK(   paParms[4].type == VBOX_HGCM_SVC_PARM_PTR
     659                                    || paParms[4].type == VBOX_HGCM_SVC_PARM_PAGES, rc = VERR_WRONG_PARAMETER_TYPE); /* buffer */
     660
     661            /* Fetch parameters. */
     662            SHFLROOT   const idRoot  = (SHFLROOT)paParms[0].u.uint32;
     663            SHFLHANDLE const hFile   = paParms[1].u.uint64;
     664            uint64_t   const offFile = paParms[2].u.uint64;
     665            uint32_t         cbRead  = paParms[3].u.uint32;
     666
     667            /* Verify parameters values. */
     668            ASSERT_GUEST_STMT_BREAK(hFile != SHFL_HANDLE_ROOT, rc == VERR_INVALID_PARAMETER);
     669            ASSERT_GUEST_STMT_BREAK(hFile != SHFL_HANDLE_NIL,  rc == VERR_INVALID_HANDLE);
     670            if (paParms[4].type == VBOX_HGCM_SVC_PARM_PTR)
     671                ASSERT_GUEST_STMT_BREAK(cbRead <= paParms[4].u.pointer.size, rc == VERR_INVALID_HANDLE);
     672            else
     673                ASSERT_GUEST_STMT_BREAK(cbRead <= paParms[4].u.Pages.cb, rc == VERR_OUT_OF_RANGE);
     674
     675            /* Execute the function. */
     676            if (g_pStatusLed)
     677            {
     678                Assert(g_pStatusLed->u32Magic == PDMLED_MAGIC);
     679                g_pStatusLed->Asserted.s.fReading = g_pStatusLed->Actual.s.fReading = 1;
     680            }
     681
     682            if (paParms[4].type == VBOX_HGCM_SVC_PARM_PTR)
     683                rc = vbsfRead(pClient, idRoot, hFile, offFile, &cbRead, (uint8_t *)paParms[4].u.pointer.addr);
     684            else
     685                rc = vbsfReadPages(pClient, idRoot, hFile, offFile, &cbRead, &paParms[4].u.Pages);
     686
     687            if (g_pStatusLed)
     688                g_pStatusLed->Actual.s.fReading = 0;
     689
     690            /* Update parameters.*/
     691            paParms[3].u.uint32 = RT_SUCCESS(rc) ? cbRead : 0  /* nothing read */;
     692            break;
     693        }
     694
     695        /* Write new object content. */
    715696        case SHFL_FN_WRITE:
     697         {
    716698            pStat     = &g_StatWrite;
    717699            pStatFail = &g_StatWriteFail;
     
    719701
    720702            /* Verify parameter count and types. */
    721             if (cParms != SHFL_CPARMS_WRITE)
    722             {
    723                 rc = VERR_INVALID_PARAMETER;
    724             }
    725             else
    726             if (   paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT   /* root */
    727                 || paParms[1].type != VBOX_HGCM_SVC_PARM_64BIT   /* handle */
    728                 || paParms[2].type != VBOX_HGCM_SVC_PARM_64BIT   /* offset */
    729                 || paParms[3].type != VBOX_HGCM_SVC_PARM_32BIT   /* count */
    730                 || paParms[4].type != VBOX_HGCM_SVC_PARM_PTR     /* buffer */
    731                     )
    732             {
    733                 rc = VERR_INVALID_PARAMETER;
    734             }
    735             else
    736             {
    737                 /* Fetch parameters. */
    738                 SHFLROOT   root    = (SHFLROOT)paParms[0].u.uint32;
    739                 SHFLHANDLE Handle  = paParms[1].u.uint64;
    740                 uint64_t   offset  = paParms[2].u.uint64;
    741                 uint32_t   count   = paParms[3].u.uint32;
    742                 uint8_t   *pBuffer = (uint8_t *)paParms[4].u.pointer.addr;
    743 
    744                 /* Verify parameters values. */
    745                 if (   Handle == SHFL_HANDLE_ROOT
    746                     || count > paParms[4].u.pointer.size
    747                    )
    748                 {
    749                     rc = VERR_INVALID_PARAMETER;
    750                 }
    751                 else
    752                 if (Handle == SHFL_HANDLE_NIL)
    753                 {
    754                     AssertMsgFailed(("Invalid handle!\n"));
    755                     rc = VERR_INVALID_HANDLE;
    756                 }
    757                 else
    758                 {
    759                     /* Execute the function. */
    760                     if (g_pStatusLed)
    761                     {
    762                         Assert(g_pStatusLed->u32Magic == PDMLED_MAGIC);
    763                         g_pStatusLed->Asserted.s.fWriting = g_pStatusLed->Actual.s.fWriting = 1;
    764                     }
    765 
    766                     rc = vbsfWrite (pClient, root, Handle, offset, &count, pBuffer);
    767                     if (g_pStatusLed)
    768                         g_pStatusLed->Actual.s.fWriting = 0;
    769 
    770                     if (RT_SUCCESS(rc))
    771                     {
    772                         /* Update parameters.*/
    773                         paParms[3].u.uint32 = count;
    774                     }
    775                     else
    776                     {
    777                         paParms[3].u.uint32 = 0;   /* nothing read */
    778                     }
    779                 }
    780             }
    781             break;
    782 
    783         /** Lock/unlock a range in the object. */
     703            ASSERT_GUEST_STMT_BREAK(cParms == SHFL_CPARMS_WRITE, rc = VERR_WRONG_PARAMETER_COUNT);
     704            ASSERT_GUEST_STMT_BREAK(paParms[0].type == VBOX_HGCM_SVC_PARM_32BIT, rc = VERR_WRONG_PARAMETER_TYPE); /* root */
     705            ASSERT_GUEST_STMT_BREAK(paParms[1].type == VBOX_HGCM_SVC_PARM_64BIT, rc = VERR_WRONG_PARAMETER_TYPE); /* handle */
     706            ASSERT_GUEST_STMT_BREAK(paParms[2].type == VBOX_HGCM_SVC_PARM_64BIT, rc = VERR_WRONG_PARAMETER_TYPE); /* offset */
     707            ASSERT_GUEST_STMT_BREAK(paParms[3].type == VBOX_HGCM_SVC_PARM_32BIT, rc = VERR_WRONG_PARAMETER_TYPE); /* count */
     708            ASSERT_GUEST_STMT_BREAK(   paParms[4].type == VBOX_HGCM_SVC_PARM_PTR
     709                                    || paParms[4].type == VBOX_HGCM_SVC_PARM_PAGES, rc = VERR_WRONG_PARAMETER_TYPE); /* buffer */
     710            /* Fetch parameters. */
     711            SHFLROOT   const idRoot   = (SHFLROOT)paParms[0].u.uint32;
     712            SHFLHANDLE const hFile    = paParms[1].u.uint64;
     713            uint64_t         offFile  = paParms[2].u.uint64;
     714            uint32_t         cbWrite  = paParms[3].u.uint32;
     715
     716            /* Verify parameters values. */
     717            ASSERT_GUEST_STMT_BREAK(hFile != SHFL_HANDLE_ROOT, rc == VERR_INVALID_PARAMETER);
     718            ASSERT_GUEST_STMT_BREAK(hFile != SHFL_HANDLE_NIL,  rc == VERR_INVALID_HANDLE);
     719            if (paParms[4].type == VBOX_HGCM_SVC_PARM_PTR)
     720                ASSERT_GUEST_STMT_BREAK(cbWrite <= paParms[4].u.pointer.size, rc == VERR_INVALID_HANDLE);
     721            else
     722                ASSERT_GUEST_STMT_BREAK(cbWrite <= paParms[4].u.Pages.cb, rc == VERR_OUT_OF_RANGE);
     723
     724            /* Execute the function. */
     725            if (g_pStatusLed)
     726            {
     727                Assert(g_pStatusLed->u32Magic == PDMLED_MAGIC);
     728                g_pStatusLed->Asserted.s.fWriting = g_pStatusLed->Actual.s.fWriting = 1;
     729            }
     730
     731            if (paParms[4].type == VBOX_HGCM_SVC_PARM_PTR)
     732                rc = vbsfWrite(pClient, idRoot, hFile, &offFile, &cbWrite, (uint8_t *)paParms[4].u.pointer.addr);
     733            else
     734                rc = vbsfWritePages(pClient, idRoot, hFile, &offFile, &cbWrite, &paParms[4].u.Pages);
     735
     736            if (g_pStatusLed)
     737                g_pStatusLed->Actual.s.fWriting = 0;
     738
     739            /* Update parameters.*/
     740            if (RT_SUCCESS(rc))
     741            {
     742                paParms[3].u.uint32 = cbWrite;
     743                paParms[4].u.uint64 = offFile;
     744            }
     745            else
     746                paParms[3].u.uint32 = 0;
     747            break;
     748        }
     749
     750        /* Lock/unlock a range in the object. */
    784751        case SHFL_FN_LOCK:
    785752            pStat     = &g_StatLock;
     
    869836            break;
    870837
    871         /** List object content. */
     838        /* List object content. */
    872839        case SHFL_FN_LIST:
    873840        {
     
    11521119        }
    11531120
    1154         /** Query/set object information. */
     1121        /* Query/set object information. */
    11551122        case SHFL_FN_INFORMATION:
    11561123        {
     
    12351202        }
    12361203
    1237         /** Remove or rename object */
     1204        /* Remove or rename object */
    12381205        case SHFL_FN_REMOVE:
    12391206        {
  • trunk/src/VBox/HostServices/SharedFolders/shflhandle.h

    r76570 r77243  
    5252        {
    5353            RTFILE        Handle;
     54            uint64_t      fOpenFlags;       /**< RTFILE_O_XXX. */
    5455        } file;
    5556        struct
     
    5758            RTDIR         Handle;
    5859            RTDIR         SearchHandle;
    59             PRTDIRENTRYEX pLastValidEntry; /* last found file in a directory search */
     60            PRTDIRENTRYEX pLastValidEntry;  /**< last found file in a directory search */
    6061        } dir;
    6162    };
  • trunk/src/VBox/HostServices/SharedFolders/vbsf.cpp

    r76553 r77243  
    3131
    3232#include <VBox/AssertGuest.h>
     33#include <VBox/param.h>
    3334#include <iprt/alloc.h>
    3435#include <iprt/assert.h>
     
    479480            {
    480481                pHandle->root = root;
     482                pHandle->file.fOpenFlags = fOpen;
    481483                rc = RTFileOpen(&pHandle->file.Handle, pszPath, fOpen);
    482484            }
     
    10171019}
    10181020
     1021/**
     1022 * Helper for vbsfReadPages and vbsfWritePages that creates a S/G buffer from a
     1023 * pages parameter.
     1024 */
     1025static int vbsfPagesToSgBuf(VBOXHGCMSVCPARMPAGES const *pPages, uint32_t cbLeft, PRTSGBUF pSgBuf)
     1026{
     1027    PRTSGSEG paSegs = (PRTSGSEG)RTMemTmpAlloc(sizeof(paSegs[0]) * pPages->cPages);
     1028    if (paSegs)
     1029    {
     1030        /*
     1031         * Convert the pages to segments.
     1032         */
     1033        uint32_t iSeg  = 0;
     1034        uint32_t iPage = 0;
     1035        for (;;)
     1036        {
     1037            Assert(iSeg < pPages->cPages);
     1038            Assert(iPage < pPages->cPages);
     1039
     1040            /* Current page. */
     1041            void *pvSeg;
     1042            paSegs[iSeg].pvSeg = pvSeg = pPages->papvPages[iPage];
     1043            size_t cbSeg = PAGE_SIZE - ((uintptr_t)pvSeg & PAGE_OFFSET_MASK);
     1044            iPage++;
     1045
     1046            /* Adjacent to the next page? */
     1047            while (   iPage < pPages->cPages
     1048                   && (uintptr_t)pvSeg + cbSeg == (uintptr_t)pPages->papvPages[iPage])
     1049            {
     1050                iPage++;
     1051                cbSeg += PAGE_SIZE;
     1052            }
     1053
     1054            /* Adjust for max size. */
     1055            if (cbLeft <= cbSeg)
     1056            {
     1057                paSegs[iSeg++].cbSeg = cbLeft;
     1058                break;
     1059            }
     1060            paSegs[iSeg++].cbSeg = cbSeg;
     1061            cbLeft -= cbSeg;
     1062        }
     1063
     1064        /*
     1065         * Initialize the s/g buffer and execute the read.
     1066         */
     1067        RTSgBufInit(pSgBuf, paSegs, iSeg);
     1068        return VINF_SUCCESS;
     1069    }
     1070    pSgBuf->paSegs = NULL;
     1071    return VERR_NO_TMP_MEMORY;
     1072}
     1073
     1074
    10191075#ifdef UNITTEST
    10201076/** Unit test the SHFL_FN_READ API.  Located here as a form of API
     
    10451101    if (RT_LIKELY(*pcbBuffer != 0))
    10461102    {
     1103/** @todo use RTFileReadAt! */
    10471104        rc = RTFileSeek(pHandle->file.Handle, offset, RTFILE_SEEK_BEGIN, NULL);
    10481105        if (RT_SUCCESS(rc))
     
    10631120    LogFunc(("%Rrc bytes read 0x%RX32\n", rc, *pcbBuffer));
    10641121    return rc;
     1122}
     1123
     1124/**
     1125 * SHFL_FN_READ w/o bounce buffering.
     1126 */
     1127int vbsfReadPages(SHFLCLIENTDATA *pClient, SHFLROOT idRoot, SHFLHANDLE hFile, uint64_t offFile,
     1128                  uint32_t *pcbRead, PVBOXHGCMSVCPARMPAGES pPages)
     1129{
     1130    LogFunc(("pClient %p, idRoot %#RX32, hFile %#RX64, offFile %#RX64, cbRead %#RX32, cPages %#x\n",
     1131             pClient, idRoot, hFile, offFile, *pcbRead, pPages->cPages));
     1132
     1133    AssertPtrReturn(pClient, VERR_INVALID_PARAMETER);
     1134
     1135    size_t          cbTotal = 0;
     1136    SHFLFILEHANDLE *pHandle = vbsfQueryFileHandle(pClient, hFile);
     1137    int rc = vbsfCheckHandleAccess(pClient, idRoot, pHandle, VBSF_CHECK_ACCESS_READ);
     1138    if (RT_SUCCESS(rc))
     1139    {
     1140        uint32_t const cbToRead = *pcbRead;
     1141        if (cbToRead > 0)
     1142        {
     1143            ASSERT_GUEST_RETURN(pPages->cPages > 0, VERR_INTERNAL_ERROR_3);
     1144
     1145            /*
     1146             * Convert to a scatter-gather buffer.
     1147             *
     1148             * We need not do any platform specific code here as the RTSGBUF
     1149             * segment array maps directly onto the posix iovec structure.
     1150             * Windows does currently benefit much from this conversion, but
     1151             * so be it.
     1152             */
     1153            RTSGBUF SgBuf;
     1154            rc = vbsfPagesToSgBuf(pPages, cbToRead, &SgBuf);
     1155            if (RT_SUCCESS(rc))
     1156            {
     1157                rc = RTFileSgReadAt(pHandle->file.Handle, offFile, &SgBuf, cbToRead, &cbTotal);
     1158                while (rc == VERR_INTERRUPTED)
     1159                {
     1160                    RTSgBufReset(&SgBuf);
     1161                    rc = RTFileSgReadAt(pHandle->file.Handle, offFile, &SgBuf, cbToRead, &cbTotal);
     1162                }
     1163
     1164                RTMemTmpFree((void *)SgBuf.paSegs);
     1165            }
     1166            else
     1167                rc = VERR_NO_TMP_MEMORY;
     1168
     1169            *pcbRead = (uint32_t)cbTotal;
     1170        }
     1171        else
     1172        {
     1173            /* Reading zero bytes always succeeds. */
     1174            rc = VINF_SUCCESS;
     1175        }
     1176    }
     1177    else
     1178        *pcbRead = 0;
     1179
     1180    LogFunc(("%Rrc bytes read %#zx\n", rc, cbTotal));
     1181    return rc;
     1182}
     1183
     1184/**
     1185 * Helps with writes to RTFILE_O_APPEND files.
     1186 */
     1187static uint64_t vbsfWriteCalcPostAppendFilePosition(RTFILE hFile, uint64_t offGuessed)
     1188{
     1189    RTFSOBJINFO ObjInfo;
     1190    int rc2 = RTFileQueryInfo(hFile, &ObjInfo, RTFSOBJATTRADD_NOTHING);
     1191    if (RT_SUCCESS(rc2) && (uint64_t)ObjInfo.cbObject >= offGuessed)
     1192        return ObjInfo.cbObject;
     1193    return offGuessed;
    10651194}
    10661195
     
    10771206}
    10781207#endif
    1079 int vbsfWrite(SHFLCLIENTDATA *pClient, SHFLROOT root, SHFLHANDLE Handle, uint64_t offset, uint32_t *pcbBuffer, uint8_t *pBuffer)
    1080 {
    1081     LogFunc(("pClient %p, root 0x%RX32, Handle 0x%RX64, offset 0x%RX64, bytes 0x%RX32\n",
    1082              pClient, root, Handle, offset, pcbBuffer? *pcbBuffer: 0));
     1208int vbsfWrite(SHFLCLIENTDATA *pClient, SHFLROOT idRoot, SHFLHANDLE hFile, uint64_t *poffFile,
     1209              uint32_t *pcbBuffer, uint8_t *pBuffer)
     1210{
     1211    uint64_t offFile = *poffFile;
     1212    LogFunc(("pClient %p, root 0x%RX32, Handle 0x%RX64, offFile 0x%RX64, bytes 0x%RX32\n",
     1213             pClient, idRoot, hFile, offFile, *pcbBuffer));
    10831214
    10841215    AssertPtrReturn(pClient, VERR_INVALID_PARAMETER);
    10851216
    1086     SHFLFILEHANDLE *pHandle = vbsfQueryFileHandle(pClient, Handle);
    1087     int rc = vbsfCheckHandleAccess(pClient, root, pHandle, VBSF_CHECK_ACCESS_WRITE);
     1217    SHFLFILEHANDLE *pHandle = vbsfQueryFileHandle(pClient, hFile);
     1218    int rc = vbsfCheckHandleAccess(pClient, idRoot, pHandle, VBSF_CHECK_ACCESS_WRITE);
    10881219    if (RT_SUCCESS(rc))
    1089     { /* likely */ }
     1220    {
     1221        size_t const cbToWrite = *pcbBuffer;
     1222        if (RT_LIKELY(cbToWrite != 0))
     1223        {
     1224/** @todo use RTFileWriteAt unless RTFILE_O_APPEND is in effect.  */
     1225            rc = RTFileSeek(pHandle->file.Handle, offFile, RTFILE_SEEK_BEGIN, NULL);
     1226            if (RT_SUCCESS(rc))
     1227            {
     1228                size_t cbWritten = 0;
     1229                rc = RTFileWrite(pHandle->file.Handle, pBuffer, cbToWrite, &cbWritten);
     1230                *pcbBuffer = (uint32_t)cbWritten;
     1231
     1232                /* Update the file offset (mainly for RTFILE_O_APPEND), */
     1233                if (RT_SUCCESS(rc))
     1234                {
     1235                    offFile += cbWritten;
     1236                    if (!(pHandle->file.fOpenFlags & RTFILE_O_APPEND))
     1237                        *poffFile = offFile;
     1238                    else
     1239                        *poffFile = vbsfWriteCalcPostAppendFilePosition(pHandle->file.Handle, offFile);
     1240                }
     1241            }
     1242            else
     1243                AssertRC(rc);
     1244        }
     1245        else
     1246        {
     1247            /** @todo What writing zero bytes should do? */
     1248            rc = VINF_SUCCESS;
     1249        }
     1250    }
    10901251    else
    1091         return rc;
    1092 
    1093     if (RT_LIKELY(*pcbBuffer != 0))
    1094     {
    1095         rc = RTFileSeek(pHandle->file.Handle, offset, RTFILE_SEEK_BEGIN, NULL);
    1096         if (RT_SUCCESS(rc))
    1097         {
    1098             size_t count = 0;
    1099             rc = RTFileWrite(pHandle->file.Handle, pBuffer, *pcbBuffer, &count);
    1100             *pcbBuffer = (uint32_t)count;
     1252        *pcbBuffer = 0;
     1253    LogFunc(("%Rrc bytes written 0x%RX32\n", rc, *pcbBuffer));
     1254    return rc;
     1255}
     1256
     1257/**
     1258 * SHFL_FN_WRITE w/o bounce buffering.
     1259 */
     1260int vbsfWritePages(SHFLCLIENTDATA *pClient, SHFLROOT idRoot, SHFLHANDLE hFile, uint64_t *poffFile,
     1261                   uint32_t *pcbWrite, PVBOXHGCMSVCPARMPAGES pPages)
     1262{
     1263    uint64_t offFile = *poffFile;
     1264    LogFunc(("pClient %p, idRoot %#RX32, hFile %#RX64, offFile %#RX64, cbWrite %#RX32, cPages %#x\n",
     1265             pClient, idRoot, hFile, offFile, *pcbWrite, pPages->cPages));
     1266
     1267    AssertPtrReturn(pClient, VERR_INVALID_PARAMETER);
     1268
     1269    size_t          cbTotal = 0;
     1270    SHFLFILEHANDLE *pHandle = vbsfQueryFileHandle(pClient, hFile);
     1271    int rc = vbsfCheckHandleAccess(pClient, idRoot, pHandle, VBSF_CHECK_ACCESS_WRITE);
     1272    if (RT_SUCCESS(rc))
     1273    {
     1274        uint32_t const cbToWrite = *pcbWrite;
     1275        if (cbToWrite > 0)
     1276        {
     1277            ASSERT_GUEST_RETURN(pPages->cPages > 0, VERR_INTERNAL_ERROR_3);
     1278
     1279            /*
     1280             * Convert to a scatter-gather buffer.
     1281             *
     1282             * We need not do any platform specific code here as the RTSGBUF
     1283             * segment array maps directly onto the posix iovec structure.
     1284             * Windows does currently benefit much from this conversion, but
     1285             * so be it.
     1286             */
     1287            RTSGBUF SgBuf;
     1288            rc = vbsfPagesToSgBuf(pPages, cbToWrite, &SgBuf);
     1289            if (RT_SUCCESS(rc))
     1290            {
     1291//#ifndef RT_OS_LINUX
     1292                /* Cannot use RTFileSgWriteAt or RTFileWriteAt when opened with
     1293                   RTFILE_O_APPEND, except for on linux where the offset is
     1294                   then ignored by the low level kernel API. */
     1295                if (pHandle->file.fOpenFlags & RTFILE_O_APPEND)
     1296                {
     1297                    /* paranoia */
     1298                    RTFileSeek(pHandle->file.Handle, 0, RTFILE_SEEK_END, NULL);
     1299
     1300                    for (size_t iSeg = 0; iSeg < SgBuf.cSegs; iSeg++)
     1301                    {
     1302                        size_t cbWrittenNow = 0;
     1303                        do
     1304                            rc = RTFileWrite(pHandle->file.Handle, SgBuf.paSegs[iSeg].pvSeg,
     1305                                             SgBuf.paSegs[iSeg].cbSeg, &cbWrittenNow);
     1306                        while (rc == VERR_INTERRUPTED);
     1307                        if (RT_SUCCESS(rc))
     1308                        {
     1309                            cbTotal += cbWrittenNow;
     1310                            if (cbWrittenNow < SgBuf.paSegs[iSeg].cbSeg)
     1311                                break;
     1312                        }
     1313                        else
     1314                        {
     1315                            if (cbTotal > 0)
     1316                                rc = VINF_SUCCESS;
     1317                            break;
     1318                        }
     1319                    }
     1320                }
     1321                else
     1322//#endif
     1323                {
     1324                    rc = RTFileSgWriteAt(pHandle->file.Handle, offFile, &SgBuf, cbToWrite, &cbTotal);
     1325                    while (rc == VERR_INTERRUPTED)
     1326                    {
     1327                        RTSgBufReset(&SgBuf);
     1328                        rc = RTFileSgWriteAt(pHandle->file.Handle, offFile, &SgBuf, cbToWrite, &cbTotal);
     1329                    }
     1330                }
     1331
     1332                RTMemTmpFree((void *)SgBuf.paSegs);
     1333
     1334                /* Update the file offset (mainly for RTFILE_O_APPEND), */
     1335                if (RT_SUCCESS(rc))
     1336                {
     1337                    offFile += cbTotal;
     1338                    if (!(pHandle->file.fOpenFlags & RTFILE_O_APPEND))
     1339                        *poffFile = offFile;
     1340                    else
     1341                        *poffFile = vbsfWriteCalcPostAppendFilePosition(pHandle->file.Handle, offFile);
     1342                }
     1343            }
     1344            else
     1345                rc = VERR_NO_TMP_MEMORY;
     1346
     1347            *pcbWrite = (uint32_t)cbTotal;
    11011348        }
    11021349        else
    1103             AssertRC(rc);
     1350        {
     1351            /* Writing zero bytes always succeeds. */
     1352            rc = VINF_SUCCESS;
     1353        }
    11041354    }
    11051355    else
    1106     {
    1107         /** @todo What writing zero bytes should do? */
    1108         rc = VINF_SUCCESS;
    1109     }
    1110 
    1111     LogFunc(("%Rrc bytes written 0x%RX32\n", rc, *pcbBuffer));
     1356        *pcbWrite = 0;
     1357
     1358    LogFunc(("%Rrc bytes written %#zx\n", rc, cbTotal));
    11121359    return rc;
    11131360}
  • trunk/src/VBox/HostServices/SharedFolders/vbsf.h

    r76570 r77243  
    3030
    3131int vbsfRead(SHFLCLIENTDATA *pClient, SHFLROOT root, SHFLHANDLE Handle, uint64_t offset, uint32_t *pcbBuffer, uint8_t *pBuffer);
    32 int vbsfWrite(SHFLCLIENTDATA *pClient, SHFLROOT root, SHFLHANDLE Handle, uint64_t offset, uint32_t *pcbBuffer, uint8_t *pBuffer);
     32int vbsfReadPages(SHFLCLIENTDATA *pClient, SHFLROOT idRoot, SHFLHANDLE hFile, uint64_t offFile,
     33                  uint32_t *pcbBuffer, PVBOXHGCMSVCPARMPAGES pPages);
     34int vbsfWrite(SHFLCLIENTDATA *pClient, SHFLROOT root, SHFLHANDLE Handle, uint64_t *poffFile, uint32_t *pcbBuffer, uint8_t *pBuffer);
     35int vbsfWritePages(SHFLCLIENTDATA *pClient, SHFLROOT idRoot, SHFLHANDLE hFile, uint64_t *poffFile,
     36                   uint32_t *pcbBuffer, PVBOXHGCMSVCPARMPAGES pPages);
     37
    3338int vbsfLock(SHFLCLIENTDATA *pClient, SHFLROOT root, SHFLHANDLE Handle, uint64_t offset, uint64_t length, uint32_t flags);
    3439int vbsfUnlock(SHFLCLIENTDATA *pClient, SHFLROOT root, SHFLHANDLE Handle, uint64_t offset, uint64_t length, uint32_t flags);
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