sys: oplock: refactoring/cleanup

This commit is contained in:
Bill Zissimopoulos 2016-11-20 14:08:23 -08:00
parent 53f60a698a
commit ce551d4e0d
10 changed files with 169 additions and 86 deletions

View File

@ -176,7 +176,7 @@ static VOID FspFsvolCleanupRequestFini(FSP_FSCTL_TRANSACT_REQ *Request, PVOID Co
FspFileNodeCleanupComplete(FileNode, FileObject);
if (!FileNode->IsDirectory)
FspCheckOplock(FspFileNodeAddrOfOplock(FileNode), Irp, 0, 0, 0);
FspFileNodeOplockCheck(FileNode, Irp);
SetFlag(FileObject->Flags, FO_CLEANUP_COMPLETE);
MainFileHandle = FileDesc->MainFileHandle;

View File

@ -595,7 +595,9 @@ NTSTATUS FspFsvolCreatePrepare(
FspFsvolCreateOpenOrOverwriteOplock(Irp, 0, &Result);
if (!Success)
{
if (!NT_SUCCESS(Result) || STATUS_PENDING == Result)
if (STATUS_PENDING == Result)
return Result;
if (!NT_SUCCESS(Result))
{
FspFileNodeRelease(FileNode, Full);
return Result;
@ -1047,7 +1049,9 @@ static NTSTATUS FspFsvolCreateTryOpen(PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Re
FspFsvolCreateOpenOrOverwriteOplock(Irp, Response, &Result);
if (!Success)
{
if (!NT_SUCCESS(Result) || STATUS_PENDING == Result)
if (STATUS_PENDING == Result)
return Result;
if (!NT_SUCCESS(Result))
{
FspFileNodeRelease(FileNode, Main);
return Result;
@ -1191,8 +1195,8 @@ static VOID FspFsvolCreateTryOpenRequestFini(FSP_FSCTL_TRANSACT_REQ *Request, PV
if (OplockIrp)
{
ASSERT(IO_TYPE_IRP == OplockIrp->Type);
FspCheckOplockEx(FspFileNodeAddrOfOplock(FileDesc->FileNode), OplockIrp,
OPLOCK_FLAG_BACK_OUT_ATOMIC_OPLOCK, 0, 0, 0);
FspFileNodeOplockCheckEx(FileDesc->FileNode, OplockIrp,
OPLOCK_FLAG_BACK_OUT_ATOMIC_OPLOCK);
}
FspFsvolCreatePostClose(FileDesc);
@ -1227,8 +1231,8 @@ static VOID FspFsvolCreateOverwriteRequestFini(FSP_FSCTL_TRANSACT_REQ *Request,
if (OplockIrp)
{
ASSERT(IO_TYPE_IRP == OplockIrp->Type);
FspCheckOplockEx(FspFileNodeAddrOfOplock(FileDesc->FileNode), OplockIrp,
OPLOCK_FLAG_BACK_OUT_ATOMIC_OPLOCK, 0, 0, 0);
FspFileNodeOplockCheckEx(FileDesc->FileNode, OplockIrp,
OPLOCK_FLAG_BACK_OUT_ATOMIC_OPLOCK);
}
FspFileNodeClose(FileDesc->FileNode, FileObject, TRUE);
@ -1299,9 +1303,9 @@ static NTSTATUS FspFsvolCreateSharingViolationOplock(
Success = DEBUGTEST(90) &&
!(FspFileNodeSharingViolationMainFile == SharingViolationReason) &&
!(FspFileNodeSharingViolationStream == SharingViolationReason) &&
!(FsRtlCurrentBatchOplock(FspFileNodeAddrOfOplock(ExtraFileNode))) &&
!(FspFileNodeOplockIsBatch(ExtraFileNode)) &&
!(!FlagOn(IrpSp->Parameters.Create.Options, FILE_COMPLETE_IF_OPLOCKED) &&
FsRtlCurrentOplockH(FspFileNodeAddrOfOplock(ExtraFileNode)));
FspFileNodeOplockIsHandle(ExtraFileNode));
FspFileNodeRelease(ExtraFileNode, Main);
@ -1354,11 +1358,10 @@ static NTSTATUS FspFsvolCreateSharingViolationOplock(
Result = STATUS_SHARING_VIOLATION;
}
else
if (FsRtlCurrentBatchOplock(FspFileNodeAddrOfOplock(ExtraFileNode)))
if (FspFileNodeOplockIsBatch(ExtraFileNode))
{
/* wait for Batch oplock break to complete */
Result = FspCheckOplock(FspFileNodeAddrOfOplock(ExtraFileNode), Irp,
0, 0, 0);
Result = FspFileNodeOplockCheck(ExtraFileNode, Irp);
if (STATUS_SUCCESS != Result)
Result = STATUS_SHARING_VIOLATION;
else
@ -1366,11 +1369,10 @@ static NTSTATUS FspFsvolCreateSharingViolationOplock(
}
else
if (!FlagOn(IrpSp->Parameters.Create.Options, FILE_COMPLETE_IF_OPLOCKED) &&
FsRtlCurrentOplockH(FspFileNodeAddrOfOplock(ExtraFileNode)))
FspFileNodeOplockIsHandle(ExtraFileNode))
{
/* wait for Handle oplock break to complete */
Result = FspOplockBreakH(FspFileNodeAddrOfOplock(ExtraFileNode), Irp,
0, 0, 0, 0);
Result = FspFileNodeOplockBreakHandle(ExtraFileNode, Irp, 0);
ASSERT(STATUS_OPLOCK_BREAK_IN_PROGRESS != Result);
if (STATUS_SUCCESS != Result)
Result = STATUS_SHARING_VIOLATION;
@ -1406,16 +1408,17 @@ static BOOLEAN FspFsvolCreateOpenOrOverwriteOplock(PIRP Irp, const FSP_FSCTL_TRA
PDEVICE_OBJECT FsvolDeviceObject = IrpSp->DeviceObject;
PFILE_OBJECT FileObject = IrpSp->FileObject;
FSP_FILE_NODE *FileNode = FileObject->FsContext;
UINT32 RequestKind = FspIrpRequest(Irp)->Kind;
ULONG OplockCount = 0;
NTSTATUS Result;
ASSERT(
FspFsctlTransactReservedKind == FspIrpRequest(Irp)->Kind ||
FspFsctlTransactOverwriteKind == FspIrpRequest(Irp)->Kind);
FspFsctlTransactReservedKind == RequestKind ||
FspFsctlTransactOverwriteKind == RequestKind);
/* add oplock key to the file object */
Result = FspCheckOplockEx(FspFileNodeAddrOfOplock(FileNode), Irp,
OPLOCK_FLAG_OPLOCK_KEY_CHECK_ONLY, 0, 0, 0);
Result = FspFileNodeOplockCheckEx(FileNode, Irp,
OPLOCK_FLAG_OPLOCK_KEY_CHECK_ONLY);
if (!NT_SUCCESS(Result))
{
*PResult = Result;
@ -1430,8 +1433,11 @@ static BOOLEAN FspFsvolCreateOpenOrOverwriteOplock(PIRP Irp, const FSP_FSCTL_TRA
/* if there are more than one handles, perform oplock check */
if (1 < OplockCount)
{
Result = FspCheckOplock(FspFileNodeAddrOfOplock(FileNode), Irp,
Result = FspFileNodeOplockCheckAsyncEx(
FileNode,
FspFsctlTransactReservedKind == RequestKind ? FspFileNodeAcquireMain : FspFileNodeAcquireFull,
(PVOID)Response,
Irp,
FspFsvolCreateOpenOrOverwriteOplockComplete,
FspFsvolCreateOpenOrOverwriteOplockPrepare);
if (STATUS_PENDING == Result)
@ -1462,8 +1468,10 @@ static VOID FspFsvolCreateOpenOrOverwriteOplockPrepare(
{
PAGED_CODE();
if (0 != Context)
FspIopSetIrpResponse(Irp, Context);
FSP_FSCTL_TRANSACT_RSP *Response = FspFileNodeReleaseForOplock(Context);
if (0 != Response)
FspIopSetIrpResponse(Irp, Response);
}
static VOID FspFsvolCreateOpenOrOverwriteOplockComplete(

View File

@ -799,8 +799,6 @@ NTSTATUS FspWqCreateAndPostIrpWorkItem(PIRP Irp,
FSP_IOP_REQUEST_WORK *WorkRoutine, FSP_IOP_REQUEST_FINI *RequestFini,
BOOLEAN CreateAndPost);
VOID FspWqPostIrpWorkItem(PIRP Irp);
VOID FspWqOplockPrepare(PVOID Context, PIRP Irp);
VOID FspWqOplockComplete(PVOID Context, PIRP Irp);
#define FspWqCreateIrpWorkItem(I, RW, RF)\
FspWqCreateAndPostIrpWorkItem(I, RW, RF, FALSE)
#define FspWqRepostIrpWorkItem(I, RW, RF)\
@ -1236,6 +1234,68 @@ BOOLEAN FspMainFileOpenCheck(PIRP Irp)
#define FspFileNodeAddrOfOplock(N) (&(N)->Header.Oplock)
#endif
/* oplock support */
typedef struct
{
FSP_FILE_NODE *FileNode;
ULONG AcquireFlags;
PVOID PrepareContext;
} FSP_FILE_NODE_OPLOCK_CONTEXT;
static inline
BOOLEAN FspFileNodeOplockIsBatch(FSP_FILE_NODE *FileNode)
{
return FsRtlCurrentBatchOplock(FspFileNodeAddrOfOplock(FileNode));
}
static inline
BOOLEAN FspFileNodeOplockIsHandle(FSP_FILE_NODE *FileNode)
{
return FsRtlCurrentOplockH(FspFileNodeAddrOfOplock(FileNode));
}
static inline
NTSTATUS FspFileNodeOplockCheck(FSP_FILE_NODE *FileNode, PIRP Irp)
{
return FspCheckOplock(FspFileNodeAddrOfOplock(FileNode), Irp, 0, 0, 0);
}
static inline
NTSTATUS FspFileNodeOplockCheckEx(FSP_FILE_NODE *FileNode, PIRP Irp, ULONG Flags)
{
return FspCheckOplockEx(FspFileNodeAddrOfOplock(FileNode), Irp, Flags, 0, 0, 0);
}
static inline
NTSTATUS FspFileNodeOplockBreakHandle(FSP_FILE_NODE *FileNode, PIRP Irp, ULONG Flags)
{
return FspOplockBreakH(FspFileNodeAddrOfOplock(FileNode), Irp, Flags, 0, 0, 0);
}
static inline
NTSTATUS FspFileNodeOplockCheckAsyncEx(
FSP_FILE_NODE *FileNode, ULONG AcquireFlags, PVOID PrepareContext,
PIRP Irp,
POPLOCK_WAIT_COMPLETE_ROUTINE CompletionRoutine,
POPLOCK_FS_PREPOST_IRP PostIrpRoutine)
{
FSP_FILE_NODE_OPLOCK_CONTEXT OplockContext;
OplockContext.FileNode = FileNode;
OplockContext.AcquireFlags = AcquireFlags;
OplockContext.PrepareContext = PrepareContext;
return FspCheckOplock(
FspFileNodeAddrOfOplock(FileNode),
Irp,
&OplockContext,
CompletionRoutine,
PostIrpRoutine);
}
static inline
PVOID FspFileNodeReleaseForOplock(FSP_FILE_NODE_OPLOCK_CONTEXT *OplockContext)
{
FspFileNodeReleaseF(OplockContext->FileNode, OplockContext->AcquireFlags);
return OplockContext->PrepareContext;
}
VOID FspFileNodeOplockPrepare(PVOID Context, PIRP Irp);
VOID FspFileNodeOplockComplete(PVOID Context, PIRP Irp);
#define FspFileNodeOplockCheckAsync(FileNode, AcquireFlags, PrepareContext, Irp)\
FspFileNodeOplockCheckAsyncEx(FileNode, AcquireFlags, (PVOID)(UINT_PTR)PrepareContext, Irp,\
FspFileNodeOplockComplete,FspFileNodeOplockPrepare)
/* multiversion support */
typedef
NTKERNELAPI

View File

@ -952,20 +952,18 @@ NTSTATUS FspFileNodeCheckBatchOplocksOnAllStreams(
{
DescendantFileNode = DescendantFileNodes[DescendantFileNodeIndex];
if (FsRtlCurrentBatchOplock(FspFileNodeAddrOfOplock(DescendantFileNode)))
if (FspFileNodeOplockIsBatch(DescendantFileNode))
{
NTSTATUS Result0 = FspCheckOplock(FspFileNodeAddrOfOplock(DescendantFileNode), OplockIrp,
0, 0, 0);
NTSTATUS Result0 = FspFileNodeOplockCheck(DescendantFileNode, OplockIrp);
if (STATUS_SUCCESS != Result0)
Result = STATUS_SHARING_VIOLATION;
else
OplockIrp->IoStatus.Information = FILE_OPBATCH_BREAK_UNDERWAY;
}
else
if (FsRtlCurrentOplockH(FspFileNodeAddrOfOplock(DescendantFileNode)))
if (FspFileNodeOplockIsHandle(DescendantFileNode))
{
NTSTATUS Result0 = FspOplockBreakH(FspFileNodeAddrOfOplock(DescendantFileNode), OplockIrp,
0, 0, 0, 0);
NTSTATUS Result0 = FspFileNodeOplockBreakHandle(DescendantFileNode, OplockIrp, 0);
ASSERT(STATUS_OPLOCK_BREAK_IN_PROGRESS != Result0);
if (STATUS_SUCCESS != Result0)
Result = STATUS_SHARING_VIOLATION;
@ -1118,9 +1116,9 @@ BOOLEAN FspFileNodeRenameCheck(PDEVICE_OBJECT FsvolDeviceObject, PIRP OplockIrp,
DescendantFileNode = (PVOID)((UINT_PTR)DescendantFileNode & ~1);
if (HasOpenHandles)
if (FsRtlCurrentBatchOplock(FspFileNodeAddrOfOplock(DescendantFileNode)) ||
FsRtlCurrentOplockH(FspFileNodeAddrOfOplock(DescendantFileNode)))
FspCheckOplock(FspFileNodeAddrOfOplock(DescendantFileNode), OplockIrp, 0, 0, 0);
if (FspFileNodeOplockIsBatch(DescendantFileNode) ||
FspFileNodeOplockIsHandle(DescendantFileNode))
FspFileNodeOplockCheck(DescendantFileNode, OplockIrp);
}
FspFsvolDeviceLockContextTable(FsvolDeviceObject);
@ -1978,6 +1976,36 @@ NTSTATUS FspMainFileClose(
return Result;
}
VOID FspFileNodeOplockPrepare(PVOID Context, PIRP Irp)
{
PAGED_CODE();
FSP_IOP_REQUEST_WORK *WorkRoutine = (FSP_IOP_REQUEST_WORK *)(UINT_PTR)
FspFileNodeReleaseForOplock(Context);
NTSTATUS Result;
FSP_FSCTL_STATIC_ASSERT(sizeof(PVOID) == sizeof(VOID (*)(VOID)),
"Data and code pointers must have same size!");
Result = FspWqCreateIrpWorkItem(Irp, WorkRoutine, 0);
if (!NT_SUCCESS(Result))
/*
* Only way to communicate failure is through ExRaiseStatus.
* We will catch it in FspCheckOplock, etc.
*/
ExRaiseStatus(Result);
}
VOID FspFileNodeOplockComplete(PVOID Context, PIRP Irp)
{
PAGED_CODE();
if (STATUS_SUCCESS == Irp->IoStatus.Status)
FspWqPostIrpWorkItem(Irp);
else
FspIopCompleteIrp(Irp, Irp->IoStatus.Status);
}
WCHAR FspFileDescDirectoryPatternMatchAll[] = L"*";
// {904862B4-EB3F-461E-ACB2-4DF2B3FC898B}

View File

@ -1067,13 +1067,13 @@ retry:
* If that is the case we release the FileNode and wait for the oplock breaks
* to complete. Once they are complete we retry the whole thing.
*/
Result = FspCheckOplockEx(FspFileNodeAddrOfOplock(FileNode), Irp,
OPLOCK_FLAG_COMPLETE_IF_OPLOCKED, 0, 0, 0);
Result = FspFileNodeOplockCheckEx(FileNode, Irp,
OPLOCK_FLAG_COMPLETE_IF_OPLOCKED);
if (STATUS_OPLOCK_BREAK_IN_PROGRESS == Result ||
DEBUGTEST_EX(NT_SUCCESS(Result), 10, FALSE))
{
FspFileNodeRelease(FileNode, Full);
Result = FspCheckOplock(FspFileNodeAddrOfOplock(FileNode), Irp, 0, 0, 0);
Result = FspFileNodeOplockCheck(FileNode, Irp);
if (!NT_SUCCESS(Result))
return Result;
goto retry;
@ -1202,14 +1202,14 @@ retry:
* If that is the case we release the FileNode and wait for the oplock breaks
* to complete. Once they are complete we retry the whole thing.
*/
Result = FspCheckOplockEx(FspFileNodeAddrOfOplock(FileNode), Irp,
OPLOCK_FLAG_COMPLETE_IF_OPLOCKED, 0, 0, 0);
Result = FspFileNodeOplockCheckEx(FileNode, Irp,
OPLOCK_FLAG_COMPLETE_IF_OPLOCKED);
if (STATUS_OPLOCK_BREAK_IN_PROGRESS == Result ||
DEBUGTEST_EX(NT_SUCCESS(Result), 10, FALSE))
{
FspFileNodeRelease(FileNode, Full);
FspFsvolDeviceFileRenameRelease(FsvolDeviceObject);
Result = FspCheckOplock(FspFileNodeAddrOfOplock(FileNode), Irp, 0, 0, 0);
Result = FspFileNodeOplockCheck(FileNode, Irp);
if (!NT_SUCCESS(Result))
return Result;
goto retry;
@ -1425,13 +1425,13 @@ retry:
* If that is the case we release the FileNode and wait for the oplock breaks
* to complete. Once they are complete we retry the whole thing.
*/
Result = FspCheckOplockEx(FspFileNodeAddrOfOplock(FileNode), Irp,
OPLOCK_FLAG_COMPLETE_IF_OPLOCKED, 0, 0, 0);
Result = FspFileNodeOplockCheckEx(FileNode, Irp,
OPLOCK_FLAG_COMPLETE_IF_OPLOCKED);
if (STATUS_OPLOCK_BREAK_IN_PROGRESS == Result ||
DEBUGTEST_EX(NT_SUCCESS(Result), 10, FALSE))
{
FspFileNodeRelease(FileNode, Full);
Result = FspCheckOplock(FspFileNodeAddrOfOplock(FileNode), Irp, 0, 0, 0);
Result = FspFileNodeOplockCheck(FileNode, Irp);
if (!NT_SUCCESS(Result))
return Result;
goto retry;

View File

@ -50,9 +50,12 @@ static NTSTATUS FspFsvolLockControlRetry(
return FspWqRepostIrpWorkItem(Irp, FspFsvolLockControlRetry, 0);
/* perform oplock check; we are only implementing Win7 behavior */
Result = FspCheckOplock(FspFileNodeAddrOfOplock(FileNode), Irp,
(PVOID)(UINT_PTR)FspFsvolLockControlRetry, FspWqOplockComplete, FspWqOplockPrepare);
if (!NT_SUCCESS(Result) || STATUS_PENDING == Result)
Result = FspFileNodeOplockCheckAsync(
FileNode, FspFileNodeAcquireMain, FspFsvolLockControlRetry,
Irp);
if (STATUS_PENDING == Result)
return Result;
if (!NT_SUCCESS(Result))
{
FspFileNodeRelease(FileNode, Main);
return Result;

View File

@ -117,9 +117,12 @@ static NTSTATUS FspFsvolReadCached(
return FspWqRepostIrpWorkItem(Irp, FspFsvolReadCached, 0);
/* perform oplock check */
Result = FspCheckOplock(FspFileNodeAddrOfOplock(FileNode), Irp,
(PVOID)(UINT_PTR)FspFsvolReadCached, FspWqOplockComplete, FspWqOplockPrepare);
if (!NT_SUCCESS(Result) || STATUS_PENDING == Result)
Result = FspFileNodeOplockCheckAsync(
FileNode, FspFileNodeAcquireMain, FspFsvolReadCached,
Irp);
if (STATUS_PENDING == Result)
return Result;
if (!NT_SUCCESS(Result))
{
FspFileNodeRelease(FileNode, Main);
return Result;
@ -248,9 +251,12 @@ static NTSTATUS FspFsvolReadNonCached(
/* perform oplock check */
if (!PagingIo)
{
Result = FspCheckOplock(FspFileNodeAddrOfOplock(FileNode), Irp,
(PVOID)(UINT_PTR)FspFsvolReadNonCached, FspWqOplockComplete, FspWqOplockPrepare);
if (!NT_SUCCESS(Result) || STATUS_PENDING == Result)
Result = FspFileNodeOplockCheckAsync(
FileNode, FspFileNodeAcquireFull, FspFsvolReadNonCached,
Irp);
if (STATUS_PENDING == Result)
return Result;
if (!NT_SUCCESS(Result))
{
FspFileNodeRelease(FileNode, Full);
return Result;

View File

@ -683,7 +683,7 @@ NTSTATUS FspOplockBreakH(
try
{
Result = FspOplockBreakH(
Result = FsRtlOplockBreakH(
Oplock,
Irp,
Flags,

View File

@ -173,31 +173,3 @@ static VOID FspWqWorkRoutine(PVOID Context)
IoSetTopLevelIrp(0);
}
VOID FspWqOplockPrepare(PVOID Context, PIRP Irp)
{
PAGED_CODE();
NTSTATUS Result;
FSP_FSCTL_STATIC_ASSERT(sizeof(PVOID) == sizeof(VOID (*)(VOID)),
"Data and code pointers must have same size!");
Result = FspWqCreateAndPostIrpWorkItem(Irp, (FSP_IOP_REQUEST_WORK *)(UINT_PTR)Context, 0, TRUE);
if (!NT_SUCCESS(Result))
/*
* Only way to communicate failure is through ExRaiseStatus.
* We will catch it in FspCheckOplock, etc.
*/
ExRaiseStatus(Result);
}
VOID FspWqOplockComplete(PVOID Context, PIRP Irp)
{
PAGED_CODE();
if (STATUS_SUCCESS == Irp->IoStatus.Status)
FspWqPostIrpWorkItem(Irp);
else
FspIopCompleteIrp(Irp, Irp->IoStatus.Status);
}

View File

@ -141,9 +141,12 @@ static NTSTATUS FspFsvolWriteCached(
return FspWqRepostIrpWorkItem(Irp, FspFsvolWriteCached, 0);
/* perform oplock check */
Result = FspCheckOplock(FspFileNodeAddrOfOplock(FileNode), Irp,
(PVOID)(UINT_PTR)FspFsvolWriteCached, FspWqOplockComplete, FspWqOplockPrepare);
if (!NT_SUCCESS(Result) || STATUS_PENDING == Result)
Result = FspFileNodeOplockCheckAsync(
FileNode, FspFileNodeAcquireMain, FspFsvolWriteCached,
Irp);
if (STATUS_PENDING == Result)
return Result;
if (!NT_SUCCESS(Result))
{
FspFileNodeRelease(FileNode, Main);
return Result;
@ -318,9 +321,12 @@ static NTSTATUS FspFsvolWriteNonCached(
/* perform oplock check */
if (!PagingIo)
{
Result = FspCheckOplock(FspFileNodeAddrOfOplock(FileNode), Irp,
(PVOID)(UINT_PTR)FspFsvolWriteNonCached, FspWqOplockComplete, FspWqOplockPrepare);
if (!NT_SUCCESS(Result) || STATUS_PENDING == Result)
Result = FspFileNodeOplockCheckAsync(
FileNode, FspFileNodeAcquireFull, FspFsvolWriteNonCached,
Irp);
if (STATUS_PENDING == Result)
return Result;
if (!NT_SUCCESS(Result))
{
FspFileNodeRelease(FileNode, Full);
return Result;