sys: FspAcquireCcFlush: improve/fix top level IRP handling

This commit is contained in:
Bill Zissimopoulos 2016-03-12 19:03:06 -08:00
parent 9fc1123cdb
commit 03522c5296
4 changed files with 47 additions and 10 deletions

View File

@ -131,12 +131,23 @@ NTSTATUS FspAcquireForCcFlush(
FSP_FILE_NODE *FileNode = FileObject->FsContext;
PIRP TopLevelIrp = IoGetTopLevelIrp();
ULONG TopFlags;
ASSERT(0 == TopLevelIrp ||
(PIRP)FSRTL_MAX_TOP_LEVEL_IRP_FLAG < TopLevelIrp);
FspFileNodeAcquireExclusive(FileNode, Full);
if (0 == TopLevelIrp)
{
FspFileNodeAcquireExclusive(FileNode, Full);
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);
}
@ -149,12 +160,22 @@ NTSTATUS FspReleaseForCcFlush(
FSP_FILE_NODE *FileNode = FileObject->FsContext;
PIRP TopLevelIrp = IoGetTopLevelIrp();
ULONG TopFlags;
ASSERT((PIRP)FSRTL_CACHE_TOP_LEVEL_IRP == TopLevelIrp ||
(PIRP)FSRTL_MAX_TOP_LEVEL_IRP_FLAG < TopLevelIrp);
if ((PIRP)FSRTL_CACHE_TOP_LEVEL_IRP == TopLevelIrp)
{
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);
}
@ -175,7 +196,8 @@ BOOLEAN FspAcquireForLazyWrite(
Result = FspFileNodeTryAcquireExclusiveF(FileNode, FspFileNodeAcquireFull, Wait);
if (Result)
{
FileNode->LazyWriteThread = PsGetCurrentThread();
ASSERT(0 == FileNode->Tls.LazyWriteThread);
FileNode->Tls.LazyWriteThread = PsGetCurrentThread();
IoSetTopLevelIrp((PIRP)FSRTL_CACHE_TOP_LEVEL_IRP);
}
@ -194,8 +216,9 @@ VOID FspReleaseFromLazyWrite(
FSP_FILE_NODE *FileNode = Context;
ASSERT((PIRP)FSRTL_CACHE_TOP_LEVEL_IRP == IoGetTopLevelIrp());
ASSERT(PsGetCurrentThread() == FileNode->Tls.LazyWriteThread);
IoSetTopLevelIrp(0);
FileNode->LazyWriteThread = 0;
FileNode->Tls.LazyWriteThread = 0;
FspFileNodeRelease(FileNode, Full);
FSP_LEAVE_VOID("Context=%p", Context);

View File

@ -793,7 +793,11 @@ typedef struct
UINT64 Security;
ULONG SecurityChangeNumber;
BOOLEAN TruncateOnClose;
PVOID LazyWriteThread;
union
{
PVOID LazyWriteThread;
UINT32 TopFlags;
} Tls;
/* read-only after creation (and insertion in the ContextTable) */
PDEVICE_OBJECT FsvolDeviceObject;
UINT64 UserContext;

View File

@ -64,15 +64,19 @@ VOID FspFileDescDelete(FSP_FILE_DESC *FileDesc);
#define FSP_FILE_NODE_GET_FLAGS() \
PIRP Irp = IoGetTopLevelIrp(); \
BOOLEAN IrpValid = (PIRP)FSRTL_MAX_TOP_LEVEL_IRP_FLAG < Irp &&\
IO_TYPE_IRP == Irp->Type;\
IO_TYPE_IRP == Irp->Type; \
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() \
if (IrpValid) \
FspIrpSetFlags(Irp, FspIrpFlags(Irp) | Flags);
FspIrpSetFlags(Irp, FspIrpFlags(Irp) | Flags)
#define FSP_FILE_NODE_CLR_FLAGS() \
if (IrpValid) \
FspIrpSetFlags(Irp, FspIrpFlags(Irp) & (~Flags & 3));
FspIrpSetFlags(Irp, FspIrpFlags(Irp) & (~Flags & 3))
NTSTATUS FspFileNodeCreate(PDEVICE_OBJECT DeviceObject,
ULONG ExtraSize, FSP_FILE_NODE **PFileNode)
@ -145,6 +149,7 @@ VOID FspFileNodeAcquireSharedF(FSP_FILE_NODE *FileNode, ULONG Flags)
PAGED_CODE();
FSP_FILE_NODE_GET_FLAGS();
FSP_FILE_NODE_ASSERT_FLAGS_CLR();
if (Flags & FspFileNodeAcquireMain)
ExAcquireResourceSharedLite(FileNode->Header.Resource, TRUE);
@ -160,6 +165,7 @@ BOOLEAN FspFileNodeTryAcquireSharedF(FSP_FILE_NODE *FileNode, ULONG Flags, BOOLE
PAGED_CODE();
FSP_FILE_NODE_GET_FLAGS();
FSP_FILE_NODE_ASSERT_FLAGS_CLR();
BOOLEAN Result = TRUE;
@ -192,6 +198,7 @@ VOID FspFileNodeAcquireExclusiveF(FSP_FILE_NODE *FileNode, ULONG Flags)
PAGED_CODE();
FSP_FILE_NODE_GET_FLAGS();
FSP_FILE_NODE_ASSERT_FLAGS_CLR();
if (Flags & FspFileNodeAcquireMain)
ExAcquireResourceExclusiveLite(FileNode->Header.Resource, TRUE);
@ -207,6 +214,7 @@ BOOLEAN FspFileNodeTryAcquireExclusiveF(FSP_FILE_NODE *FileNode, ULONG Flags, BO
PAGED_CODE();
FSP_FILE_NODE_GET_FLAGS();
FSP_FILE_NODE_ASSERT_FLAGS_CLR();
BOOLEAN Result = TRUE;
@ -254,6 +262,7 @@ VOID FspFileNodeReleaseF(FSP_FILE_NODE *FileNode, ULONG Flags)
PAGED_CODE();
FSP_FILE_NODE_GET_FLAGS();
FSP_FILE_NODE_ASSERT_FLAGS_SET();
if (Flags & FspFileNodeAcquirePgio)
ExReleaseResourceLite(FileNode->Header.PagingIoResource);
@ -269,6 +278,7 @@ VOID FspFileNodeReleaseOwnerF(FSP_FILE_NODE *FileNode, ULONG Flags, PVOID Owner)
PAGED_CODE();
FSP_FILE_NODE_GET_FLAGS();
FSP_FILE_NODE_ASSERT_FLAGS_SET();
Owner = (PVOID)((UINT_PTR)Owner | 3);

View File

@ -285,7 +285,7 @@ static NTSTATUS FspFsvolWriteNonCached(
/* if we are called by the lazy writer we must constrain writes */
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(FspTimeoutInfinity32 ==