mirror of
https://github.com/reactos/reactos.git
synced 2024-12-04 00:43:32 +08:00
[RDBSS][RXCE] Implement IRP cancellation
CORE-15441
This commit is contained in:
parent
1e141573e4
commit
a9124b412d
@ -517,6 +517,8 @@ RxReinitializeContext(
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
extern FAST_MUTEX RxContextPerFileSerializationMutex;
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
NTAPI
|
NTAPI
|
||||||
RxResumeBlockedOperations_Serially(
|
RxResumeBlockedOperations_Serially(
|
||||||
@ -527,4 +529,19 @@ VOID
|
|||||||
RxResumeBlockedOperations_ALL(
|
RxResumeBlockedOperations_ALL(
|
||||||
_Inout_ PRX_CONTEXT RxContext);
|
_Inout_ PRX_CONTEXT RxContext);
|
||||||
|
|
||||||
|
#if (_WIN32_WINNT >= 0x0600)
|
||||||
|
VOID
|
||||||
|
RxCancelBlockingOperation(
|
||||||
|
_Inout_ PRX_CONTEXT RxContext,
|
||||||
|
_In_ PIRP Irp);
|
||||||
|
#else
|
||||||
|
VOID
|
||||||
|
RxCancelBlockingOperation(
|
||||||
|
_Inout_ PRX_CONTEXT RxContext);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
VOID
|
||||||
|
RxRemoveOperationFromBlockingQueue(
|
||||||
|
_Inout_ PRX_CONTEXT RxContext);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -361,6 +361,11 @@ NTSTATUS
|
|||||||
RxNotifyChangeDirectory(
|
RxNotifyChangeDirectory(
|
||||||
PRX_CONTEXT RxContext);
|
PRX_CONTEXT RxContext);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
RxpCancelRoutine(
|
||||||
|
PVOID Context);
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
RxpQueryInfoMiniRdr(
|
RxpQueryInfoMiniRdr(
|
||||||
PRX_CONTEXT RxContext,
|
PRX_CONTEXT RxContext,
|
||||||
@ -529,7 +534,6 @@ BOOLEAN DisableFlushOnCleanup = FALSE;
|
|||||||
ULONG ReadAheadGranularity = 1 << PAGE_SHIFT;
|
ULONG ReadAheadGranularity = 1 << PAGE_SHIFT;
|
||||||
LIST_ENTRY RxActiveContexts;
|
LIST_ENTRY RxActiveContexts;
|
||||||
NPAGED_LOOKASIDE_LIST RxContextLookasideList;
|
NPAGED_LOOKASIDE_LIST RxContextLookasideList;
|
||||||
FAST_MUTEX RxContextPerFileSerializationMutex;
|
|
||||||
RDBSS_DATA RxData;
|
RDBSS_DATA RxData;
|
||||||
FCB RxDeviceFCB;
|
FCB RxDeviceFCB;
|
||||||
BOOLEAN RxLoudLowIoOpsEnabled = FALSE;
|
BOOLEAN RxLoudLowIoOpsEnabled = FALSE;
|
||||||
@ -1128,13 +1132,126 @@ RxCancelNotifyChangeDirectoryRequestsForVNetRoot(
|
|||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @implemented
|
||||||
|
*/
|
||||||
|
BOOLEAN
|
||||||
|
RxCancelOperationInOverflowQueue(
|
||||||
|
PRX_CONTEXT RxContext)
|
||||||
|
{
|
||||||
|
KIRQL OldIrql;
|
||||||
|
BOOLEAN OperationToCancel;
|
||||||
|
|
||||||
|
/* By default, nothing cancelled */
|
||||||
|
OperationToCancel = FALSE;
|
||||||
|
|
||||||
|
/* Acquire the overflow spinlock */
|
||||||
|
KeAcquireSpinLock(&RxFileSystemDeviceObject->OverflowQueueSpinLock, &OldIrql);
|
||||||
|
|
||||||
|
/* Is our context in any queue? */
|
||||||
|
if (BooleanFlagOn(RxContext->Flags, (RX_CONTEXT_FLAG_FSP_DELAYED_OVERFLOW_QUEUE | RX_CONTEXT_FLAG_FSP_CRITICAL_OVERFLOW_QUEUE)))
|
||||||
|
{
|
||||||
|
/* Make sure flag is consistent with facts... */
|
||||||
|
if (RxContext->OverflowListEntry.Flink != NULL)
|
||||||
|
{
|
||||||
|
/* Remove it from the list */
|
||||||
|
RemoveEntryList(&RxContext->OverflowListEntry);
|
||||||
|
RxContext->OverflowListEntry.Flink == NULL;
|
||||||
|
|
||||||
|
/* Decrement appropriate count */
|
||||||
|
if (BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_FSP_CRITICAL_OVERFLOW_QUEUE))
|
||||||
|
{
|
||||||
|
--RxFileSystemDeviceObject->OverflowQueueCount[CriticalWorkQueue];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
--RxFileSystemDeviceObject->OverflowQueueCount[DelayedWorkQueue];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clear the flag */
|
||||||
|
ClearFlag(RxContext->Flags, ~(RX_CONTEXT_FLAG_FSP_DELAYED_OVERFLOW_QUEUE | RX_CONTEXT_FLAG_FSP_CRITICAL_OVERFLOW_QUEUE));
|
||||||
|
|
||||||
|
/* Time to cancel! */
|
||||||
|
OperationToCancel = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
KeReleaseSpinLock(&RxFileSystemDeviceObject->OverflowQueueSpinLock, OldIrql);
|
||||||
|
|
||||||
|
/* We have something to cancel & complete */
|
||||||
|
if (OperationToCancel)
|
||||||
|
{
|
||||||
|
RxRemoveOperationFromBlockingQueue(RxContext);
|
||||||
|
RxCompleteRequest(RxContext, STATUS_CANCELLED);
|
||||||
|
}
|
||||||
|
|
||||||
|
return OperationToCancel;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @implemented
|
||||||
|
*/
|
||||||
VOID
|
VOID
|
||||||
NTAPI
|
NTAPI
|
||||||
RxCancelRoutine(
|
RxCancelRoutine(
|
||||||
PDEVICE_OBJECT DeviceObject,
|
PDEVICE_OBJECT DeviceObject,
|
||||||
PIRP Irp)
|
PIRP Irp)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED;
|
KIRQL OldIrql;
|
||||||
|
PLIST_ENTRY Entry;
|
||||||
|
PRX_CONTEXT RxContext;
|
||||||
|
|
||||||
|
/* Lock our contexts list */
|
||||||
|
KeAcquireSpinLock(&RxStrucSupSpinLock, &OldIrql);
|
||||||
|
|
||||||
|
/* Now, find a context that matches the cancelled IRP */
|
||||||
|
Entry = RxActiveContexts.Flink;
|
||||||
|
while (Entry != &RxActiveContexts)
|
||||||
|
{
|
||||||
|
RxContext = CONTAINING_RECORD(Entry, RX_CONTEXT, ContextListEntry);
|
||||||
|
Entry = Entry->Flink;
|
||||||
|
|
||||||
|
/* Found! */
|
||||||
|
if (RxContext->CurrentIrp == Irp)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we reached the end of the list, we didn't find any context, so zero the buffer
|
||||||
|
* If the context is already under cancellation, forget about it too
|
||||||
|
*/
|
||||||
|
if (Entry == &RxActiveContexts || BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_CANCELLED))
|
||||||
|
{
|
||||||
|
RxContext = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Otherwise, reference it and mark it cancelled */
|
||||||
|
SetFlag(RxContext->Flags, RX_CONTEXT_FLAG_CANCELLED);
|
||||||
|
InterlockedIncrement((volatile long *)&RxContext->ReferenceCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Done with the contexts list */
|
||||||
|
KeReleaseSpinLock(&RxStrucSupSpinLock, OldIrql);
|
||||||
|
|
||||||
|
/* And done with the cancellation, we'll do it now */
|
||||||
|
IoReleaseCancelSpinLock(Irp->CancelIrql);
|
||||||
|
|
||||||
|
/* If we have a context to cancel */
|
||||||
|
if (RxContext != NULL)
|
||||||
|
{
|
||||||
|
/* We cannot executed at dispatch, so queue a deferred cancel */
|
||||||
|
if (KeGetCurrentIrql() >= DISPATCH_LEVEL)
|
||||||
|
{
|
||||||
|
RxDispatchToWorkerThread(RxFileSystemDeviceObject, CriticalWorkQueue, RxpCancelRoutine, RxContext);
|
||||||
|
}
|
||||||
|
/* Cancel now! */
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RxpCancelRoutine(RxContext);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -7491,6 +7608,35 @@ RxNotifyChangeDirectory(
|
|||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @implemented
|
||||||
|
*/
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
RxpCancelRoutine(
|
||||||
|
PVOID Context)
|
||||||
|
{
|
||||||
|
PRX_CONTEXT RxContext;
|
||||||
|
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
RxContext = Context;
|
||||||
|
|
||||||
|
/* First, notify mini-rdr about cancellation */
|
||||||
|
if (RxContext->MRxCancelRoutine != NULL)
|
||||||
|
{
|
||||||
|
RxContext->MRxCancelRoutine(RxContext);
|
||||||
|
}
|
||||||
|
/* If we didn't find in overflow queue, try in blocking operations */
|
||||||
|
else if (!RxCancelOperationInOverflowQueue(RxContext))
|
||||||
|
{
|
||||||
|
RxCancelBlockingOperation(RxContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* And delete the context */
|
||||||
|
RxDereferenceAndDeleteRxContext_Real(RxContext);
|
||||||
|
}
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
RxPostStackOverflowRead (
|
RxPostStackOverflowRead (
|
||||||
IN PRX_CONTEXT RxContext)
|
IN PRX_CONTEXT RxContext)
|
||||||
|
@ -143,6 +143,7 @@ LIST_ENTRY RxRecurrentWorkItemsList;
|
|||||||
KDPC RxTimerDpc;
|
KDPC RxTimerDpc;
|
||||||
KTIMER RxTimer;
|
KTIMER RxTimer;
|
||||||
ULONG RxTimerTickCount;
|
ULONG RxTimerTickCount;
|
||||||
|
FAST_MUTEX RxContextPerFileSerializationMutex;
|
||||||
#if DBG
|
#if DBG
|
||||||
BOOLEAN DumpDispatchRoutine = TRUE;
|
BOOLEAN DumpDispatchRoutine = TRUE;
|
||||||
#else
|
#else
|
||||||
@ -715,6 +716,66 @@ RxBootstrapWorkerThreadDispatcher(
|
|||||||
RxpWorkerThreadDispatcher(RxWorkQueue, NULL);
|
RxpWorkerThreadDispatcher(RxWorkQueue, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @implemented
|
||||||
|
*/
|
||||||
|
VOID
|
||||||
|
RxCancelBlockingOperation(
|
||||||
|
IN OUT PRX_CONTEXT RxContext)
|
||||||
|
{
|
||||||
|
PFOBX Fobx;
|
||||||
|
BOOLEAN PostRequest;
|
||||||
|
C_ASSERT(FIELD_OFFSET(RX_CONTEXT, IoStatusBlock.Status) == 100);
|
||||||
|
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
Fobx = (PFOBX)RxContext->pFobx;
|
||||||
|
PostRequest = FALSE;
|
||||||
|
|
||||||
|
/* Acquire the pipe mutex */
|
||||||
|
ExAcquireFastMutex(&RxContextPerFileSerializationMutex);
|
||||||
|
|
||||||
|
/* If that's a blocking pipe operation which is not the CCB one, then handle it */
|
||||||
|
if (BooleanFlagOn(RxContext->FlagsForLowIo, RXCONTEXT_FLAG4LOWIO_PIPE_SYNC_OPERATION) &&
|
||||||
|
RxContext->RxContextSerializationQLinks.Flink != NULL &&
|
||||||
|
RxContext != CONTAINING_RECORD(&Fobx->Specific.NamedPipe.ReadSerializationQueue, RX_CONTEXT, RxContextSerializationQLinks) &&
|
||||||
|
RxContext != CONTAINING_RECORD(&Fobx->Specific.NamedPipe.WriteSerializationQueue, RX_CONTEXT, RxContextSerializationQLinks))
|
||||||
|
{
|
||||||
|
/* Clear it! */
|
||||||
|
ClearFlag(RxContext->FlagsForLowIo, RXCONTEXT_FLAG4LOWIO_PIPE_SYNC_OPERATION);
|
||||||
|
|
||||||
|
/* Drop it off the list */
|
||||||
|
RemoveEntryList(&RxContext->RxContextSerializationQLinks);
|
||||||
|
RxContext->RxContextSerializationQLinks.Flink = NULL;
|
||||||
|
RxContext->RxContextSerializationQLinks.Blink = NULL;
|
||||||
|
|
||||||
|
/* Set we've been cancelled */
|
||||||
|
RxContext->IoStatusBlock.Status = STATUS_CANCELLED;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If it's async, we'll post completion, otherwise, we signal to waiters
|
||||||
|
* it's being cancelled
|
||||||
|
*/
|
||||||
|
if (BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_ASYNC_OPERATION))
|
||||||
|
{
|
||||||
|
PostRequest = TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RxSignalSynchronousWaiter(RxContext);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Done */
|
||||||
|
ExReleaseFastMutex(&RxContextPerFileSerializationMutex);
|
||||||
|
|
||||||
|
/* Post if async */
|
||||||
|
if (PostRequest)
|
||||||
|
{
|
||||||
|
RxFsdPostRequest(RxContext);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @implemented
|
* @implemented
|
||||||
*/
|
*/
|
||||||
@ -7562,6 +7623,32 @@ RxRemoveNameNetFcb(
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @implemented
|
||||||
|
*/
|
||||||
|
VOID
|
||||||
|
RxRemoveOperationFromBlockingQueue(
|
||||||
|
IN OUT PRX_CONTEXT RxContext)
|
||||||
|
{
|
||||||
|
/* Acquire the pipe mutex */
|
||||||
|
ExAcquireFastMutex(&RxContextPerFileSerializationMutex);
|
||||||
|
|
||||||
|
/* Is that a blocking serial operation? */
|
||||||
|
if (BooleanFlagOn(RxContext->FlagsForLowIo, RXCONTEXT_FLAG4LOWIO_PIPE_SYNC_OPERATION))
|
||||||
|
{
|
||||||
|
/* Clear it! */
|
||||||
|
ClearFlag(RxContext->FlagsForLowIo, RXCONTEXT_FLAG4LOWIO_PIPE_SYNC_OPERATION);
|
||||||
|
|
||||||
|
/* Drop it off the list */
|
||||||
|
RemoveEntryList(&RxContext->RxContextSerializationQLinks);
|
||||||
|
RxContext->RxContextSerializationQLinks.Flink = NULL;
|
||||||
|
RxContext->RxContextSerializationQLinks.Blink = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Done */
|
||||||
|
ExReleaseFastMutex(&RxContextPerFileSerializationMutex);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @implemented
|
* @implemented
|
||||||
*/
|
*/
|
||||||
|
Loading…
Reference in New Issue
Block a user