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

[win-pv-devel] [PATCH 6/9] Implement multi-queues



Splits XENVBD_RING into multiple XENVBD_BLKIF_RINGs, one for each shared
ring. Up-to "multi-queue-max-queues" rings are used to pass
blkif_requests and blkif_responses between frontend and backend. Reworks
the ring interactions to remove the locks used by XENVBD_QUEUE,
implementing a queue system similar to XenVifs transmitter queues.

Signed-off-by: Owen Smith <owen.smith@xxxxxxxxxx>
---
 src/xenvbd/frontend.c |   18 +-
 src/xenvbd/ring.c     | 3097 +++++++++++++++++++++++++++++--------------------
 2 files changed, 1847 insertions(+), 1268 deletions(-)

diff --git a/src/xenvbd/frontend.c b/src/xenvbd/frontend.c
index 900ad2b..fd2c247 100644
--- a/src/xenvbd/frontend.c
+++ b/src/xenvbd/frontend.c
@@ -1278,15 +1278,15 @@ FrontendConnect(
         if (!NT_SUCCESS(Status))
             goto abort;
 
-        //status = XENBUS_STORE(Printf,
-        //                      &Frontend->StoreInterface,
-        //                      Transaction,
-        //                      Frontend->FrontendPath,
-        //                      "multi-queue-num-queues",
-        //                      "%u",
-        //                      __FrontendGetNumQueues(Frontend));
-        //if (!NT_SUCCESS(status))
-        //    goto abort;
+        Status = XENBUS_STORE(Printf,
+                              &Frontend->StoreInterface,
+                              Transaction,
+                              Frontend->FrontendPath,
+                              "multi-queue-num-queues",
+                              "%u",
+                              __FrontendGetNumQueues(Frontend));
+        if (!NT_SUCCESS(Status))
+            goto abort;
 
         Status = XENBUS_STORE(TransactionEnd,
                               &Frontend->StoreInterface,
diff --git a/src/xenvbd/ring.c b/src/xenvbd/ring.c
index e41c1b7..cd2cc0e 100644
--- a/src/xenvbd/ring.c
+++ b/src/xenvbd/ring.c
@@ -47,7 +47,6 @@
 #include "srbext.h"
 #include "driver.h"
 #include "granter.h"
-#include "queue.h"
 
 #include "util.h"
 #include "debug.h"
@@ -56,47 +55,72 @@
 #define XENVBD_MAX_RING_PAGE_ORDER  (4)
 #define XENVBD_MAX_RING_PAGES       (1 << XENVBD_MAX_RING_PAGE_ORDER)
 
-struct _XENVBD_RING {
-    PXENVBD_FRONTEND                Frontend;
+#define xen_mb  KeMemoryBarrier
+#define xen_wmb KeMemoryBarrier
+
+typedef struct _XENVBD_SRB_STATE {
+    LIST_ENTRY                      List;
+    ULONG                           Count;
+} XENVBD_SRB_STATE, *PXENVBD_SRB_STATE;
+
+typedef struct _XENVBD_BLKIF_RING {
+    PXENVBD_RING                    Ring;
+    ULONG                           Index;
+    PCHAR                           Path;
+    PXENBUS_CACHE                   RequestCache;
+    PXENBUS_CACHE                   SegmentCache;
+    PXENBUS_CACHE                   IndirectCache;
+    PMDL                            Mdl;
+    blkif_sring_t                   *Shared;
+    blkif_front_ring_t              Front;
+    PXENBUS_GNTTAB_ENTRY            Grants[XENVBD_MAX_RING_PAGES];
+    PXENBUS_EVTCHN_CHANNEL          Channel;
+    KDPC                            Dpc;
+    ULONG                           Dpcs;
+    ULONG                           Events;
     BOOLEAN                         Connected;
     BOOLEAN                         Enabled;
+    BOOLEAN                         Stopped;
+    PVOID                           Lock;
+    PKTHREAD                        LockThread;
+    XENVBD_SRB_STATE                State;
+    LIST_ENTRY                      SrbQueue;
+    LIST_ENTRY                      SubmittedList;
+    LIST_ENTRY                      ShutdownQueue;
+    ULONG                           SrbsQueued;
+    ULONG                           SrbsCompleted;
+    ULONG                           SrbsFailed;
+    ULONG                           RequestsPosted;
+    ULONG                           RequestsPushed;
+    ULONG                           ResponsesProcessed;
+    PXENBUS_DEBUG_CALLBACK          DebugCallback;
+} XENVBD_BLKIF_RING, *PXENVBD_BLKIF_RING;
+
+typedef enum _XENVBD_STAT {
+    XENVBD_STAT_BLKIF_OP_READ_DIRECT = 0,
+    XENVBD_STAT_BLKIF_OP_READ_INDIRECT,
+    XENVBD_STAT_BLKIF_OP_WRITE_DIRECT,
+    XENVBD_STAT_BLKIF_OP_WRITE_INDIRECT,
+    XENVBD_STAT_BLKIF_OP_WRITE_BARRIER,
+    XENVBD_STAT_BLKIF_OP_FLUSH_DISKCACHE,
+    XENVBD_STAT_BLKIF_OP_DISCARD,
+    XENVBD_STAT_BLKIF_OP_UNKNOWN,
+    XENVBD_STAT_SEGMENTS_GRANTED,
+    XENVBD_STAT_SEGMENTS_BOUNCED,
+
+    XENVBD_STAT__MAX
+} XENVBD_STAT, *PXENVBD_STAT;
 
+struct _XENVBD_RING {
+    PXENVBD_FRONTEND                Frontend;
+    XENBUS_DEBUG_INTERFACE          DebugInterface;
     XENBUS_CACHE_INTERFACE          CacheInterface;
     XENBUS_STORE_INTERFACE          StoreInterface;
     XENBUS_EVTCHN_INTERFACE         EvtchnInterface;
-    XENBUS_DEBUG_INTERFACE          DebugInterface;
-
     PXENBUS_DEBUG_CALLBACK          DebugCallback;
-
-    KSPIN_LOCK                      Lock;
-    PMDL                            Mdl;
-    blkif_sring_t*                  Shared;
-    blkif_front_ring_t              Front;
     ULONG                           Order;
-    PVOID                           Grants[XENVBD_MAX_RING_PAGES];
-    PXENBUS_EVTCHN_CHANNEL          Channel;
-    KDPC                            Dpc;
-
-    PXENBUS_CACHE                   RequestCache;
-    PXENBUS_CACHE                   SegmentCache;
-    PXENBUS_CACHE                   IndirectCache;
-    XENVBD_QUEUE                    PreparedReqs;
-    XENVBD_QUEUE                    SubmittedReqs;
-    XENVBD_QUEUE                    ShutdownSrbs;
-
-    ULONG                           Submitted;
-    ULONG                           Received;
-    ULONG                           Events;
-    ULONG                           Dpcs;
-    ULONG                           BlkOpRead;
-    ULONG                           BlkOpWrite;
-    ULONG                           BlkOpIndirectRead;
-    ULONG                           BlkOpIndirectWrite;
-    ULONG                           BlkOpBarrier;
-    ULONG                           BlkOpDiscard;
-    ULONG                           BlkOpFlush;
-    ULONG64                         SegsGranted;
-    ULONG64                         SegsBounced;
+    PXENVBD_BLKIF_RING              *Ring;
+    LONG                            Stats[XENVBD_STAT__MAX];
 };
 
 #define MAX_NAME_LEN                64
@@ -123,138 +147,119 @@ __RingFree(
                           RING_POOL_TAG);
 }
 
-static FORCEINLINE VOID
-xen_mb()
+static FORCEINLINE PCHAR
+__BlkifOperationName(
+    IN  UCHAR   Operation
+    )
 {
-    KeMemoryBarrier();
-    _ReadWriteBarrier();
+    switch (Operation) {
+    case BLKIF_OP_READ:             return "READ";
+    case BLKIF_OP_WRITE:            return "WRITE";
+    case BLKIF_OP_WRITE_BARRIER:    return "WRITE_BARRIER";
+    case BLKIF_OP_FLUSH_DISKCACHE:  return "FLUSH_DISKCACHE";
+    case BLKIF_OP_RESERVED_1:       return "RESERVED_1";
+    case BLKIF_OP_DISCARD:          return "DISCARD";
+    case BLKIF_OP_INDIRECT:         return "INDIRECT";
+    default:                        return "<unknown>";
+    }
 }
 
-static FORCEINLINE VOID
-xen_wmb()
+static FORCEINLINE PCHAR
+__StatName(
+    IN  XENVBD_STAT Operation
+    )
 {
-    KeMemoryBarrier();
-    _WriteBarrier();
+    switch (Operation) {
+    case XENVBD_STAT_BLKIF_OP_READ_DIRECT:      return "BLKIF_OP_READ 
(direct)";
+    case XENVBD_STAT_BLKIF_OP_READ_INDIRECT:    return "BLKIF_OP_READ 
(indirect)";
+    case XENVBD_STAT_BLKIF_OP_WRITE_DIRECT:     return "BLKIF_OP_WRITE 
(direct)";
+    case XENVBD_STAT_BLKIF_OP_WRITE_INDIRECT:   return "BLKIF_OP_WRITE 
(indirect)";
+    case XENVBD_STAT_BLKIF_OP_WRITE_BARRIER:    return 
"BLKIF_OP_WRITE_BARRIER";
+    case XENVBD_STAT_BLKIF_OP_FLUSH_DISKCACHE:  return 
"BLKIF_OP_FLUSH_DISKCACHE";
+    case XENVBD_STAT_BLKIF_OP_DISCARD:          return "BLKIF_OP_DISCARD";
+    case XENVBD_STAT_SEGMENTS_GRANTED:          return "SegmentsGranted";
+    case XENVBD_STAT_SEGMENTS_BOUNCED:          return "SegmentsBounced";
+    default:                                    return "UNKNOWN";
+    }
 }
 
-static FORCEINLINE VOID
-__RingInsert(
-    IN  PXENVBD_RING        Ring,
-    IN  PXENVBD_REQUEST     Request,
-    IN  blkif_request_t*    req
+static FORCEINLINE ULONG
+__SectorsPerPage(
+    IN  ULONG   SectorSize
     )
 {
-    PXENVBD_GRANTER         Granter = FrontendGetGranter(Ring->Frontend);
-
-    switch (Request->Operation) {
-    case BLKIF_OP_READ:
-    case BLKIF_OP_WRITE:
-        if (Request->NrSegments > BLKIF_MAX_SEGMENTS_PER_REQUEST) {
-            // Indirect
-            ULONG                       PageIdx;
-            ULONG                       SegIdx;
-            PLIST_ENTRY                 PageEntry;
-            PLIST_ENTRY                 SegEntry;
-            blkif_request_indirect_t*   req_indirect;
-
-            req_indirect = (blkif_request_indirect_t*)req;
-            req_indirect->operation         = BLKIF_OP_INDIRECT;
-            req_indirect->indirect_op       = Request->Operation;
-            req_indirect->nr_segments       = Request->NrSegments;
-            req_indirect->id                = (ULONG64)(ULONG_PTR)Request;
-            req_indirect->sector_number     = Request->FirstSector;
-            req_indirect->handle            = 
(USHORT)FrontendGetDeviceId(Ring->Frontend);
-
-            for (PageIdx = 0,
-                 PageEntry = Request->Indirects.Flink,
-                 SegEntry = Request->Segments.Flink;
-                    PageIdx < BLKIF_MAX_INDIRECT_PAGES_PER_REQUEST &&
-                    PageEntry != &Request->Indirects &&
-                    SegEntry != &Request->Segments;
-                        ++PageIdx, PageEntry = PageEntry->Flink) {
-                PXENVBD_INDIRECT Page = CONTAINING_RECORD(PageEntry, 
XENVBD_INDIRECT, ListEntry);
-
-                req_indirect->indirect_grefs[PageIdx] = 
GranterReference(Granter, Page->Grant);
-
-                for (SegIdx = 0;
-                        SegIdx < XENVBD_MAX_SEGMENTS_PER_PAGE &&
-                        SegEntry != &Request->Segments;
-                            ++SegIdx, SegEntry = SegEntry->Flink) {
-                    PXENVBD_SEGMENT Segment = CONTAINING_RECORD(SegEntry, 
XENVBD_SEGMENT, ListEntry);
-
-                    Page->Page[SegIdx].GrantRef = GranterReference(Granter, 
Segment->Grant);
-                    Page->Page[SegIdx].First    = Segment->FirstSector;
-                    Page->Page[SegIdx].Last     = Segment->LastSector;
-                }
-            }
-        } else {
-            // Direct
-            ULONG           Index;
-            PLIST_ENTRY     Entry;
-
-            req->operation                  = Request->Operation;
-            req->nr_segments                = (UCHAR)Request->NrSegments;
-            req->handle                     = 
(USHORT)FrontendGetDeviceId(Ring->Frontend);
-            req->id                         = (ULONG64)(ULONG_PTR)Request;
-            req->sector_number              = Request->FirstSector;
+    ASSERT3U(SectorSize, != , 0);
+    return PAGE_SIZE / SectorSize;
+}
 
-            for (Index = 0, Entry = Request->Segments.Flink;
-                    Index < BLKIF_MAX_SEGMENTS_PER_REQUEST &&
-                    Entry != &Request->Segments;
-                        ++Index, Entry = Entry->Flink) {
-                PXENVBD_SEGMENT Segment = CONTAINING_RECORD(Entry, 
XENVBD_SEGMENT, ListEntry);
-                req->seg[Index].gref        = GranterReference(Granter, 
Segment->Grant);
-                req->seg[Index].first_sect  = Segment->FirstSector;
-                req->seg[Index].last_sect   = Segment->LastSector;
-            }
-        }
+static FORCEINLINE VOID
+__Operation(
+    IN  UCHAR       CdbOp,
+    OUT PUCHAR      RingOp,
+    OUT PBOOLEAN    ReadOnly
+    )
+{
+    switch (CdbOp) {
+    case SCSIOP_READ:
+        *RingOp = BLKIF_OP_READ;
+        *ReadOnly = FALSE;
         break;
-
-    case BLKIF_OP_WRITE_BARRIER:
-    case BLKIF_OP_FLUSH_DISKCACHE:
-        req->operation                  = Request->Operation;
-        req->nr_segments                = 0;
-        req->handle                     = 
(USHORT)FrontendGetDeviceId(Ring->Frontend);
-        req->id                         = (ULONG64)(ULONG_PTR)Request;
-        req->sector_number              = Request->FirstSector;
+    case SCSIOP_WRITE:
+        *RingOp = BLKIF_OP_WRITE;
+        *ReadOnly = TRUE;
         break;
-
-    case BLKIF_OP_DISCARD: {
-        blkif_request_discard_t*        req_discard;
-        req_discard = (blkif_request_discard_t*)req;
-        req_discard->operation          = BLKIF_OP_DISCARD;
-        req_discard->flag               = Request->Flags;
-        req_discard->handle             = 
(USHORT)FrontendGetDeviceId(Ring->Frontend);
-        req_discard->id                 = (ULONG64)(ULONG_PTR)Request;
-        req_discard->sector_number      = Request->FirstSector;
-        req_discard->nr_sectors         = Request->NrSectors;
-        } break;
-
     default:
         ASSERT(FALSE);
-        break;
     }
-    ++Ring->Submitted;
+}
+
+static FORCEINLINE ULONG
+__UseIndirect(
+    IN  ULONG           SectorsPerPage,
+    IN  ULONG           MaxIndirectSegs,
+    IN  ULONG           SectorsLeft
+    )
+{
+    if (MaxIndirectSegs <= BLKIF_MAX_SEGMENTS_PER_REQUEST)
+        return BLKIF_MAX_SEGMENTS_PER_REQUEST; // not supported
+
+    if (SectorsLeft < BLKIF_MAX_SEGMENTS_PER_REQUEST * SectorsPerPage)
+        return BLKIF_MAX_SEGMENTS_PER_REQUEST; // first into a single 
BLKIF_OP_{READ/WRITE}
+
+    return MaxIndirectSegs;
+}
+
+static FORCEINLINE MM_PAGE_PRIORITY
+__Priority(
+    IN  PXENVBD_CAPS    Caps
+    )
+{
+    return (Caps->Paging ||
+            Caps->Hibernation ||
+            Caps->DumpFile) ? HighPagePriority :
+                              NormalPagePriority;
 }
 
 static PXENVBD_INDIRECT
-RingGetIndirect(
-    IN  PXENVBD_RING    Ring
+BlkifRingGetIndirect(
+    IN  PXENVBD_BLKIF_RING  BlkifRing
     )
 {
-    PXENVBD_INDIRECT    Indirect;
-    NTSTATUS            status;
-    PXENVBD_GRANTER     Granter = FrontendGetGranter(Ring->Frontend);
+    PXENVBD_RING            Ring = BlkifRing->Ring;
+    PXENVBD_FRONTEND        Frontend = Ring->Frontend;
+    PXENVBD_GRANTER         Granter = FrontendGetGranter(Frontend);
+    PXENVBD_INDIRECT        Indirect;
+    NTSTATUS                status;
 
     Indirect = XENBUS_CACHE(Get,
                             &Ring->CacheInterface,
-                            Ring->IndirectCache,
-                            FALSE);
+                            BlkifRing->IndirectCache,
+                            TRUE);
     if (Indirect == NULL)
         goto fail1;
 
-    ASSERT3P(Indirect->Mdl, !=, NULL);
-    ASSERT3P(Indirect->Page, !=, NULL);
+    ASSERT3P(Indirect->Mdl, != , NULL);
+    ASSERT3P(Indirect->Page, != , NULL);
     status = GranterGet(Granter,
                         MmGetMdlPfnArray(Indirect->Mdl)[0],
                         TRUE,
@@ -267,20 +272,22 @@ RingGetIndirect(
 fail2:
     XENBUS_CACHE(Put,
                  &Ring->CacheInterface,
-                 Ring->IndirectCache,
+                 BlkifRing->IndirectCache,
                  Indirect,
-                 FALSE);
+                 TRUE);
 fail1:
     return NULL;
 }
 
 static VOID
-RingPutIndirect(
-    IN  PXENVBD_RING        Ring,
+BlkifRingPutIndirect(
+    IN  PXENVBD_BLKIF_RING  BlkifRing,
     IN  PXENVBD_INDIRECT    Indirect
     )
 {
-    PXENVBD_GRANTER         Granter = FrontendGetGranter(Ring->Frontend);
+    PXENVBD_RING            Ring = BlkifRing->Ring;
+    PXENVBD_FRONTEND        Frontend = Ring->Frontend;
+    PXENVBD_GRANTER         Granter = FrontendGetGranter(Frontend);
 
     if (Indirect->Grant)
         GranterPut(Granter, Indirect->Grant);
@@ -290,30 +297,34 @@ RingPutIndirect(
 
     XENBUS_CACHE(Put,
                  &Ring->CacheInterface,
-                 Ring->IndirectCache,
+                 BlkifRing->IndirectCache,
                  Indirect,
-                 FALSE);
+                 TRUE);
 }
 
 static PXENVBD_SEGMENT
-RingGetSegment(
-    IN  PXENVBD_RING    Ring
+BlkifRingGetSegment(
+    IN  PXENVBD_BLKIF_RING  BlkifRing
     )
 {
+    PXENVBD_RING            Ring = BlkifRing->Ring;
+
     return XENBUS_CACHE(Get,
                         &Ring->CacheInterface,
-                        Ring->SegmentCache,
-                        FALSE);
+                        BlkifRing->SegmentCache,
+                        TRUE);
 }
 
 static VOID
-RingPutSegment(
-    IN  PXENVBD_RING    Ring,
-    IN  PXENVBD_SEGMENT Segment
+BlkifRingPutSegment(
+    IN  PXENVBD_BLKIF_RING  BlkifRing,
+    IN  PXENVBD_SEGMENT     Segment
     )
 {
-    PXENVBD_GRANTER     Granter = FrontendGetGranter(Ring->Frontend);
-    PXENVBD_BOUNCE      Bounce = Segment->Bounce;
+    PXENVBD_RING            Ring = BlkifRing->Ring;
+    PXENVBD_FRONTEND        Frontend = Ring->Frontend;
+    PXENVBD_GRANTER         Granter = FrontendGetGranter(Frontend);
+    PXENVBD_BOUNCE          Bounce = Segment->Bounce;
 
     if (Segment->Grant)
         GranterPut(Granter, Segment->Grant);
@@ -329,7 +340,7 @@ RingPutSegment(
         Bounce->SourcePfn[0] = 0;
         Bounce->SourcePfn[1] = 0;
 
-        AdapterPutBounce(TargetGetAdapter(FrontendGetTarget(Ring->Frontend)),
+        AdapterPutBounce(TargetGetAdapter(FrontendGetTarget(Frontend)),
                          Bounce);
     }
     Segment->Bounce = NULL;
@@ -340,29 +351,32 @@ RingPutSegment(
 
     XENBUS_CACHE(Put,
                  &Ring->CacheInterface,
-                 Ring->SegmentCache,
+                 BlkifRing->SegmentCache,
                  Segment,
-                 FALSE);
+                 TRUE);
 }
 
 static PXENVBD_REQUEST
-RingGetRequest(
-    IN  PXENVBD_RING    Ring
+BlkifRingGetRequest(
+    IN  PXENVBD_BLKIF_RING  BlkifRing
     )
 {
+    PXENVBD_RING            Ring = BlkifRing->Ring;
+
     return XENBUS_CACHE(Get,
                         &Ring->CacheInterface,
-                        Ring->RequestCache,
-                        FALSE);
+                        BlkifRing->RequestCache,
+                        TRUE);
 }
 
 static VOID
-RingPutRequest(
-    IN  PXENVBD_RING    Ring,
-    IN  PXENVBD_REQUEST Request
+BlkifRingPutRequest(
+    IN  PXENVBD_BLKIF_RING  BlkifRing,
+    IN  PXENVBD_REQUEST     Request
     )
 {
-    PLIST_ENTRY         ListEntry;
+    PXENVBD_RING            Ring = BlkifRing->Ring;
+    PLIST_ENTRY             ListEntry;
 
     for (;;) {
         PXENVBD_SEGMENT Segment;
@@ -371,7 +385,7 @@ RingPutRequest(
         if (ListEntry == &Request->Segments)
             break;
         Segment = CONTAINING_RECORD(ListEntry, XENVBD_SEGMENT, ListEntry);
-        RingPutSegment(Ring, Segment);
+        BlkifRingPutSegment(BlkifRing, Segment);
     }
 
     for (;;) {
@@ -381,7 +395,7 @@ RingPutRequest(
         if (ListEntry == &Request->Indirects)
             break;
         Indirect = CONTAINING_RECORD(ListEntry, XENVBD_INDIRECT, ListEntry);
-        RingPutIndirect(Ring, Indirect);
+        BlkifRingPutIndirect(BlkifRing, Indirect);
     }
 
     Request->SrbExt = NULL;
@@ -394,189 +408,277 @@ RingPutRequest(
 
     XENBUS_CACHE(Put,
                  &Ring->CacheInterface,
-                 Ring->RequestCache,
+                 BlkifRing->RequestCache,
                  Request,
-                 FALSE);
+                 TRUE);
 }
 
-static FORCEINLINE PXENVBD_REQUEST
-RingFindRequest(
-    IN  PXENVBD_RING    Ring,
-    IN  ULONG64         Id
+static DECLSPEC_NOINLINE NTSTATUS
+BlkifRingRequestCtor(
+    IN  PVOID       Argument,
+    IN  PVOID       Object
     )
 {
-    KIRQL               Irql;
-    PLIST_ENTRY         ListEntry;
-    PXENVBD_REQUEST     Request;
-    PXENVBD_QUEUE       Queue = &Ring->SubmittedReqs;
-
-    KeAcquireSpinLock(&Queue->Lock, &Irql);
+    PXENVBD_REQUEST Request = Object;
 
-    for (ListEntry = Queue->List.Flink;
-         ListEntry != &Queue->List;
-         ListEntry = ListEntry->Flink) {
-        Request = CONTAINING_RECORD(ListEntry, XENVBD_REQUEST, ListEntry);
-        if ((ULONG64)(ULONG_PTR)Request == Id) {
-            RemoveEntryList(&Request->ListEntry);
-            --Queue->Current;
-            KeReleaseSpinLock(&Queue->Lock, Irql);
-            return Request;
-        }
-    }
+    UNREFERENCED_PARAMETER(Argument);
 
-    KeReleaseSpinLock(&Queue->Lock, Irql);
-    Warning("Target[%d] : Tag %llx not found in submitted list (%u items)\n",
-            FrontendGetTargetId(Ring->Frontend),
-            Id,
-            QueueCount(Queue));
-    return NULL;
+    InitializeListHead(&Request->Segments);
+    InitializeListHead(&Request->Indirects);
+    return STATUS_SUCCESS;
 }
 
-static FORCEINLINE VOID
-__RingIncBlkifOpCount(
-    IN  PXENVBD_RING    Ring,
-    IN  PXENVBD_REQUEST Request
+static DECLSPEC_NOINLINE VOID
+BlkifRingRequestDtor(
+    IN  PVOID       Argument,
+    IN  PVOID       Object
     )
 {
-    switch (Request->Operation) {
-    case BLKIF_OP_READ:
-        if (Request->NrSegments > BLKIF_MAX_SEGMENTS_PER_REQUEST)
-            ++Ring->BlkOpIndirectRead;
-        else
-            ++Ring->BlkOpRead;
-        break;
-    case BLKIF_OP_WRITE:
-        if (Request->NrSegments > BLKIF_MAX_SEGMENTS_PER_REQUEST)
-            ++Ring->BlkOpIndirectWrite;
-        else
-            ++Ring->BlkOpWrite;
-        break;
-    case BLKIF_OP_WRITE_BARRIER:
-        ++Ring->BlkOpBarrier;
-        break;
-    case BLKIF_OP_DISCARD:
-        ++Ring->BlkOpDiscard;
-        break;
-    case BLKIF_OP_FLUSH_DISKCACHE:
-        ++Ring->BlkOpFlush;
-        break;
-    default:
-        ASSERT(FALSE);
-        break;
-    }
+    UNREFERENCED_PARAMETER(Argument);
+    UNREFERENCED_PARAMETER(Object);
 }
 
-static FORCEINLINE ULONG
-__RingSectorsPerPage(
-    IN  ULONG   SectorSize
+static DECLSPEC_NOINLINE NTSTATUS
+BlkifRingSegmentCtor(
+    IN  PVOID       Argument,
+    IN  PVOID       Object
     )
 {
-    ASSERT3U(SectorSize, !=, 0);
-    return PAGE_SIZE / SectorSize;
+    UNREFERENCED_PARAMETER(Argument);
+    UNREFERENCED_PARAMETER(Object);
+    return STATUS_SUCCESS;
 }
 
-static FORCEINLINE VOID
-__RingOperation(
-    IN  UCHAR       CdbOp,
-    OUT PUCHAR      RingOp,
-    OUT PBOOLEAN    ReadOnly
+static DECLSPEC_NOINLINE VOID
+BlkifRingSegmentDtor(
+    IN  PVOID       Argument,
+    IN  PVOID       Object
     )
 {
-    switch (CdbOp) {
-    case SCSIOP_READ:
-        *RingOp     = BLKIF_OP_READ;
-        *ReadOnly   = FALSE;
-        break;
-    case SCSIOP_WRITE:
-        *RingOp     = BLKIF_OP_WRITE;
-        *ReadOnly   = TRUE;
-        break;
-    default:
-        ASSERT(FALSE);
-    }
+    UNREFERENCED_PARAMETER(Argument);
+    UNREFERENCED_PARAMETER(Object);
 }
 
-static FORCEINLINE MM_PAGE_PRIORITY
-__RingPriority(
-    IN  PXENVBD_RING    Ring
+static DECLSPEC_NOINLINE NTSTATUS
+BlkifRingIndirectCtor(
+    IN  PVOID           Argument,
+    IN  PVOID           Object
     )
 {
-    PXENVBD_CAPS        Caps = FrontendGetCaps(Ring->Frontend);
-    if (!(Caps->Paging ||
-          Caps->Hibernation ||
-          Caps->DumpFile))
-        return NormalPagePriority;
+    PXENVBD_INDIRECT    Indirect = Object;
+    NTSTATUS            status;
+
+    UNREFERENCED_PARAMETER(Argument);
+
+    status = STATUS_NO_MEMORY;
+    Indirect->Mdl = __AllocatePage();
+    if (Indirect->Mdl == NULL)
+        goto fail1;
+
+    Indirect->Page = MmGetSystemAddressForMdlSafe(Indirect->Mdl,
+                                                  NormalPagePriority);
+    ASSERT(Indirect->Page);
 
-    return HighPagePriority;
+    return STATUS_SUCCESS;
+
+fail1:
+    Error("fail1 %08x\n", status);
+    return status;
 }
 
-static FORCEINLINE VOID
-RingRequestCopyOutput(
-    IN  PXENVBD_REQUEST Request
+static DECLSPEC_NOINLINE VOID
+BlkifRingIndirectDtor(
+    IN  PVOID           Argument,
+    IN  PVOID           Object
     )
 {
-    PLIST_ENTRY         ListEntry;
-
-    if (Request->Operation != BLKIF_OP_READ)
-        return;
+    PXENVBD_INDIRECT    Indirect = Object;
 
-    for (ListEntry = Request->Segments.Flink;
-         ListEntry != &Request->Segments;
-         ListEntry = ListEntry->Flink) {
-        PXENVBD_SEGMENT Segment = CONTAINING_RECORD(ListEntry, XENVBD_SEGMENT, 
ListEntry);
-        PXENVBD_BOUNCE  Bounce = Segment->Bounce;
+    UNREFERENCED_PARAMETER(Argument);
 
-        if (Bounce) {
-            RtlCopyMemory(Bounce->SourcePtr,
-                          Bounce->BouncePtr,
-                          MmGetMdlByteCount(&Bounce->SourceMdl));
-        }
-    }
+    __FreePages(Indirect->Mdl);
+    Indirect->Page = NULL;
+    Indirect->Mdl = NULL;
 }
 
-static BOOLEAN
-RingPrepareSegment(
-    IN  PXENVBD_RING    Ring,
-    IN  PXENVBD_SEGMENT Segment,
-    IN  PXENVBD_SRBEXT  SrbExt,
-    IN  BOOLEAN         ReadOnly,
-    IN  ULONG           SectorsLeft,
-    OUT PULONG          SectorsNow
-    )
-{
-    PFN_NUMBER          Pfn;
-    ULONG               Offset;
-    ULONG               Length;
-    NTSTATUS            Status;
-    PXENVBD_GRANTER     Granter = FrontendGetGranter(Ring->Frontend);
-    const ULONG         SectorSize = 
FrontendGetDiskInfo(Ring->Frontend)->SectorSize;
-    const ULONG         SectorsPerPage = __RingSectorsPerPage(SectorSize);
-    PXENVBD_TARGET      Target = FrontendGetTarget(Ring->Frontend);
-    PXENVBD_ADAPTER     Adapter = TargetGetAdapter(Target);
+static VOID
+BlkifRingDebugCallback(
+    IN  PVOID           Argument,
+    IN  BOOLEAN         Crashing
+    )
+{
+    PXENVBD_BLKIF_RING  BlkifRing = Argument;
+    PXENVBD_RING        Ring = BlkifRing->Ring;
 
-    Pfn = AdapterGetNextSGEntry(Adapter,
-                                SrbExt,
-                                0,
-                                &Offset,
-                                &Length);
-    if ((Offset & (SectorSize - 1)) == 0 &&
+    UNREFERENCED_PARAMETER(Crashing);
+
+    XENBUS_DEBUG(Printf,
+                 &Ring->DebugInterface,
+                 "0x%p [%s]\n",
+                 BlkifRing,
+                 (BlkifRing->Enabled) ? "ENABLED" : "DISABLED");
+
+    // Dump front ring
+    XENBUS_DEBUG(Printf,
+                 &Ring->DebugInterface,
+                 "FRONT: req_prod_pvt = %u rsp_cons = %u nr_ents = %u sring = 
%p\n",
+                 BlkifRing->Front.req_prod_pvt,
+                 BlkifRing->Front.rsp_cons,
+                 BlkifRing->Front.nr_ents,
+                 BlkifRing->Front.sring);
+
+    // Dump shared ring
+    XENBUS_DEBUG(Printf,
+                 &Ring->DebugInterface,
+                 "SHARED: req_prod = %u req_event = %u rsp_prod = %u rsp_event 
= %u\n",
+                 BlkifRing->Shared->req_prod,
+                 BlkifRing->Shared->req_event,
+                 BlkifRing->Shared->rsp_prod,
+                 BlkifRing->Shared->rsp_event);
+
+    XENBUS_DEBUG(Printf,
+                 &Ring->DebugInterface,
+                 "RequestsPosted = %u RequestsPushed = %u ResponsesProcessed = 
%u\n",
+                 BlkifRing->RequestsPosted,
+                 BlkifRing->RequestsPushed,
+                 BlkifRing->ResponsesProcessed);
+
+    XENBUS_DEBUG(Printf,
+                 &Ring->DebugInterface,
+                 "SrbsQueued = %u, SrbsCompleted = %u, SrbsFailed = %u\n",
+                 BlkifRing->SrbsQueued,
+                 BlkifRing->SrbsCompleted,
+                 BlkifRing->SrbsFailed);
+
+    XENBUS_DEBUG(Printf,
+                 &Ring->DebugInterface,
+                 "Dpcs = %u, Events = %u\n",
+                 BlkifRing->Dpcs,
+                 BlkifRing->Events);
+}
+
+static DECLSPEC_NOINLINE VOID
+__BlkifRingCompleteSrb(
+    IN  PXENVBD_BLKIF_RING  BlkifRing,
+    IN  PXENVBD_SRBEXT      SrbExt
+    )
+{
+    PXENVBD_RING            Ring = BlkifRing->Ring;
+    PXENVBD_FRONTEND        Frontend = Ring->Frontend;
+    PXENVBD_TARGET          Target = FrontendGetTarget(Frontend);
+    PXENVBD_ADAPTER         Adapter = TargetGetAdapter(Target);
+    PSCSI_REQUEST_BLOCK     Srb = SrbExt->Srb;
+
+    if (Srb->SrbStatus == SRB_STATUS_PENDING) {
+        // SRB has not hit a failure condition (BLKIF_RSP_ERROR | 
BLKIF_RSP_EOPNOTSUPP)
+        // from any of its responses. SRB must have succeeded
+        Srb->SrbStatus = SRB_STATUS_SUCCESS;
+        Srb->ScsiStatus = 0x00; // SCSI_GOOD
+        ++BlkifRing->SrbsCompleted;
+    } else {
+        // Srb->SrbStatus has already been set by 1 or more requests with 
Status != BLKIF_RSP_OKAY
+        Srb->ScsiStatus = 0x40; // SCSI_ABORTED
+        ++BlkifRing->SrbsFailed;
+    }
+
+    AdapterCompleteSrb(Adapter, SrbExt);
+}
+
+static FORCEINLINE VOID
+BlkifRingUnprepareRequest(
+    IN  PXENVBD_BLKIF_RING  BlkifRing,
+    IN  PLIST_ENTRY         List
+    )
+{
+    for (;;) {
+        PLIST_ENTRY         ListEntry;
+        PXENVBD_REQUEST     Request;
+
+        ListEntry = RemoveHeadList(List);
+        if (ListEntry == List)
+            break;
+
+        Request = CONTAINING_RECORD(ListEntry,
+                                    XENVBD_REQUEST,
+                                    ListEntry);
+
+        BlkifRingPutRequest(BlkifRing, Request);
+    }
+}
+
+static FORCEINLINE VOID
+BlkifRingQueueRequests(
+    IN  PXENVBD_BLKIF_RING  BlkifRing,
+    IN  PLIST_ENTRY         List
+    )
+{
+    PXENVBD_SRB_STATE       State = &BlkifRing->State;
+
+    for (;;) {
+        PLIST_ENTRY         ListEntry;
+        PXENVBD_REQUEST     Request;
+
+        ListEntry = RemoveHeadList(List);
+        if (ListEntry == List)
+            break;
+
+        Request = CONTAINING_RECORD(ListEntry,
+                                    XENVBD_REQUEST,
+                                    ListEntry);
+
+        InsertTailList(&State->List, ListEntry);
+        State->Count++;
+    }
+}
+
+static BOOLEAN
+BlkifRingPrepareSegment(
+    IN  PXENVBD_BLKIF_RING  BlkifRing,
+    IN  PXENVBD_SEGMENT     Segment,
+    IN  PXENVBD_SRBEXT      SrbExt,
+    IN  BOOLEAN             ReadOnly,
+    IN  ULONG               SectorsLeft,
+    OUT PULONG              SectorsNow
+    )
+{
+    PFN_NUMBER              Pfn;
+    ULONG                   Offset;
+    ULONG                   Length;
+    NTSTATUS                Status;
+    PXENVBD_RING            Ring = BlkifRing->Ring;
+    PXENVBD_GRANTER         Granter = FrontendGetGranter(Ring->Frontend);
+    PXENVBD_TARGET          Target = FrontendGetTarget(Ring->Frontend);
+    PXENVBD_ADAPTER         Adapter = TargetGetAdapter(Target);
+
+    const ULONG             SectorSize = 
FrontendGetDiskInfo(Ring->Frontend)->SectorSize;
+    const ULONG             SectorsPerPage = __SectorsPerPage(SectorSize);
+
+    Pfn = AdapterGetNextSGEntry(Adapter,
+                                SrbExt,
+                                0,
+                                &Offset,
+                                &Length);
+    if ((Offset & (SectorSize - 1)) == 0 &&
         (Length & (SectorSize - 1)) == 0) {
-        ++Ring->SegsGranted;
+        InterlockedIncrement(&Ring->Stats[XENVBD_STAT_SEGMENTS_GRANTED]);
+
         // get first sector, last sector and count
-        Segment->FirstSector    = (UCHAR)((Offset + SectorSize - 1) / 
SectorSize);
-        *SectorsNow             = __min(SectorsLeft, SectorsPerPage - 
Segment->FirstSector);
-        Segment->LastSector     = (UCHAR)(Segment->FirstSector + *SectorsNow - 
1);
+        Segment->FirstSector = (UCHAR)((Offset + SectorSize - 1) / SectorSize);
+        *SectorsNow = __min(SectorsLeft, SectorsPerPage - 
Segment->FirstSector);
+        Segment->LastSector = (UCHAR)(Segment->FirstSector + *SectorsNow - 1);
 
-        ASSERT3U((Length / SectorSize), ==, *SectorsNow);
+        ASSERT3U((Length / SectorSize), == , *SectorsNow);
     } else {
         PXENVBD_BOUNCE      Bounce;
         PMDL                Mdl;
+        PXENVBD_CAPS        Caps = FrontendGetCaps(Ring->Frontend);
+
+        InterlockedIncrement(&Ring->Stats[XENVBD_STAT_SEGMENTS_BOUNCED]);
 
-        ++Ring->SegsBounced;
         // get first sector, last sector and count
-        Segment->FirstSector    = 0;
-        *SectorsNow             = __min(SectorsLeft, SectorsPerPage);
-        Segment->LastSector     = (UCHAR)(*SectorsNow - 1);
+        Segment->FirstSector = 0;
+        *SectorsNow = __min(SectorsLeft, SectorsPerPage);
+        Segment->LastSector = (UCHAR)(*SectorsNow - 1);
 
         Bounce = AdapterGetBounce(Adapter);
         if (Bounce == NULL)
@@ -586,15 +688,15 @@ RingPrepareSegment(
 #pragma warning(push)
 #pragma warning(disable:28145)
         Mdl = &Bounce->SourceMdl;
-        Mdl->Next               = NULL;
-        Mdl->Size               = (SHORT)(sizeof(MDL) + sizeof(PFN_NUMBER));
-        Mdl->MdlFlags           = MDL_PAGES_LOCKED;
-        Mdl->Process            = NULL;
-        Mdl->MappedSystemVa     = NULL;
-        Mdl->StartVa            = NULL;
-        Mdl->ByteCount          = Length;
-        Mdl->ByteOffset         = Offset;
-        Bounce->SourcePfn[0]    = Pfn;
+        Mdl->Next = NULL;
+        Mdl->Size = (SHORT)(sizeof(MDL) + sizeof(PFN_NUMBER));
+        Mdl->MdlFlags = MDL_PAGES_LOCKED;
+        Mdl->Process = NULL;
+        Mdl->MappedSystemVa = NULL;
+        Mdl->StartVa = NULL;
+        Mdl->ByteCount = Length;
+        Mdl->ByteOffset = Offset;
+        Bounce->SourcePfn[0] = Pfn;
 
         if (Length < *SectorsNow * SectorSize) {
             Pfn = AdapterGetNextSGEntry(Adapter,
@@ -602,27 +704,27 @@ RingPrepareSegment(
                                         Length,
                                         &Offset,
                                         &Length);
-            Mdl->Size           += sizeof(PFN_NUMBER);
-            Mdl->ByteCount      += Length;
+            Mdl->Size += sizeof(PFN_NUMBER);
+            Mdl->ByteCount += Length;
             Bounce->SourcePfn[1] = Pfn;
         }
 #pragma warning(pop)
 
         ASSERT((Mdl->ByteCount & (SectorSize - 1)) == 0);
-        ASSERT3U(Mdl->ByteCount, <=, PAGE_SIZE);
-        ASSERT3U(*SectorsNow, ==, (Mdl->ByteCount / SectorSize));
+        ASSERT3U(Mdl->ByteCount, <= , PAGE_SIZE);
+        ASSERT3U(*SectorsNow, == , (Mdl->ByteCount / SectorSize));
 
         Bounce->SourcePtr = MmMapLockedPagesSpecifyCache(Mdl,
                                                          KernelMode,
                                                          MmCached,
                                                          NULL,
                                                          FALSE,
-                                                         __RingPriority(Ring));
+                                                         __Priority(Caps));
         if (Bounce->SourcePtr == NULL)
             goto fail2;
 
-        ASSERT3P(MmGetMdlPfnArray(Mdl)[0], ==, Bounce->SourcePfn[0]);
-        ASSERT3P(MmGetMdlPfnArray(Mdl)[1], ==, Bounce->SourcePfn[1]);
+        ASSERT3P(MmGetMdlPfnArray(Mdl)[0], == , Bounce->SourcePfn[0]);
+        ASSERT3P(MmGetMdlPfnArray(Mdl)[1], == , Bounce->SourcePfn[1]);
 
         // copy contents in
         if (ReadOnly) { // Operation == BLKIF_OP_WRITE
@@ -647,523 +749,510 @@ fail1:
     return FALSE;
 }
 
-static BOOLEAN
-RingPrepareBlkifReadWrite(
-    IN  PXENVBD_RING    Ring,
-    IN  PXENVBD_REQUEST Request,
-    IN  PXENVBD_SRBEXT  SrbExt,
-    IN  ULONG           MaxSegments,
-    IN  ULONG64         SectorStart,
-    IN  ULONG           SectorsLeft,
-    OUT PULONG          SectorsDone
+static NTSTATUS
+BlkifRingPrepareReadWrite(
+    IN  PXENVBD_BLKIF_RING  BlkifRing,
+    IN  PXENVBD_SRBEXT      SrbExt
     )
 {
-    PSCSI_REQUEST_BLOCK Srb = SrbExt->Srb;
-    UCHAR               Operation;
-    BOOLEAN             ReadOnly;
-    ULONG               Index;
-    __RingOperation(Cdb_OperationEx(Srb), &Operation, &ReadOnly);
-
-    Request->Operation  = Operation;
-    Request->NrSegments = 0;
-    Request->FirstSector = SectorStart;
-
-    for (Index = 0;
-                Index < MaxSegments &&
-                SectorsLeft > 0;
-                        ++Index) {
-        PXENVBD_SEGMENT Segment;
-        ULONG           SectorsNow;
-
-        Segment = RingGetSegment(Ring);
-        if (Segment == NULL)
-            goto fail1;
-
-        InsertTailList(&Request->Segments, &Segment->ListEntry);
-        ++Request->NrSegments;
+    PXENVBD_RING            Ring = BlkifRing->Ring;
+    PXENVBD_FRONTEND        Frontend = Ring->Frontend;
+    PSCSI_REQUEST_BLOCK     Srb = SrbExt->Srb;
+    ULONG64                 SectorStart = Cdb_LogicalBlock(Srb);
+    ULONG                   SectorsLeft = Cdb_TransferBlock(Srb);
+    UCHAR                   Operation;
+    BOOLEAN                 ReadOnly;
+    LIST_ENTRY              List;
 
-        if (!RingPrepareSegment(Ring,
-                                Segment,
-                                SrbExt,
-                                ReadOnly,
-                                SectorsLeft,
-                                &SectorsNow))
-            goto fail2;
+    const ULONG             SectorSize = 
FrontendGetDiskInfo(Frontend)->SectorSize;
+    const ULONG             SectorsPerPage = __SectorsPerPage(SectorSize);
+    const ULONG             MaxIndirect = 
FrontendGetFeatures(Frontend)->Indirect;
 
-        *SectorsDone += SectorsNow;
-        SectorsLeft  -= SectorsNow;
-    }
-    ASSERT3U(Request->NrSegments, >, 0);
-    ASSERT3U(Request->NrSegments, <=, MaxSegments);
+    InitializeListHead(&List);
 
-    return TRUE;
+    __Operation(Cdb_OperationEx(Srb), &Operation, &ReadOnly);
 
-fail2:
-fail1:
-    return FALSE;
-}
+    Srb->SrbStatus = SRB_STATUS_PENDING;
 
-static BOOLEAN
-RingPrepareBlkifIndirect(
-    IN  PXENVBD_RING    Ring,
-    IN  PXENVBD_REQUEST Request
-    )
-{
-    ULONG               Index;
-    ULONG               NrSegments = 0;
+    SrbExt->RequestCount = 0;
 
-    for (Index = 0;
-            Index < BLKIF_MAX_INDIRECT_PAGES_PER_REQUEST &&
-            NrSegments < Request->NrSegments;
-                ++Index) {
-        PXENVBD_INDIRECT    Indirect;
+    while (SectorsLeft > 0) {
+        ULONG           Index;
+        ULONG           MaxSegments;
+        PXENVBD_REQUEST Request;
 
-        Indirect = RingGetIndirect(Ring);
-        if (Indirect == NULL)
+        Request = BlkifRingGetRequest(BlkifRing);
+        if (Request == NULL)
             goto fail1;
-        InsertTailList(&Request->Indirects, &Indirect->ListEntry);
-
-        NrSegments += XENVBD_MAX_SEGMENTS_PER_PAGE;
-    }
-
-    return TRUE;
-
-fail1:
-    return FALSE;
-}
+        InsertTailList(&List, &Request->ListEntry);
+        SrbExt->RequestCount++;
 
-static FORCEINLINE ULONG
-RingUseIndirect(
-    IN  PXENVBD_RING    Ring,
-    IN  ULONG           SectorsLeft
-    )
-{
-    const ULONG SectorsPerPage = 
__RingSectorsPerPage(FrontendGetDiskInfo(Ring->Frontend)->SectorSize);
-    const ULONG MaxIndirectSegs = 
FrontendGetFeatures(Ring->Frontend)->Indirect;
+        Request->SrbExt = SrbExt;
 
-    if (MaxIndirectSegs <= BLKIF_MAX_SEGMENTS_PER_REQUEST)
-        return BLKIF_MAX_SEGMENTS_PER_REQUEST; // not supported
+        MaxSegments = __UseIndirect(SectorsPerPage,
+                                    MaxIndirect,
+                                    SectorsLeft);
+
+        Request->Operation = Operation;
+        Request->NrSegments = 0;
+        Request->FirstSector = SectorStart;
+
+        for (Index = 0;
+             Index < MaxSegments &&
+             SectorsLeft > 0;
+             ++Index) {
+            PXENVBD_SEGMENT Segment;
+            ULONG           SectorsNow;
+
+            Segment = BlkifRingGetSegment(BlkifRing);
+            if (Segment == NULL)
+                goto fail2;
+
+            InsertTailList(&Request->Segments, &Segment->ListEntry);
+            ++Request->NrSegments;
+
+            if (!BlkifRingPrepareSegment(BlkifRing,
+                                         Segment,
+                                         SrbExt,
+                                         ReadOnly,
+                                         SectorsLeft,
+                                         &SectorsNow))
+                goto fail3;
 
-    if (SectorsLeft < BLKIF_MAX_SEGMENTS_PER_REQUEST * SectorsPerPage)
-        return BLKIF_MAX_SEGMENTS_PER_REQUEST; // first into a single 
BLKIF_OP_{READ/WRITE}
+            SectorsLeft -= SectorsNow;
+            SectorStart += SectorsNow;
+        }
+        ASSERT3U(Request->NrSegments, >, 0);
+        ASSERT3U(Request->NrSegments, <= , MaxSegments);
 
-    return MaxIndirectSegs;
-}
+        if (MaxSegments > BLKIF_MAX_SEGMENTS_PER_REQUEST) {
+            ULONG               NrSegments = 0;
 
-static FORCEINLINE VOID
-RingQueueRequestList(
-    IN  PXENVBD_RING    Ring,
-    IN  PLIST_ENTRY     List
-    )
-{
-    for (;;) {
-        PXENVBD_REQUEST Request;
-        PLIST_ENTRY     ListEntry;
+            for (Index = 0;
+                 Index < BLKIF_MAX_INDIRECT_PAGES_PER_REQUEST &&
+                 NrSegments < Request->NrSegments;
+                 ++Index) {
+                PXENVBD_INDIRECT    Indirect;
 
-        ListEntry = RemoveHeadList(List);
-        if (ListEntry == List)
-            break;
+                Indirect = BlkifRingGetIndirect(BlkifRing);
+                if (Indirect == NULL)
+                    goto fail3;
+                InsertTailList(&Request->Indirects, &Indirect->ListEntry);
 
-        Request = CONTAINING_RECORD(ListEntry, XENVBD_REQUEST, ListEntry);
-        __RingIncBlkifOpCount(Ring, Request);
-        QueueAppend(&Ring->PreparedReqs, &Request->ListEntry);
+                NrSegments += XENVBD_MAX_SEGMENTS_PER_PAGE;
+            }
+        }
     }
-}
-
-static FORCEINLINE VOID
-RingCancelRequestList(
-    IN  PXENVBD_RING    Ring,
-    IN  PLIST_ENTRY     List
-    )
-{
-    for (;;) {
-        PXENVBD_REQUEST Request;
-        PLIST_ENTRY     ListEntry;
 
-        ListEntry = RemoveHeadList(List);
-        if (ListEntry == List)
-            break;
+    BlkifRingQueueRequests(BlkifRing, &List);
+    return STATUS_SUCCESS;
 
-        Request = CONTAINING_RECORD(ListEntry, XENVBD_REQUEST, ListEntry);
-        RingPutRequest(Ring, Request);
-    }
+fail3:
+fail2:
+fail1:
+    BlkifRingUnprepareRequest(BlkifRing, &List);
+    SrbExt->RequestCount = 0;
+    Srb->SrbStatus = SRB_STATUS_ERROR;
+    return STATUS_UNSUCCESSFUL;
 }
 
-static BOOLEAN
-RingPrepareReadWrite(
-    IN  PXENVBD_RING        Ring,
+static NTSTATUS
+BlkifRingPrepareUnmap(
+    IN  PXENVBD_BLKIF_RING  BlkifRing,
     IN  PXENVBD_SRBEXT      SrbExt
     )
 {
     PSCSI_REQUEST_BLOCK     Srb = SrbExt->Srb;
-    ULONG64                 SectorStart = Cdb_LogicalBlock(Srb);
-    ULONG                   SectorsLeft = Cdb_TransferBlock(Srb);
+    PUNMAP_LIST_HEADER      Unmap = Srb->DataBuffer;
+    ULONG                   Count;
+    ULONG                   Index;
     LIST_ENTRY              List;
 
+    InitializeListHead(&List);
+
+    Count = _byteswap_ushort(*(PUSHORT)Unmap->BlockDescrDataLength) / 
sizeof(UNMAP_BLOCK_DESCRIPTOR);
     Srb->SrbStatus = SRB_STATUS_PENDING;
 
-    InitializeListHead(&List);
     SrbExt->RequestCount = 0;
 
-    while (SectorsLeft > 0) {
-        ULONG           MaxSegments;
-        ULONG           SectorsDone = 0;
-        PXENVBD_REQUEST Request;
+    for (Index = 0; Index < Count; ++Index) {
+        PUNMAP_BLOCK_DESCRIPTOR Descr = &Unmap->Descriptors[Index];
+        PXENVBD_REQUEST         Request;
 
-        Request = RingGetRequest(Ring);
+        Request = BlkifRingGetRequest(BlkifRing);
         if (Request == NULL)
             goto fail1;
         InsertTailList(&List, &Request->ListEntry);
-        InterlockedIncrement(&SrbExt->RequestCount);
+        SrbExt->RequestCount++;
 
         Request->SrbExt = SrbExt;
-        MaxSegments = RingUseIndirect(Ring, SectorsLeft);
-
-        if (!RingPrepareBlkifReadWrite(Ring,
-                                       Request,
-                                       SrbExt,
-                                       MaxSegments,
-                                       SectorStart,
-                                       SectorsLeft,
-                                       &SectorsDone))
-            goto fail2;
-
-        if (MaxSegments > BLKIF_MAX_SEGMENTS_PER_REQUEST) {
-            if (!RingPrepareBlkifIndirect(Ring, Request))
-                goto fail3;
-        }
-
-        SectorsLeft -= SectorsDone;
-        SectorStart += SectorsDone;
+        Request->Operation = BLKIF_OP_DISCARD;
+        Request->FirstSector = _byteswap_uint64(*(PULONG64)Descr->StartingLba);
+        Request->NrSectors = _byteswap_ulong(*(PULONG)Descr->LbaCount);
+        Request->Flags = 0;
     }
 
-    RingQueueRequestList(Ring, &List);
-    return TRUE;
+    BlkifRingQueueRequests(BlkifRing, &List);
+    return STATUS_SUCCESS;
 
-fail3:
-fail2:
 fail1:
-    RingCancelRequestList(Ring, &List);
+    BlkifRingUnprepareRequest(BlkifRing, &List);
     SrbExt->RequestCount = 0;
     Srb->SrbStatus = SRB_STATUS_ERROR;
-    return FALSE;
+    return STATUS_UNSUCCESSFUL;
 }
 
-static BOOLEAN
-RingPrepareSyncCache(
-    IN  PXENVBD_RING        Ring,
+static NTSTATUS
+BlkifRingPrepareSyncCache(
+    IN  PXENVBD_BLKIF_RING  BlkifRing,
     IN  PXENVBD_SRBEXT      SrbExt
     )
 {
+    PXENVBD_RING            Ring = BlkifRing->Ring;
+    PXENVBD_FRONTEND        Frontend = Ring->Frontend;
     PSCSI_REQUEST_BLOCK     Srb = SrbExt->Srb;
     PXENVBD_REQUEST         Request;
-    LIST_ENTRY              List;
     UCHAR                   Operation;
+    LIST_ENTRY              List;
 
+    InitializeListHead(&List);
     Srb->SrbStatus = SRB_STATUS_PENDING;
 
-    if (FrontendGetDiskInfo(Ring->Frontend)->FlushCache)
+    if (FrontendGetDiskInfo(Frontend)->FlushCache)
         Operation = BLKIF_OP_FLUSH_DISKCACHE;
     else
         Operation = BLKIF_OP_WRITE_BARRIER;
 
-    InitializeListHead(&List);
     SrbExt->RequestCount = 0;
 
-    Request = RingGetRequest(Ring);
+    Request = BlkifRingGetRequest(BlkifRing);
     if (Request == NULL)
         goto fail1;
     InsertTailList(&List, &Request->ListEntry);
-    InterlockedIncrement(&SrbExt->RequestCount);
+    SrbExt->RequestCount++;
 
-    Request->SrbExt     = SrbExt;
-    Request->Operation  = Operation;
+    Request->SrbExt = SrbExt;
+    Request->Operation = Operation;
     Request->FirstSector = Cdb_LogicalBlock(Srb);
 
-    RingQueueRequestList(Ring, &List);
-    return TRUE;
+    BlkifRingQueueRequests(BlkifRing, &List);
+    return STATUS_SUCCESS;
 
 fail1:
-    RingCancelRequestList(Ring, &List);
+    BlkifRingUnprepareRequest(BlkifRing, &List);
     SrbExt->RequestCount = 0;
     Srb->SrbStatus = SRB_STATUS_ERROR;
-    return FALSE;
+    return STATUS_UNSUCCESSFUL;
 }
 
-static BOOLEAN
-RingPrepareUnmap(
-    IN  PXENVBD_RING        Ring,
+static DECLSPEC_NOINLINE NTSTATUS
+__BlkifRingPrepareSrb(
+    IN  PXENVBD_BLKIF_RING  BlkifRing,
     IN  PXENVBD_SRBEXT      SrbExt
     )
-{
-    PSCSI_REQUEST_BLOCK     Srb = SrbExt->Srb;
-    PUNMAP_LIST_HEADER      Unmap = Srb->DataBuffer;
-       ULONG                   Count = 
_byteswap_ushort(*(PUSHORT)Unmap->BlockDescrDataLength) / 
sizeof(UNMAP_BLOCK_DESCRIPTOR);
-    ULONG                   Index;
-    LIST_ENTRY              List;
-
-    Srb->SrbStatus = SRB_STATUS_PENDING;
-
-    InitializeListHead(&List);
-    SrbExt->RequestCount = 0;
-
-    for (Index = 0; Index < Count; ++Index) {
-        PUNMAP_BLOCK_DESCRIPTOR Descr = &Unmap->Descriptors[Index];
-        PXENVBD_REQUEST         Request;
-
-        Request = RingGetRequest(Ring);
-        if (Request == NULL)
-            goto fail1;
-        InsertTailList(&List, &Request->ListEntry);
-        InterlockedIncrement(&SrbExt->RequestCount);
-
-        Request->SrbExt         = SrbExt;
-        Request->Operation      = BLKIF_OP_DISCARD;
-        Request->FirstSector    = 
_byteswap_uint64(*(PULONG64)Descr->StartingLba);
-        Request->NrSectors      = _byteswap_ulong(*(PULONG)Descr->LbaCount);
-        Request->Flags          = 0;
-    }
-
-    RingQueueRequestList(Ring, &List);
-    return TRUE;
-
-fail1:
-    RingCancelRequestList(Ring, &List);
-    SrbExt->RequestCount = 0;
-    Srb->SrbStatus = SRB_STATUS_ERROR;
-    return FALSE;
-}
-
-static FORCEINLINE BOOLEAN
-RingPrepareRequest(
-    IN  PXENVBD_RING    Ring,
-    IN  PXENVBD_SRBEXT  SrbExt
-    )
 {
     switch (Cdb_OperationEx(SrbExt->Srb)) {
     case SCSIOP_READ:
     case SCSIOP_WRITE:
-        return RingPrepareReadWrite(Ring, SrbExt);
+        return BlkifRingPrepareReadWrite(BlkifRing,
+                                         SrbExt);
 
     case SCSIOP_SYNCHRONIZE_CACHE:
-        return RingPrepareSyncCache(Ring, SrbExt);
+        return BlkifRingPrepareSyncCache(BlkifRing,
+                                         SrbExt);
 
     case SCSIOP_UNMAP:
-        return RingPrepareUnmap(Ring, SrbExt);
+        return BlkifRingPrepareUnmap(BlkifRing,
+                                     SrbExt);
 
     default:
         ASSERT(FALSE);
-        return FALSE;
+        return STATUS_NOT_SUPPORTED;
     }
 }
 
-static BOOLEAN
-RingSubmit(
-    IN  PXENVBD_RING    Ring,
-    IN  PXENVBD_REQUEST Request
+static FORCEINLINE VOID
+__BlkifRingInsertRequest(
+    IN  PXENVBD_BLKIF_RING  BlkifRing,
+    IN  PXENVBD_REQUEST     Request,
+    IN  blkif_request_t     *req
     )
 {
-    KIRQL               Irql;
-    blkif_request_t*    req;
-    BOOLEAN             Notify;
-
-    KeAcquireSpinLock(&Ring->Lock, &Irql);
-    if (RING_FULL(&Ring->Front)) {
-        KeReleaseSpinLock(&Ring->Lock, Irql);
-        return FALSE;
-    }
-
-    req = RING_GET_REQUEST(&Ring->Front, Ring->Front.req_prod_pvt);
-    __RingInsert(Ring, Request, req);
-    KeMemoryBarrier();
-    ++Ring->Front.req_prod_pvt;
-
-    RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&Ring->Front, Notify);
-    KeReleaseSpinLock(&Ring->Lock, Irql);
+    PXENVBD_RING            Ring = BlkifRing->Ring;
+    PXENVBD_FRONTEND        Frontend = Ring->Frontend;
+    PXENVBD_GRANTER         Granter = FrontendGetGranter(Frontend);
 
-    if (Notify) {
-        if (!Ring->Enabled)
-            return TRUE;
-
-        XENBUS_EVTCHN(Send,
-                      &Ring->EvtchnInterface,
-                      Ring->Channel);
-    }
+    switch (Request->Operation) {
+    case BLKIF_OP_READ:
+    case BLKIF_OP_WRITE:
+        if (Request->NrSegments > BLKIF_MAX_SEGMENTS_PER_REQUEST) {
+            // Indirect
+            ULONG                       PageIdx;
+            ULONG                       SegIdx;
+            PLIST_ENTRY                 PageEntry;
+            PLIST_ENTRY                 SegEntry;
+            blkif_request_indirect_t*   req_indirect;
 
-    return TRUE;
-}
+            req_indirect = (blkif_request_indirect_t*)req;
+            req_indirect->operation = BLKIF_OP_INDIRECT;
+            req_indirect->indirect_op = Request->Operation;
+            req_indirect->nr_segments = Request->NrSegments;
+            req_indirect->id = (ULONG64)(ULONG_PTR)Request;
+            req_indirect->sector_number = Request->FirstSector;
+            req_indirect->handle = (USHORT)FrontendGetDeviceId(Frontend);
 
-static FORCEINLINE BOOLEAN
-RingSubmitRequests(
-    IN  PXENVBD_RING    Ring
-    )
-{
-    if (!Ring->Enabled) {
-        if (QueueCount(&Ring->PreparedReqs))
-            Warning("Target[%d] : Paused, not submitting new requests (%u)\n",
-                    FrontendGetTargetId(Ring->Frontend),
-                    QueueCount(&Ring->PreparedReqs));
-        return FALSE;
-    }
+            for (PageIdx = 0,
+                 PageEntry = Request->Indirects.Flink,
+                 SegEntry = Request->Segments.Flink;
+                 PageIdx < BLKIF_MAX_INDIRECT_PAGES_PER_REQUEST &&
+                 PageEntry != &Request->Indirects &&
+                 SegEntry != &Request->Segments;
+                 ++PageIdx, PageEntry = PageEntry->Flink) {
+                PXENVBD_INDIRECT Page = CONTAINING_RECORD(PageEntry, 
XENVBD_INDIRECT, ListEntry);
 
-    for (;;) {
-        PXENVBD_REQUEST Request;
-        PLIST_ENTRY     ListEntry;
+                req_indirect->indirect_grefs[PageIdx] = 
GranterReference(Granter, Page->Grant);
 
-        ListEntry = QueuePop(&Ring->PreparedReqs);
-        if (ListEntry == NULL)
-            break;
+                for (SegIdx = 0;
+                     SegIdx < XENVBD_MAX_SEGMENTS_PER_PAGE &&
+                     SegEntry != &Request->Segments;
+                     ++SegIdx, SegEntry = SegEntry->Flink) {
+                    PXENVBD_SEGMENT Segment = CONTAINING_RECORD(SegEntry, 
XENVBD_SEGMENT, ListEntry);
+
+                    Page->Page[SegIdx].GrantRef = GranterReference(Granter, 
Segment->Grant);
+                    Page->Page[SegIdx].First = Segment->FirstSector;
+                    Page->Page[SegIdx].Last = Segment->LastSector;
+                }
+            }
+            InterlockedIncrement(&Ring->Stats[(Request->Operation == 
BLKIF_OP_READ) ?
+                                 XENVBD_STAT_BLKIF_OP_READ_INDIRECT :
+                                 XENVBD_STAT_BLKIF_OP_WRITE_INDIRECT]);
+        } else {
+            // Direct
+            ULONG           Index;
+            PLIST_ENTRY     Entry;
 
-        Request = CONTAINING_RECORD(ListEntry, XENVBD_REQUEST, ListEntry);
+            req->operation = Request->Operation;
+            req->nr_segments = (UCHAR)Request->NrSegments;
+            req->handle = (USHORT)FrontendGetDeviceId(Frontend);
+            req->id = (ULONG64)(ULONG_PTR)Request;
+            req->sector_number = Request->FirstSector;
 
-        QueueAppend(&Ring->SubmittedReqs, &Request->ListEntry);
-        KeMemoryBarrier();
+            for (Index = 0, Entry = Request->Segments.Flink;
+                 Index < BLKIF_MAX_SEGMENTS_PER_REQUEST &&
+                 Entry != &Request->Segments;
+                 ++Index, Entry = Entry->Flink) {
+                PXENVBD_SEGMENT Segment = CONTAINING_RECORD(Entry, 
XENVBD_SEGMENT, ListEntry);
+                req->seg[Index].gref = GranterReference(Granter, 
Segment->Grant);
+                req->seg[Index].first_sect = Segment->FirstSector;
+                req->seg[Index].last_sect = Segment->LastSector;
+            }
+            InterlockedIncrement(&Ring->Stats[(Request->Operation == 
BLKIF_OP_READ) ?
+                                 XENVBD_STAT_BLKIF_OP_READ_DIRECT :
+                                 XENVBD_STAT_BLKIF_OP_WRITE_DIRECT]);
+        }
+        break;
 
-        if (RingSubmit(Ring, Request))
-            continue;
+    case BLKIF_OP_WRITE_BARRIER:
+    case BLKIF_OP_FLUSH_DISKCACHE:
+        req->operation = Request->Operation;
+        req->nr_segments = 0;
+        req->handle = (USHORT)FrontendGetDeviceId(Ring->Frontend);
+        req->id = (ULONG64)(ULONG_PTR)Request;
+        req->sector_number = Request->FirstSector;
+        InterlockedIncrement(&Ring->Stats[(Request->Operation == 
BLKIF_OP_WRITE_BARRIER) ?
+                             XENVBD_STAT_BLKIF_OP_WRITE_BARRIER :
+                             XENVBD_STAT_BLKIF_OP_FLUSH_DISKCACHE]);
+        break;
+
+    case BLKIF_OP_DISCARD:
+    {
+        blkif_request_discard_t*        req_discard;
+        req_discard = (blkif_request_discard_t*)req;
+        req_discard->operation = BLKIF_OP_DISCARD;
+        req_discard->flag = Request->Flags;
+        req_discard->handle = (USHORT)FrontendGetDeviceId(Frontend);
+        req_discard->id = (ULONG64)(ULONG_PTR)Request;
+        req_discard->sector_number = Request->FirstSector;
+        req_discard->nr_sectors = Request->NrSectors;
+        InterlockedIncrement(&Ring->Stats[XENVBD_STAT_BLKIF_OP_DISCARD]);
+    } break;
 
-        QueueRemove(&Ring->SubmittedReqs, &Request->ListEntry);
-        QueueUnPop(&Ring->PreparedReqs, &Request->ListEntry);
+    default:
+        ASSERT(FALSE);
         break;
     }
-
-    return QueueCount(&Ring->PreparedReqs) != 0;
 }
 
-static FORCEINLINE VOID
-RingCompleteShutdown(
-    IN  PXENVBD_RING    Ring
+static FORCEINLINE NTSTATUS
+__BlkifRingPostRequests(
+    IN  PXENVBD_BLKIF_RING  BlkifRing
     )
 {
-    PXENVBD_TARGET      Target;
-    PXENVBD_ADAPTER     Adapter;
+#define RING_SLOTS_AVAILABLE(_Front, _req_prod, _rsp_cons)   \
+        (RING_SIZE(_Front) - ((_req_prod) - (_rsp_cons)))
 
-    if (QueueCount(&Ring->ShutdownSrbs) == 0)
-        return;
+    PXENVBD_SRB_STATE       State;
+    RING_IDX                req_prod;
+    RING_IDX                rsp_cons;
+    NTSTATUS                status;
 
-    if (QueueCount(&Ring->PreparedReqs) ||
-        QueueCount(&Ring->SubmittedReqs))
-        return;
+    State = &BlkifRing->State;
 
-    Target = FrontendGetTarget(Ring->Frontend);
-    Adapter = TargetGetAdapter(Target);
-    for (;;) {
-        PXENVBD_SRBEXT      SrbExt;
-        PSCSI_REQUEST_BLOCK Srb;
+    req_prod = BlkifRing->Front.req_prod_pvt;
+    rsp_cons = BlkifRing->Front.rsp_cons;
+
+    status = STATUS_ALLOTTED_SPACE_EXCEEDED;
+    if (RING_SLOTS_AVAILABLE(&BlkifRing->Front, req_prod, rsp_cons) <= 1)
+        goto fail1;
+
+    while (State->Count != 0) {
+        blkif_request_t     *req;
+        PXENVBD_REQUEST     Request;
         PLIST_ENTRY         ListEntry;
 
-        ListEntry = QueuePop(&Ring->ShutdownSrbs);
-        if (ListEntry == NULL)
+        --State->Count;
+
+        ListEntry = RemoveHeadList(&State->List);
+        ASSERT3P(ListEntry, != , &State->List);
+
+        RtlZeroMemory(ListEntry, sizeof(LIST_ENTRY));
+
+        Request = CONTAINING_RECORD(ListEntry,
+                                    XENVBD_REQUEST,
+                                    ListEntry);
+
+        req = RING_GET_REQUEST(&BlkifRing->Front, req_prod);
+        req_prod++;
+        BlkifRing->RequestsPosted++;
+
+        __BlkifRingInsertRequest(BlkifRing,
+                                 Request,
+                                 req);
+
+        InsertTailList(&BlkifRing->SubmittedList, ListEntry);
+
+        if (RING_SLOTS_AVAILABLE(&BlkifRing->Front, req_prod, rsp_cons) <= 1)
             break;
-        SrbExt = CONTAINING_RECORD(ListEntry, XENVBD_SRBEXT, ListEntry);
-        Srb = SrbExt->Srb;
-        
-        Srb->SrbStatus = SRB_STATUS_SUCCESS;
-        AdapterCompleteSrb(Adapter, SrbExt);
     }
+
+    BlkifRing->Front.req_prod_pvt = req_prod;
+
+    return STATUS_SUCCESS;
+
+fail1:
+    return status;
+
+#undef  RING_SLOTS_AVAILABLE
 }
 
-static FORCEINLINE PCHAR
-__BlkifOperationName(
-    IN  UCHAR   Operation
+static FORCEINLINE PXENVBD_REQUEST
+__BlkifRingGetSubmittedRequest(
+    IN  PXENVBD_BLKIF_RING  BlkifRing,
+    IN  ULONG64             Id
     )
 {
-    switch (Operation) {
-    case BLKIF_OP_READ:             return "READ";
-    case BLKIF_OP_WRITE:            return "WRITE";
-    case BLKIF_OP_WRITE_BARRIER:    return "WRITE_BARRIER";
-    case BLKIF_OP_FLUSH_DISKCACHE:  return "FLUSH_DISKCACHE";
-    case BLKIF_OP_RESERVED_1:       return "RESERVED_1";
-    case BLKIF_OP_DISCARD:          return "DISCARD";
-    case BLKIF_OP_INDIRECT:         return "INDIRECT";
-    default:                        return "<unknown>";
+    PLIST_ENTRY             ListEntry;
+    PXENVBD_REQUEST         Request;
+
+    for (ListEntry = BlkifRing->SubmittedList.Flink;
+         ListEntry != &BlkifRing->SubmittedList;
+         ListEntry = ListEntry->Flink) {
+        Request = CONTAINING_RECORD(ListEntry,
+                                    XENVBD_REQUEST,
+                                    ListEntry);
+        if ((ULONG64)(ULONG_PTR)Request != Id)
+            continue;
+
+        RemoveEntryList(ListEntry);
+        return Request;
     }
+    return NULL;
 }
 
-static VOID
-RingCompleteResponse(
-    IN  PXENVBD_RING    Ring,
-    IN  ULONG64         Id,
-    IN  SHORT           Status
+static FORCEINLINE VOID
+__BlkifRingCompleteResponse(
+    IN  PXENVBD_BLKIF_RING  BlkifRing,
+    IN  PXENVBD_REQUEST     Request,
+    IN  SHORT               Status
     )
 {
-    PXENVBD_REQUEST     Request;
-    PSCSI_REQUEST_BLOCK Srb;
-    PXENVBD_SRBEXT      SrbExt;
+    PXENVBD_RING            Ring = BlkifRing->Ring;
+    PXENVBD_FRONTEND        Frontend = Ring->Frontend;
+    PSCSI_REQUEST_BLOCK     Srb;
+    PXENVBD_SRBEXT          SrbExt;
+    PLIST_ENTRY             ListEntry;
 
-    Request = RingFindRequest(Ring, Id);
-    if (Request == NULL)
-        return;
-
-    SrbExt  = Request->SrbExt;
-    Srb     = SrbExt->Srb;
+    SrbExt = Request->SrbExt;
+    Srb = SrbExt->Srb;
 
     switch (Status) {
     case BLKIF_RSP_OKAY:
-        RingRequestCopyOutput(Request);
+        if (Request->Operation != BLKIF_OP_READ)
+            break;
+
+        for (ListEntry = Request->Segments.Flink;
+             ListEntry != &Request->Segments;
+             ListEntry = ListEntry->Flink) {
+            PXENVBD_SEGMENT Segment = CONTAINING_RECORD(ListEntry, 
XENVBD_SEGMENT, ListEntry);
+            PXENVBD_BOUNCE  Bounce = Segment->Bounce;
+
+            if (Bounce) {
+                RtlCopyMemory(Bounce->SourcePtr,
+                              Bounce->BouncePtr,
+                              MmGetMdlByteCount(&Bounce->SourceMdl));
+            }
+        }
         break;
 
     case BLKIF_RSP_EOPNOTSUPP:
         // Remove appropriate feature support
-        FrontendRemoveFeature(Ring->Frontend, Request->Operation);
+        FrontendRemoveFeature(Frontend, Request->Operation);
         // Succeed this SRB, subsiquent SRBs will be succeeded instead of 
being passed to the backend.
         Srb->SrbStatus = SRB_STATUS_SUCCESS;
         break;
 
     case BLKIF_RSP_ERROR:
     default:
-        Warning("Target[%d] : %s BLKIF_RSP_ERROR (Tag %llx)\n",
-                FrontendGetTargetId(Ring->Frontend),
-                __BlkifOperationName(Request->Operation),
-                Id);
+        Warning("Target[%u][%u] : %s BLKIF_RSP_ERROR\n",
+                FrontendGetTargetId(Frontend),
+                BlkifRing->Index,
+                __BlkifOperationName(Request->Operation));
         Srb->SrbStatus = SRB_STATUS_ERROR;
         break;
     }
 
-    RingPutRequest(Ring, Request);
+    BlkifRingPutRequest(BlkifRing, Request);
 
     // complete srb
     if (InterlockedDecrement(&SrbExt->RequestCount) == 0) {
-        PXENVBD_TARGET  Target = FrontendGetTarget(Ring->Frontend);
-        PXENVBD_ADAPTER Adapter = TargetGetAdapter(Target);
-
-        if (Srb->SrbStatus == SRB_STATUS_PENDING) {
-            // SRB has not hit a failure condition (BLKIF_RSP_ERROR | 
BLKIF_RSP_EOPNOTSUPP)
-            // from any of its responses. SRB must have succeeded
-            Srb->SrbStatus = SRB_STATUS_SUCCESS;
-            Srb->ScsiStatus = 0x00; // SCSI_GOOD
-        } else {
-            // Srb->SrbStatus has already been set by 1 or more requests with 
Status != BLKIF_RSP_OKAY
-            Srb->ScsiStatus = 0x40; // SCSI_ABORTED
-        }
-
-        AdapterCompleteSrb(Adapter, SrbExt);
+        __BlkifRingCompleteSrb(BlkifRing, SrbExt);
     }
 }
 
-static BOOLEAN
-RingPoll(
-    IN  PXENVBD_RING    Ring
+static FORCEINLINE BOOLEAN
+BlkifRingPoll(
+    IN  PXENVBD_BLKIF_RING  BlkifRing
     )
 {
-    BOOLEAN             Retry = FALSE;
+#define XENVBD_BATCH(_Ring) (RING_SIZE(&(_Ring)->Front) / 4)
 
-    ASSERT3U(KeGetCurrentIrql(), ==, DISPATCH_LEVEL);
-    KeAcquireSpinLockAtDpcLevel(&Ring->Lock);
+    PXENVBD_RING            Ring;
+    BOOLEAN                 Retry;
 
-    // Guard against this locked region being called after the
-    // lock on FrontendSetState
-    if (Ring->Enabled == FALSE)
+    Ring = BlkifRing->Ring;
+    Retry = FALSE;
+
+    if (!BlkifRing->Enabled)
         goto done;
 
     for (;;) {
-        ULONG   rsp_prod;
-        ULONG   rsp_cons;
+        RING_IDX            rsp_prod;
+        RING_IDX            rsp_cons;
 
         KeMemoryBarrier();
 
-        rsp_prod = Ring->Shared->rsp_prod;
-        rsp_cons = Ring->Front.rsp_cons;
+        rsp_prod = BlkifRing->Shared->rsp_prod;
+        rsp_cons = BlkifRing->Front.rsp_cons;
 
         KeMemoryBarrier();
 
@@ -1171,318 +1260,984 @@ RingPoll(
             break;
 
         while (rsp_cons != rsp_prod && !Retry) {
-            blkif_response_t*   rsp;
+            blkif_response_t    *rsp;
+            PXENVBD_REQUEST     Request;
+
+            rsp = RING_GET_RESPONSE(&BlkifRing->Front, rsp_cons);
+            rsp_cons++;
+            BlkifRing->ResponsesProcessed++;
 
-            rsp = RING_GET_RESPONSE(&Ring->Front, rsp_cons);
-            ++rsp_cons;
-            ++Ring->Received;
+            BlkifRing->Stopped = FALSE;
 
-            RingCompleteResponse(Ring, rsp->id, rsp->status);
-            RtlZeroMemory(rsp, sizeof(union blkif_sring_entry));
+            Request = __BlkifRingGetSubmittedRequest(BlkifRing,
+                                                     rsp->id);
+            ASSERT3P(Request, != , NULL);
 
-            if (rsp_cons - Ring->Front.rsp_cons > RING_SIZE(&Ring->Front) / 4)
+            __BlkifRingCompleteResponse(BlkifRing,
+                                        Request,
+                                        rsp->status);
+
+            if (rsp_cons - BlkifRing->Front.rsp_cons > XENVBD_BATCH(BlkifRing))
                 Retry = TRUE;
         }
 
         KeMemoryBarrier();
 
-        Ring->Front.rsp_cons = rsp_cons;
-        Ring->Shared->rsp_event = rsp_cons + 1;
+        BlkifRing->Front.rsp_cons = rsp_cons;
     }
 
 done:
-    KeReleaseSpinLockFromDpcLevel(&Ring->Lock);
-
     return Retry;
+
+#undef XENVBD_BATCH
 }
 
-__drv_requiresIRQL(DISPATCH_LEVEL)
-static BOOLEAN
-RingNotifyResponses(
-    IN  PXENVBD_RING    Ring
+static FORCEINLINE VOID
+__BlkifRingSend(
+    IN  PXENVBD_BLKIF_RING  BlkifRing
     )
 {
-    BOOLEAN             Retry = FALSE;
-
-    if (!Ring->Enabled)
-        return FALSE;
+    PXENVBD_RING            Ring = BlkifRing->Ring;
 
-    Retry |= RingPoll(Ring);
-    Retry |= RingSubmitRequests(Ring);
-
-    RingCompleteShutdown(Ring);
-    return Retry;
+    XENBUS_EVTCHN(Send,
+                  &Ring->EvtchnInterface,
+                  BlkifRing->Channel);
 }
 
-KSERVICE_ROUTINE    RingInterrupt;
-
-BOOLEAN
-RingInterrupt(
-    IN  PKINTERRUPT Interrupt,
-    IN  PVOID       Context
+static FORCEINLINE VOID
+__BlkifRingPushRequests(
+    IN  PXENVBD_BLKIF_RING  BlkifRing
     )
 {
-    PXENVBD_RING    Ring = Context;
+    BOOLEAN                 Notify;
 
-    UNREFERENCED_PARAMETER(Interrupt);
+    if (BlkifRing->RequestsPosted == BlkifRing->RequestsPushed)
+        return;
 
-    ASSERT(Ring != NULL);
+#pragma warning (push)
+#pragma warning (disable:4244)
 
-    ++Ring->Events;
-    if (!Ring->Connected)
-        return TRUE;
+    BlkifRing->Shared->rsp_event = BlkifRing->Front.req_prod_pvt;
 
-    if (KeInsertQueueDpc(&Ring->Dpc, NULL, NULL))
-        ++Ring->Dpcs;
+    // Make the requests visible to the backend
+    RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&BlkifRing->Front, Notify);
 
-    return TRUE;
+#pragma warning (pop)
+
+    if (Notify)
+        __BlkifRingSend(BlkifRing);
+
+    BlkifRing->RequestsPushed = BlkifRing->RequestsPosted;
 }
 
-KDEFERRED_ROUTINE RingDpc;
+#define XENVBD_LOCK_BIT ((ULONG_PTR)1)
 
-VOID
-RingDpc(
-    __in  PKDPC     Dpc,
-    __in_opt PVOID  Context,
-    __in_opt PVOID  Arg1,
-    __in_opt PVOID  Arg2
+static DECLSPEC_NOINLINE VOID
+BlkifRingSwizzle(
+    IN  PXENVBD_BLKIF_RING  BlkifRing
     )
 {
-    PXENVBD_RING    Ring = Context;
+    ULONG_PTR               Old;
+    ULONG_PTR               New;
+    PLIST_ENTRY             ListEntry;
+    LIST_ENTRY              List;
+    ULONG                   Count;
 
-    UNREFERENCED_PARAMETER(Dpc);
-    UNREFERENCED_PARAMETER(Arg1);
-    UNREFERENCED_PARAMETER(Arg2);
+    ASSERT3P(BlkifRing->LockThread, == , KeGetCurrentThread());
 
-    ASSERT(Ring != NULL);
+    InitializeListHead(&List);
 
-    for (;;) {
-        KIRQL       Irql;
-        BOOLEAN     Retry;
+    New = XENVBD_LOCK_BIT;
+    Old = (ULONG_PTR)InterlockedExchangePointer(&BlkifRing->Lock, (PVOID)New);
 
-        KeRaiseIrql(DISPATCH_LEVEL, &Irql);
-        Retry = RingNotifyResponses(Ring);
-        KeLowerIrql(Irql);
+    ASSERT(Old & XENVBD_LOCK_BIT);
+    ListEntry = (PVOID)(Old & ~XENVBD_LOCK_BIT);
 
-        if (!Retry)
-            break;
+    if (ListEntry == NULL)
+        return;
+
+    // Packets are held in the atomic packet list in reverse order
+    // so that the most recent is always head of the list. This is
+    // necessary to allow addition to the list to be done atomically.
+
+    for (Count = 0; ListEntry != NULL; ++Count) {
+        PLIST_ENTRY     NextEntry;
+
+        NextEntry = ListEntry->Blink;
+        ListEntry->Flink = ListEntry->Blink = ListEntry;
+
+        InsertHeadList(&List, ListEntry);
+
+        ListEntry = NextEntry;
     }
 
-    XENBUS_EVTCHN(Unmask,
-                  &Ring->EvtchnInterface,
-                  Ring->Channel,
-                  FALSE);
+    if (!IsListEmpty(&List)) {
+        ListEntry = List.Flink;
+
+        RemoveEntryList(&List);
+        AppendTailList(&BlkifRing->SrbQueue, ListEntry);
+
+        BlkifRing->SrbsQueued += Count;
+    }
 }
 
 static DECLSPEC_NOINLINE VOID
-RingDebugCallback(
-    IN  PVOID       Argument,
-    IN  BOOLEAN     Crashing
+BlkifRingSchedule(
+    IN  PXENVBD_BLKIF_RING  BlkifRing
     )
 {
-    PXENVBD_RING    Ring = Argument;
-    PXENVBD_GRANTER Granter = FrontendGetGranter(Ring->Frontend);
-    ULONG           Index;
+    PXENVBD_SRB_STATE       State;
+    BOOLEAN                 Polled;
 
-    UNREFERENCED_PARAMETER(Crashing);
+    if (!BlkifRing->Enabled)
+        return;
 
-    XENBUS_DEBUG(Printf,
-                 &Ring->DebugInterface,
-                 "Submitted: %u Received: %u\n",
-                 Ring->Submitted,
-                 Ring->Received);
+    State = &BlkifRing->State;
+    Polled = FALSE;
 
-    XENBUS_DEBUG(Printf,
-                 &Ring->DebugInterface,
-                 "Events: %u Dpcs: %u\n",
-                 Ring->Events,
-                 Ring->Dpcs);
+    while (!BlkifRing->Stopped) {
+        PLIST_ENTRY         ListEntry;
+        PXENVBD_SRBEXT      SrbExt;
+        NTSTATUS            status;
 
-    XENBUS_DEBUG(Printf,
-                 &Ring->DebugInterface,
-                 "Shared : 0x%p\n",
-                 Ring->Shared);
+        if (State->Count != 0) {
+            status = __BlkifRingPostRequests(BlkifRing);
+            if (!NT_SUCCESS(status))
+                BlkifRing->Stopped = TRUE;
+        }
 
-    if (Ring->Shared) {
-        XENBUS_DEBUG(Printf,
-                     &Ring->DebugInterface,
-                     "Shared: %d / %d - %d / %d\n",
-                     Ring->Shared->req_prod,
-                     Ring->Shared->req_event,
-                     Ring->Shared->rsp_prod,
-                     Ring->Shared->rsp_event);
-    }
+        if (BlkifRing->Stopped) {
+            if (!Polled) {
+                (VOID)BlkifRingPoll(BlkifRing);
+                Polled = TRUE;
+            }
 
-    XENBUS_DEBUG(Printf,
-                 &Ring->DebugInterface,
-                 "Front: %d / %d (%d)\n",
-                 Ring->Front.req_prod_pvt,
-                 Ring->Front.rsp_cons,
-                 Ring->Front.nr_ents);
+            continue;
+        }
 
-    XENBUS_DEBUG(Printf,
-                 &Ring->DebugInterface,
-                 "Order: %d\n",
-                 Ring->Order);
+        if (BlkifRing->RequestsPosted - BlkifRing->RequestsPushed >=
+            RING_SIZE(&BlkifRing->Front) / 4)
+            __BlkifRingPushRequests(BlkifRing);
 
-    for (Index = 0; Index < (1ul << Ring->Order); ++Index) {
-        XENBUS_DEBUG(Printf,
-                     &Ring->DebugInterface,
-                     "Grants[%-2d]: 0x%p (%u)\n",
-                     Index,
-                     Ring->Grants[Index],
-                     GranterReference(Granter, Ring->Grants[Index]));
+        ASSERT3U(State->Count, == , 0);
+
+        if (IsListEmpty(&BlkifRing->SrbQueue))
+            break;
+
+        ListEntry = RemoveHeadList(&BlkifRing->SrbQueue);
+        ASSERT3P(ListEntry, != , &BlkifRing->SrbQueue);
+
+        RtlZeroMemory(ListEntry, sizeof(LIST_ENTRY));
+
+        SrbExt = CONTAINING_RECORD(ListEntry,
+                                   XENVBD_SRBEXT,
+                                   ListEntry);
+
+        status = __BlkifRingPrepareSrb(BlkifRing, SrbExt);
+        if (!NT_SUCCESS(status)) {
+            PSCSI_REQUEST_BLOCK Srb = SrbExt->Srb;
+            Srb->SrbStatus = SRB_STATUS_BUSY;
+            __BlkifRingCompleteSrb(BlkifRing, SrbExt);
+        }
     }
 
-    if (Ring->Channel) {
-        ULONG       Port = XENBUS_EVTCHN(GetPort,
-                                         &Ring->EvtchnInterface,
-                                         Ring->Channel);
+    __BlkifRingPushRequests(BlkifRing);
 
-        XENBUS_DEBUG(Printf,
-                     &Ring->DebugInterface,
-                     "Channel : %p (%d)\n",
-                     Ring->Channel,
-                     Port);
+    if (IsListEmpty(&BlkifRing->ShutdownQueue))
+        return;
+
+    if (!IsListEmpty(&BlkifRing->SrbQueue) ||
+        !IsListEmpty(&BlkifRing->SubmittedList))
+        return;
+
+    for (;;) {
+        PLIST_ENTRY         ListEntry;
+        PXENVBD_SRBEXT      SrbExt;
+        PSCSI_REQUEST_BLOCK Srb;
+
+        ListEntry = RemoveHeadList(&BlkifRing->ShutdownQueue);
+        if (ListEntry == &BlkifRing->ShutdownQueue)
+            break;
+
+        SrbExt = CONTAINING_RECORD(ListEntry,
+                                   XENVBD_SRBEXT,
+                                   ListEntry);
+
+        Srb = SrbExt->Srb;
+        Srb->SrbStatus = SRB_STATUS_SUCCESS;
+        __BlkifRingCompleteSrb(BlkifRing, SrbExt);
     }
+}
 
-    XENBUS_DEBUG(Printf,
-                 &Ring->DebugInterface,
-                 "BLKIF_OPs: READ=%u WRITE=%u\n",
-                 Ring->BlkOpRead,
-                 Ring->BlkOpWrite);
-    XENBUS_DEBUG(Printf,
-                 &Ring->DebugInterface,
-                 "BLKIF_OPs: INDIRECT_READ=%u INDIRECT_WRITE=%u\n",
-                 Ring->BlkOpIndirectRead,
-                 Ring->BlkOpIndirectWrite);
-    XENBUS_DEBUG(Printf,
-                 &Ring->DebugInterface,
-                 "BLKIF_OPs: BARRIER=%u DISCARD=%u FLUSH=%u\n",
-                 Ring->BlkOpBarrier,
-                 Ring->BlkOpDiscard,
-                 Ring->BlkOpFlush);
-    XENBUS_DEBUG(Printf,
-                 &Ring->DebugInterface,
-                 "Segments Granted=%llu Bounced=%llu\n",
-                 Ring->SegsGranted,
-                 Ring->SegsBounced);
+static FORCEINLINE BOOLEAN
+__drv_requiresIRQL(DISPATCH_LEVEL)
+__BlkifRingTryAcquireLock(
+    IN  PXENVBD_BLKIF_RING  BlkifRing
+    )
+{
+    ULONG_PTR               Old;
+    ULONG_PTR               New;
+    BOOLEAN                 Acquired;
+
+    ASSERT3U(KeGetCurrentIrql(), == , DISPATCH_LEVEL);
+
+    KeMemoryBarrier();
+
+    Old = (ULONG_PTR)BlkifRing->Lock & ~XENVBD_LOCK_BIT;
+    New = Old | XENVBD_LOCK_BIT;
+
+    Acquired = ((ULONG_PTR)InterlockedCompareExchangePointer(&BlkifRing->Lock,
+        (PVOID)New,
+                                                             (PVOID)Old) == 
Old) ? TRUE : FALSE;
 
-    QueueDebugCallback(&Ring->PreparedReqs,
-                       "Prepared ",
-                       &Ring->DebugInterface);
-    QueueDebugCallback(&Ring->SubmittedReqs,
-                       "Submitted",
-                       &Ring->DebugInterface);
-    QueueDebugCallback(&Ring->ShutdownSrbs,
-                       "Shutdown ",
-                       &Ring->DebugInterface);
+    KeMemoryBarrier();
+
+    if (Acquired) {
+        ASSERT3P(BlkifRing->LockThread, == , NULL);
+        BlkifRing->LockThread = KeGetCurrentThread();
+        KeMemoryBarrier();
+    }
+
+    return Acquired;
 }
 
-static DECLSPEC_NOINLINE VOID
-RingAcquireLock(
-    IN  PVOID       Argument
+static FORCEINLINE VOID
+__drv_requiresIRQL(DISPATCH_LEVEL)
+__BlkifRingAcquireLock(
+    IN  PXENVBD_BLKIF_RING  BlkifRing
     )
 {
-    PXENVBD_RING    Ring = Argument;
-    KeAcquireSpinLockAtDpcLevel(&Ring->Lock);
+    ASSERT3U(KeGetCurrentIrql(), == , DISPATCH_LEVEL);
+
+    for (;;) {
+        if (__BlkifRingTryAcquireLock(BlkifRing))
+            break;
+
+        _mm_pause();
+    }
 }
 
-static DECLSPEC_NOINLINE VOID
-RingReleaseLock(
-    IN  PVOID       Argument
+static VOID
+BlkifRingAcquireLock(
+    IN  PXENVBD_BLKIF_RING  BlkifRing
     )
 {
-    PXENVBD_RING    Ring = Argument;
-    KeReleaseSpinLockFromDpcLevel(&Ring->Lock);
+    __BlkifRingAcquireLock(BlkifRing);
 }
 
-static DECLSPEC_NOINLINE NTSTATUS
-RingRequestCtor(
-    IN  PVOID       Argument,
-    IN  PVOID       Object
+static FORCEINLINE BOOLEAN
+__drv_requiresIRQL(DISPATCH_LEVEL)
+__BlkifRingTryReleaseLock(
+    IN  PXENVBD_BLKIF_RING  BlkifRing
     )
 {
-    PXENVBD_REQUEST Request = Object;
+    ULONG_PTR               Old;
+    ULONG_PTR               New;
+    BOOLEAN                 Released;
 
-    UNREFERENCED_PARAMETER(Argument);
+    ASSERT3U(KeGetCurrentIrql(), == , DISPATCH_LEVEL);
+    ASSERT3P(KeGetCurrentThread(), == , BlkifRing->LockThread);
 
-    InitializeListHead(&Request->Segments);
-    InitializeListHead(&Request->Indirects);
-    return STATUS_SUCCESS;
+    Old = XENVBD_LOCK_BIT;
+    New = 0;
+
+    BlkifRing->LockThread = NULL;
+
+    KeMemoryBarrier();
+
+    Released = ((ULONG_PTR)InterlockedCompareExchangePointer(&BlkifRing->Lock,
+        (PVOID)New,
+                                                             (PVOID)Old) == 
Old) ? TRUE : FALSE;
+
+    KeMemoryBarrier();
+
+    if (!Released) {
+        ASSERT3P(BlkifRing->LockThread, == , NULL);
+        BlkifRing->LockThread = KeGetCurrentThread();
+        KeMemoryBarrier();
+    }
+
+    return Released;
 }
 
-static DECLSPEC_NOINLINE VOID
-RingRequestDtor(
-    IN  PVOID       Argument,
-    IN  PVOID       Object
+static FORCEINLINE VOID
+__drv_requiresIRQL(DISPATCH_LEVEL)
+__BlkifRingReleaseLock(
+    IN  PXENVBD_BLKIF_RING  BlkifRing
     )
 {
-    UNREFERENCED_PARAMETER(Argument);
-    UNREFERENCED_PARAMETER(Object);
+    ASSERT3U(KeGetCurrentIrql(), == , DISPATCH_LEVEL);
+
+    // As lock holder it is our responsibility to drain the atomic
+    // packet list into the transmit queue before we actually drop the
+    // lock. This may, of course, take a few attempts as another
+    // thread could be simuntaneously adding to the list.
+
+    do {
+        BlkifRingSwizzle(BlkifRing);
+        BlkifRingSchedule(BlkifRing);
+    } while (!__BlkifRingTryReleaseLock(BlkifRing));
 }
 
-static DECLSPEC_NOINLINE NTSTATUS
-RingSegmentCtor(
-    IN  PVOID       Argument,
-    IN  PVOID       Object
+static VOID
+BlkifRingReleaseLock(
+    IN  PXENVBD_BLKIF_RING  BlkifRing
     )
 {
-    UNREFERENCED_PARAMETER(Argument);
-    UNREFERENCED_PARAMETER(Object);
+    __BlkifRingReleaseLock(BlkifRing);
+}
+
+KSERVICE_ROUTINE    BlkifRingInterrupt;
+
+BOOLEAN
+BlkifRingInterrupt(
+    IN  PKINTERRUPT     InterruptObject,
+    IN  PVOID           Argument
+    )
+{
+    PXENVBD_BLKIF_RING  BlkifRing = Argument;
+
+    UNREFERENCED_PARAMETER(InterruptObject);
+
+    ASSERT(BlkifRing != NULL);
+
+    BlkifRing->Events++;
+
+    if (KeInsertQueueDpc(&BlkifRing->Dpc, NULL, NULL))
+        BlkifRing->Dpcs++;
+
+    return TRUE;
+}
+
+__drv_functionClass(KDEFERRED_ROUTINE)
+__drv_maxIRQL(DISPATCH_LEVEL)
+__drv_minIRQL(PASSIVE_LEVEL)
+__drv_sameIRQL
+static VOID
+BlkifRingDpc(
+    IN  PKDPC           Dpc,
+    IN  PVOID           Context,
+    IN  PVOID           Argument1,
+    IN  PVOID           Argument2
+    )
+{
+    PXENVBD_BLKIF_RING  BlkifRing = Context;
+    PXENVBD_RING        Ring;
+
+    UNREFERENCED_PARAMETER(Dpc);
+    UNREFERENCED_PARAMETER(Argument1);
+    UNREFERENCED_PARAMETER(Argument2);
+
+    ASSERT(BlkifRing != NULL);
+
+    Ring = BlkifRing->Ring;
+
+    for (;;) {
+        BOOLEAN         Retry;
+        KIRQL           Irql;
+
+        KeRaiseIrql(DISPATCH_LEVEL, &Irql);
+        __BlkifRingAcquireLock(BlkifRing);
+        Retry = BlkifRingPoll(BlkifRing);
+        __BlkifRingReleaseLock(BlkifRing);
+        KeLowerIrql(Irql);
+
+        if (!Retry)
+            break;
+    }
+
+    XENBUS_EVTCHN(Unmask,
+                  &Ring->EvtchnInterface,
+                  BlkifRing->Channel,
+                  FALSE);
+}
+
+static NTSTATUS
+BlkifRingCreate(
+    IN  PXENVBD_RING        Ring,
+    IN  ULONG               Index,
+    OUT PXENVBD_BLKIF_RING* BlkifRing
+    )
+{
+    PXENVBD_FRONTEND        Frontend;
+    ULONG                   Length;
+    PCHAR                   Path;
+    CHAR                    Name[MAX_NAME_LEN];
+    NTSTATUS                status;
+
+    Frontend = Ring->Frontend;
+
+    Length = (ULONG)strlen(FrontendGetFrontendPath(Frontend)) +
+        (ULONG)strlen("/queue-xxx");
+
+    Path = __RingAllocate(Length + 1);
+
+    status = STATUS_NO_MEMORY;
+    if (Path == NULL)
+        goto fail1;
+
+    status = RtlStringCchPrintfA(Path,
+                                 Length,
+                                 "%s/queue-%u",
+                                 FrontendGetFrontendPath(Frontend),
+                                 Index);
+    if (!NT_SUCCESS(status))
+        goto fail2;
+
+    *BlkifRing = __RingAllocate(sizeof(XENVBD_BLKIF_RING));
+
+    status = STATUS_NO_MEMORY;
+    if (*BlkifRing == NULL)
+        goto fail3;
+
+    (*BlkifRing)->Ring = Ring;
+    (*BlkifRing)->Index = Index;
+    (*BlkifRing)->Path = Path;
+    Path = NULL;
+
+    InitializeListHead(&(*BlkifRing)->SrbQueue);
+    InitializeListHead(&(*BlkifRing)->ShutdownQueue);
+    InitializeListHead(&(*BlkifRing)->SubmittedList);
+    InitializeListHead(&(*BlkifRing)->State.List);
+
+    KeInitializeThreadedDpc(&(*BlkifRing)->Dpc, BlkifRingDpc, *BlkifRing);
+
+    status = RtlStringCbPrintfA(Name,
+                                sizeof(Name),
+                                "vbd_%u_queue_%u_request",
+                                FrontendGetTargetId(Frontend),
+                                Index);
+    if (!NT_SUCCESS(status))
+        goto fail4;
+
+    status = XENBUS_CACHE(Create,
+                          &Ring->CacheInterface,
+                          Name,
+                          sizeof(XENVBD_REQUEST),
+                          0,
+                          BlkifRingRequestCtor,
+                          BlkifRingRequestDtor,
+                          BlkifRingAcquireLock,
+                          BlkifRingReleaseLock,
+                          *BlkifRing,
+                          &(*BlkifRing)->RequestCache);
+    if (!NT_SUCCESS(status))
+        goto fail5;
+
+    status = RtlStringCbPrintfA(Name,
+                                sizeof(Name),
+                                "vbd_%u_queue_%u_segment",
+                                FrontendGetTargetId(Frontend),
+                                Index);
+    if (!NT_SUCCESS(status))
+        goto fail6;
+
+    status = XENBUS_CACHE(Create,
+                          &Ring->CacheInterface,
+                          Name,
+                          sizeof(XENVBD_SEGMENT),
+                          0,
+                          BlkifRingSegmentCtor,
+                          BlkifRingSegmentDtor,
+                          BlkifRingAcquireLock,
+                          BlkifRingReleaseLock,
+                          *BlkifRing,
+                          &(*BlkifRing)->SegmentCache);
+    if (!NT_SUCCESS(status))
+        goto fail7;
+
+    status = RtlStringCbPrintfA(Name,
+                                sizeof(Name),
+                                "vbd_%u_queue_%u_indirect",
+                                FrontendGetTargetId(Frontend),
+                                Index);
+    if (!NT_SUCCESS(status))
+        goto fail8;
+
+    status = XENBUS_CACHE(Create,
+                          &Ring->CacheInterface,
+                          Name,
+                          sizeof(XENVBD_INDIRECT),
+                          0,
+                          BlkifRingIndirectCtor,
+                          BlkifRingIndirectDtor,
+                          BlkifRingAcquireLock,
+                          BlkifRingReleaseLock,
+                          *BlkifRing,
+                          &(*BlkifRing)->IndirectCache);
+    if (!NT_SUCCESS(status))
+        goto fail9;
+
     return STATUS_SUCCESS;
+
+fail9:
+    Error("fail9\n");
+fail8:
+    Error("fail8\n");
+    XENBUS_CACHE(Destroy,
+                 &Ring->CacheInterface,
+                 (*BlkifRing)->SegmentCache);
+    (*BlkifRing)->SegmentCache = NULL;
+fail7:
+    Error("fail7\n");
+fail6:
+    Error("fail6\n");
+    XENBUS_CACHE(Destroy,
+                 &Ring->CacheInterface,
+                 (*BlkifRing)->RequestCache);
+    (*BlkifRing)->RequestCache = NULL;
+fail5:
+    Error("fail5\n");
+fail4:
+    Error("fail4\n");
+
+    RtlZeroMemory(&(*BlkifRing)->Dpc, sizeof(KDPC));
+
+    RtlZeroMemory(&(*BlkifRing)->State.List, sizeof(LIST_ENTRY));
+    RtlZeroMemory(&(*BlkifRing)->SubmittedList, sizeof(LIST_ENTRY));
+    RtlZeroMemory(&(*BlkifRing)->ShutdownQueue, sizeof(LIST_ENTRY));
+    RtlZeroMemory(&(*BlkifRing)->SrbQueue, sizeof(LIST_ENTRY));
+
+    __RingFree((*BlkifRing)->Path);
+    (*BlkifRing)->Path;
+    (*BlkifRing)->Index = 0;
+    (*BlkifRing)->Ring = NULL;
+
+    ASSERT(IsZeroMemory(*BlkifRing, sizeof(XENVBD_BLKIF_RING)));
+    __RingFree(*BlkifRing);
+    *BlkifRing = NULL;
+fail3:
+    Error("fail3\n");
+fail2:
+    Error("fail2\n");
+    __RingFree(Path);
+fail1:
+    Error("fail1 (%08x)\n", status);
+    return status;
 }
 
-static DECLSPEC_NOINLINE VOID
-RingSegmentDtor(
-    IN  PVOID       Argument,
-    IN  PVOID       Object
+static VOID
+BlkifRingDestroy(
+    IN  PXENVBD_BLKIF_RING  BlkifRing
     )
 {
-    UNREFERENCED_PARAMETER(Argument);
-    UNREFERENCED_PARAMETER(Object);
+    PXENVBD_RING            Ring = BlkifRing->Ring;
+
+    XENBUS_CACHE(Destroy,
+                 &Ring->CacheInterface,
+                 BlkifRing->IndirectCache);
+    BlkifRing->IndirectCache = NULL;
+
+    XENBUS_CACHE(Destroy,
+                 &Ring->CacheInterface,
+                 BlkifRing->SegmentCache);
+    BlkifRing->SegmentCache = NULL;
+
+    XENBUS_CACHE(Destroy,
+                 &Ring->CacheInterface,
+                 BlkifRing->RequestCache);
+    BlkifRing->RequestCache = NULL;
+
+    RtlZeroMemory(&BlkifRing->Dpc, sizeof(KDPC));
+
+    ASSERT3U(BlkifRing->State.Count, == , 0);
+    ASSERT(IsListEmpty(&BlkifRing->State.List));
+    RtlZeroMemory(&BlkifRing->State.List, sizeof(LIST_ENTRY));
+
+    RtlZeroMemory(&BlkifRing->SubmittedList, sizeof(LIST_ENTRY));
+    RtlZeroMemory(&BlkifRing->SrbQueue, sizeof(LIST_ENTRY));
+    RtlZeroMemory(&BlkifRing->ShutdownQueue, sizeof(LIST_ENTRY));
+
+    __RingFree(BlkifRing->Path);
+    BlkifRing->Path;
+    BlkifRing->Index = 0;
+    BlkifRing->Ring = NULL;
+
+    ASSERT(IsZeroMemory(BlkifRing, sizeof(XENVBD_BLKIF_RING)));
+    __RingFree(BlkifRing);
 }
 
-static DECLSPEC_NOINLINE NTSTATUS
-RingIndirectCtor(
-    IN  PVOID           Argument,
-    IN  PVOID           Object
+static NTSTATUS
+BlkifRingConnect(
+    IN  PXENVBD_BLKIF_RING  BlkifRing
     )
 {
-    PXENVBD_INDIRECT    Indirect = Object;
-    NTSTATUS            status;
+    PXENVBD_RING            Ring = BlkifRing->Ring;
+    PXENVBD_FRONTEND        Frontend = Ring->Frontend;
+    PXENVBD_GRANTER         Granter = FrontendGetGranter(Frontend);
+    CHAR                    Name[MAX_NAME_LEN];
+    ULONG                   Index;
+    NTSTATUS                status;
 
-    UNREFERENCED_PARAMETER(Argument);
+    Trace("====> %u\n", BlkifRing->Index);
+    ASSERT(!BlkifRing->Connected);
+
+    if (FrontendGetNumQueues(Frontend) != 1) {
+        PROCESSOR_NUMBER    ProcNumber;
+
+        status = KeGetProcessorNumberFromIndex(BlkifRing->Index, &ProcNumber);
+        ASSERT(NT_SUCCESS(status));
+
+        KeSetTargetProcessorDpcEx(&BlkifRing->Dpc, &ProcNumber);
+    }
+    KeSetImportanceDpc(&BlkifRing->Dpc, MediumHighImportance);
+
+    BlkifRing->Mdl = __AllocatePages(1 << Ring->Order);
 
     status = STATUS_NO_MEMORY;
-    Indirect->Mdl = __AllocatePage();
-    if (Indirect->Mdl == NULL)
+    if (BlkifRing->Mdl == NULL)
         goto fail1;
 
-    Indirect->Page = MmGetSystemAddressForMdlSafe(Indirect->Mdl,
-                                                  NormalPagePriority);
-    ASSERT(Indirect->Page);
+    BlkifRing->Shared = MmGetSystemAddressForMdlSafe(BlkifRing->Mdl,
+                                                     NormalPagePriority);
+    ASSERT(BlkifRing->Shared != NULL);
+
+#pragma warning(push)
+#pragma warning(disable: 4305)
+#pragma warning(disable: 4311) // 'type cast' pointer truncation from 
'blkif_sring_entry[1]' to 'long'
+    SHARED_RING_INIT(BlkifRing->Shared);
+    FRONT_RING_INIT(&BlkifRing->Front, BlkifRing->Shared, PAGE_SIZE << 
Ring->Order);
+#pragma warning(pop)
+
+    for (Index = 0; Index < (1ul << Ring->Order); ++Index) {
+        status = GranterGet(Granter,
+                            MmGetMdlPfnArray(BlkifRing->Mdl)[Index],
+                            FALSE,
+                            &BlkifRing->Grants[Index]);
+        if (!NT_SUCCESS(status))
+            goto fail2;
+    }
+
+    BlkifRing->Channel = XENBUS_EVTCHN(Open,
+                                       &Ring->EvtchnInterface,
+                                       XENBUS_EVTCHN_TYPE_UNBOUND,
+                                       BlkifRingInterrupt,
+                                       BlkifRing,
+                                       
FrontendGetBackendDomain(Ring->Frontend),
+                                       TRUE);
+    status = STATUS_NO_MEMORY;
+    if (BlkifRing->Channel == NULL)
+        goto fail3;
+
+    XENBUS_EVTCHN(Unmask,
+                  &Ring->EvtchnInterface,
+                  BlkifRing->Channel,
+                  FALSE);
+
+    status = RtlStringCchPrintfA(Name,
+                                 MAX_NAME_LEN,
+                                 __MODULE__"|RING[%u]",
+                                 Index);
+    if (!NT_SUCCESS(status))
+        goto fail4;
+
+    status = XENBUS_DEBUG(Register,
+                          &Ring->DebugInterface,
+                          Name,
+                          BlkifRingDebugCallback,
+                          BlkifRing,
+                          &BlkifRing->DebugCallback);
+    if (!NT_SUCCESS(status))
+        goto fail5;
+
+    BlkifRing->Connected = TRUE;
+    Trace("<==== %u\n", BlkifRing->Index);
 
     return STATUS_SUCCESS;
 
+fail5:
+    Error("fail5\n");
+fail4:
+    Error("fail4\n");
+    XENBUS_EVTCHN(Close,
+                  &Ring->EvtchnInterface,
+                  BlkifRing->Channel);
+    BlkifRing->Channel = NULL;
+fail3:
+    Error("fail3\n");
+fail2:
+    Error("fail2\n");
+    for (Index = 0; Index < (1ul << Ring->Order); ++Index) {
+        if (BlkifRing->Grants[Index] == NULL)
+            continue;
+
+        GranterPut(Granter, BlkifRing->Grants[Index]);
+        BlkifRing->Grants[Index] = NULL;
+    }
+
+    RtlZeroMemory(&BlkifRing->Front, sizeof(blkif_front_ring_t));
+
+    __FreePages(BlkifRing->Mdl);
+    BlkifRing->Shared = NULL;
+    BlkifRing->Mdl = NULL;
 fail1:
     Error("fail1 %08x\n", status);
     return status;
 }
 
+static NTSTATUS
+BlkifRingStoreWrite(
+    IN  PXENVBD_BLKIF_RING  BlkifRing,
+    IN  PVOID               Transaction
+    )
+{
+    PXENVBD_RING            Ring = BlkifRing->Ring;
+    PXENVBD_FRONTEND        Frontend = Ring->Frontend;
+    PXENVBD_GRANTER         Granter = FrontendGetGranter(Frontend);
+    PCHAR                   Path;
+    NTSTATUS                status;
+
+    Path = (FrontendGetNumQueues(Frontend) == 1) ?
+        FrontendGetFrontendPath(Frontend) :
+        BlkifRing->Path;
+
+    status = XENBUS_STORE(Printf,
+                          &Ring->StoreInterface,
+                          Transaction,
+                          Path,
+                          "event-channel",
+                          "%u",
+                          XENBUS_EVTCHN(GetPort,
+                                        &Ring->EvtchnInterface,
+                                        BlkifRing->Channel));
+    if (!NT_SUCCESS(status))
+        goto fail1;
+
+    if (Ring->Order == 0) {
+        status = XENBUS_STORE(Printf,
+                              &Ring->StoreInterface,
+                              Transaction,
+                              Path,
+                              "ring-ref",
+                              "%u",
+                              GranterReference(Granter, BlkifRing->Grants[0]));
+        if (!NT_SUCCESS(status))
+            goto fail2;
+    } else {
+        ULONG           Index;
+
+        for (Index = 0; Index < (1ul << Ring->Order); ++Index) {
+            CHAR        Name[MAX_NAME_LEN + 1];
+
+            status = RtlStringCchPrintfA(Name,
+                                         MAX_NAME_LEN,
+                                         "ring-ref%u",
+                                         Index);
+            if (!NT_SUCCESS(status))
+                goto fail3;
+
+            status = XENBUS_STORE(Printf,
+                                  &Ring->StoreInterface,
+                                  Transaction,
+                                  Path,
+                                  Name,
+                                  "%u",
+                                  GranterReference(Granter, 
BlkifRing->Grants[Index]));
+            if (!NT_SUCCESS(status))
+                goto fail4;
+        }
+    }
+
+    return STATUS_SUCCESS;
+
+fail4:
+fail3:
+fail2:
+fail1:
+    return status;
+}
+
+static VOID
+BlkifRingEnable(
+    IN  PXENVBD_BLKIF_RING  BlkifRing
+    )
+{
+    Trace("====> %u\n", BlkifRing->Index);
+
+    __BlkifRingAcquireLock(BlkifRing);
+    ASSERT(!BlkifRing->Enabled);
+    BlkifRing->Enabled = TRUE;
+    __BlkifRingReleaseLock(BlkifRing);
+
+    Trace("<==== %u\n", BlkifRing->Index);
+}
+
+static VOID
+BlkifRingDisable(
+    IN  PXENVBD_BLKIF_RING  BlkifRing
+    )
+{
+    PXENVBD_RING            Ring = BlkifRing->Ring;
+    ULONG                   Attempt;
+
+    Trace("====> %u\n", BlkifRing->Index);
+
+    __BlkifRingAcquireLock(BlkifRing);
+    ASSERT(BlkifRing->Enabled);
+
+    // Discard any pending requests
+    while (!IsListEmpty(&BlkifRing->State.List)) {
+        PLIST_ENTRY         ListEntry;
+        PXENVBD_REQUEST     Request;
+        PXENVBD_SRBEXT      SrbExt;
+        PSCSI_REQUEST_BLOCK Srb;
+
+        ListEntry = RemoveHeadList(&BlkifRing->State.List);
+        ASSERT3P(ListEntry, != , &BlkifRing->State.List);
+
+        Request = CONTAINING_RECORD(ListEntry,
+                                    XENVBD_REQUEST,
+                                    ListEntry);
+        SrbExt = Request->SrbExt;
+        Srb = SrbExt->Srb;
+        Srb->SrbStatus = SRB_STATUS_ABORTED;
+        Srb->ScsiStatus = 0x40; // SCSI_ABORTED
+
+        BlkifRingPutRequest(BlkifRing, Request);
+
+        if (InterlockedDecrement(&SrbExt->RequestCount) == 0)
+            __BlkifRingCompleteSrb(BlkifRing, SrbExt);
+    }
+
+    ASSERT3U(BlkifRing->State.Count, == , 0);
+
+    Attempt = 0;
+    ASSERT3U(BlkifRing->RequestsPushed, == , BlkifRing->RequestsPosted);
+    while (BlkifRing->ResponsesProcessed != BlkifRing->RequestsPushed) {
+        Attempt++;
+        ASSERT(Attempt < 100);
+
+        // Try to move things along
+        __BlkifRingSend(BlkifRing);
+        (VOID)BlkifRingPoll(BlkifRing);
+
+        // We are waiting for a watch event at DISPATCH_LEVEL so
+        // it is our responsibility to poll the store ring.
+        XENBUS_STORE(Poll,
+                     &Ring->StoreInterface);
+
+        KeStallExecutionProcessor(1000);    // 1ms
+    }
+
+    BlkifRing->Enabled = FALSE;
+    __BlkifRingReleaseLock(BlkifRing);
+
+    Trace("<==== %u\n", BlkifRing->Index);
+}
+
+static VOID
+BlkifRingDisconnect(
+    IN  PXENVBD_BLKIF_RING  BlkifRing
+    )
+{
+    PXENVBD_RING            Ring = BlkifRing->Ring;
+    PXENVBD_GRANTER         Granter = FrontendGetGranter(Ring->Frontend);
+    ULONG                   Index;
+
+    Trace("====> %u\n", BlkifRing->Index);
+    ASSERT(BlkifRing->Connected);
+
+    XENBUS_DEBUG(Deregister,
+                 &Ring->DebugInterface,
+                 BlkifRing->DebugCallback);
+    BlkifRing->DebugCallback = NULL;
+
+    XENBUS_EVTCHN(Close,
+                  &Ring->EvtchnInterface,
+                  BlkifRing->Channel);
+    BlkifRing->Channel = NULL;
+
+    for (Index = 0; Index < (1ul << Ring->Order); ++Index) {
+        if (BlkifRing->Grants[Index] == NULL)
+            continue;
+
+        GranterPut(Granter, BlkifRing->Grants[Index]);
+        BlkifRing->Grants[Index] = NULL;
+    }
+
+    RtlZeroMemory(&BlkifRing->Front, sizeof(blkif_front_ring_t));
+
+    __FreePages(BlkifRing->Mdl);
+    BlkifRing->Shared = NULL;
+    BlkifRing->Mdl = NULL;
+
+    BlkifRing->Events = 0;
+    BlkifRing->Dpcs = 0;
+    BlkifRing->RequestsPosted = 0;
+    BlkifRing->RequestsPushed = 0;
+    BlkifRing->ResponsesProcessed = 0;
+
+    BlkifRing->Connected = FALSE;
+
+    Trace("<==== %u\n", BlkifRing->Index);
+}
+
+static VOID
+__BlkifRingQueueSrb(
+    IN  PXENVBD_BLKIF_RING  BlkifRing,
+    IN  PXENVBD_SRBEXT      SrbExt
+    )
+{
+    PLIST_ENTRY             ListEntry;
+    ULONG_PTR               Old;
+    ULONG_PTR               LockBit;
+    ULONG_PTR               New;
+
+    ListEntry = &SrbExt->ListEntry;
+
+    do {
+        Old = (ULONG_PTR)BlkifRing->Lock;
+        LockBit = Old & XENVBD_LOCK_BIT;
+
+        ListEntry->Blink = (PVOID)(Old & ~XENVBD_LOCK_BIT);
+        New = (ULONG_PTR)ListEntry;
+        ASSERT((New & XENVBD_LOCK_BIT) == 0);
+        New |= LockBit;
+    } while ((ULONG_PTR)InterlockedCompareExchangePointer(&BlkifRing->Lock, 
(PVOID)New, (PVOID)Old) != Old);
+
+    // __BlkifRingReleaseLock() drains the atomic SRB list into the queue 
therefore,
+    // after adding to the list we need to attempt to grab and release the 
lock. If we can't
+    // grab it then that's ok because whichever thread is holding it will have 
to call
+    // __BlkifRingReleaseLock() and will therefore drain the atomic packet 
list.
+
+    if (__BlkifRingTryAcquireLock(BlkifRing))
+        __BlkifRingReleaseLock(BlkifRing);
+}
+
+static VOID
+__BlkifRingQueueShutdown(
+    IN  PXENVBD_BLKIF_RING  BlkifRing,
+    IN  PXENVBD_SRBEXT      SrbExt
+    )
+{
+    __BlkifRingAcquireLock(BlkifRing);
+    InsertTailList(&BlkifRing->ShutdownQueue, &SrbExt->ListEntry);
+    __BlkifRingReleaseLock(BlkifRing);
+}
+
 static DECLSPEC_NOINLINE VOID
-RingIndirectDtor(
+RingDebugCallback(
     IN  PVOID       Argument,
-    IN  PVOID       Object
+    IN  BOOLEAN     Crashing
     )
 {
-    PXENVBD_INDIRECT    Indirect = Object;
+    PXENVBD_RING    Ring = Argument;
+    XENVBD_STAT     Index;
 
-    UNREFERENCED_PARAMETER(Argument);
+    UNREFERENCED_PARAMETER(Crashing);
 
-    __FreePages(Indirect->Mdl);
-    Indirect->Page = NULL;
-    Indirect->Mdl = NULL;
+    XENBUS_DEBUG(Printf,
+                 &Ring->DebugInterface,
+                 "Order: %d\n",
+                 Ring->Order);
+
+    for (Index = 0; Index < XENVBD_STAT__MAX; ++Index) {
+        XENBUS_DEBUG(Printf,
+                     &Ring->DebugInterface,
+                     "%s: %u\n",
+                     __StatName(Index),
+                     Ring->Stats[Index]);
+    }
 }
 
 NTSTATUS
@@ -1493,7 +2248,8 @@ RingCreate(
 {
     PXENVBD_TARGET          Target = FrontendGetTarget(Frontend);
     PXENVBD_ADAPTER         Adapter = TargetGetAdapter(Target);
-    CHAR                    Name[MAX_NAME_LEN];
+    ULONG                   MaxQueues;
+    ULONG                   Index;
     NTSTATUS                status;
 
     *Ring = __RingAllocate(sizeof(XENVBD_RING));
@@ -1502,127 +2258,74 @@ RingCreate(
     if (*Ring == NULL)
         goto fail1;
 
-    (*Ring)->Frontend = Frontend;
-    KeInitializeSpinLock(&(*Ring)->Lock);
-    KeInitializeThreadedDpc(&(*Ring)->Dpc, RingDpc, *Ring);
-    KeSetImportanceDpc(&(*Ring)->Dpc, MediumHighImportance);
-
-    QueueInit(&(*Ring)->PreparedReqs);
-    QueueInit(&(*Ring)->SubmittedReqs);
-    QueueInit(&(*Ring)->ShutdownSrbs);
-
-    AdapterGetCacheInterface(Adapter, &(*Ring)->CacheInterface);
-
-    status = XENBUS_CACHE(Acquire, &(*Ring)->CacheInterface);
-    if (!NT_SUCCESS(status))
-        goto fail2;
+    AdapterGetDebugInterface(Adapter,
+                             &(*Ring)->DebugInterface);
+    AdapterGetStoreInterface(Adapter,
+                             &(*Ring)->StoreInterface);
+    AdapterGetCacheInterface(Adapter,
+                             &(*Ring)->CacheInterface);
+    AdapterGetEvtchnInterface(Adapter,
+                              &(*Ring)->EvtchnInterface);
 
-    status = RtlStringCbPrintfA(Name,
-                                sizeof(Name),
-                                "vbd_%u_req",
-                                FrontendGetTargetId(Frontend));
-    if (!NT_SUCCESS(status))
-        goto fail3;
+    (*Ring)->Frontend = Frontend;
 
-    status = XENBUS_CACHE(Create,
-                          &(*Ring)->CacheInterface,
-                          Name,
-                          sizeof(XENVBD_REQUEST),
-                          32,
-                          RingRequestCtor,
-                          RingRequestDtor,
-                          RingAcquireLock,
-                          RingReleaseLock,
-                          *Ring,
-                          &(*Ring)->RequestCache);
-    if (!NT_SUCCESS(status))
-        goto fail4;
+    MaxQueues = FrontendGetMaxQueues(Frontend);
+    (*Ring)->Ring = __RingAllocate(sizeof(PXENVBD_BLKIF_RING) *
+                                   MaxQueues);
 
-    status = RtlStringCbPrintfA(Name,
-                                sizeof(Name),
-                                "vbd_%u_seg",
-                                FrontendGetTargetId(Frontend));
-    if (!NT_SUCCESS(status))
-        goto fail5;
+    status = STATUS_NO_MEMORY;
+    if ((*Ring)->Ring == NULL)
+        goto fail2;
 
-    status = XENBUS_CACHE(Create,
-                          &(*Ring)->CacheInterface,
-                          Name,
-                          sizeof(XENVBD_SEGMENT),
-                          32,
-                          RingSegmentCtor,
-                          RingSegmentDtor,
-                          RingAcquireLock,
-                          RingReleaseLock,
-                          *Ring,
-                          &(*Ring)->SegmentCache);
-    if (!NT_SUCCESS(status))
-        goto fail6;
+    Index = 0;
+    while (Index < MaxQueues) {
+        PXENVBD_BLKIF_RING  BlkifRing;
 
-    status = RtlStringCbPrintfA(Name,
-                                sizeof(Name),
-                                "vbd_%u_ind",
-                                FrontendGetTargetId(Frontend));
-    if (!NT_SUCCESS(status))
-        goto fail7;
+        status = BlkifRingCreate(*Ring, Index, &BlkifRing);
+        if (!NT_SUCCESS(status))
+            goto fail3;
 
-    status = XENBUS_CACHE(Create,
-                          &(*Ring)->CacheInterface,
-                          Name,
-                          sizeof(XENVBD_INDIRECT),
-                          1,
-                          RingIndirectCtor,
-                          RingIndirectDtor,
-                          RingAcquireLock,
-                          RingReleaseLock,
-                          *Ring,
-                          &(*Ring)->IndirectCache);
-    if (!NT_SUCCESS(status))
-        goto fail8;
+        (*Ring)->Ring[Index] = BlkifRing;
+        Index++;
+    }
 
     return STATUS_SUCCESS;
 
-fail8:
-    Error("fail8\n");
-fail7:
-    Error("fail7\n");
-    XENBUS_CACHE(Destroy,
-                 &(*Ring)->CacheInterface,
-                 (*Ring)->SegmentCache);
-    (*Ring)->SegmentCache = NULL;
-fail6:
-    Error("fail6\n");
-fail5:
-    Error("fail5\n");
-    XENBUS_CACHE(Destroy,
-                 &(*Ring)->CacheInterface,
-                 (*Ring)->RequestCache);
-    (*Ring)->RequestCache = NULL;
-fail4:
-    Error("fail4\n");
 fail3:
     Error("fail3\n");
-    XENBUS_CACHE(Release,
-                 &(*Ring)->CacheInterface);
+
+    while (--Index > 0) {
+        PXENVBD_BLKIF_RING  BlkifRing = (*Ring)->Ring[Index];
+
+        (*Ring)->Ring[Index] = NULL;
+        BlkifRingDestroy(BlkifRing);
+    }
+
+    __RingFree((*Ring)->Ring);
+    (*Ring)->Ring = NULL;
+
 fail2:
     Error("fail2\n");
 
+    (*Ring)->Frontend = NULL;
+
     RtlZeroMemory(&(*Ring)->CacheInterface,
-                  sizeof (XENBUS_CACHE_INTERFACE));
+                  sizeof(XENBUS_CACHE_INTERFACE));
+
+    RtlZeroMemory(&(*Ring)->EvtchnInterface,
+                  sizeof(XENBUS_EVTCHN_INTERFACE));
 
-    RtlZeroMemory(&(*Ring)->PreparedReqs, sizeof(XENVBD_QUEUE));
-    RtlZeroMemory(&(*Ring)->SubmittedReqs, sizeof(XENVBD_QUEUE));
-    RtlZeroMemory(&(*Ring)->ShutdownSrbs, sizeof(XENVBD_QUEUE));
+    RtlZeroMemory(&(*Ring)->StoreInterface,
+                  sizeof(XENBUS_STORE_INTERFACE));
 
-    RtlZeroMemory(&(*Ring)->Dpc, sizeof(KDPC));
-    RtlZeroMemory(&(*Ring)->Lock, sizeof(KSPIN_LOCK));
-    (*Ring)->Frontend = NULL;
+    RtlZeroMemory(&(*Ring)->DebugInterface,
+                  sizeof(XENBUS_DEBUG_INTERFACE));
 
     ASSERT(IsZeroMemory(*Ring, sizeof(XENVBD_RING)));
     __RingFree(*Ring);
-    *Ring = NULL;
+
 fail1:
-    Error("fail1 %08x\n", status);
+    Error("fail1 (%08x)\n", status);
     return status;
 }
 
@@ -1631,44 +2334,35 @@ RingDestroy(
     IN  PXENVBD_RING    Ring
     )
 {
-    XENBUS_CACHE(Destroy,
-                 &Ring->CacheInterface,
-                 Ring->IndirectCache);
-    Ring->IndirectCache = NULL;
+    ULONG               Index;
 
-    XENBUS_CACHE(Destroy,
-                 &Ring->CacheInterface,
-                 Ring->SegmentCache);
-    Ring->SegmentCache = NULL;
+    Index = FrontendGetMaxQueues(Ring->Frontend);
 
-    XENBUS_CACHE(Destroy,
-                 &Ring->CacheInterface,
-                 Ring->RequestCache);
-    Ring->RequestCache = NULL;
+    while (--Index > 0) {
+        PXENVBD_BLKIF_RING  BlkifRing = Ring->Ring[Index];
+
+        Ring->Ring[Index] = NULL;
+        BlkifRingDestroy(BlkifRing);
+    }
+
+    __RingFree(Ring->Ring);
+    Ring->Ring = NULL;
 
-    XENBUS_CACHE(Release,
-                 &Ring->CacheInterface);
+    Ring->Frontend = NULL;
 
     RtlZeroMemory(&Ring->CacheInterface,
-                  sizeof (XENBUS_CACHE_INTERFACE));
+                  sizeof(XENBUS_CACHE_INTERFACE));
 
-    RtlZeroMemory(&Ring->PreparedReqs, sizeof(XENVBD_QUEUE));
-    RtlZeroMemory(&Ring->SubmittedReqs, sizeof(XENVBD_QUEUE));
-    RtlZeroMemory(&Ring->ShutdownSrbs, sizeof(XENVBD_QUEUE));
+    RtlZeroMemory(&Ring->EvtchnInterface,
+                  sizeof(XENBUS_EVTCHN_INTERFACE));
 
-    RtlZeroMemory(&Ring->Dpc, sizeof(KDPC));
-    RtlZeroMemory(&Ring->Lock, sizeof(KSPIN_LOCK));
-    Ring->Frontend = NULL;
+    RtlZeroMemory(&Ring->StoreInterface,
+                  sizeof(XENBUS_STORE_INTERFACE));
+
+    RtlZeroMemory(&Ring->DebugInterface,
+                  sizeof(XENBUS_DEBUG_INTERFACE));
 
-    Ring->BlkOpRead = 0;
-    Ring->BlkOpWrite = 0;
-    Ring->BlkOpIndirectRead = 0;
-    Ring->BlkOpIndirectWrite = 0;
-    Ring->BlkOpBarrier = 0;
-    Ring->BlkOpDiscard = 0;
-    Ring->BlkOpFlush = 0;
-    Ring->SegsGranted = 0;
-    Ring->SegsBounced = 0;
+    RtlZeroMemory(Ring->Stats, sizeof(Ring->Stats));
 
     ASSERT(IsZeroMemory(Ring, sizeof(XENVBD_RING)));
     __RingFree(Ring);
@@ -1679,31 +2373,27 @@ RingConnect(
     IN  PXENVBD_RING    Ring
     )
 {
-    PXENVBD_TARGET      Target = FrontendGetTarget(Ring->Frontend);
-    PXENVBD_ADAPTER     Adapter = TargetGetAdapter(Target);
-    PXENVBD_GRANTER     Granter = FrontendGetGranter(Ring->Frontend);
-    PCHAR               Buffer;
+    ULONG               MaxQueues;
     ULONG               Index;
+    PCHAR               Buffer;
     NTSTATUS            status;
 
-    ASSERT(Ring->Connected == FALSE);
-
-    AdapterGetStoreInterface(Adapter, &Ring->StoreInterface);
-    AdapterGetEvtchnInterface(Adapter, &Ring->EvtchnInterface);
-    AdapterGetDebugInterface(Adapter, &Ring->DebugInterface);
-
-    status = XENBUS_STORE(Acquire, &Ring->StoreInterface);
+    status = XENBUS_DEBUG(Acquire, &Ring->DebugInterface);
     if (!NT_SUCCESS(status))
         goto fail1;
 
-    status = XENBUS_EVTCHN(Acquire, &Ring->EvtchnInterface);
+    status = XENBUS_STORE(Acquire, &Ring->StoreInterface);
     if (!NT_SUCCESS(status))
         goto fail2;
 
-    status = XENBUS_DEBUG(Acquire, &Ring->DebugInterface);
+    status = XENBUS_CACHE(Acquire, &Ring->CacheInterface);
     if (!NT_SUCCESS(status))
         goto fail3;
 
+    status = XENBUS_EVTCHN(Acquire, &Ring->EvtchnInterface);
+    if (!NT_SUCCESS(status))
+        goto fail4;
+
     status = XENBUS_STORE(Read,
                           &Ring->StoreInterface,
                           NULL,
@@ -1730,47 +2420,17 @@ RingConnect(
         Ring->Order = 0;
     }
 
-    Ring->Mdl = __AllocatePages(1 << Ring->Order);
-
-    status = STATUS_NO_MEMORY;
-    if (Ring->Mdl == NULL)
-        goto fail4;
-
-    Ring->Shared = MmGetSystemAddressForMdlSafe(Ring->Mdl,
-                                                NormalPagePriority);
-    ASSERT(Ring->Shared != NULL);
-
-#pragma warning(push)
-#pragma warning(disable: 4305)
-#pragma warning(disable: 4311) // 'type cast' pointer truncation from 
'blkif_sring_entry[1]' to 'long'
-    SHARED_RING_INIT(Ring->Shared);
-    FRONT_RING_INIT(&Ring->Front, Ring->Shared, PAGE_SIZE << Ring->Order);
-#pragma warning(pop)
+    MaxQueues = FrontendGetNumQueues(Ring->Frontend);
+    Index = 0;
+    while (Index < MaxQueues) {
+        PXENVBD_BLKIF_RING  BlkifRing = Ring->Ring[Index];
 
-    for (Index = 0; Index < (1ul << Ring->Order); ++Index) {
-        status = GranterGet(Granter,
-                            MmGetMdlPfnArray(Ring->Mdl)[Index],
-                            FALSE,
-                            &Ring->Grants[Index]);
+        status = BlkifRingConnect(BlkifRing);
         if (!NT_SUCCESS(status))
             goto fail5;
-    }
-
-    Ring->Channel = XENBUS_EVTCHN(Open,
-                                  &Ring->EvtchnInterface,
-                                  XENBUS_EVTCHN_TYPE_UNBOUND,
-                                  RingInterrupt,
-                                  Ring,
-                                  FrontendGetBackendDomain(Ring->Frontend),
-                                  TRUE);
-    status = STATUS_NO_MEMORY;
-    if (Ring->Channel == NULL)
-        goto fail6;
 
-    XENBUS_EVTCHN(Unmask,
-                  &Ring->EvtchnInterface,
-                  Ring->Channel,
-                  FALSE);
+        ++Index;
+    }
 
     status = XENBUS_DEBUG(Register,
                           &Ring->DebugInterface,
@@ -1779,55 +2439,44 @@ RingConnect(
                           Ring,
                           &Ring->DebugCallback);
     if (!NT_SUCCESS(status))
-        goto fail7;
+        goto fail6;
 
-    Ring->Connected = TRUE;
     return STATUS_SUCCESS;
 
-fail7:
-    Error("fail7\n");
-    XENBUS_EVTCHN(Close,
-                  &Ring->EvtchnInterface,
-                  Ring->Channel);
-    Ring->Channel = NULL;
 fail6:
     Error("fail6\n");
+    Index = FrontendGetNumQueues(Ring->Frontend);
 fail5:
     Error("fail5\n");
-    for (Index = 0; Index < (1ul << Ring->Order); ++Index) {
-        if (Ring->Grants[Index] == NULL)
-            continue;
 
-        GranterPut(Granter, Ring->Grants[Index]);
-        Ring->Grants[Index] = NULL;
-    }
+    while (Index != 0) {
+        PXENVBD_BLKIF_RING  BlkifRing;
+
+        --Index;
+        BlkifRing = Ring->Ring[Index];
 
-    RtlZeroMemory(&Ring->Front, sizeof(blkif_front_ring_t));
+        BlkifRingDisconnect(BlkifRing);
+    }
 
-    __FreePages(Ring->Mdl);
-    Ring->Shared = NULL;
-    Ring->Mdl = NULL;
+    XENBUS_EVTCHN(Release, &Ring->EvtchnInterface);
 
-    Ring->Order = 0;
 fail4:
     Error("fail4\n");
-    XENBUS_DEBUG(Release, &Ring->DebugInterface);
+
+    XENBUS_CACHE(Release, &Ring->CacheInterface);
+
 fail3:
     Error("fail3\n");
-    XENBUS_EVTCHN(Release, &Ring->EvtchnInterface);
+
+    XENBUS_STORE(Release, &Ring->StoreInterface);
+
 fail2:
     Error("fail2\n");
-    XENBUS_STORE(Release, &Ring->StoreInterface);
-fail1:
-    Error("fail1 %08x\n", status);
 
-    RtlZeroMemory(&Ring->DebugInterface,
-                  sizeof(XENBUS_DEBUG_INTERFACE));
-    RtlZeroMemory(&Ring->EvtchnInterface,
-                  sizeof(XENBUS_EVTCHN_INTERFACE));
-    RtlZeroMemory(&Ring->StoreInterface,
-                  sizeof(XENBUS_STORE_INTERFACE));
+    XENBUS_DEBUG(Release, &Ring->DebugInterface);
 
+fail1:
+    Error("fail1 (%08x)\n", status);
     return status;
 }
 
@@ -1837,23 +2486,33 @@ RingStoreWrite(
     IN  PVOID           Transaction
     )
 {
-    PXENVBD_GRANTER     Granter = FrontendGetGranter(Ring->Frontend);
-    ULONG               Port;
+    ULONG               NumQueues;
+    ULONG               Index;
     NTSTATUS            status;
 
-    if (Ring->Order == 0) {
-        status = XENBUS_STORE(Printf,
-                              &Ring->StoreInterface,
-                              Transaction,
-                              FrontendGetFrontendPath(Ring->Frontend),
-                              "ring-ref",
-                              "%u",
-                              GranterReference(Granter, Ring->Grants[0]));
+    NumQueues = FrontendGetNumQueues(Ring->Frontend);
+    Index = 0;
+    while (Index < NumQueues) {
+        PXENVBD_BLKIF_RING  BlkifRing = Ring->Ring[Index];
+
+        status = BlkifRingStoreWrite(BlkifRing, Transaction);
         if (!NT_SUCCESS(status))
-            return status;
-    } else {
-        ULONG           Index;
+            goto fail1;
+
+        ++Index;
+    }
+
+    status = XENBUS_STORE(Printf,
+                          &Ring->StoreInterface,
+                          Transaction,
+                          FrontendGetFrontendPath(Ring->Frontend),
+                          "multi-queue-num-queues",
+                          "%u",
+                          NumQueues);
+    if (!NT_SUCCESS(status))
+        goto fail2;
 
+    if (Ring->Order != 0) {
         status = XENBUS_STORE(Printf,
                               &Ring->StoreInterface,
                               Transaction,
@@ -1862,28 +2521,7 @@ RingStoreWrite(
                               "%u",
                               Ring->Order);
         if (!NT_SUCCESS(status))
-            return status;
-
-        for (Index = 0; Index < (1ul << Ring->Order); ++Index) {
-            CHAR        Name[MAX_NAME_LEN+1];
-
-            status = RtlStringCchPrintfA(Name,
-                                         MAX_NAME_LEN,
-                                         "ring-ref%u",
-                                         Index);
-            if (!NT_SUCCESS(status))
-                return status;
-
-            status = XENBUS_STORE(Printf,
-                                  &Ring->StoreInterface,
-                                  Transaction,
-                                  FrontendGetFrontendPath(Ring->Frontend),
-                                  Name,
-                                  "%u",
-                                  GranterReference(Granter, 
Ring->Grants[Index]));
-            if (!NT_SUCCESS(status))
-                return status;
-        }
+            goto fail3;
     }
 
     status = XENBUS_STORE(Printf,
@@ -1893,23 +2531,15 @@ RingStoreWrite(
                           "protocol",
                           XEN_IO_PROTO_ABI);
     if (!NT_SUCCESS(status))
-        return status;
-
-    Port = XENBUS_EVTCHN(GetPort,
-                         &Ring->EvtchnInterface,
-                         Ring->Channel);
-
-    status = XENBUS_STORE(Printf,
-                          &Ring->StoreInterface,
-                          Transaction,
-                          FrontendGetFrontendPath(Ring->Frontend),
-                          "event-channel",
-                          "%u",
-                          Port);
-    if (!NT_SUCCESS(status))
-        return status;
+        goto fail4;
 
     return STATUS_SUCCESS;
+
+fail4:
+fail3:
+fail2:
+fail1:
+    return status;
 }
 
 VOID
@@ -1917,12 +2547,18 @@ RingEnable(
     IN  PXENVBD_RING    Ring
     )
 {
-    ASSERT(Ring->Enabled == FALSE);
-    Ring->Enabled = TRUE;
+    ULONG               NumQueues;
+    ULONG               Index;
 
-    XENBUS_EVTCHN(Trigger,
-                  &Ring->EvtchnInterface,
-                  Ring->Channel);
+    NumQueues = FrontendGetNumQueues(Ring->Frontend);
+    Index = 0;
+    while (Index < NumQueues) {
+        PXENVBD_BLKIF_RING  BlkifRing = Ring->Ring[Index];
+
+        BlkifRingEnable(BlkifRing);
+
+        ++Index;
+    }
 }
 
 VOID
@@ -1930,55 +2566,15 @@ RingDisable(
     IN  PXENVBD_RING    Ring
     )
 {
-    ULONG               Count;
-    KIRQL               Irql;
-    PXENVBD_TARGET      Target = FrontendGetTarget(Ring->Frontend);
-    PXENVBD_ADAPTER     Adapter = TargetGetAdapter(Target);
-
-    ASSERT(Ring->Enabled == TRUE);
-    Ring->Enabled = FALSE;
-
-    // poll ring and send event channel notification every 1ms (for up to 3 
minutes)
-    Count = 0;
-    while (QueueCount(&Ring->SubmittedReqs)) {
-        if (Count > 180000)
-            break;
-        KeRaiseIrql(DISPATCH_LEVEL, &Irql);
-        RingPoll(Ring);
-        KeLowerIrql(Irql);
-        XENBUS_EVTCHN(Send,
-                      &Ring->EvtchnInterface,
-                      Ring->Channel);
-        StorPortStallExecution(1000);   // 1000 micro-seconds
-        ++Count;
-    }
-
-    Verbose("Target[%d] : %u Submitted requests left (%u iterrations)\n",
-            FrontendGetTargetId(Ring->Frontend),
-            QueueCount(&Ring->SubmittedReqs),
-            Count);
-
-    // Fail PreparedReqs
-    for (;;) {
-        PXENVBD_SRBEXT      SrbExt;
-        PSCSI_REQUEST_BLOCK Srb;
-        PXENVBD_REQUEST     Request;
-        PLIST_ENTRY         ListEntry;
-
-        ListEntry = QueuePop(&Ring->PreparedReqs);
-        if (ListEntry == NULL)
-            break;
-        Request = CONTAINING_RECORD(ListEntry, XENVBD_REQUEST, ListEntry);
-        SrbExt = Request->SrbExt;
-        Srb = SrbExt->Srb;
-
-        Srb->SrbStatus = SRB_STATUS_ABORTED;
-        Srb->ScsiStatus = 0x40; // SCSI_ABORTED
+    ULONG               Index;
 
-        RingPutRequest(Ring, Request);
+    Index = FrontendGetNumQueues(Ring->Frontend);
+    while (Index != 0) {
+        PXENVBD_BLKIF_RING  BlkifRing;
 
-        if (InterlockedDecrement(&SrbExt->RequestCount) == 0)
-            AdapterCompleteSrb(Adapter, SrbExt);
+        --Index;
+        BlkifRing = Ring->Ring[Index];
+        BlkifRingDisable(BlkifRing);
     }
 }
 
@@ -1987,54 +2583,49 @@ RingDisconnect(
     IN  PXENVBD_RING    Ring
     )
 {
-    PXENVBD_GRANTER     Granter = FrontendGetGranter(Ring->Frontend);
     ULONG               Index;
 
-    ASSERT3U(Ring->Submitted, ==, Ring->Received);
-    ASSERT(Ring->Connected);
-    Ring->Connected = FALSE;
-
     XENBUS_DEBUG(Deregister,
                  &Ring->DebugInterface,
                  Ring->DebugCallback);
     Ring->DebugCallback = NULL;
 
-    XENBUS_EVTCHN(Close,
-                  &Ring->EvtchnInterface,
-                  Ring->Channel);
-    Ring->Channel = NULL;
-
-    for (Index = 0; Index < (1ul << Ring->Order); ++Index) {
-        if (Ring->Grants[Index] == NULL)
-            continue;
+    Index = FrontendGetNumQueues(Ring->Frontend);
 
-        GranterPut(Granter, Ring->Grants[Index]);
-        Ring->Grants[Index] = NULL;
-    }
+    while (Index != 0) {
+        PXENVBD_BLKIF_RING  BlkifRing;
 
-    RtlZeroMemory(&Ring->Front, sizeof(blkif_front_ring_t));
+        --Index;
+        BlkifRing = Ring->Ring[Index];
 
-    __FreePages(Ring->Mdl);
-    Ring->Shared = NULL;
-    Ring->Mdl = NULL;
+        BlkifRingDisconnect(BlkifRing);
+    }
 
     Ring->Order = 0;
 
-    XENBUS_DEBUG(Release, &Ring->DebugInterface);
     XENBUS_EVTCHN(Release, &Ring->EvtchnInterface);
+    XENBUS_CACHE(Release, &Ring->CacheInterface);
     XENBUS_STORE(Release, &Ring->StoreInterface);
+    XENBUS_DEBUG(Release, &Ring->DebugInterface);
+}
 
-    RtlZeroMemory(&Ring->DebugInterface,
-                  sizeof(XENBUS_DEBUG_INTERFACE));
-    RtlZeroMemory(&Ring->EvtchnInterface,
-                  sizeof(XENBUS_EVTCHN_INTERFACE));
-    RtlZeroMemory(&Ring->StoreInterface,
-                  sizeof(XENBUS_STORE_INTERFACE));
+static FORCEINLINE PXENVBD_BLKIF_RING
+__RingGetBlkifRing(
+    IN  PXENVBD_RING    Ring,
+    IN  ULONG           Tag
+    )
+{
+    ULONG               Value;
+    ULONG               Index;
+
+    if (Tag == 0)
+        Value = KeGetCurrentProcessorNumberEx(NULL);
+    else
+        Value = Tag;
+
+    Index = Value % FrontendGetNumQueues(Ring->Frontend);
 
-    Ring->Events = 0;
-    Ring->Dpcs = 0;
-    Ring->Submitted = 0;
-    Ring->Received = 0;
+    return Ring->Ring[Index];
 }
 
 BOOLEAN
@@ -2044,25 +2635,14 @@ RingQueueRequest(
     )
 {
     PSCSI_REQUEST_BLOCK Srb = SrbExt->Srb;
+    PXENVBD_BLKIF_RING  BlkifRing;
 
-    if (!Ring->Enabled)
-        goto fail1;
-
-    if (!RingPrepareRequest(Ring, SrbExt))
-        goto fail2;
+    BlkifRing = __RingGetBlkifRing(Ring, Srb->QueueTag);
+    ASSERT(BlkifRing != NULL);
 
-    if (RingSubmitRequests(Ring)) {
-        // more prepared-reqs to submit
-        if (KeInsertQueueDpc(&Ring->Dpc, NULL, NULL))
-            ++Ring->Dpcs;
-    }
+    __BlkifRingQueueSrb(BlkifRing, SrbExt);
 
     return TRUE;
-
-fail2:
-fail1:
-    Srb->SrbStatus = SRB_STATUS_BUSY;
-    return FALSE;
 }
 
 VOID
@@ -2071,12 +2651,11 @@ RingQueueShutdown(
     IN  PXENVBD_SRBEXT  SrbExt
     )
 {
-    QueueAppend(&Ring->ShutdownSrbs,
-                &SrbExt->ListEntry);
+    PSCSI_REQUEST_BLOCK Srb = SrbExt->Srb;
+    PXENVBD_BLKIF_RING  BlkifRing;
 
-    if (!Ring->Enabled)
-        return;
+    BlkifRing = __RingGetBlkifRing(Ring, Srb->QueueTag);
+    ASSERT(BlkifRing != NULL);
 
-    if (KeInsertQueueDpc(&Ring->Dpc, NULL, NULL))
-           ++Ring->Dpcs;
+    __BlkifRingQueueShutdown(BlkifRing, SrbExt);
 }
-- 
2.16.2.windows.1


_______________________________________________
win-pv-devel mailing list
win-pv-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/win-pv-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.