Author: cgutman
Date: Mon May 31 00:18:50 2010
New Revision: 47470
URL:
http://svn.reactos.org/svn/reactos?rev=47470&view=rev
Log:
[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
Modified:
trunk/reactos/drivers/filesystems/npfs/rw.c
Modified: trunk/reactos/drivers/filesystems/npfs/rw.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/filesystems/npfs/r…
==============================================================================
--- trunk/reactos/drivers/filesystems/npfs/rw.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/filesystems/npfs/rw.c [iso-8859-1] Mon May 31 00:18:50 2010
@@ -51,7 +51,9 @@
PNPFS_DEVICE_EXTENSION DeviceExt;
PIO_STACK_LOCATION IoStack;
PNPFS_CCB Ccb;
- BOOLEAN Complete = FALSE;
+ PLIST_ENTRY ListEntry;
+ PNPFS_THREAD_CONTEXT ThreadContext;
+ ULONG i;
DPRINT("NpfsReadWriteCancelRoutine(DeviceObject %p, Irp %p)\n",
DeviceObject, Irp);
@@ -67,27 +69,49 @@
switch(IoStack->MajorFunction)
{
case IRP_MJ_READ:
- if (Ccb->ReadRequestListHead.Flink != &Context->ListEntry)
- {
- /* we are not the first in the list, remove an complete us */
- RemoveEntryList(&Context->ListEntry);
- Complete = TRUE;
- }
- else
- {
- KeSetEvent(&Ccb->ReadEvent, IO_NO_INCREMENT, FALSE);
- }
+ ListEntry = DeviceExt->ThreadListHead.Flink;
+ while (ListEntry != &DeviceExt->ThreadListHead)
+ {
+ ThreadContext = CONTAINING_RECORD(ListEntry, NPFS_THREAD_CONTEXT,
ListEntry);
+ /* Real events start at index 1 */
+ for (i = 1; i < ThreadContext->Count; i++)
+ {
+ if (ThreadContext->WaitIrpArray[i] == Irp)
+ {
+ 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;
default:
ASSERT(FALSE);
- }
- ExReleaseFastMutex(&Ccb->DataListLock);
- KeUnlockMutex(&DeviceExt->PipeListLock);
- if (Complete)
- {
- Irp->IoStatus.Status = STATUS_CANCELLED;
- Irp->IoStatus.Information = 0;
- IoCompleteRequest(Irp, IO_NO_INCREMENT);
}
}
@@ -96,7 +120,7 @@
{
PNPFS_THREAD_CONTEXT ThreadContext = (PNPFS_THREAD_CONTEXT) InitContext;
ULONG CurrentCount;
- ULONG Count = 0;
+ ULONG Count = 0, i;
PIRP Irp = NULL;
PIRP NextIrp;
NTSTATUS Status;
@@ -191,8 +215,20 @@
}
else
{
- /* someone has add a new wait request */
+ /* someone has add a new wait request or cancelled an old one */
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)
{