|
[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
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |