mirror of
https://github.com/winfsp/winfsp.git
synced 2025-04-23 00:43:00 -05:00
sys: oplock: misc fixes and improvements
This commit is contained in:
parent
4294182c1a
commit
358db2a54f
105
src/sys/create.c
105
src/sys/create.c
@ -981,7 +981,7 @@ NTSTATUS FspFsvolCreateComplete(
|
|||||||
/* SUCCESS! */
|
/* SUCCESS! */
|
||||||
FspIopRequestContext(Request, RequestFileDesc) = 0;
|
FspIopRequestContext(Request, RequestFileDesc) = 0;
|
||||||
Irp->IoStatus.Information = Request->Req.Overwrite.Supersede ? FILE_SUPERSEDED : FILE_OVERWRITTEN;
|
Irp->IoStatus.Information = Request->Req.Overwrite.Supersede ? FILE_SUPERSEDED : FILE_OVERWRITTEN;
|
||||||
Result = STATUS_SUCCESS;
|
Result = Irp->IoStatus.Status; /* get success value from oplock processing */
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
ASSERT(0);
|
ASSERT(0);
|
||||||
@ -1054,6 +1054,7 @@ static NTSTATUS FspFsvolCreateTryOpen(PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Re
|
|||||||
FspFileNodeClose(FileNode, FileObject, TRUE);
|
FspFileNodeClose(FileNode, FileObject, TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Irp->IoStatus.Information = 0;
|
||||||
return DeleteOnClose ? STATUS_CANNOT_DELETE : STATUS_SHARING_VIOLATION;
|
return DeleteOnClose ? STATUS_CANNOT_DELETE : STATUS_SHARING_VIOLATION;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1068,7 +1069,7 @@ static NTSTATUS FspFsvolCreateTryOpen(PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Re
|
|||||||
/* SUCCESS! */
|
/* SUCCESS! */
|
||||||
FspIopRequestContext(Request, RequestFileDesc) = 0;
|
FspIopRequestContext(Request, RequestFileDesc) = 0;
|
||||||
Irp->IoStatus.Information = Response->IoStatus.Information;
|
Irp->IoStatus.Information = Response->IoStatus.Information;
|
||||||
return STATUS_SUCCESS;
|
return Irp->IoStatus.Status; /* get success value from oplock processing */
|
||||||
}
|
}
|
||||||
|
|
||||||
static VOID FspFsvolCreatePostClose(FSP_FILE_DESC *FileDesc)
|
static VOID FspFsvolCreatePostClose(FSP_FILE_DESC *FileDesc)
|
||||||
@ -1241,8 +1242,8 @@ static NTSTATUS FspFsvolCreateSharingViolationOplock(
|
|||||||
* the CanWait parameter is TRUE.
|
* the CanWait parameter is TRUE.
|
||||||
*
|
*
|
||||||
* When CanWait is TRUE the routine is free to wait for any oplocks breaks. We
|
* When CanWait is TRUE the routine is free to wait for any oplocks breaks. We
|
||||||
* try to break both batch and CACHE_HANDLE_LEVEL oplocks and return the
|
* try to break both Batch and Handle oplocks and return the appropriate status
|
||||||
* appropriate status code.
|
* code.
|
||||||
*
|
*
|
||||||
* We acquire the FileNode shared so allow oplock breaks to happen concurrently.
|
* We acquire the FileNode shared so allow oplock breaks to happen concurrently.
|
||||||
* See https://www.osronline.com/showthread.cfm?link=248984
|
* See https://www.osronline.com/showthread.cfm?link=248984
|
||||||
@ -1255,6 +1256,8 @@ static NTSTATUS FspFsvolCreateSharingViolationOplock(
|
|||||||
NTSTATUS Result;
|
NTSTATUS Result;
|
||||||
BOOLEAN Success;
|
BOOLEAN Success;
|
||||||
|
|
||||||
|
ASSERT(FspFsctlTransactCreateKind == Request->Kind);
|
||||||
|
|
||||||
Success = DEBUGTEST(90) &&
|
Success = DEBUGTEST(90) &&
|
||||||
FspFileNodeTryAcquireSharedF(ExtraFileNode, FspFileNodeAcquireMain, CanWait);
|
FspFileNodeTryAcquireSharedF(ExtraFileNode, FspFileNodeAcquireMain, CanWait);
|
||||||
if (!Success)
|
if (!Success)
|
||||||
@ -1264,13 +1267,13 @@ static NTSTATUS FspFsvolCreateSharingViolationOplock(
|
|||||||
if (!CanWait)
|
if (!CanWait)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* If there is no batch or CACHE_HANDLE_LEVEL oplock we are done;
|
* If there is no Batch or Handle oplock we are done; else retry in a
|
||||||
* else retry in a worker thread to break the oplocks.
|
* worker thread to break the oplocks.
|
||||||
*/
|
*/
|
||||||
Success = DEBUGTEST(90) &&
|
Success = DEBUGTEST(90) &&
|
||||||
(!FsRtlCurrentBatchOplock(FspFileNodeAddrOfOplock(ExtraFileNode)) &&
|
!FsRtlCurrentBatchOplock(FspFileNodeAddrOfOplock(ExtraFileNode)) &&
|
||||||
(FlagOn(IrpSp->Parameters.Create.Options, FILE_COMPLETE_IF_OPLOCKED) ||
|
!(!FlagOn(IrpSp->Parameters.Create.Options, FILE_COMPLETE_IF_OPLOCKED) &&
|
||||||
!FsRtlCurrentOplockH(FspFileNodeAddrOfOplock(ExtraFileNode))));
|
FsRtlCurrentOplockH(FspFileNodeAddrOfOplock(ExtraFileNode)));
|
||||||
|
|
||||||
FspFileNodeRelease(ExtraFileNode, Main);
|
FspFileNodeRelease(ExtraFileNode, Main);
|
||||||
|
|
||||||
@ -1283,44 +1286,36 @@ static NTSTATUS FspFsvolCreateSharingViolationOplock(
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
#if 0
|
|
||||||
/* ???: is this needed in this case? */
|
|
||||||
Result = FspCheckOplockEx(FspFileNodeAddrOfOplock(ExtraFileNode), Irp,
|
|
||||||
OPLOCK_FLAG_OPLOCK_KEY_CHECK_ONLY, 0, 0, 0);
|
|
||||||
if (!NT_SUCCESS(Result))
|
|
||||||
{
|
|
||||||
Result = STATUS_SHARING_VIOLATION;
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (FsRtlCurrentBatchOplock(FspFileNodeAddrOfOplock(ExtraFileNode)))
|
if (FsRtlCurrentBatchOplock(FspFileNodeAddrOfOplock(ExtraFileNode)))
|
||||||
{
|
{
|
||||||
/* wait for batch oplock break to complete */
|
/* wait for Batch oplock break to complete */
|
||||||
Result = FspCheckOplock(FspFileNodeAddrOfOplock(ExtraFileNode), Irp,
|
Result = FspCheckOplock(FspFileNodeAddrOfOplock(ExtraFileNode), Irp,
|
||||||
0, 0, 0);
|
0, 0, 0);
|
||||||
if (STATUS_SUCCESS == Result)
|
if (STATUS_SUCCESS == Result)
|
||||||
OpbatchBreakUnderway = TRUE;
|
OpbatchBreakUnderway = TRUE;
|
||||||
|
|
||||||
|
/* if a Batch oplock is broken, we still return STATUS_SHARING_VIOLATION */
|
||||||
|
Result = STATUS_SHARING_VIOLATION;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
Result = STATUS_SHARING_VIOLATION;
|
|
||||||
|
|
||||||
if (!FlagOn(IrpSp->Parameters.Create.Options, FILE_COMPLETE_IF_OPLOCKED) &&
|
if (!FlagOn(IrpSp->Parameters.Create.Options, FILE_COMPLETE_IF_OPLOCKED) &&
|
||||||
FsRtlCurrentOplockH(FspFileNodeAddrOfOplock(ExtraFileNode)))
|
FsRtlCurrentOplockH(FspFileNodeAddrOfOplock(ExtraFileNode)))
|
||||||
{
|
{
|
||||||
/* wait for CACHE_HANDLE_LEVEL oplock break to complete */
|
/* wait for Handle oplock break to complete */
|
||||||
Result = FspOplockBreakH(FspFileNodeAddrOfOplock(ExtraFileNode), Irp,
|
Result = FspOplockBreakH(FspFileNodeAddrOfOplock(ExtraFileNode), Irp,
|
||||||
0, 0, 0, 0);
|
0, 0, 0, 0);
|
||||||
}
|
ASSERT(STATUS_OPLOCK_BREAK_IN_PROGRESS != Result);
|
||||||
|
|
||||||
|
/* if a Handle oplock is broken, we can actually retry the sharing check */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Result = STATUS_SHARING_VIOLATION;
|
||||||
|
|
||||||
#if 0
|
|
||||||
exit:
|
|
||||||
#endif
|
|
||||||
FspFileNodeRelease(ExtraFileNode, Main);
|
FspFileNodeRelease(ExtraFileNode, Main);
|
||||||
|
|
||||||
Response = FspIopIrpResponse(Irp);
|
Response = FspIopIrpResponse(Irp);
|
||||||
|
|
||||||
if (NT_SUCCESS(Result))
|
if (STATUS_SUCCESS == Result)
|
||||||
{
|
{
|
||||||
FspFileNodeClose(ExtraFileNode, 0, TRUE);
|
FspFileNodeClose(ExtraFileNode, 0, TRUE);
|
||||||
FspFileNodeDereference(ExtraFileNode);
|
FspFileNodeDereference(ExtraFileNode);
|
||||||
@ -1348,10 +1343,14 @@ static BOOLEAN FspFsvolCreateOpenOrOverwriteOplock(PIRP Irp, const FSP_FSCTL_TRA
|
|||||||
PDEVICE_OBJECT FsvolDeviceObject = IrpSp->DeviceObject;
|
PDEVICE_OBJECT FsvolDeviceObject = IrpSp->DeviceObject;
|
||||||
PFILE_OBJECT FileObject = IrpSp->FileObject;
|
PFILE_OBJECT FileObject = IrpSp->FileObject;
|
||||||
FSP_FILE_NODE *FileNode = FileObject->FsContext;
|
FSP_FILE_NODE *FileNode = FileObject->FsContext;
|
||||||
BOOLEAN OpenRequiringOplock, CheckOplock;
|
|
||||||
ULONG OplockCount = 0;
|
ULONG OplockCount = 0;
|
||||||
NTSTATUS Result;
|
NTSTATUS Result;
|
||||||
|
|
||||||
|
ASSERT(
|
||||||
|
FspFsctlTransactReservedKind == FspIrpRequest(Irp)->Kind ||
|
||||||
|
FspFsctlTransactOverwriteKind == FspIrpRequest(Irp)->Kind);
|
||||||
|
|
||||||
|
/* add oplock key to the file object */
|
||||||
Result = FspCheckOplockEx(FspFileNodeAddrOfOplock(FileNode), Irp,
|
Result = FspCheckOplockEx(FspFileNodeAddrOfOplock(FileNode), Irp,
|
||||||
OPLOCK_FLAG_OPLOCK_KEY_CHECK_ONLY, 0, 0, 0);
|
OPLOCK_FLAG_OPLOCK_KEY_CHECK_ONLY, 0, 0, 0);
|
||||||
if (!NT_SUCCESS(Result))
|
if (!NT_SUCCESS(Result))
|
||||||
@ -1360,22 +1359,13 @@ static BOOLEAN FspFsvolCreateOpenOrOverwriteOplock(PIRP Irp, const FSP_FSCTL_TRA
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
OpenRequiringOplock = BooleanFlagOn(IrpSp->Parameters.Create.Options,
|
/* get current handle count */
|
||||||
FILE_OPEN_REQUIRING_OPLOCK);
|
FspFsvolDeviceLockContextTable(FsvolDeviceObject);
|
||||||
CheckOplock = FALSE;
|
OplockCount = FileNode->HandleCount;
|
||||||
|
FspFsvolDeviceUnlockContextTable(FsvolDeviceObject);
|
||||||
|
|
||||||
if (OpenRequiringOplock)
|
/* if there are more than one handles, perform oplock check */
|
||||||
{
|
if (1 < OplockCount)
|
||||||
FspFsvolDeviceLockContextTable(FsvolDeviceObject);
|
|
||||||
OplockCount = FileNode->HandleCount;
|
|
||||||
FspFsvolDeviceUnlockContextTable(FsvolDeviceObject);
|
|
||||||
|
|
||||||
CheckOplock = 1 < OplockCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
CheckOplock = CheckOplock || FsRtlCurrentBatchOplock(FspFileNodeAddrOfOplock(FileNode));
|
|
||||||
|
|
||||||
if (CheckOplock)
|
|
||||||
{
|
{
|
||||||
Result = FspCheckOplock(FspFileNodeAddrOfOplock(FileNode), Irp,
|
Result = FspCheckOplock(FspFileNodeAddrOfOplock(FileNode), Irp,
|
||||||
(PVOID)Response,
|
(PVOID)Response,
|
||||||
@ -1388,24 +1378,20 @@ static BOOLEAN FspFsvolCreateOpenOrOverwriteOplock(PIRP Irp, const FSP_FSCTL_TRA
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (OpenRequiringOplock && STATUS_SUCCESS == Result)
|
/* is an oplock requested during Create? */
|
||||||
|
if (STATUS_SUCCESS == Result &&
|
||||||
|
FlagOn(IrpSp->Parameters.Create.Options, FILE_OPEN_REQUIRING_OPLOCK))
|
||||||
{
|
{
|
||||||
Result = FspOplockFsctrlCreate(FspFileNodeAddrOfOplock(FileNode), Irp, OplockCount);
|
Result = FspOplockFsctrlCreate(FspFileNodeAddrOfOplock(FileNode), Irp, OplockCount);
|
||||||
ASSERT(STATUS_PENDING != Result);
|
ASSERT(STATUS_PENDING != Result);
|
||||||
|
|
||||||
if (STATUS_SUCCESS == Result)
|
if (STATUS_SUCCESS == Result)
|
||||||
|
/* if we added an oplock, remember to remove it later in case of failure */
|
||||||
FspIopRequestContext(FspIrpRequest(Irp), FspIopRequestExtraContext) = Irp;
|
FspIopRequestContext(FspIrpRequest(Irp), FspIopRequestExtraContext) = Irp;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (STATUS_SUCCESS != Result &&
|
*PResult = Irp->IoStatus.Status = Result;
|
||||||
STATUS_OPLOCK_BREAK_IN_PROGRESS != Result)
|
return STATUS_SUCCESS == Result || STATUS_OPLOCK_BREAK_IN_PROGRESS == Result;
|
||||||
{
|
|
||||||
*PResult = Result;
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
*PResult = STATUS_SUCCESS;
|
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static VOID FspFsvolCreateOpenOrOverwriteOplockPrepare(
|
static VOID FspFsvolCreateOpenOrOverwriteOplockPrepare(
|
||||||
@ -1425,10 +1411,13 @@ static VOID FspFsvolCreateOpenOrOverwriteOplockComplete(
|
|||||||
FSP_FSCTL_TRANSACT_REQ *Request = FspIrpRequest(Irp);
|
FSP_FSCTL_TRANSACT_REQ *Request = FspIrpRequest(Irp);
|
||||||
NTSTATUS Result;
|
NTSTATUS Result;
|
||||||
|
|
||||||
|
if (FspFsctlTransactReservedKind == Request->Kind)
|
||||||
|
FspIopRetryCompleteIrp(Irp, FspIopIrpResponse(Irp), &Result);
|
||||||
|
else
|
||||||
if (FspFsctlTransactOverwriteKind == Request->Kind)
|
if (FspFsctlTransactOverwriteKind == Request->Kind)
|
||||||
FspIopRetryPrepareIrp(Irp, &Result);
|
FspIopRetryPrepareIrp(Irp, &Result);
|
||||||
else if (FspFsctlTransactReservedKind == Request->Kind)
|
else
|
||||||
FspIopRetryCompleteIrp(Irp, FspIopIrpResponse(Irp), &Result);
|
ASSERT(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS FspCreate(
|
NTSTATUS FspCreate(
|
||||||
|
@ -324,6 +324,7 @@ VOID FspIopCompleteIrpEx(PIRP Irp, NTSTATUS Result, BOOLEAN DeviceDereference)
|
|||||||
|
|
||||||
if (STATUS_SUCCESS != Result &&
|
if (STATUS_SUCCESS != Result &&
|
||||||
STATUS_REPARSE != Result &&
|
STATUS_REPARSE != Result &&
|
||||||
|
STATUS_OPLOCK_BREAK_IN_PROGRESS != Result &&
|
||||||
STATUS_BUFFER_OVERFLOW != Result &&
|
STATUS_BUFFER_OVERFLOW != Result &&
|
||||||
STATUS_SHARING_VIOLATION != Result)
|
STATUS_SHARING_VIOLATION != Result)
|
||||||
Irp->IoStatus.Information = 0;
|
Irp->IoStatus.Information = 0;
|
||||||
|
@ -779,8 +779,8 @@ NTSTATUS FspOplockFsctrlF(
|
|||||||
OpenCount);
|
OpenCount);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* When the IRP is IRP_MJ_FILE_SYSTEM_CONTROL, FsRtlOplockFsctrl always completes the IRP
|
* When the IRP is IRP_MJ_FILE_SYSTEM_CONTROL, FsRtlOplockFsctrl always takes ownership
|
||||||
* (unless it raises). So return STATUS_SUCCESS in that case.
|
* of the IRP (unless it raises). So return STATUS_SUCCESS in that case.
|
||||||
*/
|
*/
|
||||||
if (!Create)
|
if (!Create)
|
||||||
Result = STATUS_SUCCESS;
|
Result = STATUS_SUCCESS;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user