[ovs-dev] [PATCH 2/2] datapath-windows: Support for IRP cancelling mechanism

Sorin Vinturis svinturis at cloudbasesolutions.com
Wed Jul 15 08:55:31 UTC 2015


Under certain circumstances, we might need to cancel a pending IRP
that has been submitted and not yet responded. This might occur when
the request takes too long to complete or when the process which
initiated the request terminated, leaving the request outstanding.

This patch adds this missing piece by providing support for IRP
cancelling mechanism.

Signed-off-by: Sorin Vinturis <svinturis at cloudbasesolutions.com>
Reported-by: Sorin Vinturis <svinturis at cloudbasesolutions.com>
Reported-at: https://github.com/openvswitch/ovs-issues/issues/95
---
 datapath-windows/ovsext/Datapath.c     |   4 ++
 datapath-windows/ovsext/TunnelFilter.c | 110 +++++++++++++++++++++++++++++++--
 datapath-windows/ovsext/TunnelIntf.h   |   3 +
 3 files changed, 112 insertions(+), 5 deletions(-)

diff --git a/datapath-windows/ovsext/Datapath.c b/datapath-windows/ovsext/Datapath.c
index 4af909c..0ec33bd 100644
--- a/datapath-windows/ovsext/Datapath.c
+++ b/datapath-windows/ovsext/Datapath.c
@@ -922,6 +922,10 @@ exit:
          * to be processed later, so we mark the IRP as pending and complete
          * it in another thread when the request is processed. */
         IoMarkIrpPending(irp);
+
+        /* Set the Cancel routine for the pending IRP. */
+        IoSetCancelRoutine(irp, OvsTunnelFilterCancelIrp);
+        
         return status;
     }
     return OvsCompleteIrpRequest(irp, (ULONG_PTR)replyLen, status);
diff --git a/datapath-windows/ovsext/TunnelFilter.c b/datapath-windows/ovsext/TunnelFilter.c
index caaf3f6..2542f63 100644
--- a/datapath-windows/ovsext/TunnelFilter.c
+++ b/datapath-windows/ovsext/TunnelFilter.c
@@ -168,6 +168,8 @@ static VOID     OvsTunnelFilterThreadStop(POVS_TUNFLT_THREAD_CONTEXT threadCtx,
                                           BOOLEAN signalEvent);
 static NTSTATUS OvsTunnelFilterThreadInit(POVS_TUNFLT_THREAD_CONTEXT threadCtx);
 static VOID     OvsTunnelFilterThreadUninit(POVS_TUNFLT_THREAD_CONTEXT threadCtx);
+static VOID     OvsTunnelFilterSetIrpContext(POVS_TUNFLT_REQUEST_LIST listRequests,
+                                             POVS_TUNFLT_REQUEST request);
 
 /*
  * Callout driver global variables
@@ -983,6 +985,7 @@ VOID
 OvsTunnelFilterRequestPush(POVS_TUNFLT_REQUEST_LIST listRequests,
                            POVS_TUNFLT_REQUEST request)
 {
+
     NdisAcquireSpinLock(&listRequests->spinlock);
 
     InsertTailList(&listRequests->head, &(request->entry));
@@ -1012,6 +1015,10 @@ OvsTunnelFilterThreadPush(POVS_TUNFLT_REQUEST request)
         &gTunnelThreadCtx[threadIndex].listRequests,
         request);
 
+    OvsTunnelFilterSetIrpContext(
+        &gTunnelThreadCtx[threadIndex].listRequests,
+        request);
+
     KeSetEvent(&gTunnelThreadCtx[threadIndex].requestEvent,
                IO_NO_INCREMENT,
                FALSE);
@@ -1062,6 +1069,20 @@ OvsTunnelFilterRequestListProcess(POVS_TUNFLT_THREAD_CONTEXT threadCtx)
         while (NULL != (request = OvsTunnelFilterRequestPop(
             &threadCtx->listRequests))) {
 
+            if (request->irp) {
+                if (!IoSetCancelRoutine(request->irp, NULL)) {
+                    /*
+                     * The Cancel routine for the current IRP is running.
+                     * Leave the IRP alone and go to the next one.
+                     */
+                    continue;
+                }
+            }
+
+            /*
+             * The Cancel routine cannot run now and cannot already have
+             * started to run.
+             */
             status = OvsTunnelFilterExecuteAction(threadCtx->engineSession,
                                                   request);
 
@@ -1321,7 +1342,7 @@ OvsTunnelFilterThreadUninit(POVS_TUNFLT_THREAD_CONTEXT threadCtx)
  * --------------------------------------------------------------------------
  * This function creates a new tunnel filter request and push it to a thread
  * queue. If the thread stop event is signaled, the request is completed with
- * STATUS_CANCELLED without pushing it to any queue.
+ * STATUS_REQUEST_ABORTED without pushing it to any queue.
  * --------------------------------------------------------------------------
  */
 NTSTATUS
