sys: oplock testing

This commit is contained in:
Bill Zissimopoulos 2016-11-14 20:36:51 -08:00
parent 6a48087d5f
commit 959d8537c6
6 changed files with 37 additions and 22 deletions

View File

@ -649,7 +649,8 @@ NTSTATUS FspFsvolCreateComplete(
/* did the user-mode file system sent us a failure code? */ /* did the user-mode file system sent us a failure code? */
if (!NT_SUCCESS(Response->IoStatus.Status)) if (!NT_SUCCESS(Response->IoStatus.Status))
{ {
Irp->IoStatus.Information = 0; Irp->IoStatus.Information = STATUS_SHARING_VIOLATION == Response->IoStatus.Status ?
Response->IoStatus.Information : 0;
Result = Response->IoStatus.Status; Result = Response->IoStatus.Status;
FSP_RETURN(); FSP_RETURN();
} }
@ -842,8 +843,10 @@ NTSTATUS FspFsvolCreateComplete(
{ {
if (STATUS_SHARING_VIOLATION == Result) if (STATUS_SHARING_VIOLATION == Result)
{ {
ASSERT(0 != OpenedFileNode);
FspIopSetIrpResponse(Irp, Response); FspIopSetIrpResponse(Irp, Response);
FspIopRequestContext(Request, FspIopRequestExtraContext) = FileNode; FspIopRequestContext(Request, FspIopRequestExtraContext) = OpenedFileNode;
Result = FspFsvolCreateSharingViolationOplock( Result = FspFsvolCreateSharingViolationOplock(
FsvolDeviceObject, Irp, IrpSp, FALSE); FsvolDeviceObject, Irp, IrpSp, FALSE);
@ -1240,13 +1243,13 @@ static NTSTATUS FspFsvolCreateSharingViolationOplock(
FSP_FSCTL_TRANSACT_REQ *Request = FspIrpRequest(Irp); FSP_FSCTL_TRANSACT_REQ *Request = FspIrpRequest(Irp);
FSP_FSCTL_TRANSACT_RSP *Response; FSP_FSCTL_TRANSACT_RSP *Response;
FSP_FILE_NODE *FileNode = FspIopRequestContext(Request, FspIopRequestExtraContext); FSP_FILE_NODE *ExtraFileNode = FspIopRequestContext(Request, FspIopRequestExtraContext);
BOOLEAN OpbatchBreakUnderway = FALSE; BOOLEAN OpbatchBreakUnderway = FALSE;
NTSTATUS Result; NTSTATUS Result;
BOOLEAN Success; BOOLEAN Success;
Success = DEBUGTEST(90) && Success = DEBUGTEST(90) &&
FspFileNodeTryAcquireSharedF(FileNode, FspFileNodeAcquireMain, CanWait); FspFileNodeTryAcquireSharedF(ExtraFileNode, FspFileNodeAcquireMain, CanWait);
if (!Success) if (!Success)
return FspWqRepostIrpWorkItem(Irp, return FspWqRepostIrpWorkItem(Irp,
FspFsvolCreateSharingViolationOplock, FspFsvolCreateRequestFini); FspFsvolCreateSharingViolationOplock, FspFsvolCreateRequestFini);
@ -1257,11 +1260,11 @@ static NTSTATUS FspFsvolCreateSharingViolationOplock(
* If there is no batch or CACHE_HANDLE_LEVEL oplock we are done; * If there is no batch or CACHE_HANDLE_LEVEL oplock we are done;
* else retry in a worker thread to break the oplocks. * else retry in a worker thread to break the oplocks.
*/ */
Success = !FsRtlCurrentBatchOplock(FspFileNodeAddrOfOplock(FileNode)) && Success = !FsRtlCurrentBatchOplock(FspFileNodeAddrOfOplock(ExtraFileNode)) &&
(FlagOn(IrpSp->Parameters.Create.Options, FILE_COMPLETE_IF_OPLOCKED) || (FlagOn(IrpSp->Parameters.Create.Options, FILE_COMPLETE_IF_OPLOCKED) ||
!FsRtlCurrentOplockH(FspFileNodeAddrOfOplock(FileNode))); !FsRtlCurrentOplockH(FspFileNodeAddrOfOplock(ExtraFileNode)));
FspFileNodeRelease(FileNode, Main); FspFileNodeRelease(ExtraFileNode, Main);
if (!Success) if (!Success)
return FspWqRepostIrpWorkItem(Irp, return FspWqRepostIrpWorkItem(Irp,
@ -1274,7 +1277,7 @@ static NTSTATUS FspFsvolCreateSharingViolationOplock(
{ {
#if 0 #if 0
/* ???: is this needed in this case? */ /* ???: is this needed in this case? */
Result = FspCheckOplockEx(FspFileNodeAddrOfOplock(FileNode), Irp, Result = FspCheckOplockEx(FspFileNodeAddrOfOplock(ExtraFileNode), 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))
{ {
@ -1283,10 +1286,10 @@ static NTSTATUS FspFsvolCreateSharingViolationOplock(
} }
#endif #endif
if (FsRtlCurrentBatchOplock(FspFileNodeAddrOfOplock(FileNode))) if (FsRtlCurrentBatchOplock(FspFileNodeAddrOfOplock(ExtraFileNode)))
{ {
/* wait for batch oplock break to complete */ /* wait for batch oplock break to complete */
Result = FspCheckOplock(FspFileNodeAddrOfOplock(FileNode), Irp, Result = FspCheckOplock(FspFileNodeAddrOfOplock(ExtraFileNode), Irp,
0, 0, 0); 0, 0, 0);
if (STATUS_SUCCESS == Result) if (STATUS_SUCCESS == Result)
OpbatchBreakUnderway = TRUE; OpbatchBreakUnderway = TRUE;
@ -1295,24 +1298,24 @@ static NTSTATUS FspFsvolCreateSharingViolationOplock(
Result = STATUS_SHARING_VIOLATION; 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(FileNode))) FsRtlCurrentOplockH(FspFileNodeAddrOfOplock(ExtraFileNode)))
{ {
/* wait for CACHE_HANDLE_LEVEL oplock break to complete */ /* wait for CACHE_HANDLE_LEVEL oplock break to complete */
Result = FspOplockBreakH(FspFileNodeAddrOfOplock(FileNode), Irp, Result = FspOplockBreakH(FspFileNodeAddrOfOplock(ExtraFileNode), Irp,
0, 0, 0, 0); 0, 0, 0, 0);
} }
#if 0 #if 0
exit: exit:
#endif #endif
FspFileNodeRelease(FileNode, Main); FspFileNodeRelease(ExtraFileNode, Main);
Response = FspIopIrpResponse(Irp); Response = FspIopIrpResponse(Irp);
if (NT_SUCCESS(Result)) if (NT_SUCCESS(Result))
{ {
FspFileNodeClose(FileNode, 0, TRUE); FspFileNodeClose(ExtraFileNode, 0, TRUE);
FspFileNodeDereference(FileNode); FspFileNodeDereference(ExtraFileNode);
FspIopRequestContext(Request, FspIopRequestExtraContext) = 0; FspIopRequestContext(Request, FspIopRequestExtraContext) = 0;
} }
else else

View File

@ -1114,7 +1114,7 @@ VOID FspFileNodeClose(FSP_FILE_NODE *FileNode,
BOOLEAN HandleCleanup); /* TRUE to decrement handle count */ BOOLEAN HandleCleanup); /* TRUE to decrement handle count */
NTSTATUS FspFileNodeFlushAndPurgeCache(FSP_FILE_NODE *FileNode, NTSTATUS FspFileNodeFlushAndPurgeCache(FSP_FILE_NODE *FileNode,
UINT64 FlushOffset64, ULONG FlushLength, BOOLEAN FlushAndPurge); UINT64 FlushOffset64, ULONG FlushLength, BOOLEAN FlushAndPurge);
BOOLEAN FspFileNodeRenameCheck(PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, BOOLEAN FspFileNodeRenameCheck(PDEVICE_OBJECT FsvolDeviceObject, PIRP OplockIrp,
FSP_FILE_NODE *FileNode, PUNICODE_STRING FileName); FSP_FILE_NODE *FileNode, PUNICODE_STRING FileName);
VOID FspFileNodeRename(FSP_FILE_NODE *FileNode, PUNICODE_STRING NewFileName); VOID FspFileNodeRename(FSP_FILE_NODE *FileNode, PUNICODE_STRING NewFileName);
VOID FspFileNodeGetFileInfo(FSP_FILE_NODE *FileNode, FSP_FSCTL_FILE_INFO *FileInfo); VOID FspFileNodeGetFileInfo(FSP_FILE_NODE *FileNode, FSP_FSCTL_FILE_INFO *FileInfo);

View File

@ -41,7 +41,7 @@ VOID FspFileNodeClose(FSP_FILE_NODE *FileNode,
BOOLEAN HandleCleanup); /* TRUE to decrement handle count */ BOOLEAN HandleCleanup); /* TRUE to decrement handle count */
NTSTATUS FspFileNodeFlushAndPurgeCache(FSP_FILE_NODE *FileNode, NTSTATUS FspFileNodeFlushAndPurgeCache(FSP_FILE_NODE *FileNode,
UINT64 FlushOffset64, ULONG FlushLength, BOOLEAN FlushAndPurge); UINT64 FlushOffset64, ULONG FlushLength, BOOLEAN FlushAndPurge);
BOOLEAN FspFileNodeRenameCheck(PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, BOOLEAN FspFileNodeRenameCheck(PDEVICE_OBJECT FsvolDeviceObject, PIRP OplockIrp,
FSP_FILE_NODE *FileNode, PUNICODE_STRING FileName); FSP_FILE_NODE *FileNode, PUNICODE_STRING FileName);
VOID FspFileNodeRename(FSP_FILE_NODE *FileNode, PUNICODE_STRING NewFileName); VOID FspFileNodeRename(FSP_FILE_NODE *FileNode, PUNICODE_STRING NewFileName);
VOID FspFileNodeGetFileInfo(FSP_FILE_NODE *FileNode, FSP_FSCTL_FILE_INFO *FileInfo); VOID FspFileNodeGetFileInfo(FSP_FILE_NODE *FileNode, FSP_FSCTL_FILE_INFO *FileInfo);
@ -493,6 +493,7 @@ NTSTATUS FspFileNodeOpen(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject,
FlagOn(GrantedAccess, FlagOn(GrantedAccess,
FILE_EXECUTE | FILE_READ_DATA | FILE_WRITE_DATA | FILE_APPEND_DATA | DELETE)) FILE_EXECUTE | FILE_READ_DATA | FILE_WRITE_DATA | FILE_APPEND_DATA | DELETE))
{ {
OpenedFileNode = FileNode->MainFileNode;
Result = STATUS_SHARING_VIOLATION; Result = STATUS_SHARING_VIOLATION;
goto exit; goto exit;
} }
@ -833,7 +834,7 @@ NTSTATUS FspFileNodeFlushAndPurgeCache(FSP_FILE_NODE *FileNode,
return IoStatus.Status; return IoStatus.Status;
} }
BOOLEAN FspFileNodeRenameCheck(PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, BOOLEAN FspFileNodeRenameCheck(PDEVICE_OBJECT FsvolDeviceObject, PIRP OplockIrp,
FSP_FILE_NODE *FileNode, PUNICODE_STRING FileName) FSP_FILE_NODE *FileNode, PUNICODE_STRING FileName)
{ {
PAGED_CODE(); PAGED_CODE();
@ -860,6 +861,8 @@ BOOLEAN FspFileNodeRenameCheck(PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp,
DescendantFileNodes = DescendantFileNodeArray; DescendantFileNodes = DescendantFileNodeArray;
DescendantFileNodeCount = 0; DescendantFileNodeCount = 0;
FspFsvolDeviceLockContextTable(FsvolDeviceObject);
/* if we are checking the existing file name, do a quick check here */ /* if we are checking the existing file name, do a quick check here */
if (CheckingOldName) if (CheckingOldName)
{ {
@ -873,8 +876,6 @@ BOOLEAN FspFileNodeRenameCheck(PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp,
/* Note: when CheckingOldName==TRUE, the old FileNode is not included in enumerations below */ /* Note: when CheckingOldName==TRUE, the old FileNode is not included in enumerations below */
} }
FspFsvolDeviceLockContextTable(FsvolDeviceObject);
/* count descendant file nodes and try to gather them in a local array if possible */ /* count descendant file nodes and try to gather them in a local array if possible */
memset(&RestartKey, 0, sizeof RestartKey); memset(&RestartKey, 0, sizeof RestartKey);
for (;;) for (;;)
@ -895,6 +896,12 @@ BOOLEAN FspFileNodeRenameCheck(PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp,
DescendantFileNodeCount++; DescendantFileNodeCount++;
} }
if (0 == DescendantFileNodeCount)
{
ASSERT(Success);
goto unlock_exit;
}
/* if the local array is out of space, gather descendant file nodes in the pool */ /* if the local array is out of space, gather descendant file nodes in the pool */
if (ARRAYSIZE(DescendantFileNodeArray) < DescendantFileNodeCount) if (ARRAYSIZE(DescendantFileNodeArray) < DescendantFileNodeCount)
{ {
@ -956,7 +963,7 @@ BOOLEAN FspFileNodeRenameCheck(PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp,
DescendantFileNode = (PVOID)((UINT_PTR)DescendantFileNode & ~1); DescendantFileNode = (PVOID)((UINT_PTR)DescendantFileNode & ~1);
if (HasOpenHandles) if (HasOpenHandles)
FspCheckOplock(FspFileNodeAddrOfOplock(DescendantFileNode), Irp, 0, 0, 0); FspCheckOplock(FspFileNodeAddrOfOplock(DescendantFileNode), OplockIrp, 0, 0, 0);
} }
FspFsvolDeviceLockContextTable(FsvolDeviceObject); FspFsvolDeviceLockContextTable(FsvolDeviceObject);

View File

@ -1280,7 +1280,7 @@ retry:
* that has open handles (except in the batch-oplock case described earlier). * that has open handles (except in the batch-oplock case described earlier).
*/ */
Result = STATUS_SUCCESS; Result = STATUS_SUCCESS;
if (!FspFileNodeRenameCheck(FsvolDeviceObject, Irp, FileNode, &FileNode->FileName) && if (!FspFileNodeRenameCheck(FsvolDeviceObject, Irp, FileNode, &FileNode->FileName) ||
!FspFileNodeRenameCheck(FsvolDeviceObject, Irp, 0, &NewFileName)) !FspFileNodeRenameCheck(FsvolDeviceObject, Irp, 0, &NewFileName))
Result = STATUS_ACCESS_DENIED; Result = STATUS_ACCESS_DENIED;
if (!NT_SUCCESS(Result)) if (!NT_SUCCESS(Result))

View File

@ -164,6 +164,7 @@ NTSTATUS FspIopCreateRequestWorkItem(FSP_FSCTL_TRANSACT_REQ *Request)
return STATUS_INSUFFICIENT_RESOURCES; return STATUS_INSUFFICIENT_RESOURCES;
RtlZeroMemory(RequestWorkItem, sizeof *RequestWorkItem); RtlZeroMemory(RequestWorkItem, sizeof *RequestWorkItem);
RequestHeader->WorkItem = RequestWorkItem;
} }
return STATUS_SUCCESS; return STATUS_SUCCESS;

View File

@ -93,6 +93,9 @@ NTSTATUS FspWqCreateAndPostIrpWorkItem(PIRP Irp,
ExInitializeWorkItem(&RequestWorkItem->WorkQueueItem, FspWqWorkRoutine, Irp); ExInitializeWorkItem(&RequestWorkItem->WorkQueueItem, FspWqWorkRoutine, Irp);
} }
ASSERT(RequestFini == ((FSP_FSCTL_TRANSACT_REQ_HEADER *)
((PUINT8)Request - sizeof(FSP_FSCTL_TRANSACT_REQ_HEADER)))->RequestFini);
if (!CreateAndPost) if (!CreateAndPost)
return STATUS_SUCCESS; return STATUS_SUCCESS;
@ -117,6 +120,7 @@ VOID FspWqPostIrpWorkItem(PIRP Irp)
case IRP_MJ_WRITE: case IRP_MJ_WRITE:
case IRP_MJ_DIRECTORY_CONTROL: case IRP_MJ_DIRECTORY_CONTROL:
case IRP_MJ_LOCK_CONTROL: case IRP_MJ_LOCK_CONTROL:
break;
default: default:
ASSERT(0); ASSERT(0);
break; break;