]> xenbits.xensource.com Git - pvdrivers/win/xenvbd.git/commitdiff
Add extra state to frontend transition to allow reset to cleanup
authorOwen Smith <owen.smith@citrix.com>
Thu, 19 Jun 2014 14:35:34 +0000 (15:35 +0100)
committerOwen Smith <owen.smith@citrix.com>
Thu, 19 Jun 2014 14:35:34 +0000 (15:35 +0100)
requests after CLOSED transition but before disconnecting granter

Signed-off-by: Owen Smith <owen.smith@citrix.com>
src/xenvbd/frontend.c
src/xenvbd/frontend.h
src/xenvbd/pdo.c

index 06c0be0c63e87ee1da09fdf80b8138ceae3a1297..c6e63a3139f093d860c6495bb5dbf00eb9f355c7 100644 (file)
@@ -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:
index 7d7d30318384fd18597aa2c6478dd25a013bc618..66af2bbf7742003aafd448dcb5f5c9788fc7ca13 100644 (file)
 
 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 {
index aa017ff924608531cd16b583ae01a647af1655d2..e084833dc854e28b70c9870b054cff26f2df2ee6 100644 (file)
@@ -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));