@@ -1347,7 +1368,7 @@ OvsTunnelFilterQueueRequest(PIRP irp,
                                   (LARGE_INTEGER *)&timeout)) {
             /* The stop event is signaled. Completed the IRP with
              * STATUS_CANCELLED. */
-            status = STATUS_CANCELLED;
+            status = STATUS_REQUEST_ABORTED;
             break;
         }
 
@@ -1396,8 +1417,8 @@ OvsTunnelFilterQueueRequest(PIRP irp,
 
 /*
  * --------------------------------------------------------------------------
- *  This function adds a new WFP filter for the received port and returns the
- *  ID of the created WFP filter.
+ * This function adds a new WFP filter for the received port and returns the
+ * ID of the created WFP filter.
  *
  *  Note:
  *  All necessary calls to the WFP filtering engine must be running at IRQL =
@@ -1436,7 +1457,7 @@ OvsTunelFilterCreate(PIRP irp,
 
 /*
  * --------------------------------------------------------------------------
- *  This function removes a WFP filter using the received filter ID.
+ * This function removes a WFP filter using the received filter ID.
  *
  *  Note:
  *  All necessary calls to the WFP filtering engine must be running at IRQL =
@@ -1471,3 +1492,82 @@ OvsTunelFilterDelete(PIRP irp,
                                        callback,
                                        tunnelContext);
 }
+
+VOID
+OvsTunnelFilterSetIrpContext(POVS_TUNFLT_REQUEST_LIST listRequests,
+                             POVS_TUNFLT_REQUEST request)
+{
+    PIRP irp = request->irp;
+
+    if (irp) {
+        /* Set the IRP's DriverContext to be used for later. */
+        irp->Tail.Overlay.DriverContext[0] = (PVOID)request;
+        irp->Tail.Overlay.DriverContext[1] = (PVOID)listRequests;
+    }
+}
+
+/*
+ * --------------------------------------------------------------------------
+ * This function removes the cancelled request from the corresponding thread
+ * queue.
+ * --------------------------------------------------------------------------
+ */
+VOID
+OvsTunnelFilterRequestDequeue(PIRP irp)
+{
+    POVS_TUNFLT_REQUEST_LIST listRequests =
+        (POVS_TUNFLT_REQUEST_LIST)irp->Tail.Overlay.DriverContext[1];
+    PLIST_ENTRY head, link, next;
+
+    NdisAcquireSpinLock(&listRequests->spinlock);
+
+    head = &listRequests->head;
+    LIST_FORALL_SAFE(head, link, next) {
+        POVS_TUNFLT_REQUEST request = NULL;
+
+        request = CONTAINING_RECORD(link, OVS_TUNFLT_REQUEST, entry);
+
+        if (request->irp == irp) {
+            RemoveEntryList(&request->entry);
+            listRequests->numEntries--;
+            break;
+        }
+    }
+
+    NdisReleaseSpinLock(&listRequests->spinlock);
+}
+
+/*
+ * --------------------------------------------------------------------------
+ * This function is the Cancel routine to be called if the IRP is canceled.
+ * --------------------------------------------------------------------------
+ */
+VOID
+OvsTunnelFilterCancelIrp(PDEVICE_OBJECT DeviceObject,
+                         PIRP irp)
+{
+    POVS_TUNFLT_REQUEST request =
+        (POVS_TUNFLT_REQUEST)irp->Tail.Overlay.DriverContext[0];
+
+    DBG_UNREFERENCED_PARAMETER(DeviceObject);
+
+    /* Release the global cancel spinlock. */
+    IoReleaseCancelSpinLock(irp->CancelIrql);
+
+    /*
+     * Remove the request from the corresponding tunnel filter thread's
+     * queue.
+     */
+    OvsTunnelFilterRequestDequeue(irp);
+
+    /* Clear the cancel routine from the IRP. */
+    IoSetCancelRoutine(irp, NULL);
+
+    /* We are done with this IRP, so complete it with STATUS_CANCELLED. */
+    OvsTunnelFilterCompleteRequest(request->irp,
+                                   request->callback,
+                                   request->context,
+                                   STATUS_CANCELLED);
+
+    OvsFreeMemory(request);
+}
diff --git a/datapath-windows/ovsext/TunnelIntf.h b/datapath-windows/ovsext/TunnelIntf.h
index 6a2c980..ebbd564 100644
--- a/datapath-windows/ovsext/TunnelIntf.h
+++ b/datapath-windows/ovsext/TunnelIntf.h
@@ -40,5 +40,8 @@ NTSTATUS OvsTunelFilterDelete(PIRP irp,
                               UINT64 filterID,
                               PFNTunnelVportPendingOp callback,
                               PVOID context);
+
+VOID OvsTunnelFilterCancelIrp(PDEVICE_OBJECT DeviceObject,
+                              PIRP Irp);
 
 #endif /* __TUNNEL_INTF_H_ */
-- 
1.9.0.msysgit.0



More information about the dev mailing list