- Timestamp:
- May 18, 2019 2:23:00 AM (6 years ago)
- 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 28 28 * Defined Constants And Macros * 29 29 *********************************************************************************************************************************/ 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 30 33 /* How much data to transfer in one HGCM request. */ 31 34 #define VBSF_MAX_READ_WRITE_PAGES 256 … … 43 46 44 47 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 52 48 static int vbsfTransferBufferWrite(PVBGLSFCLIENT pClient, PVBGLSFMAP pMap, SHFLHANDLE hFile, 53 49 uint64_t offset, uint32_t *pcbBuffer, … … 55 51 { 56 52 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);64 53 } 65 54 … … 225 214 } 226 215 227 static NTSTATUS vbsfReadInternal(IN PRX_CONTEXT RxContext) 228 { 229 VBSFTRANSFERCTX ctx; 230 216 /** 217 * Performs a read. 218 */ 219 static NTSTATUS vbsfNtReadWorker(PRX_CONTEXT RxContext) 220 { 231 221 RxCaptureFcb; 232 222 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 { 283 260 /* 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. 289 262 */ 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 291 269 { 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; 300 272 } 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); 301 388 } 302 389 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 */ 317 400 static VOID vbsfReadWorker(VOID *pv) 318 401 { … … 321 404 Log(("VBOXSF: vbsfReadWorker: calling the worker\n")); 322 405 323 RxContext->IoStatusBlock.Status = vbsf ReadInternal(RxContext);406 RxContext->IoStatusBlock.Status = vbsfNtReadWorker(RxContext); 324 407 325 408 Log(("VBOXSF: vbsfReadWorker: Status 0x%08X\n", … … 349 432 NTSTATUS Status; 350 433 351 #if 0 352 if ( IoIsOperationSynchronous(RxContext->CurrentIrp)353 /*&& IoGetRemainingStackSize() >= 1024 - not necessary, checked by RxFsdCommonDispatch already */)354 { 355 RxContext->IoStatusBlock.Status = Status = vbsf ReadInternal(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); 356 439 Assert(Status != STATUS_PENDING); 357 440 … … 359 442 } 360 443 else 361 #endif362 444 { 363 445 Status = RxDispatchToWorkerThread(VBoxMRxDeviceObject, DelayedWorkQueue, vbsfReadWorker, RxContext); -
trunk/src/VBox/Additions/WINNT/SharedFolders/driver/vbsf.cpp
r78562 r78575 651 651 g_fHostFeatures, g_fSfFeatures, g_uSfLastFunction)); 652 652 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 653 661 /* Init the driver object. */ 654 662 DriverObject->DriverUnload = VBoxMRxUnload;
Note:
See TracChangeset
for help on using the changeset viewer.