mirror of
				https://github.com/winfsp/winfsp.git
				synced 2025-10-30 19:48:38 -05:00 
			
		
		
		
	sys: FspAcquireCcFlush: improve/fix top level IRP handling
This commit is contained in:
		| @@ -131,12 +131,23 @@ NTSTATUS FspAcquireForCcFlush( | |||||||
|  |  | ||||||
|     FSP_FILE_NODE *FileNode = FileObject->FsContext; |     FSP_FILE_NODE *FileNode = FileObject->FsContext; | ||||||
|     PIRP TopLevelIrp = IoGetTopLevelIrp(); |     PIRP TopLevelIrp = IoGetTopLevelIrp(); | ||||||
|  |     ULONG TopFlags; | ||||||
|  |  | ||||||
|     ASSERT(0 == TopLevelIrp || |     ASSERT(0 == TopLevelIrp || | ||||||
|         (PIRP)FSRTL_MAX_TOP_LEVEL_IRP_FLAG < TopLevelIrp); |         (PIRP)FSRTL_MAX_TOP_LEVEL_IRP_FLAG < TopLevelIrp); | ||||||
|     FspFileNodeAcquireExclusive(FileNode, Full); |  | ||||||
|     if (0 == TopLevelIrp) |     if (0 == TopLevelIrp) | ||||||
|  |     { | ||||||
|  |         FspFileNodeAcquireExclusive(FileNode, Full); | ||||||
|         IoSetTopLevelIrp((PIRP)FSRTL_CACHE_TOP_LEVEL_IRP); |         IoSetTopLevelIrp((PIRP)FSRTL_CACHE_TOP_LEVEL_IRP); | ||||||
|  |     } | ||||||
|  |     else | ||||||
|  |     { | ||||||
|  |         TopFlags = FspIrpTopFlags(TopLevelIrp); | ||||||
|  |         FspIrpSetTopFlags(TopLevelIrp, FspIrpFlags(TopLevelIrp)); | ||||||
|  |         FspFileNodeAcquireExclusive(FileNode, Full); | ||||||
|  |         ASSERT(0 == FileNode->Tls.TopFlags); | ||||||
|  |         FileNode->Tls.TopFlags = TopFlags; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     FSP_LEAVE("FileObject=%p", FileObject); |     FSP_LEAVE("FileObject=%p", FileObject); | ||||||
| } | } | ||||||
| @@ -149,12 +160,22 @@ NTSTATUS FspReleaseForCcFlush( | |||||||
|  |  | ||||||
|     FSP_FILE_NODE *FileNode = FileObject->FsContext; |     FSP_FILE_NODE *FileNode = FileObject->FsContext; | ||||||
|     PIRP TopLevelIrp = IoGetTopLevelIrp(); |     PIRP TopLevelIrp = IoGetTopLevelIrp(); | ||||||
|  |     ULONG TopFlags; | ||||||
|  |  | ||||||
|     ASSERT((PIRP)FSRTL_CACHE_TOP_LEVEL_IRP == TopLevelIrp || |     ASSERT((PIRP)FSRTL_CACHE_TOP_LEVEL_IRP == TopLevelIrp || | ||||||
|         (PIRP)FSRTL_MAX_TOP_LEVEL_IRP_FLAG < TopLevelIrp); |         (PIRP)FSRTL_MAX_TOP_LEVEL_IRP_FLAG < TopLevelIrp); | ||||||
|     if ((PIRP)FSRTL_CACHE_TOP_LEVEL_IRP == TopLevelIrp) |     if ((PIRP)FSRTL_CACHE_TOP_LEVEL_IRP == TopLevelIrp) | ||||||
|  |     { | ||||||
|         IoSetTopLevelIrp(0); |         IoSetTopLevelIrp(0); | ||||||
|         FspFileNodeRelease(FileNode, Full); |         FspFileNodeRelease(FileNode, Full); | ||||||
|  |     } | ||||||
|  |     else | ||||||
|  |     { | ||||||
|  |         TopFlags = FileNode->Tls.TopFlags; | ||||||
|  |         FileNode->Tls.TopFlags = 0; | ||||||
|  |         FspFileNodeRelease(FileNode, Full); | ||||||
|  |         FspIrpSetTopFlags(TopLevelIrp, TopFlags); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     FSP_LEAVE("FileObject=%p", FileObject); |     FSP_LEAVE("FileObject=%p", FileObject); | ||||||
| } | } | ||||||
| @@ -175,7 +196,8 @@ BOOLEAN FspAcquireForLazyWrite( | |||||||
|     Result = FspFileNodeTryAcquireExclusiveF(FileNode, FspFileNodeAcquireFull, Wait); |     Result = FspFileNodeTryAcquireExclusiveF(FileNode, FspFileNodeAcquireFull, Wait); | ||||||
|     if (Result) |     if (Result) | ||||||
|     { |     { | ||||||
|         FileNode->LazyWriteThread = PsGetCurrentThread(); |         ASSERT(0 == FileNode->Tls.LazyWriteThread); | ||||||
|  |         FileNode->Tls.LazyWriteThread = PsGetCurrentThread(); | ||||||
|         IoSetTopLevelIrp((PIRP)FSRTL_CACHE_TOP_LEVEL_IRP); |         IoSetTopLevelIrp((PIRP)FSRTL_CACHE_TOP_LEVEL_IRP); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -194,8 +216,9 @@ VOID FspReleaseFromLazyWrite( | |||||||
|     FSP_FILE_NODE *FileNode = Context; |     FSP_FILE_NODE *FileNode = Context; | ||||||
|  |  | ||||||
|     ASSERT((PIRP)FSRTL_CACHE_TOP_LEVEL_IRP == IoGetTopLevelIrp()); |     ASSERT((PIRP)FSRTL_CACHE_TOP_LEVEL_IRP == IoGetTopLevelIrp()); | ||||||
|  |     ASSERT(PsGetCurrentThread() == FileNode->Tls.LazyWriteThread); | ||||||
|     IoSetTopLevelIrp(0); |     IoSetTopLevelIrp(0); | ||||||
|     FileNode->LazyWriteThread = 0; |     FileNode->Tls.LazyWriteThread = 0; | ||||||
|     FspFileNodeRelease(FileNode, Full); |     FspFileNodeRelease(FileNode, Full); | ||||||
|  |  | ||||||
|     FSP_LEAVE_VOID("Context=%p", Context); |     FSP_LEAVE_VOID("Context=%p", Context); | ||||||
|   | |||||||
| @@ -793,7 +793,11 @@ typedef struct | |||||||
|     UINT64 Security; |     UINT64 Security; | ||||||
|     ULONG SecurityChangeNumber; |     ULONG SecurityChangeNumber; | ||||||
|     BOOLEAN TruncateOnClose; |     BOOLEAN TruncateOnClose; | ||||||
|  |     union | ||||||
|  |     { | ||||||
|         PVOID LazyWriteThread; |         PVOID LazyWriteThread; | ||||||
|  |         UINT32 TopFlags; | ||||||
|  |     } Tls; | ||||||
|     /* read-only after creation (and insertion in the ContextTable) */ |     /* read-only after creation (and insertion in the ContextTable) */ | ||||||
|     PDEVICE_OBJECT FsvolDeviceObject; |     PDEVICE_OBJECT FsvolDeviceObject; | ||||||
|     UINT64 UserContext; |     UINT64 UserContext; | ||||||
|   | |||||||
| @@ -64,15 +64,19 @@ VOID FspFileDescDelete(FSP_FILE_DESC *FileDesc); | |||||||
| #define FSP_FILE_NODE_GET_FLAGS()       \ | #define FSP_FILE_NODE_GET_FLAGS()       \ | ||||||
|     PIRP Irp = IoGetTopLevelIrp();      \ |     PIRP Irp = IoGetTopLevelIrp();      \ | ||||||
|     BOOLEAN IrpValid = (PIRP)FSRTL_MAX_TOP_LEVEL_IRP_FLAG < Irp &&\ |     BOOLEAN IrpValid = (PIRP)FSRTL_MAX_TOP_LEVEL_IRP_FLAG < Irp &&\ | ||||||
|         IO_TYPE_IRP == Irp->Type;\ |         IO_TYPE_IRP == Irp->Type;       \ | ||||||
|     if (IrpValid)                       \ |     if (IrpValid)                       \ | ||||||
|         Flags &= ~FspIrpTopFlags(Irp); |         Flags &= ~FspIrpTopFlags(Irp) | ||||||
|  | #define FSP_FILE_NODE_ASSERT_FLAGS_CLR()\ | ||||||
|  |     ASSERT(IrpValid ? (0 == (FspIrpFlags(Irp) & Flags)) : TRUE) | ||||||
|  | #define FSP_FILE_NODE_ASSERT_FLAGS_SET()\ | ||||||
|  |     ASSERT(IrpValid ? (Flags == (FspIrpFlags(Irp) & Flags)) : TRUE) | ||||||
| #define FSP_FILE_NODE_SET_FLAGS()       \ | #define FSP_FILE_NODE_SET_FLAGS()       \ | ||||||
|     if (IrpValid)                       \ |     if (IrpValid)                       \ | ||||||
|         FspIrpSetFlags(Irp, FspIrpFlags(Irp) | Flags); |         FspIrpSetFlags(Irp, FspIrpFlags(Irp) | Flags) | ||||||
| #define FSP_FILE_NODE_CLR_FLAGS()       \ | #define FSP_FILE_NODE_CLR_FLAGS()       \ | ||||||
|     if (IrpValid)                       \ |     if (IrpValid)                       \ | ||||||
|         FspIrpSetFlags(Irp, FspIrpFlags(Irp) & (~Flags & 3)); |         FspIrpSetFlags(Irp, FspIrpFlags(Irp) & (~Flags & 3)) | ||||||
|  |  | ||||||
| NTSTATUS FspFileNodeCreate(PDEVICE_OBJECT DeviceObject, | NTSTATUS FspFileNodeCreate(PDEVICE_OBJECT DeviceObject, | ||||||
|     ULONG ExtraSize, FSP_FILE_NODE **PFileNode) |     ULONG ExtraSize, FSP_FILE_NODE **PFileNode) | ||||||
| @@ -145,6 +149,7 @@ VOID FspFileNodeAcquireSharedF(FSP_FILE_NODE *FileNode, ULONG Flags) | |||||||
|     PAGED_CODE(); |     PAGED_CODE(); | ||||||
|  |  | ||||||
|     FSP_FILE_NODE_GET_FLAGS(); |     FSP_FILE_NODE_GET_FLAGS(); | ||||||
|  |     FSP_FILE_NODE_ASSERT_FLAGS_CLR(); | ||||||
|  |  | ||||||
|     if (Flags & FspFileNodeAcquireMain) |     if (Flags & FspFileNodeAcquireMain) | ||||||
|         ExAcquireResourceSharedLite(FileNode->Header.Resource, TRUE); |         ExAcquireResourceSharedLite(FileNode->Header.Resource, TRUE); | ||||||
| @@ -160,6 +165,7 @@ BOOLEAN FspFileNodeTryAcquireSharedF(FSP_FILE_NODE *FileNode, ULONG Flags, BOOLE | |||||||
|     PAGED_CODE(); |     PAGED_CODE(); | ||||||
|  |  | ||||||
|     FSP_FILE_NODE_GET_FLAGS(); |     FSP_FILE_NODE_GET_FLAGS(); | ||||||
|  |     FSP_FILE_NODE_ASSERT_FLAGS_CLR(); | ||||||
|  |  | ||||||
|     BOOLEAN Result = TRUE; |     BOOLEAN Result = TRUE; | ||||||
|  |  | ||||||
| @@ -192,6 +198,7 @@ VOID FspFileNodeAcquireExclusiveF(FSP_FILE_NODE *FileNode, ULONG Flags) | |||||||
|     PAGED_CODE(); |     PAGED_CODE(); | ||||||
|  |  | ||||||
|     FSP_FILE_NODE_GET_FLAGS(); |     FSP_FILE_NODE_GET_FLAGS(); | ||||||
|  |     FSP_FILE_NODE_ASSERT_FLAGS_CLR(); | ||||||
|  |  | ||||||
|     if (Flags & FspFileNodeAcquireMain) |     if (Flags & FspFileNodeAcquireMain) | ||||||
|         ExAcquireResourceExclusiveLite(FileNode->Header.Resource, TRUE); |         ExAcquireResourceExclusiveLite(FileNode->Header.Resource, TRUE); | ||||||
| @@ -207,6 +214,7 @@ BOOLEAN FspFileNodeTryAcquireExclusiveF(FSP_FILE_NODE *FileNode, ULONG Flags, BO | |||||||
|     PAGED_CODE(); |     PAGED_CODE(); | ||||||
|  |  | ||||||
|     FSP_FILE_NODE_GET_FLAGS(); |     FSP_FILE_NODE_GET_FLAGS(); | ||||||
|  |     FSP_FILE_NODE_ASSERT_FLAGS_CLR(); | ||||||
|  |  | ||||||
|     BOOLEAN Result = TRUE; |     BOOLEAN Result = TRUE; | ||||||
|  |  | ||||||
| @@ -254,6 +262,7 @@ VOID FspFileNodeReleaseF(FSP_FILE_NODE *FileNode, ULONG Flags) | |||||||
|     PAGED_CODE(); |     PAGED_CODE(); | ||||||
|  |  | ||||||
|     FSP_FILE_NODE_GET_FLAGS(); |     FSP_FILE_NODE_GET_FLAGS(); | ||||||
|  |     FSP_FILE_NODE_ASSERT_FLAGS_SET(); | ||||||
|  |  | ||||||
|     if (Flags & FspFileNodeAcquirePgio) |     if (Flags & FspFileNodeAcquirePgio) | ||||||
|         ExReleaseResourceLite(FileNode->Header.PagingIoResource); |         ExReleaseResourceLite(FileNode->Header.PagingIoResource); | ||||||
| @@ -269,6 +278,7 @@ VOID FspFileNodeReleaseOwnerF(FSP_FILE_NODE *FileNode, ULONG Flags, PVOID Owner) | |||||||
|     PAGED_CODE(); |     PAGED_CODE(); | ||||||
|  |  | ||||||
|     FSP_FILE_NODE_GET_FLAGS(); |     FSP_FILE_NODE_GET_FLAGS(); | ||||||
|  |     FSP_FILE_NODE_ASSERT_FLAGS_SET(); | ||||||
|  |  | ||||||
|     Owner = (PVOID)((UINT_PTR)Owner | 3); |     Owner = (PVOID)((UINT_PTR)Owner | 3); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -285,7 +285,7 @@ static NTSTATUS FspFsvolWriteNonCached( | |||||||
|  |  | ||||||
|     /* if we are called by the lazy writer we must constrain writes */ |     /* if we are called by the lazy writer we must constrain writes */ | ||||||
|     if (FlagOn(FspIrpTopFlags(Irp), FspFileNodeAcquireMain) &&  /* if TopLevelIrp has acquired Main */ |     if (FlagOn(FspIrpTopFlags(Irp), FspFileNodeAcquireMain) &&  /* if TopLevelIrp has acquired Main */ | ||||||
|         FileNode->LazyWriteThread == PsGetCurrentThread())      /* and this is a lazy writer thread */ |         FileNode->Tls.LazyWriteThread == PsGetCurrentThread())  /* and this is a lazy writer thread */ | ||||||
|     { |     { | ||||||
|         ASSERT(PagingIo); |         ASSERT(PagingIo); | ||||||
|         ASSERT(FspTimeoutInfinity32 == |         ASSERT(FspTimeoutInfinity32 == | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user