[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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |