sys: fsctl: oplock fixes

This commit is contained in:
Bill Zissimopoulos 2016-11-20 15:27:24 -08:00
parent ce551d4e0d
commit 127d4cc4eb
4 changed files with 18 additions and 43 deletions

View File

@ -1451,7 +1451,7 @@ static BOOLEAN FspFsvolCreateOpenOrOverwriteOplock(PIRP Irp, const FSP_FSCTL_TRA
if (STATUS_SUCCESS == Result && if (STATUS_SUCCESS == Result &&
FlagOn(IrpSp->Parameters.Create.Options, FILE_OPEN_REQUIRING_OPLOCK)) FlagOn(IrpSp->Parameters.Create.Options, FILE_OPEN_REQUIRING_OPLOCK))
{ {
Result = FspOplockFsctrlCreate(FspFileNodeAddrOfOplock(FileNode), Irp, OplockCount); Result = FspFileNodeOplockFsctl(FileNode, Irp, OplockCount);
ASSERT(STATUS_PENDING != Result); ASSERT(STATUS_PENDING != Result);
if (STATUS_SUCCESS == Result) if (STATUS_SUCCESS == Result)

View File

@ -537,11 +537,10 @@ NTSTATUS FspCheckOplockEx(
PVOID Context, PVOID Context,
POPLOCK_WAIT_COMPLETE_ROUTINE CompletionRoutine, POPLOCK_WAIT_COMPLETE_ROUTINE CompletionRoutine,
POPLOCK_FS_PREPOST_IRP PostIrpRoutine); POPLOCK_FS_PREPOST_IRP PostIrpRoutine);
NTSTATUS FspOplockFsctrlF( NTSTATUS FspOplockFsctrl(
POPLOCK Oplock, POPLOCK Oplock,
PIRP Irp, PIRP Irp,
ULONG OpenCount, ULONG OpenCount);
BOOLEAN Create);
#define FspNotifyUninitializeSync(NS)\ #define FspNotifyUninitializeSync(NS)\
FsRtlNotifyUninitializeSync(NS) FsRtlNotifyUninitializeSync(NS)
#define FspNotifyCleanupAll(NS, NL)\ #define FspNotifyCleanupAll(NS, NL)\
@ -554,10 +553,6 @@ NTSTATUS FspOplockFsctrlF(
FspNotifyFullChangeDirectory(NS, NL, FC, 0, 0, FALSE, 0, 0, 0, 0) FspNotifyFullChangeDirectory(NS, NL, FC, 0, 0, FALSE, 0, 0, 0, 0)
#define FspNotifyReportChange(NS, NL, FN, FO, NP, F, A)\ #define FspNotifyReportChange(NS, NL, FN, FO, NP, F, A)\
FspNotifyFullReportChange(NS, NL, (PSTRING)(FN), FO, 0, (PSTRING)(NP), F, A, 0) FspNotifyFullReportChange(NS, NL, (PSTRING)(FN), FO, 0, (PSTRING)(NP), F, A, 0)
#define FspOplockFsctrlCreate(OL, I, OC)\
FspOplockFsctrlF(OL, I, OC, TRUE)
#define FspOplockFsctrl(OL, I, OC)\
FspOplockFsctrlF(OL, I, OC, FALSE)
/* utility: synchronous work queue */ /* utility: synchronous work queue */
typedef struct typedef struct
@ -1242,6 +1237,11 @@ typedef struct
PVOID PrepareContext; PVOID PrepareContext;
} FSP_FILE_NODE_OPLOCK_CONTEXT; } FSP_FILE_NODE_OPLOCK_CONTEXT;
static inline static inline
NTSTATUS FspFileNodeOplockFsctl(FSP_FILE_NODE *FileNode, PIRP Irp, ULONG OpenCount)
{
return FspOplockFsctrl(FspFileNodeAddrOfOplock(FileNode), Irp, OpenCount);
}
static inline
BOOLEAN FspFileNodeOplockIsBatch(FSP_FILE_NODE *FileNode) BOOLEAN FspFileNodeOplockIsBatch(FSP_FILE_NODE *FileNode)
{ {
return FsRtlCurrentBatchOplock(FspFileNodeAddrOfOplock(FileNode)); return FsRtlCurrentBatchOplock(FspFileNodeAddrOfOplock(FileNode));

View File

@ -432,30 +432,18 @@ static NTSTATUS FspFsvolFileSystemControlOplock(
} }
/* /*
* It is possible for FspOplockFsctrl to complete the IRP immediately. * FspOplockFsctrl takes ownership of the IRP under all circumstances.
* In this case trying to access the IRP (to get its IrpFlags) in FspFileNodeRelease
* can lead to a bugcheck. For this reason we set the TopLevelIrp to NULL here.
* *
* FspFsvolFileSystemControlOplock does not need the TopLevelIrp functionality, * We mark the IRP pending so that we can safely return STATUS_PENDING.
* because it cannot be used recursively (I believe -- famous last words).
*/ */
PIRP TopLevelIrp = IoGetTopLevelIrp();
IoSetTopLevelIrp(0); IoSetTopLevelIrp(0);
Result = FspOplockFsctrl(FspFileNodeAddrOfOplock(FileNode), Irp, OplockCount); IoMarkIrpPending(Irp);
Result = FspFileNodeOplockFsctl(FileNode, Irp, OplockCount);
FspFileNodeRelease(FileNode, Main); FspFileNodeRelease(FileNode, Main);
if (!NT_SUCCESS(Result))
{
/* set back the top level IRP just in case! */
IoSetTopLevelIrp(TopLevelIrp);
FspIrpHookReset(Irp);
FspFree(CompletionContext);
return Result;
}
return STATUS_PENDING; return STATUS_PENDING;
unlock_exit: unlock_exit:

View File

@ -87,11 +87,10 @@ NTSTATUS FspCheckOplockEx(
PVOID Context, PVOID Context,
POPLOCK_WAIT_COMPLETE_ROUTINE CompletionRoutine, POPLOCK_WAIT_COMPLETE_ROUTINE CompletionRoutine,
POPLOCK_FS_PREPOST_IRP PostIrpRoutine); POPLOCK_FS_PREPOST_IRP PostIrpRoutine);
NTSTATUS FspOplockFsctrlF( NTSTATUS FspOplockFsctrl(
POPLOCK Oplock, POPLOCK Oplock,
PIRP Irp, PIRP Irp,
ULONG OpenCount, ULONG OpenCount);
BOOLEAN Create);
VOID FspInitializeSynchronousWorkItem(FSP_SYNCHRONOUS_WORK_ITEM *SynchronousWorkItem, VOID FspInitializeSynchronousWorkItem(FSP_SYNCHRONOUS_WORK_ITEM *SynchronousWorkItem,
PWORKER_THREAD_ROUTINE Routine, PVOID Context); PWORKER_THREAD_ROUTINE Routine, PVOID Context);
VOID FspExecuteSynchronousWorkItem(FSP_SYNCHRONOUS_WORK_ITEM *SynchronousWorkItem); VOID FspExecuteSynchronousWorkItem(FSP_SYNCHRONOUS_WORK_ITEM *SynchronousWorkItem);
@ -132,7 +131,7 @@ NTSTATUS FspIrpHookNext(PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context);
#pragma alloc_text(PAGE, FspOplockBreakH) #pragma alloc_text(PAGE, FspOplockBreakH)
#pragma alloc_text(PAGE, FspCheckOplock) #pragma alloc_text(PAGE, FspCheckOplock)
#pragma alloc_text(PAGE, FspCheckOplockEx) #pragma alloc_text(PAGE, FspCheckOplockEx)
#pragma alloc_text(PAGE, FspOplockFsctrlF) #pragma alloc_text(PAGE, FspOplockFsctrl)
#pragma alloc_text(PAGE, FspInitializeSynchronousWorkItem) #pragma alloc_text(PAGE, FspInitializeSynchronousWorkItem)
#pragma alloc_text(PAGE, FspExecuteSynchronousWorkItem) #pragma alloc_text(PAGE, FspExecuteSynchronousWorkItem)
#pragma alloc_text(PAGE, FspExecuteSynchronousWorkItemRoutine) #pragma alloc_text(PAGE, FspExecuteSynchronousWorkItemRoutine)
@ -757,11 +756,10 @@ NTSTATUS FspCheckOplockEx(
return Result; return Result;
} }
NTSTATUS FspOplockFsctrlF( NTSTATUS FspOplockFsctrl(
POPLOCK Oplock, POPLOCK Oplock,
PIRP Irp, PIRP Irp,
ULONG OpenCount, ULONG OpenCount)
BOOLEAN Create)
{ {
PAGED_CODE(); PAGED_CODE();
@ -769,21 +767,10 @@ NTSTATUS FspOplockFsctrlF(
try try
{ {
ASSERT(
(Create && IRP_MJ_CREATE == IoGetCurrentIrpStackLocation(Irp)->MajorFunction) ||
(!Create && IRP_MJ_FILE_SYSTEM_CONTROL == IoGetCurrentIrpStackLocation(Irp)->MajorFunction));
Result = FsRtlOplockFsctrl( Result = FsRtlOplockFsctrl(
Oplock, Oplock,
Irp, Irp,
OpenCount); OpenCount);
/*
* When the IRP is IRP_MJ_FILE_SYSTEM_CONTROL, FsRtlOplockFsctrl always takes ownership
* of the IRP (unless it raises). So return STATUS_SUCCESS in that case.
*/
if (!Create)
Result = STATUS_SUCCESS;
} }
except (EXCEPTION_EXECUTE_HANDLER) except (EXCEPTION_EXECUTE_HANDLER)
{ {