mirror of
https://github.com/winfsp/winfsp.git
synced 2025-04-23 00:43:00 -05:00
sys: FspFileNodeCheckBatchOplocksOnAllStreams: fix oplock related deadlock
- fix: initiate oplock break, release FileNode and wait for oplock break completion
This commit is contained in:
parent
37362cb8cc
commit
2e089b92c5
@ -1336,7 +1336,7 @@ static NTSTATUS FspFsvolCreateSharingViolationOplock(
|
|||||||
|
|
||||||
/* break Batch oplocks on the main file and this stream */
|
/* break Batch oplocks on the main file and this stream */
|
||||||
Result = FspFileNodeCheckBatchOplocksOnAllStreams(FsvolDeviceObject, Irp,
|
Result = FspFileNodeCheckBatchOplocksOnAllStreams(FsvolDeviceObject, Irp,
|
||||||
ExtraFileNode, &FileNode->FileName);
|
ExtraFileNode, FspFileNodeAcquireMain, &FileNode->FileName);
|
||||||
if (STATUS_SUCCESS != Result)
|
if (STATUS_SUCCESS != Result)
|
||||||
Result = STATUS_SHARING_VIOLATION;
|
Result = STATUS_SHARING_VIOLATION;
|
||||||
}
|
}
|
||||||
@ -1353,15 +1353,18 @@ static NTSTATUS FspFsvolCreateSharingViolationOplock(
|
|||||||
|
|
||||||
/* break Batch oplocks on the main file and all our streams */
|
/* break Batch oplocks on the main file and all our streams */
|
||||||
Result = FspFileNodeCheckBatchOplocksOnAllStreams(FsvolDeviceObject, Irp,
|
Result = FspFileNodeCheckBatchOplocksOnAllStreams(FsvolDeviceObject, Irp,
|
||||||
ExtraFileNode, 0);
|
ExtraFileNode, FspFileNodeAcquireMain, 0);
|
||||||
if (STATUS_SUCCESS != Result)
|
if (STATUS_SUCCESS != Result)
|
||||||
Result = STATUS_SHARING_VIOLATION;
|
Result = STATUS_SHARING_VIOLATION;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
if (FspFileNodeOplockIsBatch(ExtraFileNode))
|
if (FspFileNodeOplockIsBatch(ExtraFileNode))
|
||||||
{
|
{
|
||||||
|
FspFileNodeRelease(ExtraFileNode, Main);
|
||||||
|
|
||||||
/* wait for Batch oplock break to complete */
|
/* wait for Batch oplock break to complete */
|
||||||
Result = FspFileNodeOplockCheck(ExtraFileNode, Irp);
|
Result = FspFileNodeOplockCheck(ExtraFileNode, Irp);
|
||||||
|
ASSERT(STATUS_OPLOCK_BREAK_IN_PROGRESS != Result);
|
||||||
if (STATUS_SUCCESS != Result)
|
if (STATUS_SUCCESS != Result)
|
||||||
Result = STATUS_SHARING_VIOLATION;
|
Result = STATUS_SHARING_VIOLATION;
|
||||||
else
|
else
|
||||||
@ -1371,13 +1374,15 @@ static NTSTATUS FspFsvolCreateSharingViolationOplock(
|
|||||||
if (!FlagOn(IrpSp->Parameters.Create.Options, FILE_COMPLETE_IF_OPLOCKED) &&
|
if (!FlagOn(IrpSp->Parameters.Create.Options, FILE_COMPLETE_IF_OPLOCKED) &&
|
||||||
FspFileNodeOplockIsHandle(ExtraFileNode))
|
FspFileNodeOplockIsHandle(ExtraFileNode))
|
||||||
{
|
{
|
||||||
|
FspFileNodeRelease(ExtraFileNode, Main);
|
||||||
|
|
||||||
/* wait for Handle oplock break to complete */
|
/* wait for Handle oplock break to complete */
|
||||||
Result = FspFileNodeOplockBreakHandle(ExtraFileNode, Irp, 0);
|
Result = FspFileNodeOplockBreakHandle(ExtraFileNode, Irp, 0);
|
||||||
ASSERT(STATUS_OPLOCK_BREAK_IN_PROGRESS != Result);
|
ASSERT(STATUS_OPLOCK_BREAK_IN_PROGRESS != Result);
|
||||||
if (STATUS_SUCCESS != Result)
|
if (STATUS_SUCCESS != Result)
|
||||||
Result = STATUS_SHARING_VIOLATION;
|
Result = STATUS_SHARING_VIOLATION;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
FspFileNodeRelease(ExtraFileNode, Main);
|
FspFileNodeRelease(ExtraFileNode, Main);
|
||||||
|
|
||||||
Response = FspIopIrpResponse(Irp);
|
Response = FspIopIrpResponse(Irp);
|
||||||
|
@ -1121,6 +1121,7 @@ NTSTATUS FspFileNodeCheckBatchOplocksOnAllStreams(
|
|||||||
PDEVICE_OBJECT FsvolDeviceObject,
|
PDEVICE_OBJECT FsvolDeviceObject,
|
||||||
PIRP OplockIrp,
|
PIRP OplockIrp,
|
||||||
FSP_FILE_NODE *FileNode,
|
FSP_FILE_NODE *FileNode,
|
||||||
|
ULONG AcquireFlags,
|
||||||
PUNICODE_STRING StreamFileName);
|
PUNICODE_STRING StreamFileName);
|
||||||
BOOLEAN FspFileNodeRenameCheck(PDEVICE_OBJECT FsvolDeviceObject, PIRP OplockIrp,
|
BOOLEAN FspFileNodeRenameCheck(PDEVICE_OBJECT FsvolDeviceObject, PIRP OplockIrp,
|
||||||
FSP_FILE_NODE *FileNode, PUNICODE_STRING FileName);
|
FSP_FILE_NODE *FileNode, PUNICODE_STRING FileName);
|
||||||
|
@ -46,6 +46,7 @@ NTSTATUS FspFileNodeCheckBatchOplocksOnAllStreams(
|
|||||||
PDEVICE_OBJECT FsvolDeviceObject,
|
PDEVICE_OBJECT FsvolDeviceObject,
|
||||||
PIRP OplockIrp,
|
PIRP OplockIrp,
|
||||||
FSP_FILE_NODE *FileNode,
|
FSP_FILE_NODE *FileNode,
|
||||||
|
ULONG AcquireFlags,
|
||||||
PUNICODE_STRING StreamFileName);
|
PUNICODE_STRING StreamFileName);
|
||||||
BOOLEAN FspFileNodeRenameCheck(PDEVICE_OBJECT FsvolDeviceObject, PIRP OplockIrp,
|
BOOLEAN FspFileNodeRenameCheck(PDEVICE_OBJECT FsvolDeviceObject, PIRP OplockIrp,
|
||||||
FSP_FILE_NODE *FileNode, PUNICODE_STRING FileName);
|
FSP_FILE_NODE *FileNode, PUNICODE_STRING FileName);
|
||||||
@ -854,6 +855,7 @@ NTSTATUS FspFileNodeCheckBatchOplocksOnAllStreams(
|
|||||||
PDEVICE_OBJECT FsvolDeviceObject,
|
PDEVICE_OBJECT FsvolDeviceObject,
|
||||||
PIRP OplockIrp,
|
PIRP OplockIrp,
|
||||||
FSP_FILE_NODE *FileNode,
|
FSP_FILE_NODE *FileNode,
|
||||||
|
ULONG AcquireFlags,
|
||||||
PUNICODE_STRING StreamFileName)
|
PUNICODE_STRING StreamFileName)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@ -872,6 +874,7 @@ NTSTATUS FspFileNodeCheckBatchOplocksOnAllStreams(
|
|||||||
USHORT FileNameLength = FileNode->FileName.Length;
|
USHORT FileNameLength = FileNode->FileName.Length;
|
||||||
BOOLEAN CaseInsensitive = !FspFsvolDeviceExtension(FsvolDeviceObject)->
|
BOOLEAN CaseInsensitive = !FspFsvolDeviceExtension(FsvolDeviceObject)->
|
||||||
VolumeParams.CaseSensitiveSearch;
|
VolumeParams.CaseSensitiveSearch;
|
||||||
|
ULONG IsBatchOplock, IsHandleOplock;
|
||||||
NTSTATUS Result;
|
NTSTATUS Result;
|
||||||
|
|
||||||
DescendantFileNodes = DescendantFileNodeArray;
|
DescendantFileNodes = DescendantFileNodeArray;
|
||||||
@ -902,6 +905,8 @@ NTSTATUS FspFileNodeCheckBatchOplocksOnAllStreams(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ASSERT(0 == ((UINT_PTR)DescendantFileNode & 7));
|
||||||
|
|
||||||
/* keep a reference to the FileNode in case it goes away in later processing */
|
/* keep a reference to the FileNode in case it goes away in later processing */
|
||||||
FspFileNodeReference(DescendantFileNode);
|
FspFileNodeReference(DescendantFileNode);
|
||||||
|
|
||||||
@ -958,14 +963,59 @@ NTSTATUS FspFileNodeCheckBatchOplocksOnAllStreams(
|
|||||||
|
|
||||||
if (FspFileNodeOplockIsBatch(DescendantFileNode))
|
if (FspFileNodeOplockIsBatch(DescendantFileNode))
|
||||||
{
|
{
|
||||||
NTSTATUS Result0 = FspFileNodeOplockCheck(DescendantFileNode, OplockIrp);
|
NTSTATUS Result0 = FspFileNodeOplockCheckEx(DescendantFileNode, OplockIrp,
|
||||||
if (STATUS_SUCCESS != Result0)
|
OPLOCK_FLAG_COMPLETE_IF_OPLOCKED);
|
||||||
Result = STATUS_SHARING_VIOLATION;
|
if (STATUS_SUCCESS == Result0)
|
||||||
else
|
|
||||||
OplockIrp->IoStatus.Information = FILE_OPBATCH_BREAK_UNDERWAY;
|
OplockIrp->IoStatus.Information = FILE_OPBATCH_BREAK_UNDERWAY;
|
||||||
|
else
|
||||||
|
if (STATUS_OPLOCK_BREAK_IN_PROGRESS == Result0)
|
||||||
|
{
|
||||||
|
OplockIrp->IoStatus.Information = FILE_OPBATCH_BREAK_UNDERWAY;
|
||||||
|
DescendantFileNodes[DescendantFileNodeIndex] =
|
||||||
|
(PVOID)((UINT_PTR)DescendantFileNode | 2);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Result = STATUS_SHARING_VIOLATION;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
if (FspFileNodeOplockIsHandle(DescendantFileNode))
|
if (FspFileNodeOplockIsHandle(DescendantFileNode))
|
||||||
|
{
|
||||||
|
NTSTATUS Result0 = FspFileNodeOplockBreakHandle(DescendantFileNode, OplockIrp,
|
||||||
|
OPLOCK_FLAG_COMPLETE_IF_OPLOCKED);
|
||||||
|
if (STATUS_SUCCESS == Result0)
|
||||||
|
;
|
||||||
|
else
|
||||||
|
if (STATUS_OPLOCK_BREAK_IN_PROGRESS == Result0)
|
||||||
|
DescendantFileNodes[DescendantFileNodeIndex] =
|
||||||
|
(PVOID)((UINT_PTR)DescendantFileNode | 4);
|
||||||
|
else
|
||||||
|
Result = STATUS_SHARING_VIOLATION;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FspFileNodeReleaseF(FileNode, AcquireFlags);
|
||||||
|
|
||||||
|
/* wait for oplock breaks to finish */
|
||||||
|
Result = STATUS_SUCCESS;
|
||||||
|
for (
|
||||||
|
DescendantFileNodeIndex = 0;
|
||||||
|
DescendantFileNodeCount > DescendantFileNodeIndex;
|
||||||
|
DescendantFileNodeIndex++)
|
||||||
|
{
|
||||||
|
DescendantFileNode = DescendantFileNodes[DescendantFileNodeIndex];
|
||||||
|
IsBatchOplock = (UINT_PTR)DescendantFileNode & 2;
|
||||||
|
IsHandleOplock = (UINT_PTR)DescendantFileNode & 4;
|
||||||
|
DescendantFileNode = (PVOID)((UINT_PTR)DescendantFileNode & ~7);
|
||||||
|
|
||||||
|
if (IsBatchOplock)
|
||||||
|
{
|
||||||
|
NTSTATUS Result0 = FspFileNodeOplockCheck(DescendantFileNode, OplockIrp);
|
||||||
|
ASSERT(STATUS_OPLOCK_BREAK_IN_PROGRESS != Result0);
|
||||||
|
if (STATUS_SUCCESS != Result0)
|
||||||
|
Result = STATUS_SHARING_VIOLATION;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (IsHandleOplock)
|
||||||
{
|
{
|
||||||
NTSTATUS Result0 = FspFileNodeOplockBreakHandle(DescendantFileNode, OplockIrp, 0);
|
NTSTATUS Result0 = FspFileNodeOplockBreakHandle(DescendantFileNode, OplockIrp, 0);
|
||||||
ASSERT(STATUS_OPLOCK_BREAK_IN_PROGRESS != Result0);
|
ASSERT(STATUS_OPLOCK_BREAK_IN_PROGRESS != Result0);
|
||||||
@ -981,6 +1031,7 @@ NTSTATUS FspFileNodeCheckBatchOplocksOnAllStreams(
|
|||||||
DescendantFileNodeIndex++)
|
DescendantFileNodeIndex++)
|
||||||
{
|
{
|
||||||
DescendantFileNode = DescendantFileNodes[DescendantFileNodeIndex];
|
DescendantFileNode = DescendantFileNodes[DescendantFileNodeIndex];
|
||||||
|
DescendantFileNode = (PVOID)((UINT_PTR)DescendantFileNode & ~7);
|
||||||
|
|
||||||
FspFileNodeDereference(DescendantFileNode);
|
FspFileNodeDereference(DescendantFileNode);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user