[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [win-pv-devel] [PATCH 1/7] Merge Notifier and BlockRing into Ring
From: Owen Smith <owen.smith@xxxxxxxxxx> Remove the seperation between the event channel and shared ring. Fixes the debug callback and adds more error messages. Signed-off-by: Owen Smith <owen.smith@xxxxxxxxxx> --- src/xenvbd/blockring.c | 597 ---------------------------- src/xenvbd/blockring.h | 97 ----- src/xenvbd/frontend.c | 129 +++--- src/xenvbd/frontend.h | 36 +- src/xenvbd/notifier.c | 390 ------------------ src/xenvbd/notifier.h | 101 ----- src/xenvbd/ring.c | 911 +++++++++++++++++++++++++++++++++++++++++++ src/xenvbd/ring.h | 103 +++++ src/xenvbd/target.c | 27 +- vs2015/xenvbd/xenvbd.vcxproj | 3 +- 10 files changed, 1110 insertions(+), 1284 deletions(-) delete mode 100644 src/xenvbd/blockring.c delete mode 100644 src/xenvbd/blockring.h delete mode 100644 src/xenvbd/notifier.c delete mode 100644 src/xenvbd/notifier.h create mode 100755 src/xenvbd/ring.c create mode 100755 src/xenvbd/ring.h diff --git a/src/xenvbd/blockring.c b/src/xenvbd/blockring.c deleted file mode 100644 index cf15a6f..0000000 --- a/src/xenvbd/blockring.c +++ /dev/null @@ -1,597 +0,0 @@ -/* Copyright (c) Citrix Systems Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, - * with or without modification, are permitted provided - * that the following conditions are met: - * - * * Redistributions of source code must retain the above - * copyright notice, this list of conditions and the - * following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the - * following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "blockring.h" -#include "frontend.h" -#include "target.h" -#include "adapter.h" -#include "util.h" -#include "debug.h" -#include "srbext.h" -#include "driver.h" -#include <stdlib.h> -#include <xenvbd-ntstrsafe.h> - -#define TAG_HEADER 'gaTX' -#define XENVBD_MAX_RING_PAGE_ORDER (4) -#define XENVBD_MAX_RING_PAGES (1 << XENVBD_MAX_RING_PAGE_ORDER) - -struct _XENVBD_BLOCKRING { - PXENVBD_FRONTEND Frontend; - BOOLEAN Connected; - BOOLEAN Enabled; - - XENBUS_STORE_INTERFACE StoreInterface; - - KSPIN_LOCK Lock; - PMDL Mdl; - blkif_sring_t* SharedRing; - blkif_front_ring_t FrontRing; - ULONG DeviceId; - ULONG Order; - PVOID Grants[XENVBD_MAX_RING_PAGES]; - ULONG Submitted; - ULONG Received; -}; - -#define MAX_NAME_LEN 64 -#define BLOCKRING_POOL_TAG 'gnRX' - -#define XEN_IO_PROTO_ABI "x86_64-abi" - -static FORCEINLINE PVOID -__BlockRingAllocate( - IN ULONG Length - ) -{ - return __AllocatePoolWithTag(NonPagedPool, Length, BLOCKRING_POOL_TAG); -} - -static FORCEINLINE VOID -__BlockRingFree( - IN PVOID Buffer - ) -{ - if (Buffer) - __FreePoolWithTag(Buffer, BLOCKRING_POOL_TAG); -} - -static FORCEINLINE VOID -xen_mb() -{ - KeMemoryBarrier(); - _ReadWriteBarrier(); -} - -static FORCEINLINE VOID -xen_wmb() -{ - KeMemoryBarrier(); - _WriteBarrier(); -} - -static FORCEINLINE PFN_NUMBER -__Pfn( - __in PVOID VirtAddr - ) -{ - return (PFN_NUMBER)(ULONG_PTR)(MmGetPhysicalAddress(VirtAddr).QuadPart >> PAGE_SHIFT); -} - -static FORCEINLINE ULONG64 -__BlockRingGetTag( - IN PXENVBD_BLOCKRING BlockRing, - IN PXENVBD_REQUEST Request - ) -{ - UNREFERENCED_PARAMETER(BlockRing); - return ((ULONG64)TAG_HEADER << 32) | (ULONG64)Request->Id; -} - -static FORCEINLINE BOOLEAN -__BlockRingPutTag( - IN PXENVBD_BLOCKRING BlockRing, - IN ULONG64 Id, - OUT PULONG Tag - ) -{ - ULONG Header = (ULONG)((Id >> 32) & 0xFFFFFFFF); - - UNREFERENCED_PARAMETER(BlockRing); - - *Tag = (ULONG)(Id & 0xFFFFFFFF); - if (Header != TAG_HEADER) { - Error("PUT_TAG (%llx) TAG_HEADER (%08x%08x)\n", Id, Header, *Tag); - return FALSE; - } - - return TRUE; -} - -static FORCEINLINE VOID -__BlockRingInsert( - IN PXENVBD_BLOCKRING BlockRing, - IN PXENVBD_REQUEST Request, - IN blkif_request_t* req - ) -{ - PXENVBD_GRANTER Granter = FrontendGetGranter(BlockRing->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 = __BlockRingGetTag(BlockRing, Request); - req_indirect->sector_number = Request->FirstSector; - req_indirect->handle = (USHORT)BlockRing->DeviceId; - - 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, Entry); - - 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, Entry); - - 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)BlockRing->DeviceId; - req->id = __BlockRingGetTag(BlockRing, Request); - req->sector_number = Request->FirstSector; - - 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, Entry); - req->seg[Index].gref = GranterReference(Granter, Segment->Grant); - req->seg[Index].first_sect = Segment->FirstSector; - req->seg[Index].last_sect = Segment->LastSector; - } - } - break; - - case BLKIF_OP_WRITE_BARRIER: - case BLKIF_OP_FLUSH_DISKCACHE: - req->operation = Request->Operation; - req->nr_segments = 0; - req->handle = (USHORT)BlockRing->DeviceId; - req->id = __BlockRingGetTag(BlockRing, Request); - req->sector_number = Request->FirstSector; - 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)BlockRing->DeviceId; - req_discard->id = __BlockRingGetTag(BlockRing, Request); - req_discard->sector_number = Request->FirstSector; - req_discard->nr_sectors = Request->NrSectors; - } break; - - default: - ASSERT(FALSE); - break; - } - ++BlockRing->Submitted; -} - -NTSTATUS -BlockRingCreate( - IN PXENVBD_FRONTEND Frontend, - IN ULONG DeviceId, - OUT PXENVBD_BLOCKRING* BlockRing - ) -{ - *BlockRing = __BlockRingAllocate(sizeof(XENVBD_BLOCKRING)); - if (*BlockRing == NULL) - goto fail1; - - (*BlockRing)->Frontend = Frontend; - (*BlockRing)->DeviceId = DeviceId; - KeInitializeSpinLock(&(*BlockRing)->Lock); - - return STATUS_SUCCESS; - -fail1: - return STATUS_NO_MEMORY; -} - -VOID -BlockRingDestroy( - IN PXENVBD_BLOCKRING BlockRing - ) -{ - BlockRing->Frontend = NULL; - BlockRing->DeviceId = 0; - RtlZeroMemory(&BlockRing->Lock, sizeof(KSPIN_LOCK)); - - ASSERT(IsZeroMemory(BlockRing, sizeof(XENVBD_BLOCKRING))); - - __BlockRingFree(BlockRing); -} - -NTSTATUS -BlockRingConnect( - IN PXENVBD_BLOCKRING BlockRing - ) -{ - NTSTATUS status; - PCHAR Value; - ULONG Index, RingPages; - PXENVBD_ADAPTER Adapter = TargetGetAdapter(FrontendGetTarget(BlockRing->Frontend)); - PXENVBD_GRANTER Granter = FrontendGetGranter(BlockRing->Frontend); - - ASSERT(BlockRing->Connected == FALSE); - - AdapterGetStoreInterface(Adapter, &BlockRing->StoreInterface); - - status = XENBUS_STORE(Acquire, &BlockRing->StoreInterface); - if (!NT_SUCCESS(status)) - goto fail1; - - status = FrontendStoreReadBackend(BlockRing->Frontend, "max-ring-page-order", &Value); - if (NT_SUCCESS(status)) { - BlockRing->Order = __min(strtoul(Value, NULL, 10), XENVBD_MAX_RING_PAGE_ORDER); - FrontendStoreFree(BlockRing->Frontend, Value); - } else { - BlockRing->Order = 0; - } - - BlockRing->Mdl = __AllocatePages(1 << BlockRing->Order); - - status = STATUS_NO_MEMORY; - if (BlockRing->Mdl == NULL) - goto fail2; - - BlockRing->SharedRing = MmGetSystemAddressForMdlSafe(BlockRing->Mdl, - NormalPagePriority); - ASSERT(BlockRing->SharedRing != NULL); - -#pragma warning(push) -#pragma warning(disable: 4305) -#pragma warning(disable: 4311) - SHARED_RING_INIT(BlockRing->SharedRing); - FRONT_RING_INIT(&BlockRing->FrontRing, BlockRing->SharedRing, PAGE_SIZE << BlockRing->Order); -#pragma warning(pop) - - RingPages = (1 << BlockRing->Order); - for (Index = 0; Index < RingPages; ++Index) { - status = GranterGet(Granter, __Pfn((PUCHAR)BlockRing->SharedRing + (Index * PAGE_SIZE)), - FALSE, &BlockRing->Grants[Index]); - if (!NT_SUCCESS(status)) - goto fail3; - } - - BlockRing->Connected = TRUE; - return STATUS_SUCCESS; - -fail3: - for (Index = 0; Index < XENVBD_MAX_RING_PAGES; ++Index) { - if (BlockRing->Grants[Index]) - GranterPut(Granter, BlockRing->Grants[Index]); - BlockRing->Grants[Index] = 0; - } - - RtlZeroMemory(&BlockRing->FrontRing, sizeof(BlockRing->FrontRing)); - __FreePages(BlockRing->Mdl); - BlockRing->SharedRing = NULL; - BlockRing->Mdl = NULL; - -fail2: -fail1: - return status; -} - -NTSTATUS -BlockRingStoreWrite( - IN PXENVBD_BLOCKRING BlockRing, - IN PXENBUS_STORE_TRANSACTION Transaction, - IN PCHAR FrontendPath - ) -{ - PXENVBD_GRANTER Granter = FrontendGetGranter(BlockRing->Frontend); - NTSTATUS status; - - if (BlockRing->Order == 0) { - status = XENBUS_STORE(Printf, - &BlockRing->StoreInterface, - Transaction, - FrontendPath, - "ring-ref", - "%u", - GranterReference(Granter, BlockRing->Grants[0])); - if (!NT_SUCCESS(status)) - return status; - } else { - ULONG Index, RingPages; - - status = XENBUS_STORE(Printf, - &BlockRing->StoreInterface, - Transaction, - FrontendPath, - "ring-page-order", - "%u", - BlockRing->Order); - if (!NT_SUCCESS(status)) - return status; - - RingPages = (1 << BlockRing->Order); - for (Index = 0; Index < RingPages; ++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, - &BlockRing->StoreInterface, - Transaction, - FrontendPath, - Name, - "%u", - GranterReference(Granter, BlockRing->Grants[Index])); - if (!NT_SUCCESS(status)) - return status; - } - } - - status = XENBUS_STORE(Printf, - &BlockRing->StoreInterface, - Transaction, - FrontendPath, - "protocol", - XEN_IO_PROTO_ABI); - if (!NT_SUCCESS(status)) - return status; - - return STATUS_SUCCESS; -} - -VOID -BlockRingEnable( - IN PXENVBD_BLOCKRING BlockRing - ) -{ - ASSERT(BlockRing->Enabled == FALSE); - - BlockRing->Enabled = TRUE; -} - -VOID -BlockRingDisable( - IN PXENVBD_BLOCKRING BlockRing - ) -{ - ASSERT(BlockRing->Enabled == TRUE); - - BlockRing->Enabled = FALSE; -} - -VOID -BlockRingDisconnect( - IN PXENVBD_BLOCKRING BlockRing - ) -{ - ULONG Index; - PXENVBD_GRANTER Granter = FrontendGetGranter(BlockRing->Frontend); - - ASSERT(BlockRing->Connected == TRUE); - - BlockRing->Submitted = 0; - BlockRing->Received = 0; - - for (Index = 0; Index < XENVBD_MAX_RING_PAGES; ++Index) { - if (BlockRing->Grants[Index]) { - GranterPut(Granter, BlockRing->Grants[Index]); - } - BlockRing->Grants[Index] = 0; - } - - RtlZeroMemory(&BlockRing->FrontRing, sizeof(BlockRing->FrontRing)); - __FreePages(BlockRing->Mdl); - BlockRing->SharedRing = NULL; - BlockRing->Mdl = NULL; - - BlockRing->Order = 0; - - XENBUS_STORE(Release, &BlockRing->StoreInterface); - RtlZeroMemory(&BlockRing->StoreInterface, sizeof(XENBUS_STORE_INTERFACE)); - - BlockRing->Connected = FALSE; -} - -VOID -BlockRingDebugCallback( - IN PXENVBD_BLOCKRING BlockRing, - IN PXENBUS_DEBUG_INTERFACE Debug - ) -{ - ULONG Index; - PXENVBD_GRANTER Granter = FrontendGetGranter(BlockRing->Frontend); - - XENBUS_DEBUG(Printf, Debug, - "BLOCKRING: Requests : %d / %d\n", - BlockRing->Submitted, - BlockRing->Received); - - XENBUS_DEBUG(Printf, Debug, - "BLOCKRING: SharedRing : 0x%p\n", - BlockRing->SharedRing); - - if (BlockRing->SharedRing) { - XENBUS_DEBUG(Printf, Debug, - "BLOCKRING: SharedRing : %d / %d - %d / %d\n", - BlockRing->SharedRing->req_prod, - BlockRing->SharedRing->req_event, - BlockRing->SharedRing->rsp_prod, - BlockRing->SharedRing->rsp_event); - } - - XENBUS_DEBUG(Printf, Debug, - "BLOCKRING: FrontRing : %d / %d (%d)\n", - BlockRing->FrontRing.req_prod_pvt, - BlockRing->FrontRing.rsp_cons, - BlockRing->FrontRing.nr_ents); - - XENBUS_DEBUG(Printf, Debug, - "BLOCKRING: Order : %d\n", - BlockRing->Order); - for (Index = 0; Index < (1ul << BlockRing->Order); ++Index) { - XENBUS_DEBUG(Printf, Debug, - "BLOCKRING: Grants[%-2d] : 0x%p (%u)\n", - Index, - BlockRing->Grants[Index], - GranterReference(Granter, BlockRing->Grants[Index])); - } - - BlockRing->Submitted = BlockRing->Received = 0; -} - -BOOLEAN -BlockRingPoll( - IN PXENVBD_BLOCKRING BlockRing - ) -{ - PXENVBD_TARGET Target = FrontendGetTarget(BlockRing->Frontend); - BOOLEAN Retry = FALSE; - - ASSERT3U(KeGetCurrentIrql(), ==, DISPATCH_LEVEL); - KeAcquireSpinLockAtDpcLevel(&BlockRing->Lock); - - // Guard against this locked region being called after the - // lock on FrontendSetState - if (BlockRing->Enabled == FALSE) - goto done; - - for (;;) { - ULONG rsp_prod; - ULONG rsp_cons; - - KeMemoryBarrier(); - - rsp_prod = BlockRing->SharedRing->rsp_prod; - rsp_cons = BlockRing->FrontRing.rsp_cons; - - KeMemoryBarrier(); - - if (rsp_cons == rsp_prod || Retry) - break; - - while (rsp_cons != rsp_prod && !Retry) { - blkif_response_t* Response; - ULONG Tag; - - Response = RING_GET_RESPONSE(&BlockRing->FrontRing, rsp_cons); - ++rsp_cons; - - if (__BlockRingPutTag(BlockRing, Response->id, &Tag)) { - ++BlockRing->Received; - TargetCompleteResponse(Target, Tag, Response->status); - } - - RtlZeroMemory(Response, sizeof(union blkif_sring_entry)); - - if (rsp_cons - BlockRing->FrontRing.rsp_cons > RING_SIZE(&BlockRing->FrontRing) / 4) - Retry = TRUE; - } - - KeMemoryBarrier(); - - BlockRing->FrontRing.rsp_cons = rsp_cons; - BlockRing->SharedRing->rsp_event = rsp_cons + 1; - } - -done: - KeReleaseSpinLockFromDpcLevel(&BlockRing->Lock); - - return Retry; -} - -BOOLEAN -BlockRingSubmit( - IN PXENVBD_BLOCKRING BlockRing, - IN PXENVBD_REQUEST Request - ) -{ - KIRQL Irql; - blkif_request_t* req; - BOOLEAN Notify; - - KeAcquireSpinLock(&BlockRing->Lock, &Irql); - if (RING_FULL(&BlockRing->FrontRing)) { - KeReleaseSpinLock(&BlockRing->Lock, Irql); - return FALSE; - } - - req = RING_GET_REQUEST(&BlockRing->FrontRing, BlockRing->FrontRing.req_prod_pvt); - __BlockRingInsert(BlockRing, Request, req); - KeMemoryBarrier(); - ++BlockRing->FrontRing.req_prod_pvt; - - RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&BlockRing->FrontRing, Notify); - KeReleaseSpinLock(&BlockRing->Lock, Irql); - - if (Notify) - NotifierSend(FrontendGetNotifier(BlockRing->Frontend)); - - return TRUE; -} diff --git a/src/xenvbd/blockring.h b/src/xenvbd/blockring.h deleted file mode 100644 index 98fe278..0000000 --- a/src/xenvbd/blockring.h +++ /dev/null @@ -1,97 +0,0 @@ -/* Copyright (c) Citrix Systems Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, - * with or without modification, are permitted provided - * that the following conditions are met: - * - * * Redistributions of source code must retain the above - * copyright notice, this list of conditions and the - * following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the - * following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef _XENVBD_BLOCKRING_H -#define _XENVBD_BLOCKRING_H - -typedef struct _XENVBD_BLOCKRING XENVBD_BLOCKRING, *PXENVBD_BLOCKRING; - -#include "frontend.h" -#include <debug_interface.h> -#include <store_interface.h> - -extern NTSTATUS -BlockRingCreate( - IN PXENVBD_FRONTEND Frontend, - IN ULONG DeviceId, - OUT PXENVBD_BLOCKRING* BlockRing - ); - -extern VOID -BlockRingDestroy( - IN PXENVBD_BLOCKRING BlockRing - ); - -extern NTSTATUS -BlockRingConnect( - IN PXENVBD_BLOCKRING BlockRing - ); - -extern NTSTATUS -BlockRingStoreWrite( - IN PXENVBD_BLOCKRING BlockRing, - IN PXENBUS_STORE_TRANSACTION Transaction, - IN PCHAR FrontendPath - ); - -extern VOID -BlockRingEnable( - IN PXENVBD_BLOCKRING BlockRing - ); - -extern VOID -BlockRingDisable( - IN PXENVBD_BLOCKRING BlockRing - ); - -extern VOID -BlockRingDisconnect( - IN PXENVBD_BLOCKRING BlockRing - ); - -extern VOID -BlockRingDebugCallback( - IN PXENVBD_BLOCKRING BlockRing, - IN PXENBUS_DEBUG_INTERFACE Debug - ); - -extern BOOLEAN -BlockRingPoll( - IN PXENVBD_BLOCKRING BlockRing - ); - -extern BOOLEAN -BlockRingSubmit( - IN PXENVBD_BLOCKRING BlockRing, - IN PXENVBD_REQUEST Request - ); - -#endif // _XENVBD_BLOCKRING_H diff --git a/src/xenvbd/frontend.c b/src/xenvbd/frontend.c index 1e2b026..0b23b70 100644 --- a/src/xenvbd/frontend.c +++ b/src/xenvbd/frontend.c @@ -39,8 +39,7 @@ #include "assert.h" #include "util.h" #include "names.h" -#include "notifier.h" -#include "blockring.h" +#include "ring.h" #include "granter.h" #include "thread.h" #include <store_interface.h> @@ -73,8 +72,7 @@ struct _XENVBD_FRONTEND { PXENBUS_SUSPEND_CALLBACK SuspendLateCallback; // Ring - PXENVBD_NOTIFIER Notifier; - PXENVBD_BLOCKRING BlockRing; + PXENVBD_RING Ring; PXENVBD_GRANTER Granter; // Backend State Watch @@ -127,6 +125,38 @@ __FrontendFree( //============================================================================= // Accessors +ULONG +FrontendGetDeviceId( + IN PXENVBD_FRONTEND Frontend + ) +{ + return Frontend->DeviceId; +} + +ULONG +FrontendGetBackendDomain( + IN PXENVBD_FRONTEND Frontend + ) +{ + return Frontend->BackendId; +} + +PCHAR +FrontendGetBackendPath( + IN PXENVBD_FRONTEND Frontend + ) +{ + return Frontend->BackendPath; +} + +PCHAR +FrontendGetFrontendPath( + IN PXENVBD_FRONTEND Frontend + ) +{ + return Frontend->FrontendPath; +} + VOID FrontendRemoveFeature( IN PXENVBD_FRONTEND Frontend, @@ -182,13 +212,6 @@ FrontendGetTargetId( { return Frontend->TargetId; } -ULONG -FrontendGetDeviceId( - __in PXENVBD_FRONTEND Frontend - ) -{ - return Frontend->DeviceId; -} PVOID FrontendGetInquiry( __in PXENVBD_FRONTEND Frontend @@ -203,19 +226,12 @@ FrontendGetTarget( { return Frontend->Target; } -PXENVBD_BLOCKRING -FrontendGetBlockRing( - __in PXENVBD_FRONTEND Frontend - ) -{ - return Frontend->BlockRing; -} -PXENVBD_NOTIFIER -FrontendGetNotifier( +PXENVBD_RING +FrontendGetRing( __in PXENVBD_FRONTEND Frontend ) { - return Frontend->Notifier; + return Frontend->Ring; } PXENVBD_GRANTER FrontendGetGranter( @@ -333,7 +349,7 @@ FrontendNotifyResponses( { BOOLEAN Retry = FALSE; - Retry |= BlockRingPoll(Frontend->BlockRing); + Retry |= RingPoll(Frontend->Ring); Retry |= TargetSubmitRequests(Frontend->Target); return Retry; @@ -1146,14 +1162,10 @@ FrontendConnect( if (!NT_SUCCESS(Status)) goto fail1; - Status = BlockRingConnect(Frontend->BlockRing); + Status = RingConnect(Frontend->Ring); if (!NT_SUCCESS(Status)) goto fail2; - Status = NotifierConnect(Frontend->Notifier, Frontend->BackendId); - if (!NT_SUCCESS(Status)) - goto fail3; - // write evtchn/gnttab details in xenstore for (;;) { PXENBUS_STORE_TRANSACTION Transaction; @@ -1164,11 +1176,7 @@ FrontendConnect( if (!NT_SUCCESS(Status)) break; - Status = NotifierStoreWrite(Frontend->Notifier, Transaction, Frontend->FrontendPath); - if (!NT_SUCCESS(Status)) - goto abort; - - Status = BlockRingStoreWrite(Frontend->BlockRing, Transaction, Frontend->FrontendPath); + Status = RingStoreWrite(Frontend->Ring, Transaction); if (!NT_SUCCESS(Status)) goto abort; @@ -1223,25 +1231,25 @@ abort: break; } if (!NT_SUCCESS(Status)) - goto fail4; + goto fail3; // Frontend: -> INITIALIZED Status = ___SetState(Frontend, XenbusStateInitialised); if (!NT_SUCCESS(Status)) - goto fail5; + goto fail4; // Backend : -> CONNECTED BackendState = XenbusStateUnknown; do { Status = __WaitState(Frontend, &BackendState); if (!NT_SUCCESS(Status)) - goto fail6; + goto fail5; } while (BackendState == XenbusStateInitWait || BackendState == XenbusStateInitialising || BackendState == XenbusStateInitialised); Status = STATUS_UNSUCCESSFUL; if (BackendState != XenbusStateConnected) - goto fail7; + goto fail6; // read disk info __ReadDiskInfo(Frontend); @@ -1253,12 +1261,10 @@ abort: // Frontend: -> CONNECTED Status = ___SetState(Frontend, XenbusStateConnected); if (!NT_SUCCESS(Status)) - goto fail8; + goto fail7; return STATUS_SUCCESS; -fail8: - Error("Fail8\n"); fail7: Error("Fail7\n"); fail6: @@ -1267,10 +1273,9 @@ fail5: Error("Fail5\n"); fail4: Error("Fail4\n"); - NotifierDisconnect(Frontend->Notifier); fail3: Error("Fail3\n"); - BlockRingDisconnect(Frontend->BlockRing); + RingDisconnect(Frontend->Ring); fail2: Error("Fail2\n"); GranterDisconnect(Frontend->Granter); @@ -1284,8 +1289,7 @@ FrontendDisconnect( __in PXENVBD_FRONTEND Frontend ) { - NotifierDisconnect(Frontend->Notifier); - BlockRingDisconnect(Frontend->BlockRing); + RingDisconnect(Frontend->Ring); GranterDisconnect(Frontend->Granter); } __drv_requiresIRQL(DISPATCH_LEVEL) @@ -1298,8 +1302,7 @@ FrontendEnable( KeMemoryBarrier(); GranterEnable(Frontend->Granter); - BlockRingEnable(Frontend->BlockRing); - NotifierEnable(Frontend->Notifier); + RingEnable(Frontend->Ring); } __drv_requiresIRQL(DISPATCH_LEVEL) static FORCEINLINE VOID @@ -1309,8 +1312,7 @@ FrontendDisable( { Frontend->Caps.Connected = FALSE; - NotifierDisable(Frontend->Notifier); - BlockRingDisable(Frontend->BlockRing); + RingDisable(Frontend->Ring); GranterDisable(Frontend->Granter); } @@ -1505,7 +1507,7 @@ FrontendSuspendLateCallback( ASSERT(FALSE); } - NotifierTrigger(Frontend->Notifier); + RingTrigger(Frontend->Ring); Verbose("Target[%d] : <=== restored %s\n", Frontend->TargetId, __XenvbdStateName(Frontend->State)); } @@ -1694,21 +1696,17 @@ FrontendCreate( if (!NT_SUCCESS(status)) goto fail3; - status = NotifierCreate(Frontend, &Frontend->Notifier); + status = RingCreate(Frontend, &Frontend->Ring); if (!NT_SUCCESS(status)) goto fail4; - status = BlockRingCreate(Frontend, Frontend->DeviceId, &Frontend->BlockRing); - if (!NT_SUCCESS(status)) - goto fail5; - status = GranterCreate(Frontend, &Frontend->Granter); if (!NT_SUCCESS(status)) - goto fail6; + goto fail5; status = ThreadCreate(FrontendBackend, Frontend, &Frontend->BackendThread); if (!NT_SUCCESS(status)) - goto fail7; + goto fail6; // kernel objects KeInitializeSpinLock(&Frontend->StateLock); @@ -1717,18 +1715,14 @@ FrontendCreate( *_Frontend = Frontend; return STATUS_SUCCESS; -fail7: - Error("fail7\n"); - GranterDestroy(Frontend->Granter); - Frontend->Granter = NULL; fail6: Error("fail6\n"); - BlockRingDestroy(Frontend->BlockRing); - Frontend->BlockRing = NULL; + GranterDestroy(Frontend->Granter); + Frontend->Granter = NULL; fail5: Error("fail5\n"); - NotifierDestroy(Frontend->Notifier); - Frontend->Notifier = NULL; + RingDestroy(Frontend->Ring); + Frontend->Ring = NULL; fail4: Error("fail4\n"); fail3: @@ -1761,11 +1755,8 @@ FrontendDestroy( GranterDestroy(Frontend->Granter); Frontend->Granter = NULL; - BlockRingDestroy(Frontend->BlockRing); - Frontend->BlockRing = NULL; - - NotifierDestroy(Frontend->Notifier); - Frontend->Notifier = NULL; + RingDestroy(Frontend->Ring); + Frontend->Ring = NULL; ASSERT3P(Frontend->BackendPath, ==, NULL); ASSERT3P(Frontend->Inquiry, ==, NULL); @@ -1840,7 +1831,5 @@ FrontendDebugCallback( Frontend->DiskInfo.DiskInfo); GranterDebugCallback(Frontend->Granter, Debug); - BlockRingDebugCallback(Frontend->BlockRing, Debug); - NotifierDebugCallback(Frontend->Notifier, Debug); } diff --git a/src/xenvbd/frontend.h b/src/xenvbd/frontend.h index 4490aeb..513ace4 100644 --- a/src/xenvbd/frontend.h +++ b/src/xenvbd/frontend.h @@ -74,7 +74,26 @@ typedef struct _XENVBD_DISKINFO { typedef struct _XENVBD_FRONTEND XENVBD_FRONTEND, *PXENVBD_FRONTEND; -// Accessors +extern ULONG +FrontendGetDeviceId( + IN PXENVBD_FRONTEND Frontend + ); + +extern ULONG +FrontendGetBackendDomain( + IN PXENVBD_FRONTEND Frontend + ); + +extern PCHAR +FrontendGetBackendPath( + IN PXENVBD_FRONTEND Frontend + ); + +extern PCHAR +FrontendGetFrontendPath( + IN PXENVBD_FRONTEND Frontend + ); + extern VOID FrontendRemoveFeature( IN PXENVBD_FRONTEND Frontend, @@ -96,10 +115,6 @@ extern ULONG FrontendGetTargetId( __in PXENVBD_FRONTEND Frontend ); -extern ULONG -FrontendGetDeviceId( - __in PXENVBD_FRONTEND Frontend - ); extern PVOID FrontendGetInquiry( __in PXENVBD_FRONTEND Frontend @@ -108,14 +123,9 @@ extern PXENVBD_TARGET FrontendGetTarget( __in PXENVBD_FRONTEND Frontend ); -#include "blockring.h" -extern PXENVBD_BLOCKRING -FrontendGetBlockRing( - __in PXENVBD_FRONTEND Frontend - ); -#include "notifier.h" -extern PXENVBD_NOTIFIER -FrontendGetNotifier( +#include "ring.h" +extern PXENVBD_RING +FrontendGetRing( __in PXENVBD_FRONTEND Frontend ); #include "granter.h" diff --git a/src/xenvbd/notifier.c b/src/xenvbd/notifier.c deleted file mode 100644 index 22bfe00..0000000 --- a/src/xenvbd/notifier.c +++ /dev/null @@ -1,390 +0,0 @@ -/* Copyright (c) Citrix Systems Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, - * with or without modification, are permitted provided - * that the following conditions are met: - * - * * Redistributions of source code must retain the above - * copyright notice, this list of conditions and the - * following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the - * following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "notifier.h" -#include "frontend.h" -#include "target.h" -#include "adapter.h" -#include "util.h" -#include "debug.h" -#include <evtchn_interface.h> - -struct _XENVBD_NOTIFIER { - PXENVBD_FRONTEND Frontend; - BOOLEAN Connected; - BOOLEAN Enabled; - - XENBUS_STORE_INTERFACE StoreInterface; - XENBUS_EVTCHN_INTERFACE EvtchnInterface; - - PXENBUS_EVTCHN_CHANNEL Channel; - ULONG Port; - ULONG NumInts; - ULONG NumDpcs; - KDPC Dpc; - KDPC TimerDpc; - KTIMER Timer; -}; - -#define NOTIFIER_POOL_TAG 'yfNX' - -static FORCEINLINE PVOID -__NotifierAllocate( - IN ULONG Length - ) -{ - return __AllocatePoolWithTag(NonPagedPool, Length, NOTIFIER_POOL_TAG); -} - -static FORCEINLINE VOID -__NotifierFree( - IN PVOID Buffer - ) -{ - if (Buffer) - __FreePoolWithTag(Buffer, NOTIFIER_POOL_TAG); -} - -KSERVICE_ROUTINE NotifierInterrupt; - -BOOLEAN -NotifierInterrupt( - __in PKINTERRUPT Interrupt, - _In_opt_ PVOID Context - ) -{ - PXENVBD_NOTIFIER Notifier = Context; - - UNREFERENCED_PARAMETER(Interrupt); - - ASSERT(Notifier != NULL); - - ++Notifier->NumInts; - if (Notifier->Connected) { - if (KeInsertQueueDpc(&Notifier->Dpc, NULL, NULL)) { - ++Notifier->NumDpcs; - } - } - - return TRUE; -} - -static FORCEINLINE BOOLEAN -__NotifierDpcTimeout( - IN PXENVBD_NOTIFIER Notifier - ) -{ - KDPC_WATCHDOG_INFORMATION Watchdog; - NTSTATUS status; - - UNREFERENCED_PARAMETER(Notifier); - - RtlZeroMemory(&Watchdog, sizeof (Watchdog)); - - status = KeQueryDpcWatchdogInformation(&Watchdog); - ASSERT(NT_SUCCESS(status)); - - if (Watchdog.DpcTimeLimit == 0 || - Watchdog.DpcWatchdogLimit == 0) - return FALSE; - - if (Watchdog.DpcTimeCount > (Watchdog.DpcTimeLimit / 2) && - Watchdog.DpcWatchdogCount > (Watchdog.DpcWatchdogLimit / 2)) - return FALSE; - - return TRUE; -} - -#define TIME_US(_us) ((_us) * 10) -#define TIME_MS(_ms) (TIME_US((_ms) * 1000)) -#define TIME_S(_s) (TIME_MS((_s) * 1000)) -#define TIME_RELATIVE(_t) (-(_t)) - -KDEFERRED_ROUTINE NotifierDpc; - -VOID -NotifierDpc( - __in PKDPC Dpc, - __in_opt PVOID Context, - __in_opt PVOID Arg1, - __in_opt PVOID Arg2 - ) -{ - PXENVBD_NOTIFIER Notifier = Context; - - UNREFERENCED_PARAMETER(Dpc); - UNREFERENCED_PARAMETER(Arg1); - UNREFERENCED_PARAMETER(Arg2); - - ASSERT(Notifier != NULL); - - if (!Notifier->Connected) - return; - - for (;;) { - if (!FrontendNotifyResponses(Notifier->Frontend)) { - XENBUS_EVTCHN(Unmask, - &Notifier->EvtchnInterface, - Notifier->Channel, - FALSE); - break; - } - if (__NotifierDpcTimeout(Notifier)) { - LARGE_INTEGER Delay; - - Delay.QuadPart = TIME_RELATIVE(TIME_US(100)); - - KeSetTimer(&Notifier->Timer, - Delay, - &Notifier->TimerDpc); - break; - } - } -} - -NTSTATUS -NotifierCreate( - IN PXENVBD_FRONTEND Frontend, - OUT PXENVBD_NOTIFIER* Notifier - ) -{ - *Notifier = __NotifierAllocate(sizeof(XENVBD_NOTIFIER)); - if (*Notifier == NULL) - goto fail1; - - (*Notifier)->Frontend = Frontend; - KeInitializeDpc(&(*Notifier)->Dpc, NotifierDpc, *Notifier); - KeInitializeDpc(&(*Notifier)->TimerDpc, NotifierDpc, *Notifier); - KeInitializeTimer(&(*Notifier)->Timer); - - return STATUS_SUCCESS; - -fail1: - return STATUS_NO_MEMORY; -} - -VOID -NotifierDestroy( - IN PXENVBD_NOTIFIER Notifier - ) -{ - Notifier->Frontend = NULL; - RtlZeroMemory(&Notifier->Dpc, sizeof(KDPC)); - RtlZeroMemory(&Notifier->TimerDpc, sizeof(KDPC)); - RtlZeroMemory(&Notifier->Timer, sizeof(KTIMER)); - - ASSERT(IsZeroMemory(Notifier, sizeof(XENVBD_NOTIFIER))); - - __NotifierFree(Notifier); -} - -NTSTATUS -NotifierConnect( - IN PXENVBD_NOTIFIER Notifier, - IN USHORT BackendDomain - ) -{ - PXENVBD_ADAPTER Adapter = TargetGetAdapter(FrontendGetTarget(Notifier->Frontend)); - NTSTATUS status; - - ASSERT(Notifier->Connected == FALSE); - - AdapterGetStoreInterface(Adapter, &Notifier->StoreInterface); - AdapterGetEvtchnInterface(Adapter, &Notifier->EvtchnInterface); - - status = XENBUS_STORE(Acquire, &Notifier->StoreInterface); - if (!NT_SUCCESS(status)) - goto fail1; - - status = XENBUS_EVTCHN(Acquire, &Notifier->EvtchnInterface); - if (!NT_SUCCESS(status)) - goto fail2; - - Notifier->Channel = XENBUS_EVTCHN(Open, - &Notifier->EvtchnInterface, - XENBUS_EVTCHN_TYPE_UNBOUND, - NotifierInterrupt, - Notifier, - BackendDomain, - TRUE); - - status = STATUS_NO_MEMORY; - if (Notifier->Channel == NULL) - goto fail3; - - Notifier->Port = XENBUS_EVTCHN(GetPort, - &Notifier->EvtchnInterface, - Notifier->Channel); - - XENBUS_EVTCHN(Unmask, - &Notifier->EvtchnInterface, - Notifier->Channel, - FALSE); - - Notifier->Connected = TRUE; - return STATUS_SUCCESS; - -fail3: - XENBUS_EVTCHN(Release, &Notifier->EvtchnInterface); - RtlZeroMemory(&Notifier->EvtchnInterface, sizeof(XENBUS_EVTCHN_INTERFACE)); - -fail2: - XENBUS_STORE(Release, &Notifier->StoreInterface); - RtlZeroMemory(&Notifier->StoreInterface, sizeof(XENBUS_STORE_INTERFACE)); - -fail1: - return status; -} - -NTSTATUS -NotifierStoreWrite( - IN PXENVBD_NOTIFIER Notifier, - IN PXENBUS_STORE_TRANSACTION Transaction, - IN PCHAR FrontendPath - ) -{ - return XENBUS_STORE(Printf, - &Notifier->StoreInterface, - Transaction, - FrontendPath, - "event-channel", - "%u", - Notifier->Port); -} - -VOID -NotifierEnable( - IN PXENVBD_NOTIFIER Notifier - ) -{ - ASSERT(Notifier->Enabled == FALSE); - - XENBUS_EVTCHN(Trigger, - &Notifier->EvtchnInterface, - Notifier->Channel); - - Notifier->Enabled = TRUE; -} - -VOID -NotifierDisable( - IN PXENVBD_NOTIFIER Notifier - ) -{ - ASSERT(Notifier->Enabled == TRUE); - - Notifier->Enabled = FALSE; - - // - // No new timers can be scheduled once Enabled goes to FALSE. - // Cancel any existing ones. - // - (VOID) KeCancelTimer(&Notifier->Timer); -} - -VOID -NotifierDisconnect( - IN PXENVBD_NOTIFIER Notifier - ) -{ - ASSERT(Notifier->Connected == TRUE); - - XENBUS_EVTCHN(Close, - &Notifier->EvtchnInterface, - Notifier->Channel); - Notifier->Channel = NULL; - Notifier->Port = 0; - - XENBUS_EVTCHN(Release, &Notifier->EvtchnInterface); - RtlZeroMemory(&Notifier->EvtchnInterface, sizeof(XENBUS_EVTCHN_INTERFACE)); - - XENBUS_STORE(Release, &Notifier->StoreInterface); - RtlZeroMemory(&Notifier->StoreInterface, sizeof(XENBUS_STORE_INTERFACE)); - - Notifier->NumInts = Notifier->NumDpcs = 0; - - Notifier->Connected = FALSE; -} - -VOID -NotifierDebugCallback( - IN PXENVBD_NOTIFIER Notifier, - IN PXENBUS_DEBUG_INTERFACE Debug - ) -{ - XENBUS_DEBUG(Printf, Debug, - "NOTIFIER: Int / DPC : %d / %d\n", - Notifier->NumInts, Notifier->NumDpcs); - - if (Notifier->Channel) { - XENBUS_DEBUG(Printf, Debug, - "NOTIFIER: Channel : %p (%d)\n", - Notifier->Channel, Notifier->Port); - } - - Notifier->NumInts = 0; - Notifier->NumDpcs = 0; -} - -VOID -NotifierKick( - IN PXENVBD_NOTIFIER Notifier - ) -{ - if (Notifier->Enabled) { - if (KeInsertQueueDpc(&Notifier->Dpc, NULL, NULL)) { - ++Notifier->NumDpcs; - } - } -} - -VOID -NotifierTrigger( - IN PXENVBD_NOTIFIER Notifier - ) -{ - if (Notifier->Enabled) - XENBUS_EVTCHN(Trigger, - &Notifier->EvtchnInterface, - Notifier->Channel); -} - -VOID -NotifierSend( - IN PXENVBD_NOTIFIER Notifier - ) -{ - if (Notifier->Enabled) - XENBUS_EVTCHN(Send, - &Notifier->EvtchnInterface, - Notifier->Channel); -} - diff --git a/src/xenvbd/notifier.h b/src/xenvbd/notifier.h deleted file mode 100644 index 4cf35e7..0000000 --- a/src/xenvbd/notifier.h +++ /dev/null @@ -1,101 +0,0 @@ -/* Copyright (c) Citrix Systems Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, - * with or without modification, are permitted provided - * that the following conditions are met: - * - * * Redistributions of source code must retain the above - * copyright notice, this list of conditions and the - * following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the - * following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef _XENVBD_NOTIFIER_H -#define _XENVBD_NOTIFIER_H - -typedef struct _XENVBD_NOTIFIER XENVBD_NOTIFIER, *PXENVBD_NOTIFIER; - -#include "frontend.h" -#include <debug_interface.h> -#include <store_interface.h> - -extern NTSTATUS -NotifierCreate( - IN PXENVBD_FRONTEND Frontend, - OUT PXENVBD_NOTIFIER* Notifier - ); - -extern VOID -NotifierDestroy( - IN PXENVBD_NOTIFIER Notifier - ); - -extern NTSTATUS -NotifierConnect( - IN PXENVBD_NOTIFIER Notifier, - IN USHORT BackendDomain - ); - -extern NTSTATUS -NotifierStoreWrite( - IN PXENVBD_NOTIFIER Notifier, - IN PXENBUS_STORE_TRANSACTION Transaction, - IN PCHAR FrontendPath - ); - -extern VOID -NotifierEnable( - IN PXENVBD_NOTIFIER Notifier - ); - -extern VOID -NotifierDisable( - IN PXENVBD_NOTIFIER Notifier - ); - -extern VOID -NotifierDisconnect( - IN PXENVBD_NOTIFIER Notifier - ); - -extern VOID -NotifierDebugCallback( - IN PXENVBD_NOTIFIER Notifier, - IN PXENBUS_DEBUG_INTERFACE Debug - ); - -extern VOID -NotifierKick( - IN PXENVBD_NOTIFIER Notifier - ); - -extern VOID -NotifierTrigger( - IN PXENVBD_NOTIFIER Notifier - ); - -extern VOID -NotifierSend( - IN PXENVBD_NOTIFIER Notifier - ); - -#endif // _XENVBD_NOTIFIER_H diff --git a/src/xenvbd/ring.c b/src/xenvbd/ring.c new file mode 100755 index 0000000..eb5fcc7 --- /dev/null +++ b/src/xenvbd/ring.c @@ -0,0 +1,911 @@ +/* Copyright (c) Citrix Systems Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, + * with or without modification, are permitted provided + * that the following conditions are met: + * + * * Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <ntddk.h> +#include <stdlib.h> +#include <ntstrsafe.h> + +#include <store_interface.h> +#include <evtchn_interface.h> +#include <debug_interface.h> + +#include "ring.h" +#include "frontend.h" +#include "target.h" +#include "adapter.h" +#include "srbext.h" +#include "driver.h" +#include "granter.h" + +#include "util.h" +#include "debug.h" +#include "assert.h" + +#define TAG_HEADER 'gaTX' +#define XENVBD_MAX_RING_PAGE_ORDER (4) +#define XENVBD_MAX_RING_PAGES (1 << XENVBD_MAX_RING_PAGE_ORDER) + +struct _XENVBD_RING { + PXENVBD_FRONTEND Frontend; + BOOLEAN Connected; + BOOLEAN Enabled; + + 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; + KDPC TimerDpc; + KTIMER Timer; + + ULONG Submitted; + ULONG Received; + ULONG Events; + ULONG Dpcs; +}; + +#define MAX_NAME_LEN 64 +#define RING_POOL_TAG 'gnRX' +#define XEN_IO_PROTO_ABI "x86_64-abi" + +static FORCEINLINE PVOID +__RingAllocate( + IN ULONG Length + ) +{ + return __AllocatePoolWithTag(NonPagedPool, + Length, + RING_POOL_TAG); +} + +static FORCEINLINE VOID +__RingFree( + IN PVOID Buffer + ) +{ + if (Buffer) + __FreePoolWithTag(Buffer, + RING_POOL_TAG); +} + +static FORCEINLINE VOID +xen_mb() +{ + KeMemoryBarrier(); + _ReadWriteBarrier(); +} + +static FORCEINLINE VOID +xen_wmb() +{ + KeMemoryBarrier(); + _WriteBarrier(); +} + +static FORCEINLINE PFN_NUMBER +__Pfn( + __in PVOID VirtAddr + ) +{ + return (PFN_NUMBER)(ULONG_PTR)(MmGetPhysicalAddress(VirtAddr).QuadPart >> PAGE_SHIFT); +} + +static FORCEINLINE ULONG64 +__RingGetTag( + IN PXENVBD_RING Ring, + IN PXENVBD_REQUEST Request + ) +{ + UNREFERENCED_PARAMETER(Ring); + return ((ULONG64)TAG_HEADER << 32) | (ULONG64)Request->Id; +} + +static FORCEINLINE BOOLEAN +__RingPutTag( + IN PXENVBD_RING Ring, + IN ULONG64 Id, + OUT PULONG Tag + ) +{ + ULONG Header = (ULONG)((Id >> 32) & 0xFFFFFFFF); + + UNREFERENCED_PARAMETER(Ring); + + *Tag = (ULONG)(Id & 0xFFFFFFFF); + if (Header != TAG_HEADER) { + Error("PUT_TAG (%llx) TAG_HEADER (%08x%08x)\n", Id, Header, *Tag); + return FALSE; + } + + return TRUE; +} + +static FORCEINLINE VOID +__RingInsert( + IN PXENVBD_RING Ring, + IN PXENVBD_REQUEST Request, + IN blkif_request_t* req + ) +{ + 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 = __RingGetTag(Ring, 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, Entry); + + 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, Entry); + + 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 = __RingGetTag(Ring, Request); + req->sector_number = Request->FirstSector; + + 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, Entry); + req->seg[Index].gref = GranterReference(Granter, Segment->Grant); + req->seg[Index].first_sect = Segment->FirstSector; + req->seg[Index].last_sect = Segment->LastSector; + } + } + 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 = __RingGetTag(Ring, Request); + req->sector_number = Request->FirstSector; + 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 = __RingGetTag(Ring, Request); + req_discard->sector_number = Request->FirstSector; + req_discard->nr_sectors = Request->NrSectors; + } break; + + default: + ASSERT(FALSE); + break; + } + ++Ring->Submitted; +} + +KSERVICE_ROUTINE RingInterrupt; + +BOOLEAN +RingInterrupt( + IN PKINTERRUPT Interrupt, + IN PVOID Context + ) +{ + PXENVBD_RING Ring = Context; + + UNREFERENCED_PARAMETER(Interrupt); + + ASSERT(Ring != NULL); + + ++Ring->Events; + if (!Ring->Connected) + return TRUE; + + if (KeInsertQueueDpc(&Ring->Dpc, NULL, NULL)) + ++Ring->Dpcs; + + return TRUE; +} + +static FORCEINLINE BOOLEAN +__RingDpcTimeout( + IN PXENVBD_RING Ring + ) +{ + KDPC_WATCHDOG_INFORMATION Watchdog; + NTSTATUS status; + + UNREFERENCED_PARAMETER(Ring); + + RtlZeroMemory(&Watchdog, sizeof (Watchdog)); + + status = KeQueryDpcWatchdogInformation(&Watchdog); + ASSERT(NT_SUCCESS(status)); + + if (Watchdog.DpcTimeLimit == 0 || + Watchdog.DpcWatchdogLimit == 0) + return FALSE; + + if (Watchdog.DpcTimeCount > (Watchdog.DpcTimeLimit / 2) && + Watchdog.DpcWatchdogCount > (Watchdog.DpcWatchdogLimit / 2)) + return FALSE; + + return TRUE; +} + +#define TIME_US(_us) ((_us) * 10) +#define TIME_MS(_ms) (TIME_US((_ms) * 1000)) +#define TIME_S(_s) (TIME_MS((_s) * 1000)) +#define TIME_RELATIVE(_t) (-(_t)) + +KDEFERRED_ROUTINE RingDpc; + +VOID +RingDpc( + __in PKDPC Dpc, + __in_opt PVOID Context, + __in_opt PVOID Arg1, + __in_opt PVOID Arg2 + ) +{ + PXENVBD_RING Ring = Context; + + UNREFERENCED_PARAMETER(Dpc); + UNREFERENCED_PARAMETER(Arg1); + UNREFERENCED_PARAMETER(Arg2); + + ASSERT(Ring != NULL); + + if (!Ring->Connected) + return; + + for (;;) { + if (!FrontendNotifyResponses(Ring->Frontend)) { + XENBUS_EVTCHN(Unmask, + &Ring->EvtchnInterface, + Ring->Channel, + FALSE); + break; + } + if (__RingDpcTimeout(Ring)) { + LARGE_INTEGER Delay; + + Delay.QuadPart = TIME_RELATIVE(TIME_US(100)); + + KeSetTimer(&Ring->Timer, + Delay, + &Ring->TimerDpc); + break; + } + } +} + +static DECLSPEC_NOINLINE VOID +RingDebugCallback( + IN PVOID Argument, + IN BOOLEAN Crashing + ) +{ + PXENVBD_RING Ring = Argument; + PXENVBD_GRANTER Granter = FrontendGetGranter(Ring->Frontend); + ULONG Index; + + UNREFERENCED_PARAMETER(Crashing); + + XENBUS_DEBUG(Printf, + &Ring->DebugInterface, + "Submitted: %u Received: %u\n", + Ring->Submitted, + Ring->Received); + + XENBUS_DEBUG(Printf, + &Ring->DebugInterface, + "Events: %u Dpcs: %u\n", + Ring->Events, + Ring->Dpcs); + + XENBUS_DEBUG(Printf, + &Ring->DebugInterface, + "Shared : 0x%p\n", + Ring->Shared); + + 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); + } + + XENBUS_DEBUG(Printf, + &Ring->DebugInterface, + "Front: %d / %d (%d)\n", + Ring->Front.req_prod_pvt, + Ring->Front.rsp_cons, + Ring->Front.nr_ents); + + XENBUS_DEBUG(Printf, + &Ring->DebugInterface, + "Order: %d\n", + Ring->Order); + + 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])); + } + + if (Ring->Channel) { + ULONG Port = XENBUS_EVTCHN(GetPort, + &Ring->EvtchnInterface, + Ring->Channel); + + XENBUS_DEBUG(Printf, + &Ring->DebugInterface, + "Channel : %p (%d)\n", + Ring->Channel, + Port); + } +} + +NTSTATUS +RingCreate( + IN PXENVBD_FRONTEND Frontend, + OUT PXENVBD_RING* Ring + ) +{ + NTSTATUS status; + + *Ring = __RingAllocate(sizeof(XENVBD_RING)); + + status = STATUS_NO_MEMORY; + if (*Ring == NULL) + goto fail1; + + (*Ring)->Frontend = Frontend; + KeInitializeSpinLock(&(*Ring)->Lock); + KeInitializeDpc(&(*Ring)->Dpc, RingDpc, *Ring); + KeInitializeDpc(&(*Ring)->TimerDpc, RingDpc, *Ring); + KeInitializeTimer(&(*Ring)->Timer); + + return STATUS_SUCCESS; + +fail1: + Error("fail1 %08x\n", status); + return status; +} + +VOID +RingDestroy( + IN PXENVBD_RING Ring + ) +{ + RtlZeroMemory(&Ring->Timer, sizeof(KTIMER)); + RtlZeroMemory(&Ring->TimerDpc, sizeof(KDPC)); + RtlZeroMemory(&Ring->Dpc, sizeof(KDPC)); + RtlZeroMemory(&Ring->Lock, sizeof(KSPIN_LOCK)); + Ring->Frontend = NULL; + + ASSERT(IsZeroMemory(Ring, sizeof(XENVBD_RING))); + __RingFree(Ring); +} + +NTSTATUS +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 Index; + NTSTATUS status; + + ASSERT(Ring->Connected == FALSE); + + AdapterGetStoreInterface(Adapter, &Ring->StoreInterface); + AdapterGetEvtchnInterface(Adapter, &Ring->EvtchnInterface); + AdapterGetDebugInterface(Adapter, &Ring->DebugInterface); + + status = XENBUS_STORE(Acquire, &Ring->StoreInterface); + if (!NT_SUCCESS(status)) + goto fail1; + + status = XENBUS_EVTCHN(Acquire, &Ring->EvtchnInterface); + if (!NT_SUCCESS(status)) + goto fail2; + + status = XENBUS_DEBUG(Acquire, &Ring->DebugInterface); + if (!NT_SUCCESS(status)) + goto fail3; + + status = XENBUS_STORE(Read, + &Ring->StoreInterface, + NULL, + FrontendGetBackendPath(Ring->Frontend), + "max-ring-page-order", + &Buffer); + if (NT_SUCCESS(status)) { + Ring->Order = strtoul(Buffer, NULL, 10); + if (Ring->Order > XENVBD_MAX_RING_PAGE_ORDER) + Ring->Order = XENVBD_MAX_RING_PAGE_ORDER; + + XENBUS_STORE(Free, + &Ring->StoreInterface, + Buffer); + } else { + 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) + + for (Index = 0; Index < (1ul << Ring->Order); ++Index) { + status = GranterGet(Granter, + MmGetMdlPfnArray(Ring->Mdl)[Index], + FALSE, + &Ring->Grants[Index]); + 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); + + status = XENBUS_DEBUG(Register, + &Ring->DebugInterface, + __MODULE__"|RING", + RingDebugCallback, + Ring, + &Ring->DebugCallback); + if (!NT_SUCCESS(status)) + goto fail7; + + Ring->Connected = TRUE; + return STATUS_SUCCESS; + +fail7: + Error("fail7\n"); + XENBUS_EVTCHN(Close, + &Ring->EvtchnInterface, + Ring->Channel); + Ring->Channel = NULL; +fail6: + Error("fail6\n"); +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; + } + + RtlZeroMemory(&Ring->Front, sizeof(blkif_front_ring_t)); + + __FreePages(Ring->Mdl); + Ring->Shared = NULL; + Ring->Mdl = NULL; + + Ring->Order = 0; +fail4: + Error("fail4\n"); + XENBUS_DEBUG(Release, &Ring->DebugInterface); +fail3: + Error("fail3\n"); + XENBUS_EVTCHN(Release, &Ring->EvtchnInterface); +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)); + + return status; +} + +NTSTATUS +RingStoreWrite( + IN PXENVBD_RING Ring, + IN PVOID Transaction + ) +{ + PXENVBD_GRANTER Granter = FrontendGetGranter(Ring->Frontend); + ULONG Port; + NTSTATUS status; + + if (Ring->Order == 0) { + status = XENBUS_STORE(Printf, + &Ring->StoreInterface, + Transaction, + FrontendGetFrontendPath(Ring->Frontend), + "ring-ref", + "%u", + GranterReference(Granter, Ring->Grants[0])); + if (!NT_SUCCESS(status)) + return status; + } else { + ULONG Index; + + status = XENBUS_STORE(Printf, + &Ring->StoreInterface, + Transaction, + FrontendGetFrontendPath(Ring->Frontend), + "ring-page-order", + "%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; + } + } + + status = XENBUS_STORE(Printf, + &Ring->StoreInterface, + Transaction, + FrontendGetFrontendPath(Ring->Frontend), + "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; + + return STATUS_SUCCESS; +} + +VOID +RingEnable( + IN PXENVBD_RING Ring + ) +{ + ASSERT(Ring->Enabled == FALSE); + Ring->Enabled = TRUE; + + XENBUS_EVTCHN(Trigger, + &Ring->EvtchnInterface, + Ring->Channel); +} + +VOID +RingDisable( + IN PXENVBD_RING Ring + ) +{ + ASSERT(Ring->Enabled == TRUE); + Ring->Enabled = FALSE; + + // + // No new timers can be scheduled once Enabled goes to FALSE. + // Cancel any existing ones. + // + (VOID) KeCancelTimer(&Ring->Timer); +} + +VOID +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; + + GranterPut(Granter, Ring->Grants[Index]); + Ring->Grants[Index] = NULL; + } + + RtlZeroMemory(&Ring->Front, sizeof(blkif_front_ring_t)); + + __FreePages(Ring->Mdl); + Ring->Shared = NULL; + Ring->Mdl = NULL; + + Ring->Order = 0; + + XENBUS_DEBUG(Release, &Ring->DebugInterface); + XENBUS_EVTCHN(Release, &Ring->EvtchnInterface); + XENBUS_STORE(Release, &Ring->StoreInterface); + + RtlZeroMemory(&Ring->DebugInterface, + sizeof(XENBUS_DEBUG_INTERFACE)); + RtlZeroMemory(&Ring->EvtchnInterface, + sizeof(XENBUS_EVTCHN_INTERFACE)); + RtlZeroMemory(&Ring->StoreInterface, + sizeof(XENBUS_STORE_INTERFACE)); + + Ring->Events = 0; + Ring->Dpcs = 0; + Ring->Submitted = 0; + Ring->Received = 0; +} + +BOOLEAN +RingPoll( + IN PXENVBD_RING Ring + ) +{ + PXENVBD_TARGET Target = FrontendGetTarget(Ring->Frontend); + BOOLEAN Retry = FALSE; + + ASSERT3U(KeGetCurrentIrql(), ==, DISPATCH_LEVEL); + KeAcquireSpinLockAtDpcLevel(&Ring->Lock); + + // Guard against this locked region being called after the + // lock on FrontendSetState + if (Ring->Enabled == FALSE) + goto done; + + for (;;) { + ULONG rsp_prod; + ULONG rsp_cons; + + KeMemoryBarrier(); + + rsp_prod = Ring->Shared->rsp_prod; + rsp_cons = Ring->Front.rsp_cons; + + KeMemoryBarrier(); + + if (rsp_cons == rsp_prod || Retry) + break; + + while (rsp_cons != rsp_prod && !Retry) { + blkif_response_t* Response; + ULONG Tag; + + Response = RING_GET_RESPONSE(&Ring->Front, rsp_cons); + ++rsp_cons; + + if (__RingPutTag(Ring, Response->id, &Tag)) { + ++Ring->Received; + TargetCompleteResponse(Target, Tag, Response->status); + } + + RtlZeroMemory(Response, sizeof(union blkif_sring_entry)); + + if (rsp_cons - Ring->Front.rsp_cons > RING_SIZE(&Ring->Front) / 4) + Retry = TRUE; + } + + KeMemoryBarrier(); + + Ring->Front.rsp_cons = rsp_cons; + Ring->Shared->rsp_event = rsp_cons + 1; + } + +done: + KeReleaseSpinLockFromDpcLevel(&Ring->Lock); + + return Retry; +} + +BOOLEAN +RingSubmit( + IN PXENVBD_RING Ring, + IN PXENVBD_REQUEST Request + ) +{ + 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); + + if (Notify) + RingSend(Ring); + + return TRUE; +} + +VOID +RingKick( + IN PXENVBD_RING Ring + ) +{ + if (!Ring->Enabled) + return; + + if (KeInsertQueueDpc(&Ring->Dpc, NULL, NULL)) + ++Ring->Dpcs; +} + +VOID +RingTrigger( + IN PXENVBD_RING Ring + ) +{ + if (!Ring->Enabled) + return; + + XENBUS_EVTCHN(Trigger, + &Ring->EvtchnInterface, + Ring->Channel); +} + +VOID +RingSend( + IN PXENVBD_RING Ring + ) +{ + if (!Ring->Enabled) + return; + + XENBUS_EVTCHN(Send, + &Ring->EvtchnInterface, + Ring->Channel); +} diff --git a/src/xenvbd/ring.h b/src/xenvbd/ring.h new file mode 100755 index 0000000..3ac1c71 --- /dev/null +++ b/src/xenvbd/ring.h @@ -0,0 +1,103 @@ +/* Copyright (c) Citrix Systems Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, + * with or without modification, are permitted provided + * that the following conditions are met: + * + * * Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _XENVBD_RING_H +#define _XENVBD_RING_H + +typedef struct _XENVBD_RING XENVBD_RING, *PXENVBD_RING; + +#include "frontend.h" +#include "srbext.h" + +extern NTSTATUS +RingCreate( + IN PXENVBD_FRONTEND Frontend, + OUT PXENVBD_RING* Ring + ); + +extern VOID +RingDestroy( + IN PXENVBD_RING Ring + ); + +extern NTSTATUS +RingConnect( + IN PXENVBD_RING Ring + ); + +extern NTSTATUS +RingStoreWrite( + IN PXENVBD_RING Ring, + IN PVOID Transaction + ); + +extern VOID +RingEnable( + IN PXENVBD_RING Ring + ); + +extern VOID +RingDisable( + IN PXENVBD_RING Ring + ); + +extern VOID +RingDisconnect( + IN PXENVBD_RING Ring + ); + +extern BOOLEAN +RingPoll( + IN PXENVBD_RING Ring + ); + +extern BOOLEAN +RingSubmit( + IN PXENVBD_RING Ring, + IN PXENVBD_REQUEST Request + ); + +extern VOID +RingKick( + IN PXENVBD_RING Ring + ); + +extern VOID +RingTrigger( + IN PXENVBD_RING Ring + ); + +extern VOID +RingSend( + IN PXENVBD_RING Ring + ); + +#endif // _XENVBD_RING_H diff --git a/src/xenvbd/target.c b/src/xenvbd/target.c index 697f309..c0fa4e9 100644 --- a/src/xenvbd/target.c +++ b/src/xenvbd/target.c @@ -1063,8 +1063,7 @@ __TargetPauseDataPath( KIRQL Irql; ULONG Requests; ULONG Count = 0; - PXENVBD_NOTIFIER Notifier = FrontendGetNotifier(Target->Frontend); - PXENVBD_BLOCKRING BlockRing = FrontendGetBlockRing(Target->Frontend); + PXENVBD_RING Ring = FrontendGetRing(Target->Frontend); KeAcquireSpinLock(&Target->Lock, &Irql); ++Target->Paused; @@ -1080,9 +1079,9 @@ __TargetPauseDataPath( if (Timeout && Count > 180000) break; KeRaiseIrql(DISPATCH_LEVEL, &Irql); - BlockRingPoll(BlockRing); + RingPoll(Ring); KeLowerIrql(Irql); - NotifierSend(Notifier); // let backend know it needs to do some work + RingSend(Ring); // let backend know it needs to do some work StorPortStallExecution(1000); // 1000 micro-seconds ++Count; } @@ -1180,7 +1179,7 @@ TargetSubmitPrepared( __in PXENVBD_TARGET Target ) { - PXENVBD_BLOCKRING BlockRing = FrontendGetBlockRing(Target->Frontend); + PXENVBD_RING Ring = FrontendGetRing(Target->Frontend); if (TargetIsPaused(Target)) { if (QueueCount(&Target->PreparedReqs)) Warning("Target[%d] : Paused, not submitting new requests (%u)\n", @@ -1202,7 +1201,7 @@ TargetSubmitPrepared( QueueAppend(&Target->SubmittedReqs, &Request->Entry); KeMemoryBarrier(); - if (BlockRingSubmit(BlockRing, Request)) + if (RingSubmit(Ring, Request)) continue; QueueRemove(&Target->SubmittedReqs, &Request->Entry); @@ -1393,7 +1392,7 @@ TargetReadWrite( { PXENVBD_DISKINFO DiskInfo = FrontendGetDiskInfo(Target->Frontend); PXENVBD_SRBEXT SrbExt = GetSrbExt(Srb); - PXENVBD_NOTIFIER Notifier = FrontendGetNotifier(Target->Frontend); + PXENVBD_RING Ring = FrontendGetRing(Target->Frontend); if (FrontendGetCaps(Target->Frontend)->Connected == FALSE) { Trace("Target[%d] : Not Ready, fail SRB\n", TargetGetTargetId(Target)); @@ -1409,7 +1408,7 @@ TargetReadWrite( } QueueAppend(&Target->FreshSrbs, &SrbExt->Entry); - NotifierKick(Notifier); + RingKick(Ring); return FALSE; } @@ -1422,7 +1421,7 @@ TargetSyncCache( ) { PXENVBD_SRBEXT SrbExt = GetSrbExt(Srb); - PXENVBD_NOTIFIER Notifier = FrontendGetNotifier(Target->Frontend); + PXENVBD_RING Ring = FrontendGetRing(Target->Frontend); if (FrontendGetCaps(Target->Frontend)->Connected == FALSE) { Trace("Target[%d] : Not Ready, fail SRB\n", TargetGetTargetId(Target)); @@ -1439,7 +1438,7 @@ TargetSyncCache( } QueueAppend(&Target->FreshSrbs, &SrbExt->Entry); - NotifierKick(Notifier); + RingKick(Ring); return FALSE; } @@ -1452,7 +1451,7 @@ TargetUnmap( ) { PXENVBD_SRBEXT SrbExt = GetSrbExt(Srb); - PXENVBD_NOTIFIER Notifier = FrontendGetNotifier(Target->Frontend); + PXENVBD_RING Ring = FrontendGetRing(Target->Frontend); if (FrontendGetCaps(Target->Frontend)->Connected == FALSE) { Trace("Target[%d] : Not Ready, fail SRB\n", TargetGetTargetId(Target)); @@ -1468,7 +1467,7 @@ TargetUnmap( } QueueAppend(&Target->FreshSrbs, &SrbExt->Entry); - NotifierKick(Notifier); + RingKick(Ring); return FALSE; } @@ -1893,7 +1892,7 @@ TargetFlush( ) { QueueAppend(&Target->ShutdownSrbs, &SrbExt->Entry); - NotifierKick(FrontendGetNotifier(Target->Frontend)); + RingKick(FrontendGetRing(Target->Frontend)); } VOID @@ -1903,7 +1902,7 @@ TargetShutdown( ) { QueueAppend(&Target->ShutdownSrbs, &SrbExt->Entry); - NotifierKick(FrontendGetNotifier(Target->Frontend)); + RingKick(FrontendGetRing(Target->Frontend)); } VOID diff --git a/vs2015/xenvbd/xenvbd.vcxproj b/vs2015/xenvbd/xenvbd.vcxproj index f5b9cf7..82749ad 100644 --- a/vs2015/xenvbd/xenvbd.vcxproj +++ b/vs2015/xenvbd/xenvbd.vcxproj @@ -73,8 +73,7 @@ <ClCompile Include="../../src/xenvbd/pdoinquiry.c" /> <ClCompile Include="../../src/xenvbd/queue.c" /> <ClCompile Include="../../src/xenvbd/thread.c" /> - <ClCompile Include="../../src/xenvbd/notifier.c" /> - <ClCompile Include="../../src/xenvbd/blockring.c" /> + <ClCompile Include="../../src/xenvbd/ring.c" /> <ClCompile Include="../../src/xenvbd/granter.c" /> </ItemGroup> <ItemGroup> -- 2.8.3 _______________________________________________ win-pv-devel mailing list win-pv-devel@xxxxxxxxxxxxxxxxxxxx https://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |