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

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



> -----Original Message-----
> From: win-pv-devel [mailto:win-pv-devel-bounces@xxxxxxxxxxxxxxxxxxxx] On
> Behalf Of Owen Smith
> Sent: 29 May 2018 11:07
> To: win-pv-devel@xxxxxxxxxxxxxxxxxxxx
> Cc: Owen Smith <owen.smith@xxxxxxxxxx>
> Subject: [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>

Acked-by: Paul Durrant <paul.durrant@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
_______________________________________________
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®.