VirtualBox

Changeset 78575 in vbox for trunk/src


Ignore:
Timestamp:
May 18, 2019 2:23:00 AM (6 years ago)
Author:
vboxsync
Message:

winnt/vboxsf: Converted VBoxMRxRead the new HGCM IDC interface, only keeping the page list variant. bugref:9172

Location:
trunk/src/VBox/Additions/WINNT/SharedFolders/driver
Files:
2 edited

Legend:

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

    r78548 r78575  
    2828*   Defined Constants And Macros                                                                                                 *
    2929*********************************************************************************************************************************/
     30/** How many pages we should try transfer in one I/O request (read/write). */
     31#define VBSF_MAX_IO_PAGES   RT_MIN(_16K / sizeof(RTGCPHYS64) /* => 8MB buffer */, VMMDEV_MAX_HGCM_DATA_SIZE >> PAGE_SHIFT)
     32
    3033/* How much data to transfer in one HGCM request. */
    3134#define VBSF_MAX_READ_WRITE_PAGES 256
     
    4346
    4447
    45 static int vbsfTransferBufferRead(PVBGLSFCLIENT pClient, PVBGLSFMAP pMap, SHFLHANDLE hFile,
    46                                   uint64_t offset, uint32_t *pcbBuffer,
    47                                   uint8_t *pBuffer, bool fLocked)
    48 {
    49     return VbglR0SfRead(pClient, pMap, hFile, offset, pcbBuffer, pBuffer, fLocked);
    50 }
    51 
    5248static int vbsfTransferBufferWrite(PVBGLSFCLIENT pClient, PVBGLSFMAP pMap, SHFLHANDLE hFile,
    5349                                   uint64_t offset, uint32_t *pcbBuffer,
     
    5551{
    5652    return VbglR0SfWrite(pClient, pMap, hFile, offset, pcbBuffer, pBuffer, fLocked);
    57 }
    58 
    59 static int vbsfTransferPagesRead(PVBGLSFCLIENT pClient, PVBGLSFMAP pMap, SHFLHANDLE hFile,
    60                                  uint64_t offset, uint32_t *pcbBuffer,
    61                                  uint16_t offFirstPage, uint16_t cPages, RTGCPHYS64 *paPages)
    62 {
    63     return VbglR0SfReadPageList(pClient, pMap, hFile, offset, pcbBuffer, offFirstPage, cPages, paPages);
    6453}
    6554
     
    225214}
    226215
    227 static NTSTATUS vbsfReadInternal(IN PRX_CONTEXT RxContext)
    228 {
    229     VBSFTRANSFERCTX ctx;
    230 
     216/**
     217 * Performs a read.
     218 */
     219static NTSTATUS vbsfNtReadWorker(PRX_CONTEXT RxContext)
     220{
    231221    RxCaptureFcb;
    232222    RxCaptureFobx;
    233 
    234     PMRX_VBOX_NETROOT_EXTENSION pNetRootExtension = VBoxMRxGetNetRootExtension(capFcb->pNetRoot);
    235     PVBSFNTFCBEXT pVBoxFcbx = VBoxMRxGetFcbExtension(capFcb);
    236     PMRX_VBOX_FOBX pVBoxFobx = VBoxMRxGetFileObjectExtension(capFobx);
    237 
    238     PLOWIO_CONTEXT LowIoContext = &RxContext->LowIoContext;
    239 
    240     PMDL BufferMdl = LowIoContext->ParamsFor.ReadWrite.Buffer;
    241 
    242     PVOID pbUserBuffer = RxLowIoGetBufferAddress(RxContext);
    243 
    244 #ifdef LOG_ENABLED
    245     BOOLEAN AsyncIo = BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_ASYNC_OPERATION);
    246     LONGLONG FileSize;
    247     RxGetFileSizeWithLock((PFCB)capFcb, &FileSize);
    248 #endif
    249 
    250     Log(("VBOXSF: vbsfReadInternal: AsyncIo = %d, Fcb->FileSize = 0x%RX64\n",
    251          AsyncIo, capFcb->Header.FileSize.QuadPart));
    252     Log(("VBOXSF: vbsfReadInternal: UserBuffer %p, BufferMdl %p\n",
    253          pbUserBuffer, BufferMdl));
    254     Log(("VBOXSF: vbsfReadInternal: ByteCount 0x%X, ByteOffset 0x%RX64, FileSize 0x%RX64\n",
    255          LowIoContext->ParamsFor.ReadWrite.ByteCount, LowIoContext->ParamsFor.ReadWrite.ByteOffset, FileSize));
    256 
    257     AssertReturn(BufferMdl, STATUS_INVALID_PARAMETER);
    258     Assert(LowIoContext->ParamsFor.ReadWrite.ByteCount > 0); /* ASSUME this is taken care of elsewhere already. */
    259 
    260     ctx.pClient = &g_SfClient;
    261     ctx.pMap    = &pNetRootExtension->map;
    262     ctx.hFile   = pVBoxFobx->hFile;
    263     ctx.offset  = LowIoContext->ParamsFor.ReadWrite.ByteOffset;
    264     ctx.cbData  = LowIoContext->ParamsFor.ReadWrite.ByteCount;
    265     ctx.pMdl    = BufferMdl;
    266     ctx.pBuffer = (uint8_t *)pbUserBuffer;
    267     ctx.fLocked = true;
    268     ctx.pfnTransferBuffer = vbsfTransferBufferRead;
    269     ctx.pfnTransferPages = vbsfTransferPagesRead;
    270 
    271     int vrc = vbsfTransferCommon(&ctx);
    272 
    273     NTSTATUS Status;
    274     if (RT_SUCCESS(vrc))
    275     {
    276         pVBoxFobx->fTimestampsImplicitlyUpdated |= VBOX_FOBX_F_INFO_LASTACCESS_TIME;
    277         if (pVBoxFcbx->pFobxLastAccessTime != pVBoxFobx)
    278             pVBoxFcbx->pFobxLastAccessTime = NULL;
    279         Status = STATUS_SUCCESS;
    280         if (ctx.cbData == 0 && LowIoContext->ParamsFor.ReadWrite.ByteCount > 0)
    281             Status = STATUS_END_OF_FILE;
    282 
     223    PMRX_VBOX_NETROOT_EXTENSION pNetRootX  = VBoxMRxGetNetRootExtension(capFcb->pNetRoot);
     224    PVBSFNTFCBEXT               pVBoxFcbX  = VBoxMRxGetFcbExtension(capFcb);
     225    PMRX_VBOX_FOBX              pVBoxFobX  = VBoxMRxGetFileObjectExtension(capFobx);
     226    PMDL                        pBufferMdl = RxContext->LowIoContext.ParamsFor.ReadWrite.Buffer;
     227
     228    LogFlow(("vbsfNtReadWorker: hFile=%#RX64 offFile=%#RX64 cbToRead=%#x %s\n", pVBoxFobX->hFile,
     229             RxContext->LowIoContext.ParamsFor.ReadWrite.ByteOffset, RxContext->LowIoContext.ParamsFor.ReadWrite.ByteCount,
     230             RxContext->Flags, RX_CONTEXT_FLAG_ASYNC_OPERATION ? " async" : "sync"));
     231
     232    AssertReturn(pBufferMdl,  STATUS_INTERNAL_ERROR);
     233
     234
     235    /*
     236     * We should never get a zero byte request (RDBSS checks), but in case we
     237     * do, it should succeed.
     238     */
     239    uint32_t cbRet  = 0;
     240    uint32_t cbLeft = RxContext->LowIoContext.ParamsFor.ReadWrite.ByteCount;
     241    AssertReturnStmt(cbLeft > 0, RxContext->InformationToReturn = 0, STATUS_SUCCESS);
     242
     243    Assert(cbLeft <= MmGetMdlByteCount(pBufferMdl));
     244
     245    /*
     246     * Allocate a request buffer.
     247     */
     248    uint32_t            cPagesLeft = ADDRESS_AND_SIZE_TO_SPAN_PAGES(MmGetMdlVirtualAddress(pBufferMdl), cbLeft);
     249    uint32_t            cMaxPages  = RT_MIN(cPagesLeft, VBSF_MAX_IO_PAGES);
     250    VBOXSFREADPGLSTREQ *pReq = (VBOXSFREADPGLSTREQ *)VbglR0PhysHeapAlloc(RT_UOFFSETOF_DYN(VBOXSFREADPGLSTREQ,
     251                                                                                          PgLst.aPages[cMaxPages]));
     252    while (!pReq && cMaxPages > 4)
     253    {
     254        cMaxPages /= 2;
     255        pReq = (VBOXSFREADPGLSTREQ *)VbglR0PhysHeapAlloc(RT_UOFFSETOF_DYN(VBOXSFREADPGLSTREQ, PgLst.aPages[cMaxPages]));
     256    }
     257    NTSTATUS rcNt = STATUS_SUCCESS;
     258    if (pReq)
     259    {
    283260        /*
    284          * See if we've reached the EOF early or read beyond what we thought were the EOF.
    285          *
    286          * Note! We don't dare do this (yet) if we're in paging I/O as we then hold the
    287          *       PagingIoResource in shared mode and would probably deadlock in the
    288          *       updating code when taking the lock in exclusive mode.
     261         * The read loop.
    289262         */
    290         if (RxContext->LowIoContext.Resource != capFcb->Header.PagingIoResource)
     263        RTFOFF      offFile = RxContext->LowIoContext.ParamsFor.ReadWrite.ByteOffset;
     264        PPFN_NUMBER paPfns  = MmGetMdlPfnArray(pBufferMdl);
     265        uint32_t    offPage = MmGetMdlByteOffset(pBufferMdl);
     266        if (offPage < PAGE_SIZE)
     267        { /* likely */ }
     268        else
    291269        {
    292             LONGLONG const offEndOfRead = LowIoContext->ParamsFor.ReadWrite.ByteOffset + ctx.cbData;
    293             LONGLONG       cbFileRdbss;
    294             RxGetFileSizeWithLock((PFCB)capFcb, &cbFileRdbss);
    295             if (   offEndOfRead < cbFileRdbss
    296                 && ctx.cbData < LowIoContext->ParamsFor.ReadWrite.ByteCount /* hit EOF */)
    297                 vbsfNtUpdateFcbSize(RxContext->pFobx->AssociatedFileObject, capFcb, pVBoxFobx, offEndOfRead, cbFileRdbss, -1);
    298             else if (offEndOfRead > cbFileRdbss)
    299                 vbsfNtQueryAndUpdateFcbSize(pNetRootExtension, RxContext->pFobx->AssociatedFileObject, pVBoxFobx, capFcb, pVBoxFcbx);
     270            paPfns  += offPage >> PAGE_SHIFT;
     271            offPage &= PAGE_OFFSET_MASK;
    300272        }
     273
     274        for (;;)
     275        {
     276            /*
     277             * Figure out how much to process now and set up the page list for it.
     278             */
     279            uint32_t cPagesInChunk;
     280            uint32_t cbChunk;
     281            if (cPagesLeft <= cMaxPages)
     282            {
     283                cPagesInChunk = cPagesLeft;
     284                cbChunk       = cbLeft;
     285            }
     286            else
     287            {
     288                cPagesInChunk = cMaxPages;
     289                cbChunk       = (cMaxPages << PAGE_SHIFT) - offPage;
     290            }
     291
     292            size_t iPage = cPagesInChunk;
     293            while (iPage-- > 0)
     294                pReq->PgLst.aPages[iPage] = (RTGCPHYS)paPfns[iPage] << PAGE_SHIFT;
     295            pReq->PgLst.offFirstPage = offPage;
     296
     297            /*
     298             * Issue the request and unlock the pages.
     299             */
     300            int vrc = VbglR0SfHostReqReadPgLst(pNetRootX->map.root, pReq, pVBoxFobX->hFile, offFile, cbChunk, cPagesInChunk);
     301            if (RT_SUCCESS(vrc))
     302            {
     303                /*
     304                 * Success, advance position and buffer.
     305                 */
     306                uint32_t cbActual = pReq->Parms.cb32Read.u.value32;
     307                AssertStmt(cbActual <= cbChunk, cbActual = cbChunk);
     308                cbRet   += cbActual;
     309                offFile += cbActual;
     310                cbLeft  -= cbActual;
     311
     312                /*
     313                 * Update timestamp state (FCB is shared).
     314                 */
     315                pVBoxFobX->fTimestampsImplicitlyUpdated |= VBOX_FOBX_F_INFO_LASTACCESS_TIME;
     316                if (pVBoxFcbX->pFobxLastAccessTime != pVBoxFobX)
     317                    pVBoxFcbX->pFobxLastAccessTime = NULL;
     318
     319                /*
     320                 * Are we done already?
     321                 */
     322                if (!cbLeft || cbActual < cbChunk)
     323                {
     324                    /*
     325                     * Flag EOF.
     326                     */
     327                    if (cbActual != 0 || cbRet != 0)
     328                    { /* typical */ }
     329                    else
     330                        rcNt = STATUS_END_OF_FILE;
     331
     332                    /*
     333                     * See if we've reached the EOF early or read beyond what we thought were the EOF.
     334                     *
     335                     * Note! We don't dare do this (yet) if we're in paging I/O as we then hold the
     336                     *       PagingIoResource in shared mode and would probably deadlock in the
     337                     *       updating code when taking the lock in exclusive mode.
     338                     */
     339                    if (RxContext->LowIoContext.Resource != capFcb->Header.PagingIoResource)
     340                    {
     341                        LONGLONG cbFileRdbss;
     342                        RxGetFileSizeWithLock((PFCB)capFcb, &cbFileRdbss);
     343                        if (   offFile < cbFileRdbss
     344                            && cbActual < cbChunk /* hit EOF */)
     345                            vbsfNtUpdateFcbSize(RxContext->pFobx->AssociatedFileObject, capFcb, pVBoxFobX, offFile, cbFileRdbss, -1);
     346                        else if (offFile > cbFileRdbss)
     347                            vbsfNtQueryAndUpdateFcbSize(pNetRootX, RxContext->pFobx->AssociatedFileObject,
     348                                                        pVBoxFobX, capFcb, pVBoxFcbX);
     349                    }
     350                    break;
     351                }
     352
     353                /*
     354                 * More to read, advance page related variables and loop.
     355                 */
     356                paPfns     += cPagesInChunk;
     357                cPagesLeft -= cPagesInChunk;
     358                offPage     = 0;
     359            }
     360            else if (vrc == VERR_NO_MEMORY && cMaxPages > 4)
     361            {
     362                /*
     363                 * The host probably doesn't have enough heap to handle the
     364                 * request, reduce the page count and retry.
     365                 */
     366                cMaxPages /= 4;
     367                Assert(cMaxPages > 0);
     368            }
     369            else
     370            {
     371                /*
     372                 * If we've successfully read stuff, return it rather than
     373                 * the error.  (Not sure if this is such a great idea...)
     374                 */
     375                if (cbRet > 0)
     376                    Log(("vbsfNtReadWorker: read at %#RX64 -> %Rrc; got cbRet=%#zx already\n", offFile, vrc, cbRet));
     377                else
     378                {
     379                    rcNt = vbsfNtVBoxStatusToNt(vrc);
     380                    Log(("vbsfNtReadWorker: read at %#RX64 -> %Rrc (rcNt=%#x)\n", offFile, vrc, rcNt));
     381                }
     382                break;
     383            }
     384
     385        }
     386
     387        VbglR0PhysHeapFree(pReq);
    301388    }
    302389    else
    303     {
    304         ctx.cbData = 0; /* Nothing read. */
    305         Status = vbsfNtVBoxStatusToNt(vrc);
    306     }
    307 
    308     RxContext->InformationToReturn = ctx.cbData;
    309 
    310     Log(("VBOXSF: vbsfReadInternal: Status = 0x%08X, ByteCount = 0x%X\n",
    311          Status, ctx.cbData));
    312 
    313     return Status;
    314 }
    315 
    316 
     390        rcNt = STATUS_INSUFFICIENT_RESOURCES;
     391    RxContext->InformationToReturn = cbRet;
     392    LogFlow(("vbsfNtReadWorker: returns %#x cbRet=%#x @ %#RX64\n",
     393             rcNt, cbRet, RxContext->LowIoContext.ParamsFor.ReadWrite.ByteOffset));
     394    return rcNt;
     395}
     396
     397/**
     398 * Wrapper for RxDispatchToWorkerThread().
     399 */
    317400static VOID vbsfReadWorker(VOID *pv)
    318401{
     
    321404    Log(("VBOXSF: vbsfReadWorker: calling the worker\n"));
    322405
    323     RxContext->IoStatusBlock.Status = vbsfReadInternal(RxContext);
     406    RxContext->IoStatusBlock.Status = vbsfNtReadWorker(RxContext);
    324407
    325408    Log(("VBOXSF: vbsfReadWorker: Status 0x%08X\n",
     
    349432    NTSTATUS Status;
    350433
    351 #if 0
    352     if (   IoIsOperationSynchronous(RxContext->CurrentIrp)
    353         /*&& IoGetRemainingStackSize() >= 1024 - not necessary, checked by RxFsdCommonDispatch already */)
    354     {
    355         RxContext->IoStatusBlock.Status = Status = vbsfReadInternal(RxContext);
     434    /* If synchronous operation, keep it on this thread (RDBSS already checked
     435       if we've got enough stack before calling us).   */
     436    if (!(RxContext->Flags & RX_CONTEXT_FLAG_ASYNC_OPERATION))
     437    {
     438        RxContext->IoStatusBlock.Status = Status = vbsfNtReadWorker(RxContext);
    356439        Assert(Status != STATUS_PENDING);
    357440
     
    359442    }
    360443    else
    361 #endif
    362444    {
    363445        Status = RxDispatchToWorkerThread(VBoxMRxDeviceObject, DelayedWorkQueue, vbsfReadWorker, RxContext);
  • trunk/src/VBox/Additions/WINNT/SharedFolders/driver/vbsf.cpp

    r78562 r78575  
    651651            g_fHostFeatures, g_fSfFeatures, g_uSfLastFunction));
    652652
     653    if (!VbglR0CanUsePhysPageList())
     654    {
     655        LogRel(("vboxsf: Host does not support physical page lists.  Refuses to load!\n"));
     656        VbglR0SfTerm();
     657        RTR0Term();
     658        return STATUS_UNSUCCESSFUL;
     659    }
     660
    653661    /* Init the driver object. */
    654662    DriverObject->DriverUnload = VBoxMRxUnload;
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