[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[win-pv-devel] [PATCH] Add DPC timeout check



From: Owen Smith <owen.smith@xxxxxxxxxx>

Check the DPC has not exceeded 1/2 its alloted time every
* 1/4 ring of responses processed
* all outstanding prepared requests submitted
* 1 queued SRB prepared

Signed-off-by: Owen Smith <owen.smith@xxxxxxxxxx>
---
 src/xenvbd/blockring.c | 12 ++++++---
 src/xenvbd/blockring.h |  2 +-
 src/xenvbd/frontend.c  | 10 +++++---
 src/xenvbd/frontend.h  |  2 +-
 src/xenvbd/notifier.c  | 66 ++++++++++++++++++++++++++++++++++++++++++++++----
 src/xenvbd/target.c    | 13 ++++++++--
 src/xenvbd/target.h    |  2 +-
 7 files changed, 91 insertions(+), 16 deletions(-)

diff --git a/src/xenvbd/blockring.c b/src/xenvbd/blockring.c
index e00b64a..24e47c0 100644
--- a/src/xenvbd/blockring.c
+++ b/src/xenvbd/blockring.c
@@ -506,12 +506,13 @@ BlockRingDebugCallback(
     BlockRing->Submitted = BlockRing->Received = 0;
 }
 
-VOID
+BOOLEAN
 BlockRingPoll(
     IN  PXENVBD_BLOCKRING           BlockRing
     )
 {
     PXENVBD_TARGET Target = FrontendGetTarget(BlockRing->Frontend);
+    BOOLEAN         Retry = FALSE;
 
     ASSERT3U(KeGetCurrentIrql(), ==, DISPATCH_LEVEL);
     KeAcquireSpinLockAtDpcLevel(&BlockRing->Lock);
@@ -532,10 +533,10 @@ BlockRingPoll(
 
         KeMemoryBarrier();
 
-        if (rsp_cons == rsp_prod)
+        if (rsp_cons == rsp_prod || Retry)
             break;
 
-        while (rsp_cons != rsp_prod) {
+        while (rsp_cons != rsp_prod && !Retry) {
             blkif_response_t*   Response;
             ULONG               Tag;
 
@@ -548,6 +549,9 @@ BlockRingPoll(
             }
 
             RtlZeroMemory(Response, sizeof(union blkif_sring_entry));
+
+            if (rsp_cons - BlockRing->FrontRing.rsp_cons > 
RING_SIZE(&BlockRing->FrontRing) / 4)
+                Retry = TRUE;
         }
 
         KeMemoryBarrier();
@@ -558,6 +562,8 @@ BlockRingPoll(
 
 done:
     KeReleaseSpinLockFromDpcLevel(&BlockRing->Lock);
+
+    return Retry;
 }
 
 BOOLEAN
diff --git a/src/xenvbd/blockring.h b/src/xenvbd/blockring.h
index 1117d73..98fe278 100644
--- a/src/xenvbd/blockring.h
+++ b/src/xenvbd/blockring.h
@@ -83,7 +83,7 @@ BlockRingDebugCallback(
     IN  PXENBUS_DEBUG_INTERFACE     Debug
     );
 
-extern VOID
+extern BOOLEAN
 BlockRingPoll(
     IN  PXENVBD_BLOCKRING           BlockRing
     );
diff --git a/src/xenvbd/frontend.c b/src/xenvbd/frontend.c
index c909ea8..2ec082d 100644
--- a/src/xenvbd/frontend.c
+++ b/src/xenvbd/frontend.c
@@ -326,13 +326,17 @@ out:
 
 //=============================================================================
 __drv_requiresIRQL(DISPATCH_LEVEL)
-VOID
+BOOLEAN
 FrontendNotifyResponses(
     __in  PXENVBD_FRONTEND        Frontend
     )
 {
-    BlockRingPoll(Frontend->BlockRing);
-    TargetSubmitRequests(Frontend->Target);
+    BOOLEAN     Retry = FALSE;
+    
+    Retry |= BlockRingPoll(Frontend->BlockRing);
+    Retry |= TargetSubmitRequests(Frontend->Target);
+
+    return Retry;
 }
 
 //=============================================================================
diff --git a/src/xenvbd/frontend.h b/src/xenvbd/frontend.h
index 8a6cc04..4490aeb 100644
--- a/src/xenvbd/frontend.h
+++ b/src/xenvbd/frontend.h
@@ -149,7 +149,7 @@ FrontendWriteUsage(
 
 // Ring
 __drv_requiresIRQL(DISPATCH_LEVEL)
-extern VOID
+extern BOOLEAN
 FrontendNotifyResponses(
     __in  PXENVBD_FRONTEND        Frontend
     );
diff --git a/src/xenvbd/notifier.c b/src/xenvbd/notifier.c
index a87c3bd..22bfe00 100644
--- a/src/xenvbd/notifier.c
+++ b/src/xenvbd/notifier.c
@@ -50,6 +50,8 @@ struct _XENVBD_NOTIFIER {
     ULONG                           NumInts;
     ULONG                           NumDpcs;
     KDPC                            Dpc;
+    KDPC                            TimerDpc;
+    KTIMER                          Timer;
 };
 
 #define NOTIFIER_POOL_TAG           'yfNX'
@@ -95,6 +97,37 @@ NotifierInterrupt(
     return TRUE;
 }
 
+static FORCEINLINE BOOLEAN
+__NotifierDpcTimeout(
+    IN  PXENVBD_NOTIFIER        Notifier
+    )
+{
+    KDPC_WATCHDOG_INFORMATION   Watchdog;
+    NTSTATUS                    status;
+
+    UNREFERENCED_PARAMETER(Notifier);
+
+    RtlZeroMemory(&Watchdog, sizeof (Watchdog));
+
+    status = KeQueryDpcWatchdogInformation(&Watchdog);
+    ASSERT(NT_SUCCESS(status));
+
+    if (Watchdog.DpcTimeLimit == 0 ||
+        Watchdog.DpcWatchdogLimit == 0)
+        return FALSE;
+
+    if (Watchdog.DpcTimeCount > (Watchdog.DpcTimeLimit / 2) &&
+        Watchdog.DpcWatchdogCount > (Watchdog.DpcWatchdogLimit / 2))
+        return FALSE;
+
+    return TRUE;
+}
+
+#define TIME_US(_us)        ((_us) * 10)
+#define TIME_MS(_ms)        (TIME_US((_ms) * 1000))
+#define TIME_S(_s)          (TIME_MS((_s) * 1000))
+#define TIME_RELATIVE(_t)   (-(_t))
+
 KDEFERRED_ROUTINE NotifierDpc;
 
 VOID 
@@ -116,12 +149,25 @@ NotifierDpc(
     if (!Notifier->Connected)
         return;
 
-    FrontendNotifyResponses(Notifier->Frontend);
+    for (;;) {
+        if (!FrontendNotifyResponses(Notifier->Frontend)) {
+            XENBUS_EVTCHN(Unmask,
+                          &Notifier->EvtchnInterface,
+                          Notifier->Channel,
+                          FALSE);
+            break;
+        }
+        if (__NotifierDpcTimeout(Notifier)) {
+            LARGE_INTEGER   Delay;
 
-    XENBUS_EVTCHN(Unmask,
-                  &Notifier->EvtchnInterface,
-                  Notifier->Channel,
-                  FALSE);
+            Delay.QuadPart = TIME_RELATIVE(TIME_US(100));
+
+            KeSetTimer(&Notifier->Timer,
+                       Delay,
+                       &Notifier->TimerDpc);
+            break;
+        }
+    }
 }
 
 NTSTATUS
@@ -136,6 +182,8 @@ NotifierCreate(
 
     (*Notifier)->Frontend = Frontend;
     KeInitializeDpc(&(*Notifier)->Dpc, NotifierDpc, *Notifier);
+    KeInitializeDpc(&(*Notifier)->TimerDpc, NotifierDpc, *Notifier);
+    KeInitializeTimer(&(*Notifier)->Timer);
 
     return STATUS_SUCCESS;
 
@@ -150,6 +198,8 @@ NotifierDestroy(
 {
     Notifier->Frontend = NULL;
     RtlZeroMemory(&Notifier->Dpc, sizeof(KDPC));
+    RtlZeroMemory(&Notifier->TimerDpc, sizeof(KDPC));
+    RtlZeroMemory(&Notifier->Timer, sizeof(KTIMER));
 
     ASSERT(IsZeroMemory(Notifier, sizeof(XENVBD_NOTIFIER)));
     
@@ -252,6 +302,12 @@ NotifierDisable(
     ASSERT(Notifier->Enabled == TRUE);
 
     Notifier->Enabled = FALSE;
+
+    //
+    // No new timers can be scheduled once Enabled goes to FALSE.
+    // Cancel any existing ones.
+    //
+    (VOID) KeCancelTimer(&Notifier->Timer);
 }
 
 VOID
diff --git a/src/xenvbd/target.c b/src/xenvbd/target.c
index ffffa3e..697f309 100644
--- a/src/xenvbd/target.c
+++ b/src/xenvbd/target.c
@@ -1254,11 +1254,13 @@ BlkifOperationName(
     }
 }
 
-VOID
+BOOLEAN
 TargetSubmitRequests(
     IN  PXENVBD_TARGET  Target
     )
 {
+    BOOLEAN             Retry = FALSE;
+
     for (;;) {
         // submit all prepared requests (0 or more requests)
         // return TRUE if submitted 0 or more requests from prepared queue
@@ -1271,10 +1273,17 @@ TargetSubmitRequests(
         // return FALSE if prepare failed or fresh queue empty
         if (!TargetPrepareFresh(Target))
             break;
+
+        // back off, check DPC timeout and try again
+        Retry = TRUE;
+        break;
     }
 
     // if no requests/SRBs outstanding, complete any shutdown SRBs
-    TargetCompleteShutdown(Target);
+    if (!Retry)
+        TargetCompleteShutdown(Target);
+
+    return Retry;
 }
 
 VOID
diff --git a/src/xenvbd/target.h b/src/xenvbd/target.h
index 1e2b3ed..b790eb4 100644
--- a/src/xenvbd/target.h
+++ b/src/xenvbd/target.h
@@ -93,7 +93,7 @@ TargetSetDeviceObject(
     IN  PDEVICE_OBJECT  DeviceObject
     );
 
-extern VOID
+extern BOOLEAN
 TargetSubmitRequests(
     IN  PXENVBD_TARGET  Target
     );
-- 
2.8.3


_______________________________________________
win-pv-devel mailing list
win-pv-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.