From db4fa941e0d0eab1272d46f7ca1dc4bfa36545a8 Mon Sep 17 00:00:00 2001 From: Owen Smith Date: Thu, 19 Jun 2014 15:35:34 +0100 Subject: [PATCH] Add extra state to frontend transition to allow reset to cleanup requests after CLOSED transition but before disconnecting granter Signed-off-by: Owen Smith --- src/xenvbd/frontend.c | 24 ++++++++++++++++++++++-- src/xenvbd/frontend.h | 11 ++++++----- src/xenvbd/pdo.c | 34 +++++++++++++++++++++++++++++++++- 3 files changed, 61 insertions(+), 8 deletions(-) diff --git a/src/xenvbd/frontend.c b/src/xenvbd/frontend.c index 06c0be0..c6e63a3 100644 --- a/src/xenvbd/frontend.c +++ b/src/xenvbd/frontend.c @@ -93,6 +93,7 @@ __XenvbdStateName( switch (State) { case XENVBD_STATE_INVALID: return "STATE_INVALID"; case XENVBD_INITIALIZED: return "INITIALIZED"; + case XENVBD_CLOSING: return "CLOSING"; case XENVBD_CLOSED: return "CLOSED"; case XENVBD_PREPARED: return "PREPARED"; case XENVBD_CONNECTED: return "CONNECTED"; @@ -1045,6 +1046,7 @@ __FrontendSetState( switch (Frontend->State) { case XENVBD_INITIALIZED: switch (State) { + case XENVBD_CLOSING: case XENVBD_CLOSED: case XENVBD_PREPARED: case XENVBD_CONNECTED: @@ -1107,6 +1109,7 @@ __FrontendSetState( Failed = TRUE; } break; + case XENVBD_CLOSING: case XENVBD_CLOSED: Status = FrontendClose(Frontend); if (NT_SUCCESS(Status)) { @@ -1128,12 +1131,12 @@ __FrontendSetState( FrontendEnable(Frontend); Frontend->State = XENVBD_ENABLED; break; + case XENVBD_CLOSING: case XENVBD_CLOSED: case XENVBD_PREPARED: Status = FrontendClose(Frontend); - FrontendDisconnect(Frontend); if (NT_SUCCESS(Status)) { - Frontend->State = XENVBD_CLOSED; + Frontend->State = XENVBD_CLOSING; } else { Frontend->State = XENVBD_STATE_INVALID; Failed = TRUE; @@ -1145,8 +1148,25 @@ __FrontendSetState( } break; + case XENVBD_CLOSING: + switch (State) { + case XENVBD_INITIALIZED: + case XENVBD_CLOSED: + case XENVBD_PREPARED: + case XENVBD_CONNECTED: + case XENVBD_ENABLED: + FrontendDisconnect(Frontend); + Frontend->State = XENVBD_CLOSED; + break; + default: + Failed = TRUE; + break; + } + break; + case XENVBD_ENABLED: switch (State) { + case XENVBD_CLOSING: case XENVBD_CLOSED: case XENVBD_PREPARED: case XENVBD_CONNECTED: diff --git a/src/xenvbd/frontend.h b/src/xenvbd/frontend.h index 7d7d303..66af2bb 100644 --- a/src/xenvbd/frontend.h +++ b/src/xenvbd/frontend.h @@ -37,11 +37,12 @@ typedef enum _XENVBD_STATE { XENVBD_STATE_INVALID, - XENVBD_INITIALIZED, - XENVBD_CLOSED, - XENVBD_PREPARED, - XENVBD_CONNECTED, - XENVBD_ENABLED + XENVBD_INITIALIZED, // -> { CLOSED } + XENVBD_CLOSING, // -> { CLOSED } + XENVBD_CLOSED, // -> { PREPARED } + XENVBD_PREPARED, // -> { CLOSING, CONNECTED } + XENVBD_CONNECTED, // -> { ENABLED, CLOSING } + XENVBD_ENABLED // -> { CLOSING } } XENVBD_STATE, *PXENVBD_STATE; typedef struct _XENVBD_CAPS { diff --git a/src/xenvbd/pdo.c b/src/xenvbd/pdo.c index aa017ff..e084833 100644 --- a/src/xenvbd/pdo.c +++ b/src/xenvbd/pdo.c @@ -2284,6 +2284,34 @@ __PdoQueueShutdown( NotifierTrigger(Notifier); } +static FORCEINLINE VOID +__PdoCleanupSubmittedReqs( + IN PXENVBD_PDO Pdo + ) +{ + // Fail PreparedReqs + for (;;) { + PXENVBD_SRBEXT SrbExt; + PXENVBD_REQUEST Request; + PLIST_ENTRY Entry = QueuePop(&Pdo->SubmittedReqs); + if (Entry == NULL) + break; + Request = CONTAINING_RECORD(Entry, XENVBD_REQUEST, Entry); + SrbExt = GetSrbExt(Request->Srb); + + Verbose("Target[%d] : SubmittedReq 0x%p -> FAILED\n", PdoGetTargetId(Pdo), Request); + + RequestCleanup(Pdo, Request); + __LookasideFree(&Pdo->RequestList, Request); + + if (InterlockedDecrement(&SrbExt->Count) == 0) { + SrbExt->Srb->SrbStatus = SRB_STATUS_ABORTED; + SrbExt->Srb->ScsiStatus = 0x40; // SCSI_ABORTED + FdoCompleteSrb(PdoGetFdo(Pdo), SrbExt->Srb); + } + } +} + VOID PdoReset( __in PXENVBD_PDO Pdo @@ -2299,9 +2327,13 @@ PdoReset( if (QueueCount(&Pdo->SubmittedReqs)) { Error("Target[%d] : backend has %u outstanding requests after a PdoReset\n", PdoGetTargetId(Pdo), QueueCount(&Pdo->SubmittedReqs)); - BUG("backend contains outstanding requests after reset"); } + Status = FrontendSetState(Pdo->Frontend, XENVBD_CLOSING); + ASSERT(NT_SUCCESS(Status)); + + __PdoCleanupSubmittedReqs(Pdo); + Status = FrontendSetState(Pdo->Frontend, XENVBD_CLOSED); ASSERT(NT_SUCCESS(Status)); -- 2.39.5