mirror of
https://github.com/reactos/reactos.git
synced 2025-02-24 17:34:57 +00:00
[NPFS]
- Fix race conditions in read IRP cancellation that resulting in random crashes and hangs - Fixes MULTIPLE_IRP_COMPLETE_REQUESTS bug checks and failed cancellations resulting in hangs during ntdll:file test svn path=/trunk/; revision=47470
This commit is contained in:
parent
1c2429510e
commit
5de258d708
1 changed files with 55 additions and 19 deletions
|
@ -51,7 +51,9 @@ NpfsReadWriteCancelRoutine(IN PDEVICE_OBJECT DeviceObject,
|
||||||
PNPFS_DEVICE_EXTENSION DeviceExt;
|
PNPFS_DEVICE_EXTENSION DeviceExt;
|
||||||
PIO_STACK_LOCATION IoStack;
|
PIO_STACK_LOCATION IoStack;
|
||||||
PNPFS_CCB Ccb;
|
PNPFS_CCB Ccb;
|
||||||
BOOLEAN Complete = FALSE;
|
PLIST_ENTRY ListEntry;
|
||||||
|
PNPFS_THREAD_CONTEXT ThreadContext;
|
||||||
|
ULONG i;
|
||||||
|
|
||||||
DPRINT("NpfsReadWriteCancelRoutine(DeviceObject %p, Irp %p)\n", DeviceObject, Irp);
|
DPRINT("NpfsReadWriteCancelRoutine(DeviceObject %p, Irp %p)\n", DeviceObject, Irp);
|
||||||
|
|
||||||
|
@ -67,28 +69,50 @@ NpfsReadWriteCancelRoutine(IN PDEVICE_OBJECT DeviceObject,
|
||||||
switch(IoStack->MajorFunction)
|
switch(IoStack->MajorFunction)
|
||||||
{
|
{
|
||||||
case IRP_MJ_READ:
|
case IRP_MJ_READ:
|
||||||
if (Ccb->ReadRequestListHead.Flink != &Context->ListEntry)
|
ListEntry = DeviceExt->ThreadListHead.Flink;
|
||||||
|
while (ListEntry != &DeviceExt->ThreadListHead)
|
||||||
{
|
{
|
||||||
/* we are not the first in the list, remove an complete us */
|
ThreadContext = CONTAINING_RECORD(ListEntry, NPFS_THREAD_CONTEXT, ListEntry);
|
||||||
RemoveEntryList(&Context->ListEntry);
|
/* Real events start at index 1 */
|
||||||
Complete = TRUE;
|
for (i = 1; i < ThreadContext->Count; i++)
|
||||||
}
|
{
|
||||||
else
|
if (ThreadContext->WaitIrpArray[i] == Irp)
|
||||||
{
|
{
|
||||||
KeSetEvent(&Ccb->ReadEvent, IO_NO_INCREMENT, FALSE);
|
ASSERT(ThreadContext->WaitObjectArray[i] == Context->WaitEvent);
|
||||||
|
|
||||||
|
ThreadContext->WaitIrpArray[i] = NULL;
|
||||||
|
|
||||||
|
RemoveEntryList(&Context->ListEntry);
|
||||||
|
|
||||||
|
Irp->IoStatus.Status = STATUS_CANCELLED;
|
||||||
|
Irp->IoStatus.Information = 0;
|
||||||
|
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
|
||||||
|
KeSetEvent(&ThreadContext->Event, IO_NO_INCREMENT, FALSE);
|
||||||
|
|
||||||
|
ExReleaseFastMutex(&Ccb->DataListLock);
|
||||||
|
KeUnlockMutex(&DeviceExt->PipeListLock);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ListEntry = ListEntry->Flink;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RemoveEntryList(&Context->ListEntry);
|
||||||
|
|
||||||
|
ExReleaseFastMutex(&Ccb->DataListLock);
|
||||||
|
KeUnlockMutex(&DeviceExt->PipeListLock);
|
||||||
|
|
||||||
|
Irp->IoStatus.Status = STATUS_CANCELLED;
|
||||||
|
Irp->IoStatus.Information = 0;
|
||||||
|
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ASSERT(FALSE);
|
ASSERT(FALSE);
|
||||||
}
|
}
|
||||||
ExReleaseFastMutex(&Ccb->DataListLock);
|
|
||||||
KeUnlockMutex(&DeviceExt->PipeListLock);
|
|
||||||
if (Complete)
|
|
||||||
{
|
|
||||||
Irp->IoStatus.Status = STATUS_CANCELLED;
|
|
||||||
Irp->IoStatus.Information = 0;
|
|
||||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static VOID NTAPI
|
static VOID NTAPI
|
||||||
|
@ -96,7 +120,7 @@ NpfsWaiterThread(PVOID InitContext)
|
||||||
{
|
{
|
||||||
PNPFS_THREAD_CONTEXT ThreadContext = (PNPFS_THREAD_CONTEXT) InitContext;
|
PNPFS_THREAD_CONTEXT ThreadContext = (PNPFS_THREAD_CONTEXT) InitContext;
|
||||||
ULONG CurrentCount;
|
ULONG CurrentCount;
|
||||||
ULONG Count = 0;
|
ULONG Count = 0, i;
|
||||||
PIRP Irp = NULL;
|
PIRP Irp = NULL;
|
||||||
PIRP NextIrp;
|
PIRP NextIrp;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
@ -191,8 +215,20 @@ NpfsWaiterThread(PVOID InitContext)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* someone has add a new wait request */
|
/* someone has add a new wait request or cancelled an old one */
|
||||||
Irp = NULL;
|
Irp = NULL;
|
||||||
|
|
||||||
|
/* Look for cancelled requests */
|
||||||
|
for (i = 1; i < ThreadContext->Count; i++)
|
||||||
|
{
|
||||||
|
if (ThreadContext->WaitIrpArray[i] == NULL)
|
||||||
|
{
|
||||||
|
ThreadContext->Count--;
|
||||||
|
ThreadContext->DeviceExt->EmptyWaiterCount++;
|
||||||
|
ThreadContext->WaitObjectArray[i] = ThreadContext->WaitObjectArray[ThreadContext->Count];
|
||||||
|
ThreadContext->WaitIrpArray[i] = ThreadContext->WaitIrpArray[ThreadContext->Count];
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (ThreadContext->Count == 1 && ThreadContext->DeviceExt->EmptyWaiterCount >= MAXIMUM_WAIT_OBJECTS)
|
if (ThreadContext->Count == 1 && ThreadContext->DeviceExt->EmptyWaiterCount >= MAXIMUM_WAIT_OBJECTS)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue