[ros-diffs] [cgutman] 47470: [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

cgutman at svn.reactos.org cgutman at svn.reactos.org
Mon May 31 00:18:51 CEST 2010


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/rw.c?rev=47470&r1=47469&r2=47470&view=diff
==============================================================================
--- 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)
         {




More information about the Ros-diffs mailing list