[MSFS]
authorPierre Schweitzer <pierre@reactos.org>
Sat, 10 Oct 2015 12:50:33 +0000 (12:50 +0000)
committerPierre Schweitzer <pierre@reactos.org>
Sat, 10 Oct 2015 12:50:33 +0000 (12:50 +0000)
Fix a FIXME: properly reset timer when re-using a queued IRP for reading.
Also fix a possible race condition between time out DPC and IRP re-use.

Thanks to Thomas for his help with DPC & timers.

CORE-10245

svn path=/trunk/; revision=69483

reactos/drivers/filesystems/msfs/msfs.h
reactos/drivers/filesystems/msfs/msfssup.c
reactos/drivers/filesystems/msfs/rw.c

index 14934fb..7393af9 100644 (file)
@@ -46,6 +46,7 @@ typedef struct _MSFS_DPC_CTX
     KTIMER Timer;
     KDPC Dpc;
     PIO_CSQ Csq;
+    KEVENT Event;
     IO_CSQ_IRP_CONTEXT CsqContext;
 } MSFS_DPC_CTX, *PMSFS_DPC_CTX;
 
index b59a2e9..2ece881 100644 (file)
@@ -117,14 +117,20 @@ MsfsTimeout(PKDPC Dpc,
 
     Context = (PMSFS_DPC_CTX)DeferredContext;
 
+    /* Try to get the IRP */
     Irp = IoCsqRemoveIrp(Context->Csq, &Context->CsqContext);
     if (Irp != NULL)
     {
+        /* It timed out, complete it (it's ours) and free context */
         Irp->IoStatus.Status = STATUS_IO_TIMEOUT;
         IoCompleteRequest(Irp, IO_NO_INCREMENT);
+        ExFreePoolWithTag(Context, 'NFsM');
+    }
+    else
+    {
+        /* We were racing with writing and failed, signal we're done */
+        KeSetEvent(&Context->Event, IO_NO_INCREMENT, FALSE);
     }
-
-    ExFreePool(Context);
 }
 
 /* EOF */
index e6b3c1c..22bc555 100644 (file)
@@ -107,10 +107,12 @@ MsfsRead(PDEVICE_OBJECT DeviceObject,
         return STATUS_INSUFFICIENT_RESOURCES;
     }
 
+    KeInitializeEvent(&Context->Event, SynchronizationEvent, FALSE);
     IoCsqInsertIrp(&Fcb->CancelSafeQueue, Irp, &Context->CsqContext);
     Timer = &Context->Timer;
     Dpc = &Context->Dpc;
     Context->Csq = &Fcb->CancelSafeQueue;
+    Irp->Tail.Overlay.DriverContext[0] = Context;
 
     /* No timer for INFINITY_WAIT */
     if (Timeout.QuadPart != -1)
@@ -139,6 +141,7 @@ MsfsWrite(PDEVICE_OBJECT DeviceObject,
     ULONG Length;
     PVOID Buffer;
     PIRP CsqIrp;
+    PMSFS_DPC_CTX Context;
 
     DPRINT("MsfsWrite(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
 
@@ -193,7 +196,16 @@ MsfsWrite(PDEVICE_OBJECT DeviceObject,
     CsqIrp = IoCsqRemoveNextIrp(&Fcb->CancelSafeQueue, NULL);
     if (CsqIrp != NULL)
     {
-        /* FIXME: It is necessary to reset the timers. */
+        /* Get the context */
+        Context = CsqIrp->Tail.Overlay.DriverContext[0];
+        /* DPC was queued, wait for it to fail (IRP is ours) */
+        if (Fcb->TimeOut.QuadPart != -1 && !KeCancelTimer(&Context->Timer))
+        {
+            KeWaitForSingleObject(&Context->Event, Executive, KernelMode, FALSE, NULL);
+        }
+
+        /* Free context & attempt read */
+        ExFreePoolWithTag(Context, 'NFsM');
         MsfsRead(DeviceObject, CsqIrp);
     }