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

[win-pv-devel] [PATCH] Add STORE watchdog



There have been occasions during testing when xenstored has apparently
missed sending notification to the frontend that data is on the ring.
This patch adds a watchdog to the code to notice when either of the rings
has stalled and try to move things along.

Signed-off-by: Paul Durrant <paul.durrant@xxxxxxxxxx>
---
 src/xenbus/store.c | 134 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 134 insertions(+)

diff --git a/src/xenbus/store.c b/src/xenbus/store.c
index 127bb98..dc4e7f3 100644
--- a/src/xenbus/store.c
+++ b/src/xenbus/store.c
@@ -37,6 +37,7 @@
 
 #include "store.h"
 #include "evtchn.h"
+#include "thread.h"
 #include "fdo.h"
 #include "dbg_print.h"
 #include "assert.h"
@@ -143,6 +144,8 @@ struct _XENBUS_STORE_CONTEXT {
     PXENBUS_SUSPEND_CALLBACK            SuspendCallbackEarly;
     PXENBUS_SUSPEND_CALLBACK            SuspendCallbackLate;
     PXENBUS_DEBUG_CALLBACK              DebugCallback;
+    PXENBUS_THREAD                      WatchdogThread;
+    BOOLEAN                             Enabled;
 };
 
 C_ASSERT(sizeof (struct xenstore_domain_interface) <= PAGE_SIZE);
@@ -1816,6 +1819,93 @@ StorePoll(
     KeReleaseSpinLockFromDpcLevel(&Context->Lock);
 }
 
+#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))
+
+#define XENBUS_STORE_WATCHDOG_PERIOD 15
+
+static NTSTATUS
+StoreWatchdog(
+    IN  PXENBUS_THREAD                  Self,
+    IN  PVOID                           _Context
+    )
+{
+    PXENBUS_STORE_CONTEXT               Context = _Context;
+    LARGE_INTEGER                       Timeout;
+    XENSTORE_RING_IDX                   req_prod;
+    XENSTORE_RING_IDX                   req_cons;
+    XENSTORE_RING_IDX                   rsp_prod;
+    XENSTORE_RING_IDX                   rsp_cons;
+
+    Trace("====>\n");
+
+    Timeout.QuadPart = TIME_RELATIVE(TIME_S(XENBUS_STORE_WATCHDOG_PERIOD));
+
+    req_prod = 0;
+    req_cons = 0;
+    rsp_prod = 0;
+    rsp_cons = 0;
+
+    for (;;) {
+        PKEVENT Event;
+        KIRQL   Irql;
+
+        Event = ThreadGetEvent(Self);
+
+        (VOID) KeWaitForSingleObject(Event,
+                                     Executive,
+                                     KernelMode,
+                                     FALSE,
+                                     &Timeout);
+        KeClearEvent(Event);
+
+        if (ThreadIsAlerted(Self))
+            break;
+
+        KeRaiseIrql(DISPATCH_LEVEL, &Irql);
+        KeAcquireSpinLockAtDpcLevel(&Context->Lock);
+
+        if (Context->Enabled) {
+            struct xenstore_domain_interface    *Shared;
+
+            Shared = Context->Shared;
+
+            KeMemoryBarrier();
+
+            if ((Shared->rsp_prod != rsp_prod &&
+                 Shared->rsp_cons == rsp_cons) ||
+                (Shared->req_prod != req_prod &&
+                 Shared->req_cons == req_cons)) {
+                XENBUS_DEBUG(Trigger,
+                             &Context->DebugInterface,
+                             Context->DebugCallback);
+
+                // Try to move things along
+                (VOID) XENBUS_EVTCHN(Send,
+                                     &Context->EvtchnInterface,
+                                     Context->Channel);
+                StorePollLocked(Context);
+            }
+
+            KeMemoryBarrier();
+
+            req_prod = Shared->req_prod;
+            req_cons = Shared->req_cons;
+            rsp_prod = Shared->rsp_prod;
+            rsp_cons = Shared->rsp_cons;
+        }
+
+        KeReleaseSpinLockFromDpcLevel(&Context->Lock);
+        KeLowerIrql(Irql);
+    }
+
+    Trace("<====\n");
+
+    return STATUS_SUCCESS;
+}
+
 static NTSTATUS
 StorePermissionToString(
     IN  PXENBUS_STORE_PERMISSION    Permission,
@@ -2017,6 +2107,8 @@ StoreDisable(
     IN PXENBUS_STORE_CONTEXT    Context
     )
 {
+    Context->Enabled = FALSE;
+
     XENBUS_EVTCHN(Close,
                   &Context->EvtchnInterface,
                   Context->Channel);
@@ -2055,6 +2147,8 @@ StoreEnable(
                   Context->Channel,
                   FALSE);
 
+    Context->Enabled = TRUE;
+
     // Trigger an initial poll
     KeInsertQueueDpc(&Context->Dpc, NULL, NULL);
 }
@@ -2573,12 +2667,48 @@ StoreInitialize(
 
     KeInitializeDpc(&(*Context)->Dpc, StoreDpc, *Context);
 
+    status = ThreadCreate(StoreWatchdog,
+                          *Context,
+                          &(*Context)->WatchdogThread);
+    if (!NT_SUCCESS(status))
+        goto fail2;
+
     (*Context)->Fdo = Fdo;
 
     Trace("<====\n");
 
     return STATUS_SUCCESS;
 
+fail2:
+    Error("fail2\n");
+
+    RtlZeroMemory(&(*Context)->Dpc, sizeof (KDPC));
+
+    RtlZeroMemory(&(*Context)->BufferList, sizeof (LIST_ENTRY));
+
+    RtlZeroMemory(&(*Context)->WatchList, sizeof (LIST_ENTRY));
+    (*Context)->WatchId = 0;
+
+    RtlZeroMemory(&(*Context)->TransactionList, sizeof (LIST_ENTRY));
+
+    RtlZeroMemory(&(*Context)->PendingList, sizeof (LIST_ENTRY));
+    RtlZeroMemory(&(*Context)->SubmittedList, sizeof (LIST_ENTRY));
+    (*Context)->RequestId = 0;
+
+    RtlZeroMemory(&(*Context)->Lock, sizeof (KSPIN_LOCK));
+
+    RtlZeroMemory(&(*Context)->DebugInterface,
+                  sizeof (XENBUS_DEBUG_INTERFACE));
+
+    RtlZeroMemory(&(*Context)->SuspendInterface,
+                  sizeof (XENBUS_SUSPEND_INTERFACE));
+
+    RtlZeroMemory(&(*Context)->EvtchnInterface,
+                  sizeof (XENBUS_EVTCHN_INTERFACE));
+
+    ASSERT(IsZeroMemory(*Context, sizeof (XENBUS_STORE_CONTEXT)));
+    __StoreFree(*Context);
+
 fail1:
     Error("fail1 (%08x)\n", status);
 
@@ -2647,6 +2777,10 @@ StoreTeardown(
 {
     Trace("====>\n");
 
+    ThreadAlert(Context->WatchdogThread);
+    ThreadJoin(Context->WatchdogThread);
+    Context->WatchdogThread = NULL;
+
     ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL);
     KeFlushQueuedDpcs();
 
-- 
2.1.1


_______________________________________________
win-pv-devel mailing list
win-pv-devel@xxxxxxxxxxxxxxxxxxxx
http://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®.