Changeset 78365 in vbox for trunk/src/VBox
- Timestamp:
- May 2, 2019 9:49:04 PM (6 years ago)
- Location:
- trunk/src/VBox/Additions/WINNT/SharedFolders/driver
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/WINNT/SharedFolders/driver/file.cpp
r78363 r78365 227 227 static NTSTATUS vbsfReadInternal(IN PRX_CONTEXT RxContext) 228 228 { 229 NTSTATUS Status = STATUS_SUCCESS;230 229 VBSFTRANSFERCTX ctx; 231 230 … … 240 239 241 240 PMDL BufferMdl = LowIoContext->ParamsFor.ReadWrite.Buffer; 242 uint32_t ByteCount = LowIoContext->ParamsFor.ReadWrite.ByteCount;243 RXVBO ByteOffset = LowIoContext->ParamsFor.ReadWrite.ByteOffset;244 241 245 242 PVOID pbUserBuffer = RxLowIoGetBufferAddress(RxContext); 246 247 int vrc;248 243 249 244 #ifdef LOG_ENABLED … … 258 253 pbUserBuffer, BufferMdl)); 259 254 Log(("VBOXSF: vbsfReadInternal: ByteCount 0x%X, ByteOffset 0x%RX64, FileSize 0x%RX64\n", 260 ByteCount,ByteOffset, FileSize));255 LowIoContext->ParamsFor.ReadWrite.ByteCount, LowIoContext->ParamsFor.ReadWrite.ByteOffset, FileSize)); 261 256 262 257 AssertReturn(BufferMdl, STATUS_INVALID_PARAMETER); 263 Assert( ByteCount > 0); /* ASSUME this is taken care of elsewhere already. */258 Assert(LowIoContext->ParamsFor.ReadWrite.ByteCount > 0); /* ASSUME this is taken care of elsewhere already. */ 264 259 265 260 ctx.pClient = &g_SfClient; 266 261 ctx.pMap = &pNetRootExtension->map; 267 262 ctx.hFile = pVBoxFobx->hFile; 268 ctx.offset = (uint64_t)ByteOffset;269 ctx.cbData = ByteCount;263 ctx.offset = LowIoContext->ParamsFor.ReadWrite.ByteOffset; 264 ctx.cbData = LowIoContext->ParamsFor.ReadWrite.ByteCount; 270 265 ctx.pMdl = BufferMdl; 271 266 ctx.pBuffer = (uint8_t *)pbUserBuffer; … … 274 269 ctx.pfnTransferPages = vbsfTransferPagesRead; 275 270 276 vrc = vbsfTransferCommon(&ctx); 277 278 ByteCount = ctx.cbData; 279 280 Status = vbsfNtVBoxStatusToNt(vrc); 281 282 if (Status == STATUS_SUCCESS) 271 int vrc = vbsfTransferCommon(&ctx); 272 273 NTSTATUS Status; 274 if (RT_SUCCESS(vrc)) 283 275 { 284 276 pVBoxFobx->fTimestampsImplicitlyUpdated |= VBOX_FOBX_F_INFO_LASTACCESS_TIME; 285 277 if (pVBoxFcbx->pFobxLastAccessTime != pVBoxFobx) 286 278 pVBoxFcbx->pFobxLastAccessTime = NULL; 279 Status = STATUS_SUCCESS; 280 281 /* 282 * See if we've reached the EOF early or read beyond what we thought were the EOF. 283 * 284 * Note! We don't dare do this (yet) if we're in paging I/O as we then hold the 285 * PagingIoResource in shared mode and would probably deadlock in the 286 * updating code when taking the lock in exclusive mode. 287 */ 288 if (RxContext->LowIoContext.Resource != capFcb->Header.PagingIoResource) 289 { 290 LONGLONG const offEndOfRead = LowIoContext->ParamsFor.ReadWrite.ByteOffset + ctx.cbData; 291 LONGLONG cbFileRdbss; 292 RxGetFileSizeWithLock((PFCB)capFcb, &cbFileRdbss); 293 if ( offEndOfRead < cbFileRdbss 294 && ctx.cbData < LowIoContext->ParamsFor.ReadWrite.ByteCount /* hit EOF */) 295 vbsfNtUpdateFcbSize(RxContext->pFobx->AssociatedFileObject, capFcb, pVBoxFobx, offEndOfRead, cbFileRdbss, -1); 296 else if (offEndOfRead > cbFileRdbss) 297 vbsfNtQueryAndUpdateFcbSize(pNetRootExtension, RxContext->pFobx->AssociatedFileObject, pVBoxFobx, capFcb, pVBoxFcbx); 298 } 287 299 } 288 300 else 289 ByteCount = 0; /* Nothing read. */ 290 291 RxContext->InformationToReturn = ByteCount; 292 293 /** @todo if we read past the end-of-file as we know it, or if we reached 294 * end-of-file earlier than we though, update the file size. The 295 * RxLowIoReadShellCompletion() routine does not seem to do this for is and 296 * I (bird) couldn't find anyone else doing it either. */ 301 { 302 ctx.cbData = 0; /* Nothing read. */ 303 Status = vbsfNtVBoxStatusToNt(vrc); 304 } 305 306 RxContext->InformationToReturn = ctx.cbData; 297 307 298 308 Log(("VBOXSF: vbsfReadInternal: Status = 0x%08X, ByteCount = 0x%X\n", 299 Status, ByteCount));309 Status, ctx.cbData)); 300 310 301 311 return Status; … … 317 327 } 318 328 329 /** 330 * Read stuff from a file. 331 * 332 * Prior to calling us, RDBSS will have: 333 * - Called CcFlushCache() for uncached accesses. 334 * - For non-paging access the Fcb.Header.Resource lock in shared mode in one 335 * way or another (ExAcquireResourceSharedLite, 336 * ExAcquireSharedWaitForExclusive). 337 * - For paging the FCB isn't, but the Fcb.Header.PagingResource is taken 338 * in shared mode (ExAcquireResourceSharedLite). 339 * 340 * Upon completion, it will update the file pointer if applicable. There are no 341 * EOF checks and corresponding file size updating like in the write case, so 342 * that's something we have to do ourselves it seems since the library relies on 343 * the size information to be accurate in a few places (set EOF, cached reads). 344 */ 319 345 NTSTATUS VBoxMRxRead(IN PRX_CONTEXT RxContext) 320 346 { -
trunk/src/VBox/Additions/WINNT/SharedFolders/driver/info.cpp
r78355 r78365 926 926 927 927 /** 928 * Updates the FCBs copy of the file size. 929 * 930 * The RDBSS is using the file size from the FCB in a few places without giving 931 * us the chance to make sure that the value is up to date and properly 932 * reflecting the size of the actual file on the host. Thus this mess to try 933 * keep the the size up to date where ever possible as well as some hacks to 934 * bypass RDBSS' use of the FCB file size. (And no, we cannot just make the 935 * FCB_STATE_FILESIZECACHEING_ENABLED flag isn't set, because it was never 936 * implemented.) 937 * 938 * @param pFileObj The file object. 939 * @param pFcb The FCB. 940 * @param pVBoxFobX Out file object extension data. 941 * @param cbFileNew The new file size. 942 * @param cbFileOld The old file size from the FCB/RDBSS. 943 * @param cbAllocated The allocated size for the file, -1 if not 944 * available. 945 * 946 * @note Will acquire the paging I/O resource lock in exclusive mode. Caller 947 * must not be holding it in shared mode. 948 */ 949 void vbsfNtUpdateFcbSize(PFILE_OBJECT pFileObj, PMRX_FCB pFcb, PMRX_VBOX_FOBX pVBoxFobX, 950 LONGLONG cbFileNew, LONGLONG cbFileOld, LONGLONG cbAllocated) 951 { 952 Assert(cbFileNew != cbFileOld); 953 Assert(cbFileNew >= 0); 954 Assert( !ExIsResourceAcquiredSharedLite(pFcb->Header.PagingIoResource) 955 || ExIsResourceAcquiredExclusiveLite(pFcb->Header.PagingIoResource)); 956 957 /* 958 * Lock the paging I/O resources before trying to modify the header variables. 959 * 960 * Note! RxAcquirePagingIoResource and RxReleasePagingIoResource are unsafe 961 * macros in need of {} wrappers when used with if statements. 962 */ 963 NTSTATUS rcNtLock = RxAcquirePagingIoResource(NULL, pFcb); 964 965 LONGLONG cbFileOldRecheck; 966 RxGetFileSizeWithLock((PFCB)pFcb, &cbFileOldRecheck); 967 if (cbFileOldRecheck == cbFileOld) 968 { 969 LONGLONG cbFileNewCopy = cbFileNew; 970 RxSetFileSizeWithLock((PFCB)pFcb, &cbFileNewCopy); 971 972 /* The valid data length is the same as the file size for us. */ 973 if (pFcb->Header.ValidDataLength.QuadPart != cbFileNew) 974 pFcb->Header.ValidDataLength.QuadPart = cbFileNew; 975 976 /* The allocation size must be larger or equal to the file size says https://www.osronline.com/article.cfm%5Eid=167.htm . */ 977 if (cbAllocated >= cbFileNew) 978 { 979 if (pFcb->Header.AllocationSize.QuadPart != cbAllocated) 980 pFcb->Header.AllocationSize.QuadPart = cbAllocated; 981 } 982 else if (pFcb->Header.AllocationSize.QuadPart < cbFileNew) 983 pFcb->Header.AllocationSize.QuadPart = cbFileNew; 984 985 /* Update our copy. */ 986 pVBoxFobX->Info.cbObject = cbFileNew; 987 if (cbAllocated >= 0) 988 pVBoxFobX->Info.cbAllocated = cbAllocated; 989 990 /* 991 * Tell the cache manager if we can. 992 * 993 * According to the MSDN documentation, we must update the cache manager when 994 * the file size changes, allocation size increases, valid data length descreases, 995 * and when a non-cached I/O operation increases the valid data length. 996 */ 997 SECTION_OBJECT_POINTERS *pSectPtrs = pFileObj->SectionObjectPointer; 998 if (pSectPtrs) 999 { 1000 LARGE_INTEGER NewSize; 1001 NewSize.QuadPart = cbFileNew; 1002 if ( cbFileNew >= cbFileOld 1003 || MmCanFileBeTruncated(pSectPtrs, &NewSize)) /** @todo do we need to check this? */ 1004 { 1005 CC_FILE_SIZES FileSizes; 1006 FileSizes.AllocationSize = pFcb->Header.AllocationSize; 1007 FileSizes.FileSize.QuadPart = cbFileNew; 1008 FileSizes.ValidDataLength.QuadPart = cbFileNew; 1009 1010 /* RDBSS leave the lock before calling CcSetFileSizes, so we do that too then.*/ 1011 if (NT_SUCCESS(rcNtLock)) 1012 { 1013 RxReleasePagingIoResource(NULL, pFcb); 1014 } 1015 1016 __try 1017 { 1018 CcSetFileSizes(pFileObj, &FileSizes); 1019 } 1020 __except(EXCEPTION_EXECUTE_HANDLER) 1021 { 1022 #ifdef LOG_ENABLED 1023 NTSTATUS rcNt = GetExceptionCode(); 1024 Log(("vbsfNtUpdateFcbSize: CcSetFileSizes -> %#x\n", rcNt)); 1025 #endif 1026 } 1027 return; 1028 } 1029 /** @todo should we flag this so we can try again later? */ 1030 } 1031 } 1032 else 1033 Log(("vbsfNtUpdateFcbSize: Seems we raced someone updating the file size: old size = %#RX64, new size = %#RX64, current size = %#RX64\n", 1034 cbFileOld, cbFileNew, cbFileOldRecheck)); 1035 1036 if (NT_SUCCESS(rcNtLock)) 1037 { 1038 RxReleasePagingIoResource(NULL, pFcb); 1039 } 1040 } 1041 1042 1043 /** 928 1044 * Updates the object info to the VBox file object extension data. 929 1045 * 930 * @param pVBoxFob xThe VBox file object extension data.1046 * @param pVBoxFobX The VBox file object extension data. 931 1047 * @param pObjInfo The fresh data from the host. Okay to modify. 932 * @param pVBoxFcb xThe VBox FCB extension data.1048 * @param pVBoxFcbX The VBox FCB extension data. 933 1049 * @param fTimestampsToCopyAnyway VBOX_FOBX_F_INFO_XXX mask of timestamps to 934 1050 * copy regardless of their suppressed state. … … 936 1052 * get current copies of newly modified and 937 1053 * suppressed fields. 1054 * @param pFileObj Pointer to the file object if we should 1055 * update the cache manager, otherwise NULL. 1056 * @param pFcb Pointer to the FCB if we should update its 1057 * copy of the file size, NULL if we should 1058 * leave it be. Must be NULL when pFileObj is. 938 1059 */ 939 static void vbsfNtCopyInfo(PMRX_VBOX_FOBX pVBoxFob x, PSHFLFSOBJINFO pObjInfo,940 PVBSFNTFCBEXT pVBoxFcbx, uint8_t fTimestampsToCopyAnyway)1060 static void vbsfNtCopyInfo(PMRX_VBOX_FOBX pVBoxFobX, PSHFLFSOBJINFO pObjInfo, PVBSFNTFCBEXT pVBoxFcbX, 1061 uint8_t fTimestampsToCopyAnyway, PFILE_OBJECT pFileObj, PMRX_FCB pFcb) 941 1062 { 942 1063 /* 943 * Check if the size changed. 1064 * Check if the size changed because RDBSS and the cache manager have 1065 * cached copies of the file and allocation sizes. 944 1066 */ 945 if (pObjInfo->cbObject != pVBoxFobx->Info.cbObject) 946 { 947 /** @todo Tell RDBSS about this? Seems we have to tell the cache manager 948 * ourselves, which sucks considering that RDBSS was supposed to 949 * shield us from crap like that (see the MS sales brochure). */ 1067 if (pFcb && pFileObj) 1068 { 1069 LONGLONG cbFileRdbss; 1070 RxGetFileSizeWithLock((PFCB)pFcb, &cbFileRdbss); 1071 if (pObjInfo->cbObject != cbFileRdbss) 1072 vbsfNtUpdateFcbSize(pFileObj, pFcb, pVBoxFobX, pObjInfo->cbObject, cbFileRdbss, pObjInfo->cbAllocated); 950 1073 } 951 1074 … … 960 1083 * structure before preforming the copy. 961 1084 */ 962 Assert((pVBoxFob x->fTimestampsSetByUser & ~pVBoxFobx->fTimestampsUpdatingSuppressed) == 0);963 uint8_t fCopyTs = pVBoxFob x->fTimestampsUpdatingSuppressed & ~fTimestampsToCopyAnyway;1085 Assert((pVBoxFobX->fTimestampsSetByUser & ~pVBoxFobX->fTimestampsUpdatingSuppressed) == 0); 1086 uint8_t fCopyTs = pVBoxFobX->fTimestampsUpdatingSuppressed & ~fTimestampsToCopyAnyway; 964 1087 if (fCopyTs) 965 1088 { 966 1089 if ( (fCopyTs & VBOX_FOBX_F_INFO_LASTACCESS_TIME) 967 && pVBoxFcb x->pFobxLastAccessTime == pVBoxFobx)968 pObjInfo->AccessTime = pVBoxFob x->Info.AccessTime;1090 && pVBoxFcbX->pFobxLastAccessTime == pVBoxFobX) 1091 pObjInfo->AccessTime = pVBoxFobX->Info.AccessTime; 969 1092 970 1093 if ( (fCopyTs & VBOX_FOBX_F_INFO_LASTWRITE_TIME) 971 && pVBoxFcb x->pFobxLastWriteTime == pVBoxFobx)972 pObjInfo->ModificationTime = pVBoxFob x->Info.ModificationTime;1094 && pVBoxFcbX->pFobxLastWriteTime == pVBoxFobX) 1095 pObjInfo->ModificationTime = pVBoxFobX->Info.ModificationTime; 973 1096 974 1097 if ( (fCopyTs & VBOX_FOBX_F_INFO_CHANGE_TIME) 975 && pVBoxFcb x->pFobxChangeTime == pVBoxFobx)976 pObjInfo->ChangeTime = pVBoxFob x->Info.ChangeTime;977 } 978 pVBoxFob x->Info = *pObjInfo;1098 && pVBoxFcbX->pFobxChangeTime == pVBoxFobX) 1099 pObjInfo->ChangeTime = pVBoxFobX->Info.ChangeTime; 1100 } 1101 pVBoxFobX->Info = *pObjInfo; 979 1102 980 1103 /* 981 1104 * Try eliminate this one. 982 1105 */ 983 vbsfNtBasicInfoFromVBoxObjInfo(&pVBoxFob x->FileBasicInfo, pObjInfo);1106 vbsfNtBasicInfoFromVBoxObjInfo(&pVBoxFobX->FileBasicInfo, pObjInfo); 984 1107 } 985 1108 1109 /** 1110 * Queries the current file stats from the host and updates the RDBSS' copy of 1111 * the file size if necessary. 1112 * 1113 * @returns IPRT status code 1114 * @param pNetRootX Our net root extension data. 1115 * @param pFileObj The file object. 1116 * @param pVBoxFobX Our file object extension data. 1117 * @param pFcb The FCB. 1118 * @param pVBoxFcbX Our FCB extension data. 1119 */ 1120 int vbsfNtQueryAndUpdateFcbSize(PMRX_VBOX_NETROOT_EXTENSION pNetRootX, PFILE_OBJECT pFileObj, 1121 PMRX_VBOX_FOBX pVBoxFobX, PMRX_FCB pFcb, PVBSFNTFCBEXT pVBoxFcbX) 1122 { 1123 VBOXSFOBJINFOREQ *pReq = (VBOXSFOBJINFOREQ *)VbglR0PhysHeapAlloc(sizeof(*pReq)); 1124 AssertReturn(pReq, VERR_NO_MEMORY); 1125 1126 int vrc = VbglR0SfHostReqQueryObjInfo(pNetRootX->map.root, pReq, pVBoxFobX->hFile); 1127 if (RT_SUCCESS(vrc)) 1128 vbsfNtCopyInfo(pVBoxFobX, &pReq->ObjInfo, pVBoxFcbX, 0, pFileObj, pFcb); 1129 else 1130 AssertMsgFailed(("vrc=%Rrc\n", vrc)); 1131 1132 VbglR0PhysHeapFree(pReq); 1133 return vrc; 1134 } 986 1135 987 1136 /** … … 989 1138 * 990 1139 * The RDBSS code has done various things before we get here wrt locking and 991 * request pre-processing. 1140 * request pre-processing. Unless this is a paging file (FCB_STATE_PAGING_FILE) 1141 * or FileNameInformation is being queried, the FCB is locked. For all except 1142 * for FileCompressionInformation, a shared FCB access (FCB.Header.Resource) is 1143 * acquired, where as for FileCompressionInformation it is taken exclusively. 992 1144 */ 993 1145 NTSTATUS VBoxMRxQueryFileInfo(IN PRX_CONTEXT RxContext) … … 1117 1269 int vrc = VbglR0SfHostReqQueryObjInfo(pNetRootExtension->map.root, pReq, pVBoxFobx->hFile); 1118 1270 if (RT_SUCCESS(vrc)) 1119 vbsfNtCopyInfo(pVBoxFobx, &pReq->ObjInfo, pVBoxFcbx, 0); 1271 vbsfNtCopyInfo(pVBoxFobx, &pReq->ObjInfo, pVBoxFcbx, 0, /* ASSUMES that PageingIoResource is not */ 1272 RxContext->pFobx->AssociatedFileObject, capFcb); /* held in shared mode here! */ 1120 1273 else 1121 1274 { … … 1302 1455 1303 1456 /** 1304 * Worker for vbsfNtSetBasicInfo.1457 * Worker for VBoxMRxSetFileInfo. 1305 1458 */ 1306 static NTSTATUS vbsfNtSetBasicInfo(PMRX_VBOX_ FOBX pVBoxFobx, PMRX_VBOX_NETROOT_EXTENSION pNetRootExtension,1307 P VBSFNTFCBEXT pVBoxFcbx, PFILE_BASIC_INFORMATION pBasicInfo)1459 static NTSTATUS vbsfNtSetBasicInfo(PMRX_VBOX_NETROOT_EXTENSION pNetRootExtension, PFILE_OBJECT pFileObj, PMRX_VBOX_FOBX pVBoxFobx, 1460 PMRX_FCB pFcb, PVBSFNTFCBEXT pVBoxFcbx, PFILE_BASIC_INFORMATION pBasicInfo) 1308 1461 { 1309 1462 Log(("VBOXSF: MRxSetFileInfo: FileBasicInformation: CreationTime %RX64\n", pBasicInfo->CreationTime.QuadPart)); … … 1465 1618 } 1466 1619 1467 vbsfNtCopyInfo(pVBoxFobx, &pReq->ObjInfo, pVBoxFcbx, fSuppressed );1620 vbsfNtCopyInfo(pVBoxFobx, &pReq->ObjInfo, pVBoxFcbx, fSuppressed, pFileObj, pFcb); 1468 1621 1469 1622 /* … … 1497 1650 1498 1651 /** 1499 * Worker for vbsfNtSetBasicInfo.1652 * Worker for VBoxMRxSetFileInfo. 1500 1653 */ 1501 1654 static NTSTATUS vbsfNtSetEndOfFile(IN OUT struct _RX_CONTEXT * RxContext, IN uint64_t cbNewFileSize) … … 1556 1709 1557 1710 /** 1558 * Worker for vbsfNtSetBasicInfo.1711 * Worker for VBoxMRxSetFileInfo. 1559 1712 */ 1560 1713 static NTSTATUS vbsfNtRename(IN PRX_CONTEXT RxContext, … … 1636 1789 * 1637 1790 * The RDBSS code has done various things before we get here wrt locking and 1638 * request pre-processing. It will normally acquire an exclusive lock, but not1639 * if this is related to a page file (FCB_STATE_PAGING_FILE set).1791 * request pre-processing. It will normally acquire an exclusive FCB lock, but 1792 * not if this is related to a page file (FCB_STATE_PAGING_FILE set). 1640 1793 */ 1641 1794 NTSTATUS VBoxMRxSetFileInfo(IN PRX_CONTEXT RxContext) … … 1702 1855 { 1703 1856 Assert(RxContext->Info.Length >= sizeof(FILE_BASIC_INFORMATION)); 1704 Status = vbsfNtSetBasicInfo(p VBoxFobx, pNetRootExtension, VBoxMRxGetFcbExtension(capFcb),1705 (PFILE_BASIC_INFORMATION)RxContext->Info.Buffer);1857 Status = vbsfNtSetBasicInfo(pNetRootExtension, RxContext->pFobx->AssociatedFileObject, pVBoxFobx, capFcb, 1858 VBoxMRxGetFcbExtension(capFcb), (PFILE_BASIC_INFORMATION)RxContext->Info.Buffer); 1706 1859 break; 1707 1860 } … … 1831 1984 return STATUS_SUCCESS; 1832 1985 } 1986 -
trunk/src/VBox/Additions/WINNT/SharedFolders/driver/path.cpp
r78355 r78365 571 571 RxFinishFcbInitialization(capFcb, (RX_FILE_TYPE)RDBSS_NTC_STORAGE_TYPE_FILE, &InitPacket); 572 572 } 573 /* 574 * See if the size has changed and update the FCB if it has. 575 */ 576 else 577 { 578 /** @todo Need to check RDBSS stack for locking semantics before updating 579 * anything. */ 580 } 573 581 574 582 SrvOpen->BufferingFlags = 0; -
trunk/src/VBox/Additions/WINNT/SharedFolders/driver/vbsf.h
r78357 r78365 145 145 /** The RTTimeSystemNanoTS value when Info was retrieved, 0 to force update. */ 146 146 uint64_t nsUpToDate; 147 /** Cached object info. */ 147 /** Cached object info. 148 * @todo Consider moving it to VBSFNTFCBEXT. Better fit than on "handle". */ 148 149 SHFLFSOBJINFO Info; 149 150 /** NT version of Info. … … 263 264 #endif 264 265 266 void vbsfNtUpdateFcbSize(PFILE_OBJECT pFileObj, PMRX_FCB pFcb, PMRX_VBOX_FOBX pVBoxFobX, 267 LONGLONG cbFileNew, LONGLONG cbFileOld, LONGLONG cbAllocated); 268 int vbsfNtQueryAndUpdateFcbSize(PMRX_VBOX_NETROOT_EXTENSION pNetRootX, PFILE_OBJECT pFileObj, 269 PMRX_VBOX_FOBX pVBoxFobX, PMRX_FCB pFcb, PVBSFNTFCBEXT pVBoxFcbX); 270 265 271 /** 266 272 * Converts VBox (IPRT) file mode to NT file attributes.
Note:
See TracChangeset
for help on using the changeset viewer.