|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH] Force close the frontend if responses have been faked
If the ring disable process ended up faking responses, the shared ring
is no longer reusable and must be disconnected first. Otherwise, if the
ring is reenabled, the backend and frontend will desync.
Add a Poisoned flag to rings to indicate that they have been made
unusable. Introduce a transient Poisoned state to the frontend state
machine. If any ring has been poisoned, close the frontend before
reenabling it.
Signed-off-by: Tu Dinh <ngoc-tu.dinh@xxxxxxxxxx>
---
src/xenvbd/frontend.c | 30 +++++++++++++++++++++++++++++-
src/xenvbd/frontend.h | 3 ++-
src/xenvbd/ring.c | 25 +++++++++++++++++++++++++
src/xenvbd/ring.h | 5 +++++
4 files changed, 61 insertions(+), 2 deletions(-)
diff --git a/src/xenvbd/frontend.c b/src/xenvbd/frontend.c
index d8e3287..3b078da 100644
--- a/src/xenvbd/frontend.c
+++ b/src/xenvbd/frontend.c
@@ -108,6 +108,7 @@ __XenvbdStateName(
case XENVBD_CLOSED: return "CLOSED";
case XENVBD_PREPARED: return "PREPARED";
case XENVBD_CONNECTED: return "CONNECTED";
+ case XENVBD_POISONED: return "POISONED";
case XENVBD_ENABLED: return "ENABLED";
default: return "UNKNOWN";
}
@@ -1349,6 +1350,14 @@ FrontendDisable(
RingDisable(Frontend->Ring);
GranterDisable(Frontend->Granter);
}
+__drv_requiresIRQL(DISPATCH_LEVEL)
+static FORCEINLINE BOOLEAN
+FrontendIsPoisoned(
+ __in PXENVBD_FRONTEND Frontend
+ )
+{
+ return RingIsPoisoned(Frontend->Ring);
+}
//=============================================================================
// Init/Term
@@ -1488,6 +1497,21 @@ __FrontendSetState(
}
break;
+ case XENVBD_POISONED:
+ switch (State) {
+ case XENVBD_CLOSING:
+ case XENVBD_CLOSED:
+ case XENVBD_PREPARED:
+ case XENVBD_CONNECTED:
+ Status = FrontendClose(Frontend);
+ Frontend->State = XENVBD_CLOSING;
+ break;
+ default:
+ Failed = TRUE;
+ break;
+ }
+ break;
+
case XENVBD_ENABLED:
switch (State) {
case XENVBD_CLOSING:
@@ -1495,7 +1519,11 @@ __FrontendSetState(
case XENVBD_PREPARED:
case XENVBD_CONNECTED:
FrontendDisable(Frontend);
- Frontend->State = XENVBD_CONNECTED;
+ if (FrontendIsPoisoned(Frontend)) {
+ Frontend->State = XENVBD_POISONED;
+ } else {
+ Frontend->State = XENVBD_CONNECTED;
+ }
break;
default:
Failed = TRUE;
diff --git a/src/xenvbd/frontend.h b/src/xenvbd/frontend.h
index 6c7665d..18cc4fb 100644
--- a/src/xenvbd/frontend.h
+++ b/src/xenvbd/frontend.h
@@ -47,7 +47,8 @@ typedef enum _XENVBD_STATE {
XENVBD_CLOSED, // -> { PREPARED }
XENVBD_PREPARED, // -> { CLOSING, CONNECTED }
XENVBD_CONNECTED, // -> { ENABLED, CLOSING }
- XENVBD_ENABLED // -> { CLOSING }
+ XENVBD_POISONED, // -> { CLOSING }
+ XENVBD_ENABLED // -> { CONNECTED, POISONED }
} XENVBD_STATE, *PXENVBD_STATE;
typedef struct _XENVBD_CAPS {
diff --git a/src/xenvbd/ring.c b/src/xenvbd/ring.c
index d7daaab..0b56831 100644
--- a/src/xenvbd/ring.c
+++ b/src/xenvbd/ring.c
@@ -75,6 +75,7 @@ typedef struct _XENVBD_BLKIF_RING {
BOOLEAN Connected;
BOOLEAN Enabled;
BOOLEAN Stopped;
+ BOOLEAN Poisoned;
PVOID Lock;
#if DBG
PKTHREAD LockThread;
@@ -2172,6 +2173,7 @@ BlkifRingEnable(
Trace("====> %u\n", BlkifRing->Index);
__BlkifRingAcquireLock(BlkifRing);
+ BUG_ON(BlkifRing->Poisoned);
ASSERT(!BlkifRing->Enabled);
BlkifRing->Enabled = TRUE;
__BlkifRingReleaseLock(BlkifRing);
@@ -2249,6 +2251,8 @@ BlkifRingDisable(
Request = CONTAINING_RECORD(ListEntry, XENVBD_REQUEST, ListEntry);
BlkifRing->ResponsesProcessed++;
__BlkifRingCompleteResponse(BlkifRing, Request, BLKIF_RSP_ERROR);
+
+ BlkifRing->Poisoned = TRUE;
}
while (!IsListEmpty(&BlkifRing->PreparedQueue)) {
@@ -2315,6 +2319,7 @@ BlkifRingDisconnect(
BlkifRing->ResponsesProcessed = 0;
BlkifRing->Connected = FALSE;
+ BlkifRing->Poisoned = FALSE;
Trace("<==== %u\n", BlkifRing->Index);
}
@@ -2770,6 +2775,26 @@ RingDisconnect(
XENBUS_DEBUG(Release, &Ring->DebugInterface);
}
+BOOLEAN
+RingIsPoisoned(
+ IN PXENVBD_RING Ring
+ )
+{
+ ULONG NumQueues;
+ ULONG Index;
+
+ NumQueues = FrontendGetNumQueues(Ring->Frontend);
+ for (Index = 0; Index < NumQueues; Index++) {
+ PXENVBD_BLKIF_RING BlkifRing = Ring->Ring[Index];
+
+ if (BlkifRing->Poisoned) {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
static FORCEINLINE PXENVBD_BLKIF_RING
__RingGetBlkifRing(
IN PXENVBD_RING Ring,
diff --git a/src/xenvbd/ring.h b/src/xenvbd/ring.h
index c459838..5644c7c 100644
--- a/src/xenvbd/ring.h
+++ b/src/xenvbd/ring.h
@@ -75,6 +75,11 @@ RingDisconnect(
IN PXENVBD_RING Ring
);
+extern BOOLEAN
+RingIsPoisoned(
+ IN PXENVBD_RING Ring
+ );
+
extern BOOLEAN
RingQueueRequest(
IN PXENVBD_RING Ring,
--
2.55.0.windows.3
--
Ngoc Tu Dinh | Vates XCP-ng Developer
XCP-ng & Xen Orchestra - Vates solutions
web: https://vates.tech
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |