|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [win-pv-devel] [PATCH 06/26] Refactor target.c
From: Owen Smith <owen.smith@xxxxxxxxxx>
Signed-off-by: Owen Smith <owen.smith@xxxxxxxxxx>
---
src/xenvbd/adapter.c | 52 +-
src/xenvbd/blockring.c | 783 +++++---
src/xenvbd/blockring.h | 46 +-
src/xenvbd/frontend.c | 1769 -----------------
src/xenvbd/frontend.h | 198 --
src/xenvbd/granter.c | 167 +-
src/xenvbd/granter.h | 48 +-
src/xenvbd/notifier.c | 334 ----
src/xenvbd/notifier.h | 101 -
src/xenvbd/pdoinquiry.c | 530 -----
src/xenvbd/pdoinquiry.h | 64 -
src/xenvbd/queue.c | 139 --
src/xenvbd/queue.h | 86 -
src/xenvbd/srbext.h | 53 +-
src/xenvbd/target.c | 4370 +++++++++++++++++++++++-------------------
src/xenvbd/target.h | 188 +-
vs2012/xenvbd/xenvbd.vcxproj | 4 -
vs2013/xenvbd/xenvbd.vcxproj | 4 -
vs2015/xenvbd/xenvbd.vcxproj | 4 -
19 files changed, 3164 insertions(+), 5776 deletions(-)
delete mode 100644 src/xenvbd/frontend.c
delete mode 100644 src/xenvbd/frontend.h
delete mode 100644 src/xenvbd/notifier.c
delete mode 100644 src/xenvbd/notifier.h
delete mode 100644 src/xenvbd/pdoinquiry.c
delete mode 100644 src/xenvbd/pdoinquiry.h
delete mode 100644 src/xenvbd/queue.c
delete mode 100644 src/xenvbd/queue.h
diff --git a/src/xenvbd/adapter.c b/src/xenvbd/adapter.c
index 3c5229b..4ce9711 100644
--- a/src/xenvbd/adapter.c
+++ b/src/xenvbd/adapter.c
@@ -111,7 +111,8 @@ __AdapterFree(
IN PVOID Buffer
)
{
- ExFreePoolWithTag(Buffer, ADAPTER_POOL_TAG);
+ if (Buffer)
+ ExFreePoolWithTag(Buffer, ADAPTER_POOL_TAG);
}
static FORCEINLINE PANSI_STRING
@@ -449,7 +450,7 @@ __AdapterEnumerate(
}
}
- if (Missing && !TargetIsMissing(Target)) {
+ if (Missing && !TargetGetMissing(Target)) {
TargetSetMissing(Target, "Device Disappeared");
if (TargetGetDevicePnpState(Target) == Present)
TargetSetDevicePnpState(Target, Deleted);
@@ -480,7 +481,7 @@ __AdapterEnumerate(
continue;
status = TargetCreate(Adapter,
- Device->Buffer,
+ Device,
&Target);
if (status == STATUS_RETRY)
NeedReboot = TRUE;
@@ -881,7 +882,6 @@ AdapterDebugCallback(
)
{
PXENVBD_ADAPTER Adapter = Context;
- ULONG TargetId;
XENBUS_DEBUG(Printf,
&Adapter->DebugInterface,
@@ -911,24 +911,6 @@ AdapterDebugCallback(
Adapter->Completed);
BufferDebugCallback(&Adapter->DebugInterface);
-
- for (TargetId = 0; TargetId < XENVBD_MAX_TARGETS; ++TargetId) {
- // no need to use AdapterGetTarget (which is locked at DISPATCH) as
called at HIGH_LEVEL
- PXENVBD_TARGET Target = Adapter->TargetList[TargetId];
- if (Target == NULL)
- continue;
-
- XENBUS_DEBUG(Printf, &Adapter->DebugInterface,
- "ADAPTER: ====> Target[%-3d] : 0x%p\n",
- TargetId, Target);
-
- // call Target's debug callback directly
- TargetDebugCallback(Target, &Adapter->DebugInterface);
-
- XENBUS_DEBUG(Printf, &Adapter->DebugInterface,
- "ADAPTER: <==== Target[%-3d] : 0x%p\n",
- TargetId, Target);
- }
}
static NTSTATUS
@@ -1476,13 +1458,27 @@ __AdapterSrbPnp(
IN PSCSI_PNP_REQUEST_BLOCK Srb
)
{
- if (!(Srb->SrbPnPFlags & SRB_PNP_FLAGS_ADAPTER_REQUEST)) {
- PXENVBD_TARGET Target;
+ PXENVBD_TARGET Target;
- Target = AdapterGetTarget(Adapter, Srb->TargetId);
- if (Target) {
- TargetSrbPnp(Target, Srb);
- }
+ if (Srb->SrbPnPFlags & SRB_PNP_FLAGS_ADAPTER_REQUEST)
+ return;
+
+ Target = AdapterGetTarget(Adapter, Srb->TargetId);
+ if (Target == NULL)
+ return;
+
+ switch (Srb->PnPAction) {
+ case StorQueryCapabilities: {
+ PSTOR_DEVICE_CAPABILITIES DeviceCaps = Srb->DataBuffer;
+
+ DeviceCaps->Removable = TargetGetRemovable(Target);
+ DeviceCaps->EjectSupported = TargetGetRemovable(Target);
+ DeviceCaps->SurpriseRemovalOK = TargetGetRemovable(Target);
+ DeviceCaps->UniqueID = 1;
+
+ } break;
+ default:
+ break;
}
}
diff --git a/src/xenvbd/blockring.c b/src/xenvbd/blockring.c
index bcef877..dac03b5 100644
--- a/src/xenvbd/blockring.c
+++ b/src/xenvbd/blockring.c
@@ -29,227 +29,218 @@
* SUCH DAMAGE.
*/
+#include <ntddk.h>
+#include <ntstrsafe.h>
+#include <stdlib.h>
+
+#include <xen.h>
+#include <gnttab_interface.h>
+#include <debug_interface.h>
+#include <evtchn_interface.h>
+
#include "blockring.h"
-#include "frontend.h"
#include "target.h"
#include "adapter.h"
+#include "granter.h"
+#include "adapter.h"
+
#include "util.h"
#include "debug.h"
-#include "srbext.h"
-#include "driver.h"
-#include <stdlib.h>
-#include <xenvbd-ntstrsafe.h>
+#include "assert.h"
-#define TAG_HEADER 'gaTX'
+#define XEN_IO_PROTO_ABI "x86_64-abi"
#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;
+ PXENVBD_TARGET Target;
+ BOOLEAN Connected;
+ BOOLEAN Enabled;
+
+ XENBUS_STORE_INTERFACE StoreInterface;
+ XENBUS_DEBUG_INTERFACE DebugInterface;
+ XENBUS_EVTCHN_INTERFACE EvtchnInterface;
+
+ 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;
+
+ ULONG Submitted;
+ ULONG Completed;
+ ULONG Interrupts;
+ ULONG Dpcs;
};
-#define MAX_NAME_LEN 64
-#define BLOCKRING_POOL_TAG 'gnRX'
-
-#define XEN_IO_PROTO_ABI "x86_64-abi"
+#define BLOCKRING_POOL_TAG 'gnRX'
+#define xen_mb KeMemoryBarrier
+#define xen_wmb KeMemoryBarrier
+#define xen_rmb KeMemoryBarrier
static FORCEINLINE PVOID
__BlockRingAllocate(
- IN ULONG Length
+ IN ULONG Size
)
{
- return __AllocatePoolWithTag(NonPagedPool, Length, BLOCKRING_POOL_TAG);
+ PVOID Buffer;
+ Buffer = ExAllocatePoolWithTag(NonPagedPool,
+ Size,
+ BLOCKRING_POOL_TAG);
+ if (Buffer)
+ RtlZeroMemory(Buffer, Size);
+ return Buffer;
}
static FORCEINLINE VOID
__BlockRingFree(
- IN PVOID Buffer
+ IN PVOID Buffer
)
{
if (Buffer)
- __FreePoolWithTag(Buffer, BLOCKRING_POOL_TAG);
-}
-
-static FORCEINLINE VOID
-xen_mb()
-{
- KeMemoryBarrier();
- _ReadWriteBarrier();
+ ExFreePoolWithTag(Buffer, BLOCKRING_POOL_TAG);
}
-static FORCEINLINE VOID
-xen_wmb()
-{
- KeMemoryBarrier();
- _WriteBarrier();
-}
+KSERVICE_ROUTINE BlockRingInterrupt;
-static FORCEINLINE PFN_NUMBER
-__Pfn(
- __in PVOID VirtAddr
+BOOLEAN
+BlockRingInterrupt(
+ __in PKINTERRUPT Interrupt,
+ _In_opt_ PVOID Context
)
{
- return (PFN_NUMBER)(ULONG_PTR)(MmGetPhysicalAddress(VirtAddr).QuadPart >>
PAGE_SHIFT);
-}
+ PXENVBD_BLOCKRING BlockRing = Context;
+
+ UNREFERENCED_PARAMETER(Interrupt);
-static FORCEINLINE ULONG64
-__BlockRingGetTag(
- IN PXENVBD_BLOCKRING BlockRing,
- IN PXENVBD_REQUEST Request
- )
-{
- UNREFERENCED_PARAMETER(BlockRing);
- return ((ULONG64)TAG_HEADER << 32) | (ULONG64)Request->Id;
+ ASSERT(BlockRing != NULL);
+
+ ++BlockRing->Interrupts;
+ if (KeInsertQueueDpc(&BlockRing->Dpc, NULL, NULL))
+ ++BlockRing->Dpcs;
+
+ return TRUE;
}
-static FORCEINLINE BOOLEAN
-__BlockRingPutTag(
- IN PXENVBD_BLOCKRING BlockRing,
- IN ULONG64 Id,
- OUT PULONG Tag
+KDEFERRED_ROUTINE BlockRingDpc;
+
+VOID
+BlockRingDpc(
+ __in PKDPC Dpc,
+ __in_opt PVOID Context,
+ __in_opt PVOID Arg1,
+ __in_opt PVOID Arg2
)
{
- ULONG Header = (ULONG)((Id >> 32) & 0xFFFFFFFF);
+ PXENVBD_BLOCKRING BlockRing = Context;
- UNREFERENCED_PARAMETER(BlockRing);
+ UNREFERENCED_PARAMETER(Dpc);
+ UNREFERENCED_PARAMETER(Arg1);
+ UNREFERENCED_PARAMETER(Arg2);
- *Tag = (ULONG)(Id & 0xFFFFFFFF);
- if (Header != TAG_HEADER) {
- Error("PUT_TAG (%llx) TAG_HEADER (%08x%08x)\n", Id, Header, *Tag);
- return FALSE;
- }
+ ASSERT(BlockRing != NULL);
- return TRUE;
+ (VOID) BlockRingPoll(BlockRing);
+
+ XENBUS_EVTCHN(Unmask,
+ &BlockRing->EvtchnInterface,
+ BlockRing->Channel,
+ FALSE);
}
-static FORCEINLINE VOID
-__BlockRingInsert(
- IN PXENVBD_BLOCKRING BlockRing,
- IN PXENVBD_REQUEST Request,
- IN blkif_request_t* req
+static DECLSPEC_NOINLINE VOID
+BlockRingDebugCallback(
+ IN PVOID Context,
+ IN BOOLEAN Crashing
)
{
- PXENVBD_GRANTER Granter =
FrontendGetGranter(BlockRing->Frontend);
+ PXENVBD_BLOCKRING BlockRing = Context;
+ PXENVBD_GRANTER Granter;
+ ULONG Port;
+ ULONG Grant;
+ ULONG Index;
- 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);
+ UNREFERENCED_PARAMETER(Crashing);
- 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;
+ XENBUS_DEBUG(Printf,
+ &BlockRing->DebugInterface,
+ "Order: %u\n",
+ BlockRing->Order);
- 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;
+ Granter = TargetGetGranter(BlockRing->Target);
+ for (Index = 0; Index < (1ul << BlockRing->Order); ++Index) {
+ Grant = GranterReference(Granter, BlockRing->Grants[Index]);
- default:
- ASSERT(FALSE);
- break;
+ XENBUS_DEBUG(Printf,
+ &BlockRing->DebugInterface,
+ "Grant[%02u] : 0x%p (%u)\n",
+ Index,
+ BlockRing->Grants[Index],
+ Grant);
}
- ++BlockRing->Submitted;
+
+ XENBUS_DEBUG(Printf,
+ &BlockRing->DebugInterface,
+ "Shared:0x%p : req_prod:%u, req_event:%u, rsp_prod:%u,
rsp_event:%u\n",
+ BlockRing->Shared,
+ BlockRing->Shared->req_prod,
+ BlockRing->Shared->req_event,
+ BlockRing->Shared->rsp_prod,
+ BlockRing->Shared->rsp_event);
+
+ XENBUS_DEBUG(Printf,
+ &BlockRing->DebugInterface,
+ "Front: req_prod_pvt:%u, rsp_cons:%u, nr_ents:%u,
sring:0x%p\n",
+ BlockRing->Front.req_prod_pvt,
+ BlockRing->Front.rsp_cons,
+ BlockRing->Front.nr_ents,
+ BlockRing->Front.sring);
+
+ XENBUS_DEBUG(Printf,
+ &BlockRing->DebugInterface,
+ "Submitted: %u, Completed: %u\n",
+ BlockRing->Submitted,
+ BlockRing->Completed);
+
+ Port = XENBUS_EVTCHN(GetPort,
+ &BlockRing->EvtchnInterface,
+ BlockRing->Channel);
+
+ XENBUS_DEBUG(Printf,
+ &BlockRing->DebugInterface,
+ "Channel: 0x%p (%u)\n",
+ BlockRing->Channel,
+ Port);
+
+ XENBUS_DEBUG(Printf,
+ &BlockRing->DebugInterface,
+ "Interrupts: %u, DPCs: %u\n",
+ BlockRing->Interrupts,
+ BlockRing->Dpcs);
+
+ BlockRing->Interrupts = 0;
+ BlockRing->Dpcs = 0;
}
NTSTATUS
BlockRingCreate(
- IN PXENVBD_FRONTEND Frontend,
- IN ULONG DeviceId,
- OUT PXENVBD_BLOCKRING* BlockRing
+ IN PXENVBD_TARGET Target,
+ OUT PXENVBD_BLOCKRING* BlockRing
)
{
*BlockRing = __BlockRingAllocate(sizeof(XENVBD_BLOCKRING));
if (*BlockRing == NULL)
goto fail1;
- (*BlockRing)->Frontend = Frontend;
- (*BlockRing)->DeviceId = DeviceId;
+ (*BlockRing)->Target = Target;
KeInitializeSpinLock(&(*BlockRing)->Lock);
+ KeInitializeDpc(&(*BlockRing)->Dpc, BlockRingDpc, *BlockRing);
return STATUS_SUCCESS;
@@ -259,12 +250,12 @@ fail1:
VOID
BlockRingDestroy(
- IN PXENVBD_BLOCKRING BlockRing
+ IN PXENVBD_BLOCKRING BlockRing
)
{
- BlockRing->Frontend = NULL;
- BlockRing->DeviceId = 0;
+ BlockRing->Target = NULL;
RtlZeroMemory(&BlockRing->Lock, sizeof(KSPIN_LOCK));
+ RtlZeroMemory(&BlockRing->Dpc, sizeof(KDPC));
ASSERT(IsZeroMemory(BlockRing, sizeof(XENVBD_BLOCKRING)));
@@ -273,122 +264,201 @@ BlockRingDestroy(
NTSTATUS
BlockRingConnect(
- IN PXENVBD_BLOCKRING BlockRing
+ IN PXENVBD_BLOCKRING BlockRing
)
{
- NTSTATUS status;
- PCHAR Value;
- ULONG Index, RingPages;
- PXENVBD_ADAPTER Adapter =
TargetGetAdapter(FrontendGetTarget(BlockRing->Frontend));
- PXENVBD_GRANTER Granter = FrontendGetGranter(BlockRing->Frontend);
+ PXENVBD_GRANTER Granter;
+ PXENVBD_ADAPTER Adapter;
+ PCHAR Buffer;
+ ULONG Index;
+ NTSTATUS status;
ASSERT(BlockRing->Connected == FALSE);
+ Adapter = TargetGetAdapter(BlockRing->Target);
+
AdapterGetStoreInterface(Adapter, &BlockRing->StoreInterface);
-
+ AdapterGetDebugInterface(Adapter, &BlockRing->DebugInterface);
+ AdapterGetEvtchnInterface(Adapter, &BlockRing->EvtchnInterface);
+
status = XENBUS_STORE(Acquire, &BlockRing->StoreInterface);
if (!NT_SUCCESS(status))
goto fail1;
- status = FrontendStoreReadBackend(BlockRing->Frontend,
"max-ring-page-order", &Value);
+ status = XENBUS_DEBUG(Acquire, &BlockRing->DebugInterface);
+ if (!NT_SUCCESS(status))
+ goto fail2;
+
+ status = XENBUS_EVTCHN(Acquire, &BlockRing->EvtchnInterface);
+ if (!NT_SUCCESS(status))
+ goto fail3;
+
+ status = XENBUS_STORE(Read,
+ &BlockRing->StoreInterface,
+ NULL,
+ TargetGetBackendPath(BlockRing->Target),
+ "max-ring-page-order",
+ &Buffer);
if (NT_SUCCESS(status)) {
- BlockRing->Order = __min(strtoul(Value, NULL, 10),
XENVBD_MAX_RING_PAGE_ORDER);
- FrontendStoreFree(BlockRing->Frontend, Value);
+ BlockRing->Order = strtoul(Buffer, NULL, 10);
+ BlockRing->Order = min(BlockRing->Order, XENVBD_MAX_RING_PAGE_ORDER);
+
+ XENBUS_STORE(Free,
+ &BlockRing->StoreInterface,
+ Buffer);
} else {
BlockRing->Order = 0;
}
- BlockRing->Mdl = __AllocatePages(1 << BlockRing->Order);
-
status = STATUS_NO_MEMORY;
+ BlockRing->Mdl = __AllocatePages(1 << BlockRing->Order);
if (BlockRing->Mdl == NULL)
- goto fail2;
+ goto fail4;
- BlockRing->SharedRing = MmGetSystemAddressForMdlSafe(BlockRing->Mdl,
- NormalPagePriority);
- ASSERT(BlockRing->SharedRing != NULL);
+ BlockRing->Shared = MmGetSystemAddressForMdlSafe(BlockRing->Mdl,
NormalPagePriority);
+ ASSERT(BlockRing->Shared != 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);
+ SHARED_RING_INIT(BlockRing->Shared);
+ FRONT_RING_INIT(&BlockRing->Front, BlockRing->Shared, 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]);
+ Granter = TargetGetGranter(BlockRing->Target);
+ for (Index = 0; Index < (1ul << BlockRing->Order); ++Index) {
+ status = GranterGet(Granter,
+ MmGetMdlPfnArray(BlockRing->Mdl)[Index],
+ FALSE,
+ &BlockRing->Grants[Index]);
if (!NT_SUCCESS(status))
- goto fail3;
+ goto fail5;
}
+ status = STATUS_NO_MEMORY;
+ BlockRing->Channel = XENBUS_EVTCHN(Open,
+ &BlockRing->EvtchnInterface,
+ XENBUS_EVTCHN_TYPE_UNBOUND,
+ BlockRingInterrupt,
+ BlockRing,
+ TargetGetBackendId(BlockRing->Target),
+ TRUE);
+ if (BlockRing->Channel == NULL)
+ goto fail6;
+
+ status = XENBUS_DEBUG(Register,
+ &BlockRing->DebugInterface,
+ __MODULE__,
+ BlockRingDebugCallback,
+ BlockRing,
+ &BlockRing->DebugCallback);
+ if (!NT_SUCCESS(status))
+ goto fail7;
+
+ XENBUS_EVTCHN(Unmask,
+ &BlockRing->EvtchnInterface,
+ BlockRing->Channel,
+ FALSE);
+
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;
+fail7:
+ Error("fail7\n");
+ XENBUS_EVTCHN(Close,
+ &BlockRing->EvtchnInterface,
+ BlockRing->Channel);
+ BlockRing->Channel = NULL;
+fail6:
+ Error("fail6\n");
+fail5:
+ Error("fail5\n");
+ for (Index = 0; Index < (1ul << BlockRing->Order); ++Index) {
+ if (BlockRing->Grants[Index] == NULL)
+ continue;
+
+ GranterPut(Granter, BlockRing->Grants[Index]);
+ BlockRing->Grants[Index] = NULL;
}
- RtlZeroMemory(&BlockRing->FrontRing, sizeof(BlockRing->FrontRing));
+ RtlZeroMemory(&BlockRing->Front, sizeof(blkif_front_ring_t));
+ BlockRing->Shared = NULL;
+
__FreePages(BlockRing->Mdl);
- BlockRing->SharedRing = NULL;
BlockRing->Mdl = NULL;
-
+fail4:
+ Error("fail4\n");
+ XENBUS_EVTCHN(Release, &BlockRing->EvtchnInterface);
+ RtlZeroMemory(&BlockRing->EvtchnInterface,
sizeof(XENBUS_EVTCHN_INTERFACE));
+fail3:
+ Error("fail3\n");
+ XENBUS_DEBUG(Release, &BlockRing->DebugInterface);
+ RtlZeroMemory(&BlockRing->DebugInterface, sizeof(XENBUS_DEBUG_INTERFACE));
fail2:
+ Error("fail2\n");
+ XENBUS_STORE(Release, &BlockRing->StoreInterface);
+ RtlZeroMemory(&BlockRing->StoreInterface, sizeof(XENBUS_STORE_INTERFACE));
fail1:
- return status;
+ Error("fail1 %08x\n", status);
+ return status;
}
NTSTATUS
BlockRingStoreWrite(
- IN PXENVBD_BLOCKRING BlockRing,
- IN PXENBUS_STORE_TRANSACTION Transaction,
- IN PCHAR FrontendPath
+ IN PXENVBD_BLOCKRING BlockRing,
+ IN PVOID Transaction
)
{
- PXENVBD_GRANTER Granter =
FrontendGetGranter(BlockRing->Frontend);
- NTSTATUS status;
+ PXENVBD_GRANTER Granter;
+ ULONG Port;
+ ULONG Grant;
+ NTSTATUS status;
+ Granter = TargetGetGranter(BlockRing->Target);
if (BlockRing->Order == 0) {
+ Grant = GranterReference(Granter, BlockRing->Grants[0]);
+
status = XENBUS_STORE(Printf,
&BlockRing->StoreInterface,
Transaction,
- FrontendPath,
+ TargetGetPath(BlockRing->Target),
"ring-ref",
"%u",
- GranterReference(Granter, BlockRing->Grants[0]));
+ Grant);
if (!NT_SUCCESS(status))
return status;
} else {
- ULONG Index, RingPages;
+ ULONG Index;
status = XENBUS_STORE(Printf,
&BlockRing->StoreInterface,
Transaction,
- FrontendPath,
+ TargetGetPath(BlockRing->Target),
"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);
+ for (Index = 0; Index < (1ul << BlockRing->Order); ++Index) {
+ CHAR Name[sizeof("ring-refXX")];
+
+ status = RtlStringCbPrintfA(Name,
+ sizeof(Name),
+ "ring-ref%u",
+ Index);
if (!NT_SUCCESS(status))
return status;
+
+ Grant = GranterReference(Granter, BlockRing->Grants[Index]);
+
status = XENBUS_STORE(Printf,
&BlockRing->StoreInterface,
Transaction,
- FrontendPath,
+ TargetGetPath(BlockRing->Target),
Name,
"%u",
- GranterReference(Granter,
BlockRing->Grants[Index]));
+ Grant);
if (!NT_SUCCESS(status))
return status;
}
@@ -397,28 +467,46 @@ BlockRingStoreWrite(
status = XENBUS_STORE(Printf,
&BlockRing->StoreInterface,
Transaction,
- FrontendPath,
+ TargetGetPath(BlockRing->Target),
"protocol",
+ "%s",
XEN_IO_PROTO_ABI);
if (!NT_SUCCESS(status))
return status;
+ Port = XENBUS_EVTCHN(GetPort,
+ &BlockRing->EvtchnInterface,
+ BlockRing->Channel);
+
+ status = XENBUS_STORE(Printf,
+ &BlockRing->StoreInterface,
+ Transaction,
+ TargetGetPath(BlockRing->Target),
+ "event-channel",
+ "%u",
+ Port);
+ if (!NT_SUCCESS(status))
+ return status;
+
return STATUS_SUCCESS;
}
VOID
BlockRingEnable(
- IN PXENVBD_BLOCKRING BlockRing
+ IN PXENVBD_BLOCKRING BlockRing
)
{
ASSERT(BlockRing->Enabled == FALSE);
-
BlockRing->Enabled = TRUE;
+
+ XENBUS_EVTCHN(Trigger,
+ &BlockRing->EvtchnInterface,
+ BlockRing->Channel);
}
VOID
BlockRingDisable(
- IN PXENVBD_BLOCKRING BlockRing
+ IN PXENVBD_BLOCKRING BlockRing
)
{
ASSERT(BlockRing->Enabled == TRUE);
@@ -428,30 +516,44 @@ BlockRingDisable(
VOID
BlockRingDisconnect(
- IN PXENVBD_BLOCKRING BlockRing
+ IN PXENVBD_BLOCKRING BlockRing
)
{
- ULONG Index;
- PXENVBD_GRANTER Granter = FrontendGetGranter(BlockRing->Frontend);
+ PXENVBD_GRANTER Granter;
+ ULONG Index;
ASSERT(BlockRing->Connected == TRUE);
- BlockRing->Submitted = 0;
- BlockRing->Received = 0;
+ XENBUS_DEBUG(Deregister,
+ &BlockRing->DebugInterface,
+ BlockRing->DebugCallback);
+ BlockRing->DebugCallback = NULL;
- for (Index = 0; Index < XENVBD_MAX_RING_PAGES; ++Index) {
- if (BlockRing->Grants[Index]) {
- GranterPut(Granter, BlockRing->Grants[Index]);
- }
- BlockRing->Grants[Index] = 0;
+ XENBUS_EVTCHN(Close,
+ &BlockRing->EvtchnInterface,
+ BlockRing->Channel);
+ BlockRing->Channel = NULL;
+
+ Granter = TargetGetGranter(BlockRing->Target);
+ for (Index = 0; Index < (1ul << BlockRing->Order); ++Index) {
+ if (BlockRing->Grants[Index] == NULL)
+ continue;
+
+ GranterPut(Granter, BlockRing->Grants[Index]);
+ BlockRing->Grants[Index] = NULL;
}
- RtlZeroMemory(&BlockRing->FrontRing, sizeof(BlockRing->FrontRing));
+ RtlZeroMemory(&BlockRing->Front, sizeof(blkif_front_ring_t));
+ BlockRing->Shared = NULL;
+
__FreePages(BlockRing->Mdl);
- BlockRing->SharedRing = NULL;
BlockRing->Mdl = NULL;
- BlockRing->Order = 0;
+ XENBUS_EVTCHN(Release, &BlockRing->EvtchnInterface);
+ RtlZeroMemory(&BlockRing->EvtchnInterface,
sizeof(XENBUS_EVTCHN_INTERFACE));
+
+ XENBUS_DEBUG(Release, &BlockRing->DebugInterface);
+ RtlZeroMemory(&BlockRing->DebugInterface, sizeof(XENBUS_DEBUG_INTERFACE));
XENBUS_STORE(Release, &BlockRing->StoreInterface);
RtlZeroMemory(&BlockRing->StoreInterface, sizeof(XENBUS_STORE_INTERFACE));
@@ -459,60 +561,11 @@ BlockRingDisconnect(
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;
-}
-
-VOID
+ULONG
BlockRingPoll(
- IN PXENVBD_BLOCKRING BlockRing
+ IN PXENVBD_BLOCKRING BlockRing
)
{
- PXENVBD_TARGET Target = FrontendGetTarget(BlockRing->Frontend);
-
ASSERT3U(KeGetCurrentIrql(), ==, DISPATCH_LEVEL);
KeAcquireSpinLockAtDpcLevel(&BlockRing->Lock);
@@ -527,8 +580,8 @@ BlockRingPoll(
KeMemoryBarrier();
- rsp_prod = BlockRing->SharedRing->rsp_prod;
- rsp_cons = BlockRing->FrontRing.rsp_cons;
+ rsp_prod = BlockRing->Shared->rsp_prod;
+ rsp_cons = BlockRing->Front.rsp_cons;
KeMemoryBarrier();
@@ -536,56 +589,170 @@ BlockRingPoll(
break;
while (rsp_cons != rsp_prod) {
- 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);
+ blkif_response_t* rsp;
+
+ rsp = RING_GET_RESPONSE(&BlockRing->Front, rsp_cons);
+ if (rsp->id == 0) {
+ Warning("Bad Response (%llu, %u, &d) @ slot %u\n",
+ rsp->id,
+ rsp->operation,
+ rsp->status,
+ rsp_cons & (RING_SIZE(&BlockRing->Front) - 1));
+ // dump submitted reqs?
+ } else {
+ TargetCompleteResponse(BlockRing->Target,
+ rsp->id,
+ rsp->status);
+ ++BlockRing->Completed;
}
+ ++rsp_cons;
- RtlZeroMemory(Response, sizeof(union blkif_sring_entry));
+ RtlZeroMemory(rsp, sizeof(union blkif_sring_entry));
}
KeMemoryBarrier();
- BlockRing->FrontRing.rsp_cons = rsp_cons;
- BlockRing->SharedRing->rsp_event = rsp_cons + 1;
+ BlockRing->Front.rsp_cons = rsp_cons;
+ BlockRing->Shared->rsp_event = rsp_cons + 1;
}
done:
KeReleaseSpinLockFromDpcLevel(&BlockRing->Lock);
+
+ // submit all prepared requests, prepare the next srb
+ TargetSubmitRequests(BlockRing->Target);
+
+ return BlockRing->Submitted - BlockRing->Completed;
}
BOOLEAN
BlockRingSubmit(
- IN PXENVBD_BLOCKRING BlockRing,
- IN PXENVBD_REQUEST Request
+ IN PXENVBD_BLOCKRING BlockRing,
+ IN PXENVBD_REQUEST Request
)
{
- KIRQL Irql;
- blkif_request_t* req;
- BOOLEAN Notify;
+ PLIST_ENTRY ListEntry;
+ ULONG Index;
+ PXENVBD_GRANTER Granter;
+ KIRQL Irql;
+ blkif_request_t* req;
+ BOOLEAN Notify;
KeAcquireSpinLock(&BlockRing->Lock, &Irql);
- if (RING_FULL(&BlockRing->FrontRing)) {
+ if (RING_FULL(&BlockRing->Front)) {
KeReleaseSpinLock(&BlockRing->Lock, Irql);
return FALSE;
}
- req = RING_GET_REQUEST(&BlockRing->FrontRing,
BlockRing->FrontRing.req_prod_pvt);
- __BlockRingInsert(BlockRing, Request, req);
+ req = RING_GET_REQUEST(&BlockRing->Front, BlockRing->Front.req_prod_pvt);
+ ++BlockRing->Front.req_prod_pvt;
+ ++BlockRing->Submitted;
+
+ Granter = TargetGetGranter(BlockRing->Target);
+ switch (Request->Operation) {
+ case BLKIF_OP_DISCARD: {
+ blkif_request_discard_t* req_d;
+ req_d = (blkif_request_discard_t*)req;
+ req_d->operation = BLKIF_OP_DISCARD;
+ req_d->flag = Request->Flags;
+ req_d->handle = (USHORT)TargetGetDeviceId(BlockRing->Target);
+ req_d->id = Request->Id;
+ req_d->sector_number = Request->FirstSector;
+ req_d->nr_sectors = Request->NrSectors;
+ } break;
+
+ case BLKIF_OP_READ:
+ case BLKIF_OP_WRITE:
+ if (Request->NrSegments > BLKIF_MAX_SEGMENTS_PER_REQUEST) {
+ // Indirect
+ blkif_request_indirect_t* req_i;
+ ULONG PageIdx;
+ ULONG SegIdx;
+ PLIST_ENTRY PageEntry;
+ PLIST_ENTRY SegEntry;
+
+ req_i = (blkif_request_indirect_t*)req;
+ req_i->operation = BLKIF_OP_INDIRECT;
+ req_i->indirect_op = Request->Operation;
+ req_i->nr_segments = Request->NrSegments;
+ req_i->id = Request->Id;
+ req_i->sector_number = Request->FirstSector;
+ req_i->handle =
(USHORT)TargetGetDeviceId(BlockRing->Target);
+
+ PageEntry = Request->Indirects.Flink;
+ SegEntry = Request->Segments.Flink;
+ for (PageIdx = 0; PageIdx < BLKIF_MAX_INDIRECT_PAGES_PER_REQUEST;
++PageIdx) {
+ PXENVBD_INDIRECT Page;
+
+ if (PageEntry != &Request->Indirects)
+ break;
+ if (SegEntry != &Request->Segments)
+ break;
+
+ Page = CONTAINING_RECORD(PageEntry, XENVBD_INDIRECT,
ListEntry);
+ req_i->indirect_grefs[PageIdx] = GranterReference(Granter,
Page->Grant);
+
+ for (SegIdx = 0; SegIdx < XENVBD_MAX_SEGMENTS_PER_PAGE;
++SegIdx) {
+ PXENVBD_SEGMENT Segment;
+
+ if (SegEntry != &Request->Segments)
+ break;
+
+ 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;
+
+ SegEntry = SegEntry->Flink;
+ }
+
+ PageEntry = PageEntry->Flink;
+ }
+ break; // out of switch
+ }
+ // intentional fall through
+ case BLKIF_OP_WRITE_BARRIER:
+ case BLKIF_OP_FLUSH_DISKCACHE:
+ default:
+ req->operation = Request->Operation;
+ req->nr_segments = (UCHAR)Request->NrSegments;
+ req->handle = (USHORT)TargetGetDeviceId(BlockRing->Target);
+ req->id = Request->Id;
+ req->sector_number = Request->FirstSector;
+
+ for (ListEntry = Request->Segments.Flink, Index = 0;
+ ListEntry != &Request->Segments && Index <
BLKIF_MAX_SEGMENTS_PER_REQUEST;
+ ListEntry = ListEntry->Flink, ++Index) {
+ PXENVBD_SEGMENT Segment = CONTAINING_RECORD(ListEntry,
XENVBD_SEGMENT, ListEntry);
+ ULONG Grant;
+
+ Grant = GranterReference(Granter, Segment->Grant);
+
+ req->seg[Index].first_sect = Segment->FirstSector;
+ req->seg[Index].last_sect = Segment->LastSector;
+ req->seg[Index].gref = Grant;
+ }
+ break;
+ }
+
KeMemoryBarrier();
- ++BlockRing->FrontRing.req_prod_pvt;
- RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&BlockRing->FrontRing, Notify);
+ RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&BlockRing->Front, Notify);
KeReleaseSpinLock(&BlockRing->Lock, Irql);
- if (Notify)
- NotifierSend(FrontendGetNotifier(BlockRing->Frontend));
+ if (Notify) {
+ XENBUS_EVTCHN(Send,
+ &BlockRing->EvtchnInterface,
+ BlockRing->Channel);
+ }
return TRUE;
}
+
+VOID
+BlockRingKick(
+ IN PXENVBD_BLOCKRING BlockRing
+ )
+{
+ KeInsertQueueDpc(&BlockRing->Dpc, NULL, NULL);
+}
diff --git a/src/xenvbd/blockring.h b/src/xenvbd/blockring.h
index 1117d73..2660e47 100644
--- a/src/xenvbd/blockring.h
+++ b/src/xenvbd/blockring.h
@@ -32,66 +32,64 @@
#ifndef _XENVBD_BLOCKRING_H
#define _XENVBD_BLOCKRING_H
+#include <ntddk.h>
+
typedef struct _XENVBD_BLOCKRING XENVBD_BLOCKRING, *PXENVBD_BLOCKRING;
-#include "frontend.h"
-#include <debug_interface.h>
-#include <store_interface.h>
+#include "target.h"
+#include "srbext.h"
extern NTSTATUS
BlockRingCreate(
- IN PXENVBD_FRONTEND Frontend,
- IN ULONG DeviceId,
- OUT PXENVBD_BLOCKRING* BlockRing
+ IN PXENVBD_TARGET Target,
+ OUT PXENVBD_BLOCKRING* BlockRing
);
extern VOID
BlockRingDestroy(
- IN PXENVBD_BLOCKRING BlockRing
+ IN PXENVBD_BLOCKRING BlockRing
);
extern NTSTATUS
BlockRingConnect(
- IN PXENVBD_BLOCKRING BlockRing
+ IN PXENVBD_BLOCKRING BlockRing
);
extern NTSTATUS
BlockRingStoreWrite(
- IN PXENVBD_BLOCKRING BlockRing,
- IN PXENBUS_STORE_TRANSACTION Transaction,
- IN PCHAR FrontendPath
+ IN PXENVBD_BLOCKRING BlockRing,
+ IN PVOID Transaction
);
extern VOID
BlockRingEnable(
- IN PXENVBD_BLOCKRING BlockRing
+ IN PXENVBD_BLOCKRING BlockRing
);
extern VOID
BlockRingDisable(
- IN PXENVBD_BLOCKRING BlockRing
+ IN PXENVBD_BLOCKRING BlockRing
);
extern VOID
BlockRingDisconnect(
- IN PXENVBD_BLOCKRING BlockRing
- );
-
-extern VOID
-BlockRingDebugCallback(
- IN PXENVBD_BLOCKRING BlockRing,
- IN PXENBUS_DEBUG_INTERFACE Debug
+ IN PXENVBD_BLOCKRING BlockRing
);
-extern VOID
+extern ULONG
BlockRingPoll(
- IN PXENVBD_BLOCKRING BlockRing
+ IN PXENVBD_BLOCKRING BlockRing
);
extern BOOLEAN
BlockRingSubmit(
- IN PXENVBD_BLOCKRING BlockRing,
- IN PXENVBD_REQUEST Request
+ IN PXENVBD_BLOCKRING BlockRing,
+ IN PXENVBD_REQUEST Request
+ );
+
+extern VOID
+BlockRingKick(
+ IN PXENVBD_BLOCKRING BlockRing
);
#endif // _XENVBD_BLOCKRING_H
diff --git a/src/xenvbd/frontend.c b/src/xenvbd/frontend.c
deleted file mode 100644
index 691ea3a..0000000
--- a/src/xenvbd/frontend.c
+++ /dev/null
@@ -1,1769 +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 <ntddk.h>
-#include <ntstrsafe.h>
-
-#include "frontend.h"
-#include "registry.h"
-#include "driver.h"
-#include "adapter.h"
-#include "pdoinquiry.h"
-#include "srbext.h"
-#include "debug.h"
-#include "assert.h"
-#include "util.h"
-#include "names.h"
-#include "notifier.h"
-#include "blockring.h"
-#include "granter.h"
-#include "thread.h"
-#include <store_interface.h>
-#include <suspend_interface.h>
-
-#include <stdlib.h>
-
-struct _XENVBD_FRONTEND {
- // Frontend
- PXENVBD_TARGET Target;
- ULONG TargetId;
- ULONG DeviceId;
- CHAR FrontendPath[sizeof("device/vbd/XXXXXXXX")];
- PCHAR BackendPath;
- CHAR TargetPath[sizeof("data/scsi/target/XXXX")];
- USHORT BackendId;
- XENVBD_STATE State;
- KSPIN_LOCK StateLock;
-
- XENVBD_CAPS Caps;
- XENVBD_FEATURES Features;
- XENVBD_DISKINFO DiskInfo;
- PVOID Inquiry;
-
- // Interfaces to XenBus
- XENBUS_STORE_INTERFACE StoreInterface;
- XENBUS_SUSPEND_INTERFACE SuspendInterface;
-
- PXENBUS_SUSPEND_CALLBACK SuspendLateCallback;
-
- // Ring
- PXENVBD_NOTIFIER Notifier;
- PXENVBD_BLOCKRING BlockRing;
- PXENVBD_GRANTER Granter;
-
- // Backend State Watch
- BOOLEAN Active;
- PXENVBD_THREAD BackendThread;
- PXENBUS_STORE_WATCH BackendWatch;
-};
-
-#define DOMID_INVALID (0x7FF4U)
-
-static const PCHAR
-__XenvbdStateName(
- IN XENVBD_STATE State
- )
-{
- switch (State) {
- case XENVBD_STATE_INVALID: return "STATE_INVALID";
- case XENVBD_INITIALIZED: return "INITIALIZED";
- case XENVBD_CLOSING: return "CLOSING";
- case XENVBD_CLOSED: return "CLOSED";
- case XENVBD_PREPARED: return "PREPARED";
- case XENVBD_CONNECTED: return "CONNECTED";
- case XENVBD_ENABLED: return "ENABLED";
- default: return "UNKNOWN";
- }
-}
-//=============================================================================
-#define FRONTEND_POOL_TAG 'tnFX'
-__checkReturn
-__drv_allocatesMem(mem)
-__bcount(Size)
-static FORCEINLINE PVOID
-#pragma warning(suppress: 28195)
-__FrontendAlloc(
- __in ULONG Size
- )
-{
- return __AllocatePoolWithTag(NonPagedPool, Size, FRONTEND_POOL_TAG);
-}
-
-static FORCEINLINE VOID
-#pragma warning(suppress: 28197)
-__FrontendFree(
- __in __drv_freesMem(mem) PVOID Buffer
- )
-{
- if (Buffer)
- __FreePoolWithTag(Buffer, FRONTEND_POOL_TAG);
-}
-
-//=============================================================================
-// Accessors
-VOID
-FrontendRemoveFeature(
- IN PXENVBD_FRONTEND Frontend,
- IN UCHAR BlkifOperation
- )
-{
- switch (BlkifOperation) {
- case BLKIF_OP_FLUSH_DISKCACHE:
- Verbose("FLUSH_DISKCACHE\n");
- Frontend->DiskInfo.FlushCache = FALSE;
- break;
- case BLKIF_OP_WRITE_BARRIER:
- Verbose("WRITE_BARRIER\n");
- Frontend->DiskInfo.Barrier = FALSE;
- break;
- case BLKIF_OP_DISCARD:
- Verbose("DISCARD\n");
- Frontend->DiskInfo.Discard = FALSE;
- break;
- case BLKIF_OP_INDIRECT:
- Verbose("INDIRECT\n");
- Frontend->Features.Indirect = 0;
- break;
- default:
- break;
- }
-}
-PXENVBD_CAPS
-FrontendGetCaps(
- __in PXENVBD_FRONTEND Frontend
- )
-{
- return &Frontend->Caps;
-}
-PXENVBD_FEATURES
-FrontendGetFeatures(
- __in PXENVBD_FRONTEND Frontend
- )
-{
- return &Frontend->Features;
-}
-PXENVBD_DISKINFO
-FrontendGetDiskInfo(
- __in PXENVBD_FRONTEND Frontend
- )
-{
- return &Frontend->DiskInfo;
-}
-ULONG
-FrontendGetTargetId(
- __in PXENVBD_FRONTEND Frontend
- )
-{
- return Frontend->TargetId;
-}
-ULONG
-FrontendGetDeviceId(
- __in PXENVBD_FRONTEND Frontend
- )
-{
- return Frontend->DeviceId;
-}
-PVOID
-FrontendGetInquiry(
- __in PXENVBD_FRONTEND Frontend
- )
-{
- return Frontend->Inquiry;
-}
-PXENVBD_TARGET
-FrontendGetTarget(
- __in PXENVBD_FRONTEND Frontend
- )
-{
- return Frontend->Target;
-}
-PXENVBD_BLOCKRING
-FrontendGetBlockRing(
- __in PXENVBD_FRONTEND Frontend
- )
-{
- return Frontend->BlockRing;
-}
-PXENVBD_NOTIFIER
-FrontendGetNotifier(
- __in PXENVBD_FRONTEND Frontend
- )
-{
- return Frontend->Notifier;
-}
-PXENVBD_GRANTER
-FrontendGetGranter(
- __in PXENVBD_FRONTEND Frontend
- )
-{
- return Frontend->Granter;
-}
-
-NTSTATUS
-FrontendStoreWriteFrontend(
- __in PXENVBD_FRONTEND Frontend,
- __in PCHAR Name,
- __in PCHAR Value
- )
-{
- return XENBUS_STORE(Printf,
- &Frontend->StoreInterface,
- NULL,
- Frontend->FrontendPath,
- Name,
- Value);
-}
-NTSTATUS
-FrontendStoreReadBackend(
- __in PXENVBD_FRONTEND Frontend,
- __in PCHAR Name,
- __out PCHAR* Value
- )
-{
- NTSTATUS Status;
-
- Status = STATUS_INVALID_PARAMETER;
- if (Frontend->BackendPath == NULL)
- goto fail1;
-
- Status = XENBUS_STORE(Read,
- &Frontend->StoreInterface,
- NULL,
- Frontend->BackendPath,
- Name,
- Value);
- if (!NT_SUCCESS(Status))
- goto fail2;
-
- return STATUS_SUCCESS;
-
-fail2:
-fail1:
- return Status;
-}
-VOID
-FrontendStoreFree(
- __in PXENVBD_FRONTEND Frontend,
- __in PCHAR Value
- )
-{
- XENBUS_STORE(Free,
- &Frontend->StoreInterface,
- Value);
-}
-__drv_maxIRQL(DISPATCH_LEVEL)
-NTSTATUS
-FrontendWriteUsage(
- __in PXENVBD_FRONTEND Frontend
- )
-{
- NTSTATUS Status;
-
- Status = XENBUS_STORE(Printf,
- &Frontend->StoreInterface,
- NULL,
- Frontend->TargetPath,
- "paging",
- "%u",
- Frontend->Caps.Paging);
- if (!NT_SUCCESS(Status))
- goto out;
-
- Status = XENBUS_STORE(Printf,
- &Frontend->StoreInterface,
- NULL,
- Frontend->TargetPath,
- "hibernation",
- "%u",
- Frontend->Caps.Hibernation);
- if (!NT_SUCCESS(Status))
- goto out;
-
- Status = XENBUS_STORE(Printf,
- &Frontend->StoreInterface,
- NULL,
- Frontend->TargetPath,
- "dump",
- "%u",
- Frontend->Caps.DumpFile);
- if (!NT_SUCCESS(Status))
- goto out;
-
- Verbose("Target[%d] : %s %s %s\n", Frontend->TargetId,
- Frontend->Caps.DumpFile ? "DUMP" : "NOT_DUMP",
- Frontend->Caps.Hibernation ? "HIBER" : "NOT_HIBER",
- Frontend->Caps.Paging ? "PAGE" : "NOT_PAGE");
-
-out:
- return Status;
-}
-
-//=============================================================================
-__drv_requiresIRQL(DISPATCH_LEVEL)
-VOID
-FrontendNotifyResponses(
- __in PXENVBD_FRONTEND Frontend
- )
-{
- BlockRingPoll(Frontend->BlockRing);
- TargetSubmitRequests(Frontend->Target);
-}
-
-//=============================================================================
-__drv_requiresIRQL(DISPATCH_LEVEL)
-static NTSTATUS
-__UpdateBackendPath(
- __in PXENVBD_FRONTEND Frontend
- )
-{
- NTSTATUS Status;
- PCHAR Value;
- ULONG Length;
-
- Status = XENBUS_STORE(Read,
- &Frontend->StoreInterface,
- NULL,
- Frontend->FrontendPath,
- "backend-id",
- &Value);
- if (NT_SUCCESS(Status)) {
- Frontend->BackendId = (USHORT)strtoul(Value, NULL, 10);
- XENBUS_STORE(Free,
- &Frontend->StoreInterface,
- Value);
- } else {
- Frontend->BackendId = 0;
- }
-
- Status = XENBUS_STORE(Read,
- &Frontend->StoreInterface,
- NULL,
- Frontend->FrontendPath,
- "backend",
- &Value);
- if (NT_SUCCESS(Status)) {
- if (Frontend->BackendPath) {
- Trace("<< %s\n", Frontend->BackendPath);
- __FrontendFree(Frontend->BackendPath);
- Frontend->BackendPath = NULL;
- }
-
- Length = (ULONG)strlen(Value);
- Frontend->BackendPath = (PCHAR)__FrontendAlloc(Length + 1);
-
- if (Frontend->BackendPath) {
- RtlCopyMemory(Frontend->BackendPath, Value, Length);
- Trace(">> %s\n", Frontend->BackendPath);
- }
-
- XENBUS_STORE(Free,
- &Frontend->StoreInterface,
- Value);
- } else {
- Warning("Failed to read \'backend\' from \'%s\' (%08x)\n",
- Frontend->FrontendPath, Status);
- }
-
- return Status;
-}
-__drv_maxIRQL(DISPATCH_LEVEL)
-static NTSTATUS
-__ReadState(
- __in PXENVBD_FRONTEND Frontend,
- __in_opt PXENBUS_STORE_TRANSACTION Transaction,
- __in PCHAR Path,
- __out XenbusState* State
- )
-{
- NTSTATUS Status;
- PCHAR Buffer;
-
- Status = XENBUS_STORE(Read,
- &Frontend->StoreInterface,
- Transaction,
- Path,
- "state",
- &Buffer);
- if (!NT_SUCCESS(Status))
- goto fail;
-
- *State = (XenbusState)strtoul(Buffer, NULL, 10);
- XENBUS_STORE(Free,
- &Frontend->StoreInterface,
- Buffer);
-
- return STATUS_SUCCESS;
-
-fail:
- *State = XenbusStateUnknown;
- return Status;
-}
-__drv_requiresIRQL(DISPATCH_LEVEL)
-static NTSTATUS
-__WaitState(
- __in PXENVBD_FRONTEND Frontend,
- __inout XenbusState* State
- )
-{
- NTSTATUS Status;
- XenbusState OldState = *State;
- PXENBUS_STORE_WATCH Watch;
- KEVENT Event;
- LARGE_INTEGER Timeout;
-
- LARGE_INTEGER StartTime;
- LARGE_INTEGER CurrentTime;
- ULONG Count = 0;
-
- KeInitializeEvent(&Event, NotificationEvent, FALSE);
- Timeout.QuadPart = 0;
-
- ASSERT3P(Frontend->BackendPath, !=, NULL);
- Status = XENBUS_STORE(WatchAdd,
- &Frontend->StoreInterface,
- Frontend->BackendPath,
- "state",
- &Event,
- &Watch);
- if (!NT_SUCCESS(Status))
- goto fail1;
-
- KeQuerySystemTime(&StartTime);
-
- while (OldState == *State) {
- // check event and spin or read
-#pragma prefast(suppress:28121)
- if (KeWaitForSingleObject(&Event, Executive, KernelMode,
- FALSE, &Timeout) == STATUS_TIMEOUT) {
- XENBUS_STORE(Poll,
- &Frontend->StoreInterface);
-
- KeQuerySystemTime(&CurrentTime);
- if ((CurrentTime.QuadPart - StartTime.QuadPart) > 10000) {
- Warning("Target[%d] : %d Waited for %d ms\n",
Frontend->TargetId,
- Count, (ULONG)((CurrentTime.QuadPart -
StartTime.QuadPart) / 10));
- StartTime.QuadPart = CurrentTime.QuadPart;
- ++Count;
- }
-
- continue;
- }
-
- Status = __ReadState(Frontend, NULL, Frontend->BackendPath, State);
- if (!NT_SUCCESS(Status))
- goto fail2;
- }
-
- XENBUS_STORE(WatchRemove,
- &Frontend->StoreInterface,
- Watch);
-
- Trace("Target[%d] : BACKEND_STATE -> %s\n",
- Frontend->TargetId,
- XenbusStateName(*State));
-
- return STATUS_SUCCESS;
-
-fail2:
- Error("Fail2\n");
-
- XENBUS_STORE(WatchRemove,
- &Frontend->StoreInterface,
- Watch);
-fail1:
- Error("Fail1 (%08x)\n", Status);
-
- return Status;
-}
-__drv_requiresIRQL(DISPATCH_LEVEL)
-static NTSTATUS
-___SetState(
- __in PXENVBD_FRONTEND Frontend,
- __in XenbusState State
- )
-{
- NTSTATUS Status;
-
- Status = XENBUS_STORE(Printf,
- &Frontend->StoreInterface,
- NULL,
- Frontend->FrontendPath,
- "state",
- "%u",
- State);
- if (NT_SUCCESS(Status)) {
- Trace("Target[%d] : FRONTEND_STATE -> %s\n",
- Frontend->TargetId,
- XenbusStateName(State));
- } else {
- Error("Fail (%08x)\n", Status);
- }
-
- return Status;
-}
-__drv_requiresIRQL(DISPATCH_LEVEL)
-static FORCEINLINE VOID
-__CheckBackendForEject(
- __in PXENVBD_FRONTEND Frontend
- )
-{
- XenbusState FrontendState;
- XenbusState BackendState;
- BOOLEAN Online;
- ULONG Attempt;
- NTSTATUS Status;
-
- if (Frontend->FrontendPath == NULL)
- return;
- if (Frontend->BackendPath == NULL)
- return;
-
- // get FrontendState, BackendState and Online
- Attempt = 0;
- FrontendState = XenbusStateUnknown;
- BackendState = XenbusStateUnknown;
- Online = TRUE;
- for (;;) {
- PXENBUS_STORE_TRANSACTION Transaction;
- PCHAR Buffer;
-
- Status = XENBUS_STORE(TransactionStart,
- &Frontend->StoreInterface,
- &Transaction);
- if (!NT_SUCCESS(Status))
- break;
-
- Status = __ReadState(Frontend,
- Transaction,
- Frontend->FrontendPath,
- &FrontendState);
- if (!NT_SUCCESS(Status))
- goto abort;
-
- Status = __ReadState(Frontend,
- Transaction,
- Frontend->BackendPath,
- &BackendState);
- if (!NT_SUCCESS(Status))
- goto abort;
-
- Status = XENBUS_STORE(Read,
- &Frontend->StoreInterface,
- Transaction,
- Frontend->BackendPath,
- "online",
- &Buffer);
- if (!NT_SUCCESS(Status))
- goto abort;
-
- Online = (BOOLEAN)strtol(Buffer, NULL, 2);
- XENBUS_STORE(Free,
- &Frontend->StoreInterface,
- Buffer);
-
- Status = XENBUS_STORE(TransactionEnd,
- &Frontend->StoreInterface,
- Transaction,
- TRUE);
- if (Status != STATUS_RETRY || ++Attempt > 10)
- break;
-
- continue;
-
-abort:
- (VOID) XENBUS_STORE(TransactionEnd,
- &Frontend->StoreInterface,
- Transaction,
- FALSE);
- break;
- }
- if (!NT_SUCCESS(Status))
- return;
-
- // check to see eject required
- if (!Online && BackendState == XenbusStateClosing) {
- Trace("Target[%d] : BackendState(%s) FrontendState(%s)\n",
- Frontend->TargetId, XenbusStateName(BackendState),
XenbusStateName(FrontendState));
-
- TargetIssueDeviceEject(Frontend->Target,
XenbusStateName(BackendState));
- }
-}
-
-static FORCEINLINE BOOLEAN
-FrontendReadFeature(
- IN PXENVBD_FRONTEND Frontend,
- IN PCHAR Name,
- IN PBOOLEAN Value
- )
-{
- NTSTATUS status;
- PCHAR Buffer;
- ULONG Override;
- BOOLEAN Old = *Value;
-
- status = XENBUS_STORE(Read,
- &Frontend->StoreInterface,
- NULL,
- Frontend->BackendPath,
- Name,
- &Buffer);
- if (!NT_SUCCESS(status))
- return FALSE; // no value, unchanged
-
- *Value = !!(strtoul(Buffer, NULL, 10));
- XENBUS_STORE(Free,
- &Frontend->StoreInterface,
- Buffer);
-
- // check registry for disable-override
- status = RegistryQueryDwordValue(DriverGetParametersKey(),
- Name,
- &Override);
- if (NT_SUCCESS(status)) {
- if (Override == 0)
- *Value = FALSE;
- }
-
- return Old != *Value;
-}
-
-static FORCEINLINE BOOLEAN
-FrontendReadValue32(
- IN PXENVBD_FRONTEND Frontend,
- IN PCHAR Name,
- IN BOOLEAN AllowOverride,
- IN PULONG Value
- )
-{
- NTSTATUS status;
- PCHAR Buffer;
- ULONG Override;
- ULONG Old = *Value;
-
- status = XENBUS_STORE(Read,
- &Frontend->StoreInterface,
- NULL,
- Frontend->BackendPath,
- Name,
- &Buffer);
- if (!NT_SUCCESS(status))
- return FALSE; // no value, unchanged
-
- *Value = strtoul(Buffer, NULL, 10);
- XENBUS_STORE(Free,
- &Frontend->StoreInterface,
- Buffer);
-
- // check registry for disable-override
- if (AllowOverride) {
- status = RegistryQueryDwordValue(DriverGetParametersKey(),
- Name,
- &Override);
- if (NT_SUCCESS(status)) {
- *Value = Override;
- }
- }
-
- return Old != *Value;
-}
-
-static FORCEINLINE BOOLEAN
-FrontendReadValue64(
- IN PXENVBD_FRONTEND Frontend,
- IN PCHAR Name,
- IN OUT PULONG64 Value
- )
-{
- NTSTATUS status;
- PCHAR Buffer;
- ULONG64 Old = *Value;
-
- status = XENBUS_STORE(Read,
- &Frontend->StoreInterface,
- NULL,
- Frontend->BackendPath,
- Name,
- &Buffer);
- if (!NT_SUCCESS(status))
- return FALSE; // no value, unchanged
-
- *Value = _strtoui64(Buffer, NULL, 10);
- XENBUS_STORE(Free,
- &Frontend->StoreInterface,
- Buffer);
-
- return Old != *Value;
-}
-
-static FORCEINLINE ULONG
-__Size(
- __in PXENVBD_DISKINFO Info
- )
-{
- ULONG64 MBytes = (Info->SectorSize * Info->SectorCount) >> 20; // / (1024
* 1024);
- if (MBytes < 10240)
- return (ULONG)MBytes;
- return (ULONG)(MBytes >> 10); // / 1024
-}
-static FORCEINLINE PCHAR
-__Units(
- __in PXENVBD_DISKINFO Info
- )
-{
- ULONG64 MBytes = (Info->SectorSize * Info->SectorCount) >> 20; // / (1024
* 1024);
- if (MBytes < 10240)
- return "MB";
- return "GB";
-}
-
-__drv_requiresIRQL(DISPATCH_LEVEL)
-static VOID
-__ReadDiskInfo(
- __in PXENVBD_FRONTEND Frontend
- )
-{
- BOOLEAN Changed = FALSE;
-
- Changed |= FrontendReadValue32(Frontend,
- "info",
- FALSE,
- &Frontend->DiskInfo.DiskInfo);
- Changed |= FrontendReadValue32(Frontend,
- "sector-size",
- FALSE,
- &Frontend->DiskInfo.SectorSize);
- Changed |= FrontendReadValue32(Frontend,
- "physical-sector-size",
- FALSE,
- &Frontend->DiskInfo.PhysSectorSize);
- Changed |= FrontendReadValue64(Frontend,
- "sectors",
- &Frontend->DiskInfo.SectorCount);
-
- if (!Changed)
- return;
-
- Frontend->Caps.SurpriseRemovable = !!(Frontend->DiskInfo.DiskInfo &
VDISK_REMOVABLE);
- if (Frontend->DiskInfo.DiskInfo & VDISK_READONLY) {
- Warning("Target[%d] : DiskInfo contains VDISK_READONLY flag!\n",
Frontend->TargetId);
- }
- if (Frontend->DiskInfo.DiskInfo & VDISK_CDROM) {
- Warning("Target[%d] : DiskInfo contains VDISK_CDROM flag!\n",
Frontend->TargetId);
- }
- if (Frontend->DiskInfo.SectorSize == 0) {
- Error("Target[%d] : Invalid SectorSize!\n", Frontend->TargetId);
- }
- if (Frontend->DiskInfo.SectorCount == 0) {
- Error("Target[%d] : Invalid SectorCount!\n", Frontend->TargetId);
- }
- if (Frontend->DiskInfo.PhysSectorSize == 0) {
- Frontend->DiskInfo.PhysSectorSize = Frontend->DiskInfo.SectorSize;
- }
-
- // dump actual values
- Verbose("Target[%d] : %lld sectors of %d bytes (%d)\n", Frontend->TargetId,
- Frontend->DiskInfo.SectorCount, Frontend->DiskInfo.SectorSize,
- Frontend->DiskInfo.PhysSectorSize);
- Verbose("Target[%d] : %d %s (%08x) %s\n", Frontend->TargetId,
- __Size(&Frontend->DiskInfo), __Units(&Frontend->DiskInfo),
- Frontend->DiskInfo.DiskInfo,
- Frontend->Caps.SurpriseRemovable ? "SURPRISE_REMOVABLE" : "");
-}
-
-static FORCEINLINE VOID
-FrontendReadFeatures(
- IN PXENVBD_FRONTEND Frontend
- )
-{
- BOOLEAN Changed = FALSE;
-
- Changed |= FrontendReadFeature(Frontend,
- "removable",
- &Frontend->Caps.Removable);
- Changed |= FrontendReadValue32(Frontend,
- "feature-max-indirect-segments",
- TRUE,
- &Frontend->Features.Indirect);
- Changed |= FrontendReadFeature(Frontend,
- "feature-persistent",
- &Frontend->Features.Persistent);
-
- if (!Changed)
- return;
-
- Verbose("Target[%d] : Features: %s%s%s\n",
- Frontend->TargetId,
- Frontend->Features.Persistent ? "PERSISTENT " : "",
- Frontend->Features.Indirect ? "INDIRECT " : "",
- Frontend->Caps.Removable ? "REMOVABLE" : "");
- if (Frontend->Features.Indirect) {
- Verbose("Target[%d] : INDIRECT %x\n",
- Frontend->TargetId,
- Frontend->Features.Indirect);
- }
-}
-
-static FORCEINLINE VOID
-FrontendReadDiskInfo(
- IN PXENVBD_FRONTEND Frontend
- )
-{
- BOOLEAN Changed = FALSE;
- BOOLEAN Discard;
- BOOLEAN DiscardFeature = FALSE;
- BOOLEAN DiscardEnable = TRUE;
-
- Changed |= FrontendReadFeature(Frontend,
- "feature-barrier",
- &Frontend->DiskInfo.Barrier);
- Changed |= FrontendReadFeature(Frontend,
- "feature-flush-cache",
- &Frontend->DiskInfo.FlushCache);
-
- // discard related
- FrontendReadFeature(Frontend,
- "feature-discard",
- &DiscardFeature);
- FrontendReadFeature(Frontend,
- "discard-enable",
- &DiscardEnable);
- Discard = DiscardFeature && DiscardEnable;
- Changed |= (Discard != Frontend->DiskInfo.Discard);
- Frontend->DiskInfo.Discard = Discard;
- Changed |= FrontendReadFeature(Frontend,
- "discard-secure",
- &Frontend->DiskInfo.DiscardSecure);
- Changed |= FrontendReadValue32(Frontend,
- "discard-alignment",
- TRUE,
- &Frontend->DiskInfo.DiscardAlignment);
- Changed |= FrontendReadValue32(Frontend,
- "discard-granularity",
- TRUE,
- &Frontend->DiskInfo.DiscardGranularity);
-
- if (!Changed)
- return;
-
- Verbose("Target[%d] : Features: %s%s%s\n",
- Frontend->TargetId,
- Frontend->DiskInfo.Barrier ? "BARRIER " : "",
- Frontend->DiskInfo.FlushCache ? "FLUSH " : "",
- Frontend->DiskInfo.Discard ? "DISCARD " : "");
- if (Frontend->DiskInfo.Discard) {
- Verbose("Target[%d] : DISCARD %s%x/%x\n",
- Frontend->TargetId,
- Frontend->DiskInfo.DiscardSecure ? "SECURE " : "",
- Frontend->DiskInfo.DiscardAlignment,
- Frontend->DiskInfo.DiscardGranularity);
- }
-}
-
-//=============================================================================
-__drv_requiresIRQL(DISPATCH_LEVEL)
-static NTSTATUS
-FrontendClose(
- __in PXENVBD_FRONTEND Frontend
- )
-{
- NTSTATUS Status;
- XenbusState BackendState;
-
- // unwatch backend (null check for initial close operation)
- if (Frontend->BackendWatch)
- XENBUS_STORE(WatchRemove,
- &Frontend->StoreInterface,
- Frontend->BackendWatch);
- Frontend->BackendWatch = NULL;
-
- Frontend->BackendId = DOMID_INVALID;
-
- // get/update backend path
- Status = __UpdateBackendPath(Frontend);
- if (!NT_SUCCESS(Status))
- goto fail1;
-
- // Backend : -> !INITIALIZING
- BackendState = XenbusStateUnknown;
- do {
- Status = __WaitState(Frontend, &BackendState);
- if (!NT_SUCCESS(Status))
- goto fail2;
- } while (BackendState == XenbusStateInitialising);
-
- // Frontend: -> CLOSING
- // Backend : -> CLOSING
- while (BackendState != XenbusStateClosing &&
- BackendState != XenbusStateClosed) {
- Status = ___SetState(Frontend, XenbusStateClosing);
- if (!NT_SUCCESS(Status))
- goto fail3;
- Status = __WaitState(Frontend, &BackendState);
- if (!NT_SUCCESS(Status))
- goto fail4;
- }
-
- // Frontend: -> CLOSED
- // Backend : -> CLOSED
- while (BackendState != XenbusStateClosed) {
- Status = ___SetState(Frontend, XenbusStateClosed);
- if (!NT_SUCCESS(Status))
- goto fail5;
- Status = __WaitState(Frontend, &BackendState);
- if (!NT_SUCCESS(Status))
- goto fail6;
- }
-
- return STATUS_SUCCESS;
-
-fail6:
-fail5:
-fail4:
-fail3:
-fail2:
-fail1:
- return Status;
-}
-__drv_requiresIRQL(DISPATCH_LEVEL)
-static NTSTATUS
-FrontendPrepare(
- __in PXENVBD_FRONTEND Frontend
- )
-{
- NTSTATUS Status;
- XenbusState BackendState;
-
- // get/update backend path
- Status = __UpdateBackendPath(Frontend);
- if (!NT_SUCCESS(Status))
- goto fail1;
-
- // watch backend (4 paths needed)
- Status = XENBUS_STORE(WatchAdd,
- &Frontend->StoreInterface,
- NULL,
- Frontend->BackendPath,
- ThreadGetEvent(Frontend->BackendThread),
- &Frontend->BackendWatch);
- if (!NT_SUCCESS(Status))
- goto fail2;
-
- // write targetpath
- Status = FrontendWriteUsage(Frontend);
- if (!NT_SUCCESS(Status))
- goto fail3;
-
- Status = XENBUS_STORE(Printf,
- &Frontend->StoreInterface,
- NULL,
- Frontend->TargetPath,
- "frontend",
- "%s",
- Frontend->FrontendPath);
- if (!NT_SUCCESS(Status))
- goto fail4;
-
- Status = XENBUS_STORE(Printf,
- &Frontend->StoreInterface,
- NULL,
- Frontend->TargetPath,
- "device",
- "%u",
- Frontend->DeviceId);
- if (!NT_SUCCESS(Status))
- goto fail5;
-
- // Frontend: -> INITIALIZING
- Status = ___SetState(Frontend, XenbusStateInitialising);
- if (!NT_SUCCESS(Status))
- goto fail6;
-
- // Backend : -> INITWAIT
- BackendState = XenbusStateUnknown;
- do {
- Status = __WaitState(Frontend, &BackendState);
- if (!NT_SUCCESS(Status))
- goto fail7;
- } while (BackendState == XenbusStateClosed ||
- BackendState == XenbusStateInitialising);
- Status = STATUS_UNSUCCESSFUL;
- if (BackendState != XenbusStateInitWait)
- goto fail8;
-
- // read inquiry data
- if (Frontend->Inquiry == NULL)
- PdoReadInquiryData(Frontend, &Frontend->Inquiry);
- PdoUpdateInquiryData(Frontend, Frontend->Inquiry);
-
- // read features and caps (removable, ring-order, ...)
- Verbose("Target[%d] : BackendId %d (%s)\n",
- Frontend->TargetId,
- Frontend->BackendId,
- Frontend->BackendPath);
-
- FrontendReadFeatures(Frontend);
-
- return STATUS_SUCCESS;
-
-fail8:
- Error("Fail8\n");
-fail7:
- Error("Fail7\n");
-fail6:
- Error("Fail6\n");
-fail5:
- Error("Fail5\n");
-fail4:
- Error("Fail4\n");
-fail3:
- Error("Fail3\n");
- (VOID) XENBUS_STORE(WatchRemove,
- &Frontend->StoreInterface,
- Frontend->BackendWatch);
- Frontend->BackendWatch = NULL;
-fail2:
- Error("Fail2\n");
-fail1:
- Error("Fail1 (%08x)\n", Status);
- return Status;
-}
-__drv_requiresIRQL(DISPATCH_LEVEL)
-static NTSTATUS
-FrontendConnect(
- __in PXENVBD_FRONTEND Frontend
- )
-{
- NTSTATUS Status;
- XenbusState BackendState;
-
- // Alloc Ring, Create Evtchn, Gnttab map
- Status = GranterConnect(Frontend->Granter, Frontend->BackendId);
- if (!NT_SUCCESS(Status))
- goto fail1;
-
- Status = BlockRingConnect(Frontend->BlockRing);
- 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;
-
- Status = XENBUS_STORE(TransactionStart,
- &Frontend->StoreInterface,
- &Transaction);
- 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);
- if (!NT_SUCCESS(Status))
- goto abort;
-
- Status = GranterStoreWrite(Frontend->Granter, Transaction,
Frontend->FrontendPath);
- if (!NT_SUCCESS(Status))
- goto abort;
-
- Status = XENBUS_STORE(Printf,
- &Frontend->StoreInterface,
- Transaction,
- Frontend->FrontendPath,
- "target-id",
- "%u",
- Frontend->TargetId);
- if (!NT_SUCCESS(Status))
- goto abort;
-
- Status = XENBUS_STORE(Printf,
- &Frontend->StoreInterface,
- Transaction,
- Frontend->FrontendPath,
- "feature-surprise-remove",
- "%u",
- 1);
- if (!NT_SUCCESS(Status))
- goto abort;
-
- Status = XENBUS_STORE(Printf,
- &Frontend->StoreInterface,
- Transaction,
- Frontend->FrontendPath,
- "feature-online-resize",
- "%u",
- 1);
- if (!NT_SUCCESS(Status))
- goto abort;
-
- Status = XENBUS_STORE(TransactionEnd,
- &Frontend->StoreInterface,
- Transaction,
- TRUE);
- if (Status == STATUS_RETRY)
- continue;
-
- break;
-
-abort:
- (VOID) XENBUS_STORE(TransactionEnd,
- &Frontend->StoreInterface,
- Transaction,
- FALSE);
- break;
- }
- if (!NT_SUCCESS(Status))
- goto fail4;
-
- // Frontend: -> INITIALIZED
- Status = ___SetState(Frontend, XenbusStateInitialised);
- if (!NT_SUCCESS(Status))
- goto fail5;
-
- // Backend : -> CONNECTED
- BackendState = XenbusStateUnknown;
- do {
- Status = __WaitState(Frontend, &BackendState);
- if (!NT_SUCCESS(Status))
- goto fail6;
- } while (BackendState == XenbusStateInitWait ||
- BackendState == XenbusStateInitialising ||
- BackendState == XenbusStateInitialised);
- Status = STATUS_UNSUCCESSFUL;
- if (BackendState != XenbusStateConnected)
- goto fail7;
-
- // read disk info
- __ReadDiskInfo(Frontend);
- FrontendReadDiskInfo(Frontend);
-
- // blkback doesnt write features before InitWait, blkback writes features
before Connected!
- FrontendReadFeatures(Frontend);
-
- // Frontend: -> CONNECTED
- Status = ___SetState(Frontend, XenbusStateConnected);
- if (!NT_SUCCESS(Status))
- goto fail8;
-
- return STATUS_SUCCESS;
-
-fail8:
- Error("Fail8\n");
-fail7:
- Error("Fail7\n");
-fail6:
- Error("Fail6\n");
-fail5:
- Error("Fail5\n");
-fail4:
- Error("Fail4\n");
- NotifierDisconnect(Frontend->Notifier);
-fail3:
- Error("Fail3\n");
- BlockRingDisconnect(Frontend->BlockRing);
-fail2:
- Error("Fail2\n");
- GranterDisconnect(Frontend->Granter);
-fail1:
- Error("Fail1 (%08x)\n", Status);
- return Status;
-}
-__drv_requiresIRQL(DISPATCH_LEVEL)
-static FORCEINLINE VOID
-FrontendDisconnect(
- __in PXENVBD_FRONTEND Frontend
- )
-{
- NotifierDisconnect(Frontend->Notifier);
- BlockRingDisconnect(Frontend->BlockRing);
- GranterDisconnect(Frontend->Granter);
-}
-__drv_requiresIRQL(DISPATCH_LEVEL)
-static FORCEINLINE VOID
-FrontendEnable(
- __in PXENVBD_FRONTEND Frontend
- )
-{
- Frontend->Caps.Connected = TRUE;
- KeMemoryBarrier();
-
- GranterEnable(Frontend->Granter);
- BlockRingEnable(Frontend->BlockRing);
- NotifierEnable(Frontend->Notifier);
-}
-__drv_requiresIRQL(DISPATCH_LEVEL)
-static FORCEINLINE VOID
-FrontendDisable(
- __in PXENVBD_FRONTEND Frontend
- )
-{
- Frontend->Caps.Connected = FALSE;
-
- NotifierDisable(Frontend->Notifier);
- BlockRingDisable(Frontend->BlockRing);
- GranterDisable(Frontend->Granter);
-}
-
-//=============================================================================
-// Init/Term
-static DECLSPEC_NOINLINE NTSTATUS
-__FrontendSetState(
- __in PXENVBD_FRONTEND Frontend,
- __in XENVBD_STATE State
- )
-{
- NTSTATUS Status;
- const ULONG TargetId = Frontend->TargetId;
- BOOLEAN Failed = FALSE;
-
- Trace("Target[%d] @ (%d) =====>\n", TargetId, KeGetCurrentIrql());
- Verbose("Target[%d] : %s ----> %s\n",
- TargetId,
- __XenvbdStateName(Frontend->State),
- __XenvbdStateName(State));
- ASSERT3U(KeGetCurrentIrql(), ==, DISPATCH_LEVEL);
-
- while (!Failed && Frontend->State != State) {
- switch (Frontend->State) {
- case XENVBD_INITIALIZED:
- switch (State) {
- case XENVBD_CLOSING:
- case XENVBD_CLOSED:
- case XENVBD_PREPARED:
- case XENVBD_CONNECTED:
- case XENVBD_ENABLED:
- Status = FrontendClose(Frontend);
- if (NT_SUCCESS(Status)) {
- Frontend->State = XENVBD_CLOSED;
- } else {
- Failed = TRUE;
- }
- break;
- default:
- Failed = TRUE;
- break;
- }
- break;
-
- case XENVBD_CLOSED:
- switch (State) {
- case XENVBD_INITIALIZED:
- // ONLY Closed->Initialized is valid, which can occur with a
very early resume from suspend
- // i.e. VM was suspended before the Initianized->Closed
transition, and each resume needs
- // the Close transition to properly close the frontend
and backend devices.
- Frontend->State = XENVBD_INITIALIZED;
- break;
- case XENVBD_PREPARED:
- case XENVBD_CONNECTED:
- case XENVBD_ENABLED:
- Status = FrontendPrepare(Frontend);
- if (NT_SUCCESS(Status)) {
- Frontend->State = XENVBD_PREPARED;
- } else {
- Status = FrontendClose(Frontend);
- if (NT_SUCCESS(Status))
- Frontend->State = XENVBD_CLOSED;
- else
- Frontend->State = XENVBD_STATE_INVALID;
- Failed = TRUE;
- }
- break;
- default:
- Failed = TRUE;
- break;
- }
- break;
-
- case XENVBD_PREPARED:
- switch (State) {
- case XENVBD_CONNECTED:
- case XENVBD_ENABLED:
- Status = FrontendConnect(Frontend);
- if (NT_SUCCESS(Status)) {
- Frontend->State = XENVBD_CONNECTED;
- } else {
- Status = FrontendClose(Frontend);
- if (NT_SUCCESS(Status))
- Frontend->State = XENVBD_CLOSED;
- else
- Frontend->State = XENVBD_STATE_INVALID;
- Failed = TRUE;
- }
- break;
- case XENVBD_CLOSING:
- case XENVBD_CLOSED:
- Status = FrontendClose(Frontend);
- if (NT_SUCCESS(Status)) {
- Frontend->State = XENVBD_CLOSED;
- } else {
- Frontend->State = XENVBD_STATE_INVALID;
- Failed = TRUE;
- }
- break;
- default:
- Failed = TRUE;
- break;
- }
- break;
-
- case XENVBD_CONNECTED:
- switch (State) {
- case XENVBD_ENABLED:
- FrontendEnable(Frontend);
- Frontend->State = XENVBD_ENABLED;
- break;
- case XENVBD_CLOSING:
- case XENVBD_CLOSED:
- case XENVBD_PREPARED:
- Status = FrontendClose(Frontend);
- Frontend->State = XENVBD_CLOSING;
- break;
- default:
- Failed = TRUE;
- break;
- }
- break;
-
- case XENVBD_CLOSING:
- switch (State) {
- case XENVBD_INITIALIZED:
- case XENVBD_CLOSED:
- case XENVBD_PREPARED:
- case XENVBD_CONNECTED:
- case XENVBD_ENABLED:
- FrontendDisconnect(Frontend);
- Frontend->State = XENVBD_CLOSED;
- break;
- default:
- Failed = TRUE;
- break;
- }
- break;
-
- case XENVBD_ENABLED:
- switch (State) {
- case XENVBD_CLOSING:
- case XENVBD_CLOSED:
- case XENVBD_PREPARED:
- case XENVBD_CONNECTED:
- FrontendDisable(Frontend);
- Frontend->State = XENVBD_CONNECTED;
- break;
- default:
- Failed = TRUE;
- break;
- }
- break;
-
- default:
- Failed = TRUE;
- break;
- }
- Verbose("Target[%d] : in state %s\n", TargetId,
__XenvbdStateName(Frontend->State));
- }
- Trace("Target[%d] @ (%d) <===== (%s)\n", TargetId, KeGetCurrentIrql(),
Failed ? "FAILED" : "SUCCEEDED");
- return Failed ? STATUS_UNSUCCESSFUL : STATUS_SUCCESS;
-}
-
-__drv_requiresIRQL(DISPATCH_LEVEL)
-static DECLSPEC_NOINLINE VOID
-FrontendSuspendLateCallback(
- __in PVOID Argument
- )
-{
- NTSTATUS Status;
- XENVBD_STATE State;
- PXENVBD_FRONTEND Frontend = (PXENVBD_FRONTEND)Argument;
-
- Verbose("Target[%d] : ===> from %s\n", Frontend->TargetId,
__XenvbdStateName(Frontend->State));
- State = Frontend->State;
-
- TargetPreResume(Frontend->Target);
-
- // dont acquire state lock - called at DISPATCH on 1 vCPU with interrupts
enabled
- Status = __FrontendSetState(Frontend, XENVBD_CLOSED);
- if (!NT_SUCCESS(Status)) {
- Error("Target[%d] : SetState CLOSED (%08x)\n", Frontend->TargetId,
Status);
- ASSERT(FALSE);
- }
-
- // dont acquire state lock - called at DISPATCH on 1 vCPU with interrupts
enabled
- Status = __FrontendSetState(Frontend, State);
- if (!NT_SUCCESS(Status)) {
- Error("Target[%d] : SetState %s (%08x)\n", Frontend->TargetId,
__XenvbdStateName(State), Status);
- ASSERT(FALSE);
- }
-
- TargetPostResume(Frontend->Target);
- NotifierTrigger(Frontend->Notifier);
-
- Verbose("Target[%d] : <=== restored %s\n", Frontend->TargetId,
__XenvbdStateName(Frontend->State));
-}
-
-__checkReturn
-__drv_maxIRQL(DISPATCH_LEVEL)
-NTSTATUS
-FrontendD3ToD0(
- __in PXENVBD_FRONTEND Frontend
- )
-{
- PXENVBD_ADAPTER Adapter = TargetGetAdapter(Frontend->Target);
- NTSTATUS Status;
- KIRQL Irql;
-
- KeAcquireSpinLock(&Frontend->StateLock, &Irql);
-
- // acquire interfaces
- AdapterGetStoreInterface(Adapter, &Frontend->StoreInterface);
- AdapterGetSuspendInterface(Adapter, &Frontend->SuspendInterface);
-
- Status = XENBUS_STORE(Acquire, &Frontend->StoreInterface);
- if (!NT_SUCCESS(Status))
- goto fail1;
-
- Status = XENBUS_SUSPEND(Acquire, &Frontend->SuspendInterface);
- if (!NT_SUCCESS(Status))
- goto fail2;
-
- // register suspend callback
- ASSERT3P(Frontend->SuspendLateCallback, ==, NULL);
- Status = XENBUS_SUSPEND(Register,
- &Frontend->SuspendInterface,
- SUSPEND_CALLBACK_LATE,
- FrontendSuspendLateCallback,
- Frontend,
- &Frontend->SuspendLateCallback);
- if (!NT_SUCCESS(Status))
- goto fail3;
-
- // update state
- Frontend->Active = TRUE;
-
- KeReleaseSpinLock(&Frontend->StateLock, Irql);
- return STATUS_SUCCESS;
-
-fail3:
- Error("Fail3\n");
-
- XENBUS_SUSPEND(Release, &Frontend->SuspendInterface);
- RtlZeroMemory(&Frontend->SuspendInterface,
sizeof(XENBUS_SUSPEND_INTERFACE));
-
-fail2:
- Error("Fail2\n");
-
- XENBUS_STORE(Release, &Frontend->StoreInterface);
- RtlZeroMemory(&Frontend->StoreInterface, sizeof(XENBUS_STORE_INTERFACE));
-
-fail1:
- Error("Fail1 (%08x)\n", Status);
-
- KeReleaseSpinLock(&Frontend->StateLock, Irql);
- return Status;
-}
-
-__drv_maxIRQL(DISPATCH_LEVEL)
-VOID
-FrontendD0ToD3(
- __in PXENVBD_FRONTEND Frontend
- )
-{
- KIRQL Irql;
-
- KeAcquireSpinLock(&Frontend->StateLock, &Irql);
-
- // update state
- Frontend->Active = FALSE;
-
- // deregister suspend callback
- if (Frontend->SuspendLateCallback != NULL) {
- XENBUS_SUSPEND(Deregister,
- &Frontend->SuspendInterface,
- Frontend->SuspendLateCallback);
- Frontend->SuspendLateCallback = NULL;
- }
- // Free backend path before dropping store interface
- if (Frontend->BackendPath) {
- __FrontendFree(Frontend->BackendPath);
- Frontend->BackendPath = NULL;
- }
-
- // release interfaces
- XENBUS_SUSPEND(Release, &Frontend->SuspendInterface);
- RtlZeroMemory(&Frontend->SuspendInterface,
sizeof(XENBUS_SUSPEND_INTERFACE));
-
- XENBUS_STORE(Release, &Frontend->StoreInterface);
- RtlZeroMemory(&Frontend->StoreInterface, sizeof(XENBUS_STORE_INTERFACE));
-
- KeReleaseSpinLock(&Frontend->StateLock, Irql);
-}
-
-__checkReturn
-NTSTATUS
-FrontendSetState(
- __in PXENVBD_FRONTEND Frontend,
- __in XENVBD_STATE State
- )
-{
- NTSTATUS Status;
- KIRQL Irql;
-
- KeAcquireSpinLock(&Frontend->StateLock, &Irql);
-
- Status = __FrontendSetState(Frontend, State);
-
- KeReleaseSpinLock(&Frontend->StateLock, Irql);
- return Status;
-}
-
-__checkReturn
-static DECLSPEC_NOINLINE NTSTATUS
-FrontendBackend(
- __in PXENVBD_THREAD Thread,
- __in PVOID Context
- )
-{
- PXENVBD_FRONTEND Frontend = Context;
-
- for (;;) {
- KIRQL Irql;
-
- if (!ThreadWait(Thread))
- break;
-
- KeAcquireSpinLock(&Frontend->StateLock, &Irql);
- // Only attempt this if Active, Active is set/cleared on D3->D0/D0->D3
- if (Frontend->Active) {
- __ReadDiskInfo(Frontend);
- __CheckBackendForEject(Frontend);
- }
- KeReleaseSpinLock(&Frontend->StateLock, Irql);
- }
-
- return STATUS_SUCCESS;
-
-}
-
-NTSTATUS
-FrontendCreate(
- IN PXENVBD_TARGET Target,
- IN PCHAR DeviceId,
- IN ULONG TargetId,
- OUT PXENVBD_FRONTEND* _Frontend
- )
-{
- NTSTATUS status;
- PXENVBD_FRONTEND Frontend;
-
- Trace("Target[%d] @ (%d) =====>\n", TargetId, KeGetCurrentIrql());
-
- Frontend = __FrontendAlloc(sizeof(XENVBD_FRONTEND));
-
- status = STATUS_NO_MEMORY;
- if (Frontend == NULL)
- goto fail1;
-
- // populate members
- Frontend->Target = Target;
- Frontend->TargetId = TargetId;
- Frontend->DeviceId = strtoul(DeviceId, NULL, 10);
- Frontend->State = XENVBD_INITIALIZED;
- Frontend->DiskInfo.SectorSize = 512; // default sector size
- Frontend->BackendId = DOMID_INVALID;
-
- status = RtlStringCbPrintfA(Frontend->FrontendPath,
- sizeof(Frontend->FrontendPath),
- "device/vbd/%u",
- Frontend->DeviceId);
- if (!NT_SUCCESS(status))
- goto fail2;
-
- status = RtlStringCbPrintfA(Frontend->TargetPath,
- sizeof(Frontend->TargetPath),
- "data/scsi/target/%u",
- TargetId);
- if (!NT_SUCCESS(status))
- goto fail3;
-
- status = NotifierCreate(Frontend, &Frontend->Notifier);
- 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;
-
- status = ThreadCreate(FrontendBackend, Frontend, &Frontend->BackendThread);
- if (!NT_SUCCESS(status))
- goto fail7;
-
- // kernel objects
- KeInitializeSpinLock(&Frontend->StateLock);
-
- Trace("Target[%d] @ (%d) <===== (STATUS_SUCCESS)\n", Frontend->TargetId,
KeGetCurrentIrql());
- *_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;
-fail5:
- Error("fail5\n");
- NotifierDestroy(Frontend->Notifier);
- Frontend->Notifier = NULL;
-fail4:
- Error("fail4\n");
-fail3:
- Error("fail3\n");
-fail2:
- Error("Fail2\n");
- __FrontendFree(Frontend);
-fail1:
- Error("Fail1 (%08x)\n", status);
- *_Frontend = NULL;
- return status;
-}
-
-VOID
-FrontendDestroy(
- __in PXENVBD_FRONTEND Frontend
- )
-{
- const ULONG TargetId = Frontend->TargetId;
-
- Trace("Target[%d] @ (%d) =====>\n", TargetId, KeGetCurrentIrql());
-
- PdoFreeInquiryData(Frontend->Inquiry);
- Frontend->Inquiry = NULL;
-
- ThreadAlert(Frontend->BackendThread);
- ThreadJoin(Frontend->BackendThread);
- Frontend->BackendThread = NULL;
-
- GranterDestroy(Frontend->Granter);
- Frontend->Granter = NULL;
-
- BlockRingDestroy(Frontend->BlockRing);
- Frontend->BlockRing = NULL;
-
- NotifierDestroy(Frontend->Notifier);
- Frontend->Notifier = NULL;
-
- ASSERT3P(Frontend->BackendPath, ==, NULL);
- ASSERT3P(Frontend->Inquiry, ==, NULL);
- ASSERT3P(Frontend->SuspendLateCallback, ==, NULL);
- ASSERT3P(Frontend->BackendWatch, ==, NULL);
-
- __FrontendFree(Frontend);
- Trace("Target[%d] @ (%d) <=====\n", TargetId, KeGetCurrentIrql());
-}
-
-//=============================================================================
-// Debug
-VOID
-FrontendDebugCallback(
- __in PXENVBD_FRONTEND Frontend,
- __in PXENBUS_DEBUG_INTERFACE Debug
- )
-{
- XENBUS_DEBUG(Printf, Debug,
- "FRONTEND: TargetId=%d DeviceId=%d BackendId=%d\n",
- Frontend->TargetId,
- Frontend->DeviceId,
- Frontend->BackendId);
- XENBUS_DEBUG(Printf, Debug,
- "FRONTEND: FrontendPath %s\n",
- Frontend->FrontendPath);
- XENBUS_DEBUG(Printf, Debug,
- "FRONTEND: BackendPath %s\n",
- Frontend->BackendPath ? Frontend->BackendPath : "NULL");
- XENBUS_DEBUG(Printf, Debug,
- "FRONTEND: TargetPath %s\n",
- Frontend->TargetPath);
- XENBUS_DEBUG(Printf, Debug,
- "FRONTEND: State : %s\n",
- __XenvbdStateName(Frontend->State));
-
- XENBUS_DEBUG(Printf, Debug,
- "FRONTEND: Caps : %s%s%s%s%s%s\n",
- Frontend->Caps.Connected ? "CONNECTED " : "",
- Frontend->Caps.Removable ? "REMOVABLE " : "",
- Frontend->Caps.SurpriseRemovable ? "SURPRISE " : "",
- Frontend->Caps.Paging ? "PAGING " : "",
- Frontend->Caps.Hibernation ? "HIBER " : "",
- Frontend->Caps.DumpFile ? "DUMP " : "");
-
- XENBUS_DEBUG(Printf, Debug,
- "FRONTEND: Features: %s%s%s%s%s\n",
- Frontend->Features.Persistent ? "PERSISTENT " : "",
- Frontend->Features.Indirect > 0 ? "INDIRECT " : "",
- Frontend->DiskInfo.Barrier ? "BARRIER " : "",
- Frontend->DiskInfo.FlushCache ? "FLUSH " : "",
- Frontend->DiskInfo.Discard ? "DISCARD " : "");
-
- if (Frontend->Features.Indirect > 0) {
- XENBUS_DEBUG(Printf, Debug,
- "FRONTEND: INDIRECT %x\n",
- Frontend->Features.Indirect);
- }
- if (Frontend->DiskInfo.Discard) {
- XENBUS_DEBUG(Printf, Debug,
- "FRONTEND: DISCARD %s%x/%x\n",
- Frontend->DiskInfo.DiscardSecure ? "SECURE " : "",
- Frontend->DiskInfo.DiscardAlignment,
- Frontend->DiskInfo.DiscardGranularity);
- }
-
- XENBUS_DEBUG(Printf, Debug,
- "FRONTEND: DiskInfo: %llu @ %u (%u) %08x\n",
- Frontend->DiskInfo.SectorCount,
- Frontend->DiskInfo.SectorSize,
- Frontend->DiskInfo.PhysSectorSize,
- 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
deleted file mode 100644
index f466ef8..0000000
--- a/src/xenvbd/frontend.h
+++ /dev/null
@@ -1,198 +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_FRONTEND_H
-#define _XENVBD_FRONTEND_H
-
-#include "target.h"
-#include <debug_interface.h>
-
-typedef enum _XENVBD_STATE {
- XENVBD_STATE_INVALID,
- XENVBD_INITIALIZED, // -> { CLOSED }
- XENVBD_CLOSING, // -> { CLOSED }
- XENVBD_CLOSED, // -> { PREPARED }
- XENVBD_PREPARED, // -> { CLOSING, CONNECTED }
- XENVBD_CONNECTED, // -> { ENABLED, CLOSING }
- XENVBD_ENABLED // -> { CLOSING }
-} XENVBD_STATE, *PXENVBD_STATE;
-
-typedef struct _XENVBD_CAPS {
- BOOLEAN Connected;
- BOOLEAN Removable;
- BOOLEAN SurpriseRemovable;
- BOOLEAN Paging;
- BOOLEAN Hibernation;
- BOOLEAN DumpFile;
-} XENVBD_CAPS, *PXENVBD_CAPS;
-
-typedef struct _XENVBD_FEATURES {
- ULONG Indirect;
- BOOLEAN Persistent;
-} XENVBD_FEATURES, *PXENVBD_FEATURES;
-
-typedef struct _XENVBD_DISKINFO {
- ULONG64 SectorCount;
- ULONG SectorSize;
- ULONG PhysSectorSize;
- ULONG DiskInfo;
- BOOLEAN Barrier;
- BOOLEAN FlushCache;
- BOOLEAN Discard;
- BOOLEAN DiscardSecure;
- ULONG DiscardAlignment;
- ULONG DiscardGranularity;
-} XENVBD_DISKINFO, *PXENVBD_DISKINFO;
-
-typedef struct _XENVBD_FRONTEND XENVBD_FRONTEND, *PXENVBD_FRONTEND;
-
-// Accessors
-extern VOID
-FrontendRemoveFeature(
- IN PXENVBD_FRONTEND Frontend,
- IN UCHAR BlkifOperation
- );
-extern PXENVBD_CAPS
-FrontendGetCaps(
- __in PXENVBD_FRONTEND Frontend
- );
-extern PXENVBD_FEATURES
-FrontendGetFeatures(
- __in PXENVBD_FRONTEND Frontend
- );
-extern PXENVBD_DISKINFO
-FrontendGetDiskInfo(
- __in PXENVBD_FRONTEND Frontend
- );
-extern ULONG
-FrontendGetTargetId(
- __in PXENVBD_FRONTEND Frontend
- );
-extern ULONG
-FrontendGetDeviceId(
- __in PXENVBD_FRONTEND Frontend
- );
-extern PVOID
-FrontendGetInquiry(
- __in PXENVBD_FRONTEND Frontend
- );
-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(
- __in PXENVBD_FRONTEND Frontend
- );
-#include "granter.h"
-extern PXENVBD_GRANTER
-FrontendGetGranter(
- __in PXENVBD_FRONTEND Frontend
- );
-
-extern NTSTATUS
-FrontendStoreWriteFrontend(
- __in PXENVBD_FRONTEND Frontend,
- __in PCHAR Name,
- __in PCHAR Value
- );
-extern NTSTATUS
-FrontendStoreReadBackend(
- __in PXENVBD_FRONTEND Frontend,
- __in PCHAR Name,
- __out PCHAR* Value
- );
-extern VOID
-FrontendStoreFree(
- __in PXENVBD_FRONTEND Frontend,
- __in PCHAR Value
- );
-__drv_maxIRQL(DISPATCH_LEVEL)
-extern NTSTATUS
-FrontendWriteUsage(
- __in PXENVBD_FRONTEND Frontend
- );
-
-// Ring
-__drv_requiresIRQL(DISPATCH_LEVEL)
-extern VOID
-FrontendNotifyResponses(
- __in PXENVBD_FRONTEND Frontend
- );
-
-// Init/Term
-__checkReturn
-__drv_maxIRQL(DISPATCH_LEVEL)
-extern NTSTATUS
-FrontendD3ToD0(
- __in PXENVBD_FRONTEND Frontend
- );
-
-__drv_maxIRQL(DISPATCH_LEVEL)
-extern VOID
-FrontendD0ToD3(
- __in PXENVBD_FRONTEND Frontend
- );
-
-__checkReturn
-extern NTSTATUS
-FrontendSetState(
- __in PXENVBD_FRONTEND Frontend,
- __in XENVBD_STATE State
- );
-
-extern NTSTATUS
-FrontendCreate(
- IN PXENVBD_TARGET Target,
- IN PCHAR DeviceId,
- IN ULONG TargetId,
- OUT PXENVBD_FRONTEND* _Frontend
- );
-
-extern VOID
-FrontendDestroy(
- __in PXENVBD_FRONTEND Frontend
- );
-
-// Debug
-extern VOID
-FrontendDebugCallback(
- __in PXENVBD_FRONTEND Frontend,
- __in PXENBUS_DEBUG_INTERFACE Debug
- );
-
-#endif // _XENVBD_FRONTEND_H
diff --git a/src/xenvbd/granter.c b/src/xenvbd/granter.c
index d61b8b2..22147f3 100644
--- a/src/xenvbd/granter.c
+++ b/src/xenvbd/granter.c
@@ -32,50 +32,62 @@
#include <ntddk.h>
#include <ntstrsafe.h>
-#include "frontend.h"
+#include <gnttab_interface.h>
+#include <debug_interface.h>
+
+#include "granter.h"
#include "target.h"
#include "adapter.h"
+
#include "util.h"
#include "debug.h"
-#include "thread.h"
-#include <gnttab_interface.h>
+#include "assert.h"
struct _XENVBD_GRANTER {
- PXENVBD_FRONTEND Frontend;
- BOOLEAN Connected;
- BOOLEAN Enabled;
+ PXENVBD_TARGET Target;
+ BOOLEAN Connected;
+ BOOLEAN Enabled;
+
+ XENBUS_DEBUG_INTERFACE DebugInterface;
+ XENBUS_GNTTAB_INTERFACE GnttabInterface;
- XENBUS_GNTTAB_INTERFACE GnttabInterface;
- PXENBUS_GNTTAB_CACHE Cache;
- KSPIN_LOCK Lock;
+ PXENBUS_DEBUG_CALLBACK DebugCallback;
- USHORT BackendDomain;
- LONG Current;
- LONG Maximum;
+ PXENBUS_GNTTAB_CACHE Cache;
+ KSPIN_LOCK Lock;
+
+ LONG Current;
+ LONG Maximum;
};
-#define GRANTER_POOL_TAG 'tnGX'
+#define GRANTER_POOL_TAG 'tnGX'
static FORCEINLINE PVOID
__GranterAllocate(
- IN ULONG Length
+ IN ULONG Size
)
{
- return __AllocatePoolWithTag(NonPagedPool, Length, GRANTER_POOL_TAG);
+ PVOID Buffer;
+ Buffer = ExAllocatePoolWithTag(NonPagedPool,
+ Size,
+ GRANTER_POOL_TAG);
+ if (Buffer)
+ RtlZeroMemory(Buffer, Size);
+ return Buffer;
}
static FORCEINLINE VOID
__GranterFree(
- IN PVOID Buffer
+ IN PVOID Buffer
)
{
if (Buffer)
- __FreePoolWithTag(Buffer, GRANTER_POOL_TAG);
+ ExFreePoolWithTag(Buffer, GRANTER_POOL_TAG);
}
NTSTATUS
GranterCreate(
- IN PXENVBD_FRONTEND Frontend,
- OUT PXENVBD_GRANTER* Granter
+ IN PXENVBD_TARGET Target,
+ OUT PXENVBD_GRANTER* Granter
)
{
NTSTATUS status;
@@ -85,7 +97,7 @@ GranterCreate(
if (*Granter == NULL)
goto fail1;
- (*Granter)->Frontend = Frontend;
+ (*Granter)->Target = Target;
KeInitializeSpinLock(&(*Granter)->Lock);
return STATUS_SUCCESS;
@@ -96,10 +108,10 @@ fail1:
VOID
GranterDestroy(
- IN PXENVBD_GRANTER Granter
+ IN PXENVBD_GRANTER Granter
)
{
- Granter->Frontend = NULL;
+ Granter->Target = NULL;
RtlZeroMemory(&Granter->Lock, sizeof(KSPIN_LOCK));
ASSERT(IsZeroMemory(Granter, sizeof(XENVBD_GRANTER)));
@@ -134,34 +146,54 @@ GranterReleaseLock(
KeReleaseSpinLockFromDpcLevel(&Granter->Lock);
}
-#define MAXNAMELEN 32
+static DECLSPEC_NOINLINE VOID
+GranterDebugCallback(
+ IN PVOID Context,
+ IN BOOLEAN Crashing
+ )
+{
+ PXENVBD_GRANTER Granter = Context;
+
+ UNREFERENCED_PARAMETER(Crashing);
+
+ XENBUS_DEBUG(Printf,
+ &Granter->DebugInterface,
+ "%u / %u Grants\n",
+ Granter->Current,
+ Granter->Maximum);
+ Granter->Maximum = Granter->Current;
+}
NTSTATUS
GranterConnect(
- IN PXENVBD_GRANTER Granter,
- IN USHORT BackendDomain
+ IN PXENVBD_GRANTER Granter
)
{
- PXENVBD_ADAPTER Adapter =
TargetGetAdapter(FrontendGetTarget(Granter->Frontend));
- CHAR Name[MAXNAMELEN];
- NTSTATUS status;
+ PXENVBD_ADAPTER Adapter;
+ CHAR Name[sizeof("xenvbd_XXXX_gnttab")];
+ NTSTATUS status;
ASSERT(Granter->Connected == FALSE);
+ Adapter = TargetGetAdapter(Granter->Target);
+
AdapterGetGnttabInterface(Adapter, &Granter->GnttabInterface);
+ AdapterGetDebugInterface(Adapter, &Granter->DebugInterface);
status = XENBUS_GNTTAB(Acquire, &Granter->GnttabInterface);
if (!NT_SUCCESS(status))
goto fail1;
- Granter->BackendDomain = BackendDomain;
+ status = XENBUS_DEBUG(Acquire, &Granter->DebugInterface);
+ if (!NT_SUCCESS(status))
+ goto fail2;
status = RtlStringCbPrintfA(Name,
- sizeof (Name),
- "disk_%u",
- FrontendGetTargetId(Granter->Frontend));
+ sizeof(Name),
+ "xenvbd_%u_gnttab",
+ TargetGetTargetId(Granter->Target));
if (!NT_SUCCESS(status))
- goto fail2;
+ goto fail3;
status = XENBUS_GNTTAB(CreateCache,
&Granter->GnttabInterface,
@@ -172,37 +204,56 @@ GranterConnect(
Granter,
&Granter->Cache);
if (!NT_SUCCESS(status))
- goto fail3;
+ goto fail4;
+
+ status = XENBUS_DEBUG(Register,
+ &Granter->DebugInterface,
+ __MODULE__,
+ GranterDebugCallback,
+ Granter,
+ &Granter->DebugCallback);
+ if (!NT_SUCCESS(status))
+ goto fail5;
Granter->Connected = TRUE;
return STATUS_SUCCESS;
+fail5:
+ Error("fail5\n");
+ XENBUS_GNTTAB(DestroyCache,
+ &Granter->GnttabInterface,
+ Granter->Cache);
+ Granter->Cache = NULL;
+fail4:
+ Error("fail4\n");
fail3:
+ Error("fail3\n");
+ XENBUS_DEBUG(Release, &Granter->DebugInterface);
+ RtlZeroMemory(&Granter->DebugInterface, sizeof(XENBUS_DEBUG_INTERFACE));
fail2:
- Granter->BackendDomain = 0;
+ Error("fail2\n");
XENBUS_GNTTAB(Release, &Granter->GnttabInterface);
RtlZeroMemory(&Granter->GnttabInterface, sizeof(XENBUS_GNTTAB_INTERFACE));
fail1:
+ Error("fail1 %08x\n", status);
return status;
}
NTSTATUS
GranterStoreWrite(
- IN PXENVBD_GRANTER Granter,
- IN PXENBUS_STORE_TRANSACTION Transaction,
- IN PCHAR FrontendPath
+ IN PXENVBD_GRANTER Granter,
+ IN PVOID Transaction
)
{
UNREFERENCED_PARAMETER(Granter);
UNREFERENCED_PARAMETER(Transaction);
- UNREFERENCED_PARAMETER(FrontendPath);
return STATUS_SUCCESS;
}
VOID
GranterEnable(
- IN PXENVBD_GRANTER Granter
+ IN PXENVBD_GRANTER Granter
)
{
ASSERT(Granter->Enabled == FALSE);
@@ -212,7 +263,7 @@ GranterEnable(
VOID
GranterDisable(
- IN PXENVBD_GRANTER Granter
+ IN PXENVBD_GRANTER Granter
)
{
ASSERT(Granter->Enabled == TRUE);
@@ -222,43 +273,33 @@ GranterDisable(
VOID
GranterDisconnect(
- IN PXENVBD_GRANTER Granter
+ IN PXENVBD_GRANTER Granter
)
{
ASSERT(Granter->Connected == TRUE);
- ASSERT3S(Granter->Current, ==, 0);
+ Granter->Current = 0;
Granter->Maximum = 0;
+ XENBUS_DEBUG(Deregister,
+ &Granter->DebugInterface,
+ Granter->DebugCallback);
+ Granter->DebugCallback = NULL;
+
XENBUS_GNTTAB(DestroyCache,
&Granter->GnttabInterface,
Granter->Cache);
Granter->Cache = NULL;
+ XENBUS_DEBUG(Release, &Granter->DebugInterface);
+ RtlZeroMemory(&Granter->DebugInterface, sizeof(XENBUS_DEBUG_INTERFACE));
+
XENBUS_GNTTAB(Release, &Granter->GnttabInterface);
RtlZeroMemory(&Granter->GnttabInterface, sizeof(XENBUS_GNTTAB_INTERFACE));
- Granter->BackendDomain = 0;
Granter->Connected = FALSE;
}
-VOID
-GranterDebugCallback(
- IN PXENVBD_GRANTER Granter,
- IN PXENBUS_DEBUG_INTERFACE Debug
- )
-{
- XENBUS_DEBUG(Printf, Debug,
- "GRANTER: %s %s\n",
- Granter->Connected ? "CONNECTED" : "DISCONNECTED",
- Granter->Enabled ? "ENABLED" : "DISABLED");
- XENBUS_DEBUG(Printf, Debug,
- "GRANTER: %d / %d\n",
- Granter->Current,
- Granter->Maximum);
- Granter->Maximum = Granter->Current;
-}
-
NTSTATUS
GranterGet(
IN PXENVBD_GRANTER Granter,
@@ -279,7 +320,7 @@ GranterGet(
&Granter->GnttabInterface,
Granter->Cache,
FALSE,
- Granter->BackendDomain,
+ TargetGetBackendId(Granter->Target),
Pfn,
ReadOnly,
&Entry);
@@ -294,7 +335,9 @@ GranterGet(
return STATUS_SUCCESS;
fail2:
+ Error("fail2\n");
fail1:
+ Error("fail1 %08x\n", status);
return status;
}
diff --git a/src/xenvbd/granter.h b/src/xenvbd/granter.h
index de7701c..da17698 100644
--- a/src/xenvbd/granter.h
+++ b/src/xenvbd/granter.h
@@ -32,75 +32,67 @@
#ifndef _XENVBD_GRANTER_H
#define _XENVBD_GRANTER_H
+#include <ntddk.h>
+
typedef struct _XENVBD_GRANTER XENVBD_GRANTER, *PXENVBD_GRANTER;
-#include <debug_interface.h>
-#include <store_interface.h>
-#include "frontend.h"
+#include "target.h"
extern NTSTATUS
GranterCreate(
- IN PXENVBD_FRONTEND Frontend,
- OUT PXENVBD_GRANTER* Granter
+ IN PXENVBD_TARGET Target,
+ OUT PXENVBD_GRANTER* Granter
);
extern VOID
GranterDestroy(
- IN PXENVBD_GRANTER Granter
+ IN PXENVBD_GRANTER Granter
);
extern NTSTATUS
GranterConnect(
- IN PXENVBD_GRANTER Granter,
- IN USHORT BackendDomain
+ IN PXENVBD_GRANTER Granter
);
extern NTSTATUS
GranterStoreWrite(
- IN PXENVBD_GRANTER Granter,
- IN PXENBUS_STORE_TRANSACTION Transaction,
- IN PCHAR FrontendPath
+ IN PXENVBD_GRANTER Granter,
+ IN PVOID Transaction
);
extern VOID
GranterEnable(
- IN PXENVBD_GRANTER Granter
+ IN PXENVBD_GRANTER Granter
);
extern VOID
GranterDisable(
- IN PXENVBD_GRANTER Granter
+ IN PXENVBD_GRANTER Granter
);
extern VOID
GranterDisconnect(
- IN PXENVBD_GRANTER Granter
- );
-
-extern VOID
-GranterDebugCallback(
- IN PXENVBD_GRANTER Granter,
- IN PXENBUS_DEBUG_INTERFACE Debug
+ IN PXENVBD_GRANTER Granter
);
extern NTSTATUS
GranterGet(
- IN PXENVBD_GRANTER Granter,
- IN PFN_NUMBER Pfn,
- IN BOOLEAN ReadOnly,
- OUT PVOID *Handle
+ IN PXENVBD_GRANTER Granter,
+ IN PFN_NUMBER Pfn,
+ IN BOOLEAN ReadOnly,
+ OUT PVOID *Handle
);
extern VOID
GranterPut(
- IN PXENVBD_GRANTER Granter,
- IN PVOID Handle
+ IN PXENVBD_GRANTER Granter,
+ IN PVOID Handle
);
extern ULONG
GranterReference(
- IN PXENVBD_GRANTER Granter,
- IN PVOID Handle
+ IN PXENVBD_GRANTER Granter,
+ IN PVOID Handle
);
#endif // _XENVBD_GRANTER_H
diff --git a/src/xenvbd/notifier.c b/src/xenvbd/notifier.c
deleted file mode 100644
index 1e0c057..0000000
--- a/src/xenvbd/notifier.c
+++ /dev/null
@@ -1,334 +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;
-};
-
-#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;
-}
-
-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;
-
- FrontendNotifyResponses(Notifier->Frontend);
-
- XENBUS_EVTCHN(Unmask,
- &Notifier->EvtchnInterface,
- Notifier->Channel,
- FALSE);
-}
-
-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);
-
- return STATUS_SUCCESS;
-
-fail1:
- return STATUS_NO_MEMORY;
-}
-
-VOID
-NotifierDestroy(
- IN PXENVBD_NOTIFIER Notifier
- )
-{
- Notifier->Frontend = NULL;
- RtlZeroMemory(&Notifier->Dpc, sizeof(KDPC));
-
- 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;
-}
-
-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/pdoinquiry.c b/src/xenvbd/pdoinquiry.c
deleted file mode 100644
index 2608fbf..0000000
--- a/src/xenvbd/pdoinquiry.c
+++ /dev/null
@@ -1,530 +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 "pdoinquiry.h"
-#include "driver.h"
-#include "debug.h"
-#include "assert.h"
-#include "util.h"
-#include <xencdb.h>
-#include <xenvbd-ntstrsafe.h>
-#include <stdlib.h>
-
-// "00000000-0000-0000-0000-000000000000"
-#define GUID_LENGTH 36
-
-// 00 00 00 00 00 00 00 00 "XENSRC 00000000"
-#define PAGE83_MIN_SIZE (4 + 4 + 16)
-
-// 00 00 00 00 + GUID_LENGTH
-#define VDI_ID_LENGTH (4 + GUID_LENGTH)
-
-#define INQUIRY_POOL_TAG 'qnIX'
-
-typedef struct _XENVBD_PAGE {
- PCHAR Data;
- ULONG Length;
-} XENVBD_PAGE, *PXENVBD_PAGE;
-
-typedef struct _XENVBD_INQUIRY {
- XENVBD_PAGE Page80;
- XENVBD_PAGE Page83;
- CHAR VdiUuid[GUID_LENGTH + 1];
-} XENVBD_INQUIRY, *PXENVBD_INQUIRY;
-
-static FORCEINLINE ULONG
-__Min3(
- __in ULONG A,
- __in ULONG B,
- __in ULONG C
- )
-{
- return A < B ? __min(A, C) : __min(B, C);
-}
-
-__checkReturn
-__drv_allocatesMem(mem)
-__bcount(Size)
-static FORCEINLINE PVOID
-#pragma warning(suppress: 28195)
-__InquiryAlloc(
- __in SIZE_T Size
- )
-{
- return __AllocatePoolWithTag(NonPagedPool, Size, INQUIRY_POOL_TAG);
-}
-
-static FORCEINLINE VOID
-#pragma warning(suppress: 28197)
-__InquiryFree(
- __in __drv_freesMem(mem) PVOID Buffer
- )
-{
- if (Buffer != NULL)
- __FreePoolWithTag(Buffer, INQUIRY_POOL_TAG);
-}
-
-static FORCEINLINE UCHAR
-__DecodeChar(
- __in CHAR Char
- )
-{
- if (Char >= 'A' && Char <= 'Z') return Char - 'A';
- if (Char >= 'a' && Char <= 'z') return Char - 'a' + 26;
- if (Char >= '0' && Char <= '9') return Char - '0' + 52;
- if (Char == '+') return 62;
- if (Char == '/') return 63;
- if (Char == '=') return 0;
- return 0xFF;
-}
-static DECLSPEC_NOINLINE UCHAR
-__Decode(
- __in PUCHAR Dest,
- __in PCHAR Src,
- __in ULONG RemainingChars
- )
-{
- UCHAR Values[4];
-
- if (RemainingChars < 4)
- return 0xFF;
-
- // take 4 Src chars -> 1, 2, or 3 Dest bytes
- Values[0] = __DecodeChar(Src[0]);
- Values[1] = __DecodeChar(Src[1]);
- Values[2] = __DecodeChar(Src[2]);
- Values[3] = __DecodeChar(Src[3]);
-
- // sanity checks
- if ((Src[0] == '=' || Src[1] == '=') ||
- (Src[2] == '=' && Src[3] != '='))
- return 0xFF;
- if (Values[0] == 0xFF || Values[1] == 0xFF ||
- Values[2] == 0xFF || Values[3] == 0xFF)
- return 0xFF;
-
- // convert
- Dest[0] = (Values[1] >> 4) | (Values[0] << 2);
- if (Src[2] == '=') return 2;
- Dest[1] = (Values[2] >> 2) | (Values[1] << 4);
- if (Src[3] == '=') return 1;
- Dest[2] = (Values[3] ) | (Values[2] << 6);
- return 0;
-}
-__checkReturn
-static NTSTATUS
-__DecodeBase64(
- __in PCHAR Base64,
- __in ULONG Base64Length,
- __out PVOID *_Buffer,
- __out PULONG BufferLength
- )
-{
- // convert Base64(4chars) into Buffer(3bytes)
- PUCHAR Buffer;
- ULONG NumBlocks;
- ULONG i;
- UCHAR Pad = 0;
-
- NumBlocks = Base64Length / 4;
-
- Buffer = (PUCHAR)__InquiryAlloc(NumBlocks * 3);
- if (Buffer == NULL) {
- Error("__InquiryAlloc (STATUS_INSUFFICIENT_RESOURCES)\n");
- goto fail1;
- }
-
- for (i = 0; i < NumBlocks; ++i) {
- if (Pad) goto invalid_base64;
- Pad = __Decode(Buffer + (i * 3), Base64 + (i * 4), Base64Length - (i *
4));
- if (Pad > 2) goto invalid_base64;
- }
-
- *BufferLength = (NumBlocks * 3) - Pad;
- *_Buffer = Buffer;
- return STATUS_SUCCESS;
-
-invalid_base64:
- Error("Invalid BASE64 encoding\n");
- __InquiryFree((PVOID)Buffer);
- return STATUS_UNSUCCESSFUL;
-
-fail1:
- return STATUS_INSUFFICIENT_RESOURCES;
-}
-static DECLSPEC_NOINLINE BOOLEAN
-__ReadPage(
- __in PXENVBD_FRONTEND Frontend,
- __in PXENVBD_PAGE Page,
- __in PCHAR Path
- )
-{
- NTSTATUS Status;
- PCHAR Value;
-
- Status = FrontendStoreReadBackend(Frontend, Path, &Value);
- if (!NT_SUCCESS(Status))
- goto fail1;
-
- Status = __DecodeBase64(Value, (ULONG)strlen(Value), (PVOID*)&Page->Data,
&Page->Length);
- if (!NT_SUCCESS(Status))
- goto fail2;
-
- FrontendStoreFree(Frontend, Value);
- return TRUE;
-
-fail2:
- FrontendStoreFree(Frontend, Value);
-fail1:
- Page->Data = NULL;
- Page->Length = 0;
- return FALSE;
-}
-
-static FORCEINLINE BOOLEAN
-__HandlePageStd(
- __in PSCSI_REQUEST_BLOCK Srb
- )
-{
- PINQUIRYDATA Data = (PINQUIRYDATA)Srb->DataBuffer;
- ULONG Length = Srb->DataTransferLength;
-
- if (Length < INQUIRYDATABUFFERSIZE)
- return FALSE;
-
- Data->DeviceType = DIRECT_ACCESS_DEVICE;
- Data->DeviceTypeQualifier = DEVICE_CONNECTED;
- Data->Versions = 4;
- Data->ResponseDataFormat = 2;
- Data->AdditionalLength = INQUIRYDATABUFFERSIZE - 4;
- Data->CommandQueue = 1;
- RtlCopyMemory(Data->VendorId, "XENSRC ", 8);
- RtlCopyMemory(Data->ProductId, "PVDISK ", 16);
- RtlCopyMemory(Data->ProductRevisionLevel, "2.0 ", 4);
-
- Srb->DataTransferLength = INQUIRYDATABUFFERSIZE;
- return TRUE;
-}
-static FORCEINLINE BOOLEAN
-__HandlePage00(
- __in PSCSI_REQUEST_BLOCK Srb
- )
-{
- PCHAR Data = (PCHAR)Srb->DataBuffer;
- ULONG Length = Srb->DataTransferLength;
-
- if (Length < 7)
- return FALSE;
- RtlZeroMemory(Data, Length);
-
- // 00 00 00 NumPages+1 00 [Page [...]]
- Data[3] = 3;
- Data[4] = 0x00;
- Data[5] = 0x80;
- Data[6] = 0x83;
- Srb->DataTransferLength = 7;
-
- return TRUE;
-}
-static FORCEINLINE BOOLEAN
-__HandlePage80(
- __in ULONG TargetId,
- __in PXENVBD_INQUIRY Inquiry,
- __in PSCSI_REQUEST_BLOCK Srb
- )
-{
- PCHAR Data = (PCHAR)Srb->DataBuffer;
- ULONG Length = Srb->DataTransferLength;
-
- RtlZeroMemory(Data, Length);
- if (Inquiry == NULL ||
- Inquiry->Page80.Data == NULL ||
- Inquiry->Page80.Length == 0) {
- // generate the serial number page
- PVPD_SERIAL_NUMBER_PAGE Serial;
- if (Length < sizeof(VPD_SERIAL_NUMBER_PAGE) + 4)
- return FALSE;
-
- Serial = (PVPD_SERIAL_NUMBER_PAGE)Data;
- Serial->PageCode = 0x80;
- Serial->PageLength = 4;
- (VOID) RtlStringCchPrintfA((PCHAR)Serial->SerialNumber, 5, "%04u",
TargetId);
-
- Verbose("Target[%u] : INQUIRY Using Fake Page80 Data\n", TargetId);
-
- Srb->DataTransferLength = sizeof(VPD_SERIAL_NUMBER_PAGE) + 4;
- // VPD_SERIAL_NUMBER_PAGE includes 1 char already
- } else {
- if (Length < Inquiry->Page80.Length)
- return FALSE;
-
- RtlCopyMemory(Data, Inquiry->Page80.Data,
Inquiry->Page80.Length);
- Srb->DataTransferLength = Inquiry->Page80.Length;
- }
-
- // if possible, append additional data
- //if (Inquiry && Length >= Srb->DataTransferLength + ADDITIONAL_LENGTH) {
- // Srb->DataTransferLength += ADDITIONAL_LENGTH;
- //}
- return TRUE;
-}
-static FORCEINLINE BOOLEAN
-__HandlePage83(
- __in ULONG TargetId,
- __in PXENVBD_INQUIRY Inquiry,
- __in PSCSI_REQUEST_BLOCK Srb
- )
-{
- PCHAR Data = (PCHAR)Srb->DataBuffer;
- ULONG Length = Srb->DataTransferLength;
-
- RtlZeroMemory(Data, Length);
- if (Inquiry == NULL ||
- Inquiry->Page83.Data == NULL ||
- Inquiry->Page83.Length == 0) {
- // generate the id page data
- PVPD_IDENTIFICATION_DESCRIPTOR Id;
- CHAR Buffer[17];
-
- if (Length < PAGE83_MIN_SIZE)
- return FALSE;
-
- Data[1] = 0x83;
- Data[3] = 16;
-
- Id = (PVPD_IDENTIFICATION_DESCRIPTOR)(Data + 4);
- Id->CodeSet = VpdCodeSetAscii;
- Id->IdentifierType = VpdIdentifierTypeVendorId;
- Id->IdentifierLength = 16;
- (VOID)RtlStringCchPrintfA(Buffer, 17, "XENSRC %08u", TargetId);
- RtlCopyMemory((PCHAR)Id->Identifier, Buffer, 16);
-
- Verbose("Target[%u] : INQUIRY Using Fake Page83 Data\n", TargetId);
-
- Srb->DataTransferLength = PAGE83_MIN_SIZE;
- } else {
- if (Length < Inquiry->Page83.Length)
- return FALSE;
-
- RtlCopyMemory(Data, Inquiry->Page83.Data, Inquiry->Page83.Length);
- Srb->DataTransferLength = Inquiry->Page83.Length;
- }
-
- // if possible, append vdi-uuid as VendorSpecific
- if (Inquiry && Length >= Srb->DataTransferLength + VDI_ID_LENGTH) {
- PVPD_IDENTIFICATION_DESCRIPTOR Id;
-
- // update internal size
- *(Data + 3) += VDI_ID_LENGTH;
-
- // copy new data
- Id = (PVPD_IDENTIFICATION_DESCRIPTOR)(Data + Srb->DataTransferLength);
- Id->CodeSet = VpdCodeSetAscii;
- Id->IdentifierType = VpdIdentifierTypeVendorSpecific;
- Id->IdentifierLength = GUID_LENGTH;
- RtlCopyMemory(Id->Identifier, Inquiry->VdiUuid, GUID_LENGTH);
-
- Srb->DataTransferLength += VDI_ID_LENGTH;
- }
- return TRUE;
-}
-
-#define MAX_BUFFER 64
-
-static FORCEINLINE VOID
-__TracePage80(
- __in ULONG TargetId,
- __in PXENVBD_INQUIRY Inquiry
- )
-{
- ULONG Length;
- CHAR Buffer[MAX_BUFFER+1];
-
- Length = __Min3(Inquiry->Page80.Data[3], MAX_BUFFER,
Inquiry->Page80.Length - 4);
- RtlCopyMemory(Buffer, Inquiry->Page80.Data + 4, Length);
- Buffer[Length] = 0;
- Verbose("Target[%u] : SerialNumber = \"%s\"\n", TargetId, Buffer);
-}
-static FORCEINLINE VOID
-__TracePage83(
- __in ULONG TargetId,
- __in PXENVBD_INQUIRY Inquiry
- )
-{
- ULONG Length;
- ULONG Index;
- CHAR Buffer[MAX_BUFFER+1];
-
- for (Index = 4; Index < Inquiry->Page83.Length; ) {
- PVPD_IDENTIFICATION_DESCRIPTOR Identifier =
(PVPD_IDENTIFICATION_DESCRIPTOR)&Inquiry->Page83.Data[Index];
-
- switch (Identifier->CodeSet) {
- case VpdCodeSetAscii:
- Length = __Min3(Identifier->IdentifierLength, MAX_BUFFER,
Inquiry->Page83.Length - Index - 4);
- RtlCopyMemory(Buffer, Identifier->Identifier, Length);
- Buffer[Length] = 0;
- Verbose("Target[%u] : Identifier (ASCII, Type %02x, \"%s\")\n",
- TargetId, Identifier->IdentifierType, Buffer);
- break;
-
- default:
- Verbose("Target[%u] : Identifier (CodeSet %02x, Type %02x, Length
%02x)\n",
- TargetId, Identifier->CodeSet, Identifier->IdentifierType,
Identifier->IdentifierLength);
- break;
- }
-
- Index += (4 + Identifier->IdentifierLength);
- }
-}
-
-VOID
-#pragma warning(suppress: 28195)
-PdoReadInquiryData(
- __in PXENVBD_FRONTEND Frontend,
- __out __drv_allocatesMem(mem) PVOID* _Inquiry
- )
-{
- PXENVBD_INQUIRY Inquiry;
- const CHAR GuidNull[] = "00000000-0000-0000-0000-000000000000";
- const ULONG TargetId = FrontendGetTargetId(Frontend);
-
- *_Inquiry = NULL;
- Inquiry = (PXENVBD_INQUIRY)__InquiryAlloc(sizeof(XENVBD_INQUIRY));
- if (Inquiry == NULL) {
- Error("Target[%d] : Memory allocation getting INQUIRY data (%d bytes
failed)\n",
- TargetId, sizeof(XENVBD_INQUIRY));
- return;
- }
-
- // initialize VDI-UUID
- RtlCopyMemory(Inquiry->VdiUuid, GuidNull, GUID_LENGTH);
- Inquiry->VdiUuid[GUID_LENGTH] = 0;
-
- // read page80
- if (!__ReadPage(Frontend, &Inquiry->Page80, "sm-data/scsi/0x12/0x80")) {
- Warning("Target[%d] : Failed to get Page80 data\n", TargetId);
- } else {
- __TracePage80(TargetId, Inquiry);
- }
-
- // read page83
- if (!__ReadPage(Frontend, &Inquiry->Page83, "sm-data/scsi/0x12/0x83")) {
- Warning("Target[%d] : Failed to get Page83 data\n", TargetId);
- } else {
- __TracePage83(TargetId, Inquiry);
- }
-
- *_Inquiry = Inquiry;
-}
-
-VOID
-PdoFreeInquiryData(
- __in __drv_freesMem(mem) PVOID _Inquiry
- )
-{
- PXENVBD_INQUIRY Inquiry = (PXENVBD_INQUIRY)_Inquiry;
-
- if (_Inquiry == NULL)
- return;
-
- __InquiryFree((PVOID)Inquiry->Page80.Data);
- __InquiryFree((PVOID)Inquiry->Page83.Data);
- __InquiryFree((PVOID)Inquiry);
-}
-
-VOID
-PdoUpdateInquiryData(
- __in PXENVBD_FRONTEND Frontend,
- __in PVOID _Inquiry
- )
-{
- PXENVBD_INQUIRY Inquiry = (PXENVBD_INQUIRY)_Inquiry;
- NTSTATUS Status;
- PCHAR Value;
- ULONG Length;
- const CHAR GuidNull[] = "00000000-0000-0000-0000-000000000000";
-
- if (_Inquiry == NULL)
- return;
-
- RtlCopyMemory(Inquiry->VdiUuid, GuidNull, GUID_LENGTH);
- Inquiry->VdiUuid[GUID_LENGTH] = 0;
-
- Status = FrontendStoreReadBackend(Frontend, "sm-data/vdi-uuid", &Value);
- if (NT_SUCCESS(Status)) {
- Length = (ULONG)strlen(Value);
-
- if (Length == GUID_LENGTH) {
- RtlCopyMemory(Inquiry->VdiUuid, Value, Length);
- Inquiry->VdiUuid[GUID_LENGTH] = 0;
- }
-
- FrontendStoreFree(Frontend, Value);
- }
-
- Verbose("Target[%u] : VDI-UUID = {%s}\n", FrontendGetTargetId(Frontend),
Inquiry->VdiUuid);
-}
-
-VOID
-PdoInquiry(
- __in ULONG TargetId,
- __in PVOID Inquiry,
- __in PSCSI_REQUEST_BLOCK Srb
- )
-{
- BOOLEAN Success;
- const UCHAR Evpd = Cdb_EVPD(Srb);
- const UCHAR PageCode = Cdb_PageCode(Srb);
-
- Trace("Target[%d] : INQUIRY %02x%s\n", TargetId, PageCode, Evpd ? " EVPD"
: "");
- if (Evpd) {
- switch (PageCode) {
- case 0x00: Success = __HandlePage00(Srb); break;
- case 0x80: Success = __HandlePage80(TargetId,
(PXENVBD_INQUIRY)Inquiry, Srb); break;
- case 0x83: Success = __HandlePage83(TargetId,
(PXENVBD_INQUIRY)Inquiry, Srb); break;
- default: Success = FALSE; break;
- }
- } else {
- switch (PageCode) {
- case 0x00: Success = __HandlePageStd(Srb); break;
- default: Success = FALSE; break;
- }
- }
-
- if (Success) {
- Srb->ScsiStatus = 0; /* SUCCESS */
- Srb->SrbStatus = SRB_STATUS_SUCCESS;
- } else {
- Error("Target[%d] : INQUIRY failed %02x%s\n", TargetId, PageCode, Evpd
? " EVPD" : "");
- Srb->ScsiStatus = 0x02; /* CHECK_CONDITION */
- Srb->SrbStatus = SRB_STATUS_ERROR;
- }
-}
diff --git a/src/xenvbd/pdoinquiry.h b/src/xenvbd/pdoinquiry.h
deleted file mode 100644
index a8cb155..0000000
--- a/src/xenvbd/pdoinquiry.h
+++ /dev/null
@@ -1,64 +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_PDO_INQUIRY_H
-#define _XENVBD_PDO_INQUIRY_H
-
-#include <ntddk.h>
-#include <xenvbd-storport.h>
-#include "frontend.h"
-
-extern VOID
-PdoReadInquiryData(
- __in PXENVBD_FRONTEND Frontend,
- __out __drv_allocatesMem(mem) PVOID* _Inquiry
- );
-
-extern VOID
-PdoFreeInquiryData(
- __in __drv_freesMem(mem) PVOID Inquiry
- );
-
-extern VOID
-PdoUpdateInquiryData(
- __in PXENVBD_FRONTEND Frontend,
- __in PVOID _Inquiry
- );
-
-extern VOID
-PdoInquiry(
- __in ULONG TargetId,
- __in PVOID Inquiry,
- __in PSCSI_REQUEST_BLOCK Srb
- );
-
-#endif // _XENVBD_PDO_INQUIRY_H
-
diff --git a/src/xenvbd/queue.c b/src/xenvbd/queue.c
deleted file mode 100644
index fc70459..0000000
--- a/src/xenvbd/queue.c
+++ /dev/null
@@ -1,139 +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 "queue.h"
-#include "debug.h"
-#include "assert.h"
-
-VOID
-QueueInit(
- __in PXENVBD_QUEUE Queue
- )
-{
- RtlZeroMemory(Queue, sizeof(XENVBD_QUEUE));
- KeInitializeSpinLock(&Queue->Lock);
- InitializeListHead(&Queue->List);
-}
-
-ULONG
-QueueCount(
- __in PXENVBD_QUEUE Queue
- )
-{
- return Queue->Current;
-}
-
-__checkReturn
-PLIST_ENTRY
-QueuePop(
- __in PXENVBD_QUEUE Queue
- )
-{
- KIRQL Irql;
- PLIST_ENTRY Entry = NULL;
-
- KeAcquireSpinLock(&Queue->Lock, &Irql);
-
- if (!IsListEmpty(&Queue->List)) {
- Entry = RemoveHeadList(&Queue->List);
- ASSERT3P(Entry, !=, &Queue->List);
- --Queue->Current;
- }
-
- KeReleaseSpinLock(&Queue->Lock, Irql);
-
- return Entry;
-}
-
-VOID
-QueueUnPop(
- __in PXENVBD_QUEUE Queue,
- __in PLIST_ENTRY Entry
- )
-{
- KIRQL Irql;
-
- KeAcquireSpinLock(&Queue->Lock, &Irql);
-
- InsertHeadList(&Queue->List, Entry);
- if (++Queue->Current > Queue->Maximum)
- Queue->Maximum = Queue->Current;
-
- KeReleaseSpinLock(&Queue->Lock, Irql);
-}
-
-VOID
-QueueAppend(
- __in PXENVBD_QUEUE Queue,
- __in PLIST_ENTRY Entry
- )
-{
- KIRQL Irql;
-
- KeAcquireSpinLock(&Queue->Lock, &Irql);
-
- InsertTailList(&Queue->List, Entry);
- if (++Queue->Current > Queue->Maximum)
- Queue->Maximum = Queue->Current;
-
- KeReleaseSpinLock(&Queue->Lock, Irql);
-}
-
-VOID
-QueueRemove(
- __in PXENVBD_QUEUE Queue,
- __in PLIST_ENTRY Entry
- )
-{
- KIRQL Irql;
-
- KeAcquireSpinLock(&Queue->Lock, &Irql);
-
- RemoveEntryList(Entry);
- --Queue->Current;
-
- KeReleaseSpinLock(&Queue->Lock, Irql);
-}
-
-VOID
-QueueDebugCallback(
- __in PXENVBD_QUEUE Queue,
- __in __nullterminated const CHAR* Name,
- __in PXENBUS_DEBUG_INTERFACE Debug
- )
-{
- XENBUS_DEBUG(Printf, Debug,
- "QUEUE: %s : %u / %u\n",
- Name, Queue->Current, Queue->Maximum);
-
- Queue->Maximum = Queue->Current;
-}
-
diff --git a/src/xenvbd/queue.h b/src/xenvbd/queue.h
deleted file mode 100644
index 0434198..0000000
--- a/src/xenvbd/queue.h
+++ /dev/null
@@ -1,86 +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_QUEUE_H
-#define _XENVBD_QUEUE_H
-
-#include <ntddk.h>
-#include <debug_interface.h>
-
-typedef struct _XENVBD_QUEUE {
- KSPIN_LOCK Lock;
- LIST_ENTRY List;
- ULONG Current;
- ULONG Maximum;
-} XENVBD_QUEUE, *PXENVBD_QUEUE;
-
-extern VOID
-QueueInit(
- __in PXENVBD_QUEUE Queue
- );
-
-extern ULONG
-QueueCount(
- __in PXENVBD_QUEUE Queue
- );
-
-__checkReturn
-extern PLIST_ENTRY
-QueuePop(
- __in PXENVBD_QUEUE Queue
- );
-
-extern VOID
-QueueUnPop(
- __in PXENVBD_QUEUE Queue,
- __in PLIST_ENTRY Entry
- );
-
-extern VOID
-QueueAppend(
- __in PXENVBD_QUEUE Queue,
- __in PLIST_ENTRY Entry
- );
-
-extern VOID
-QueueRemove(
- __in PXENVBD_QUEUE Queue,
- __in PLIST_ENTRY Entry
- );
-
-extern VOID
-QueueDebugCallback(
- __in PXENVBD_QUEUE Queue,
- __in __nullterminated const CHAR* Name,
- __in PXENBUS_DEBUG_INTERFACE Debug
- );
-
-#endif // _XENVBD_QUEUE_H
diff --git a/src/xenvbd/srbext.h b/src/xenvbd/srbext.h
index 51b5e77..2e79de8 100644
--- a/src/xenvbd/srbext.h
+++ b/src/xenvbd/srbext.h
@@ -37,6 +37,27 @@
#include <xen.h>
#include "assert.h"
+typedef struct _XENVBD_SRBEXT {
+ PSCSI_REQUEST_BLOCK Srb;
+ LIST_ENTRY ListEntry;
+ LONG RequestCount;
+} XENVBD_SRBEXT, *PXENVBD_SRBEXT;
+
+typedef struct _XENVBD_REQUEST {
+ PXENVBD_SRBEXT SrbExt;
+ LIST_ENTRY ListEntry;
+ ULONG64 Id; // = (ULONG64)(ULONG_PTR)this
+
+ UCHAR Operation; //
BLKIF_OP_{READ/WRITE/BARRIER/DISCARD}
+ UCHAR Flags; // BLKIF_OP_DISCARD only
+ USHORT NrSegments; // BLKIF_OP_{READ/WRITE} only, 0-11
(direct) or 11-4096 (indirect)
+ LIST_ENTRY Segments; // BLKIF_OP_{READ/WRITE} only
+
+ ULONG64 FirstSector;
+ ULONG64 NrSectors; // BLKIF_OP_DISCARD only
+ LIST_ENTRY Indirects; // BLKIF_OP_{READ/WRITE} with
NrSegments > 11 only
+} XENVBD_REQUEST, *PXENVBD_REQUEST;
+
#pragma pack(push, 1)
typedef struct _BLKIF_SEGMENT {
ULONG GrantRef;
@@ -46,19 +67,18 @@ typedef struct _BLKIF_SEGMENT {
} BLKIF_SEGMENT, *PBLKIF_SEGMENT;
#pragma pack(pop)
-#define XENVBD_MAX_SEGMENTS_PER_PAGE (PAGE_SIZE / sizeof(BLKIF_SEGMENT))
+#define XENVBD_MAX_SEGMENTS_PER_PAGE (PAGE_SIZE / sizeof(BLKIF_SEGMENT))
+#define XENVBD_MAX_SEGMENTS_PER_INDIRECT (XENVBD_MAX_SEGMENTS_PER_PAGE * 2)
// limited Indirecting
-// Internal indirect context
typedef struct _XENVBD_INDIRECT {
- LIST_ENTRY Entry;
+ LIST_ENTRY ListEntry;
PBLKIF_SEGMENT Page;
PVOID Grant;
PMDL Mdl;
} XENVBD_INDIRECT, *PXENVBD_INDIRECT;
-// Internal segment context
typedef struct _XENVBD_SEGMENT {
- LIST_ENTRY Entry;
+ LIST_ENTRY ListEntry;
PVOID Grant;
UCHAR FirstSector;
UCHAR LastSector;
@@ -69,27 +89,4 @@ typedef struct _XENVBD_SEGMENT {
PFN_NUMBER Pfn[2];
} XENVBD_SEGMENT, *PXENVBD_SEGMENT;
-// Internal request context
-typedef struct _XENVBD_REQUEST {
- PSCSI_REQUEST_BLOCK Srb;
- LIST_ENTRY Entry;
- ULONG Id;
-
- UCHAR Operation; //
BLKIF_OP_{READ/WRITE/BARRIER/DISCARD}
- UCHAR Flags; // BLKIF_OP_DISCARD only
- USHORT NrSegments; // BLKIF_OP_{READ/WRITE} only, 0-11
(direct) or 11-4096 (indirect)
- LIST_ENTRY Segments; // BLKIF_OP_{READ/WRITE} only
-
- ULONG64 FirstSector;
- ULONG64 NrSectors; // BLKIF_OP_DISCARD only
- LIST_ENTRY Indirects; // BLKIF_OP_{READ/WRITE} with
NrSegments > 11 only
-} XENVBD_REQUEST, *PXENVBD_REQUEST;
-
-// SRBExtension - context for SRBs
-typedef struct _XENVBD_SRBEXT {
- PSCSI_REQUEST_BLOCK Srb;
- LIST_ENTRY ListEntry;
- LONG RequestCount;
-} XENVBD_SRBEXT, *PXENVBD_SRBEXT;
-
#endif // _XENVBD_SRBEXT_H
diff --git a/src/xenvbd/target.c b/src/xenvbd/target.c
index c939738..5b14a73 100644
--- a/src/xenvbd/target.c
+++ b/src/xenvbd/target.c
@@ -37,25 +37,91 @@
#include <xencdb.h>
#include <names.h>
#include <store_interface.h>
-#include <evtchn_interface.h>
-#include <gnttab_interface.h>
#include <debug_interface.h>
#include <suspend_interface.h>
#include "target.h"
#include "driver.h"
#include "adapter.h"
-#include "frontend.h"
-#include "queue.h"
+#include "thread.h"
#include "srbext.h"
#include "buffer.h"
-#include "pdoinquiry.h"
+#include "granter.h"
+#include "blockring.h"
#include "util.h"
#include "debug.h"
#include "assert.h"
-#define XENVBD_MAX_QUEUE_DEPTH (254)
+#define TARGET_POOL_TAG 'raTX'
+#define REQUEST_POOL_TAG 'qeRX'
+#define SEGMENT_POOL_TAG 'geSX'
+#define INDIRECT_POOL_TAG 'dnIX'
+#define XENVBD_MAX_QUEUE_DEPTH (254)
+
+typedef enum _XENVBD_STATE {
+ XENVBD_STATE_INVALID,
+ XENVBD_INITIALIZED, // -> { CLOSED }
+ XENVBD_CLOSING, // -> { CLOSED }
+ XENVBD_CLOSED, // -> { PREPARED }
+ XENVBD_PREPARED, // -> { CLOSING, CONNECTED }
+ XENVBD_CONNECTED, // -> { ENABLED, CLOSING }
+ XENVBD_ENABLED // -> { CLOSING }
+} XENVBD_STATE;
+
+struct _XENVBD_TARGET {
+ PXENVBD_ADAPTER Adapter;
+ PDEVICE_OBJECT DeviceObject;
+ DEVICE_PNP_STATE PrevPnpState;
+ DEVICE_PNP_STATE DevicePnpState;
+ DEVICE_POWER_STATE DevicePowerState;
+ XENVBD_STATE State;
+ KSPIN_LOCK StateLock;
+ KSPIN_LOCK QueueLock;
+ BOOLEAN Missing;
+ PXENVBD_GRANTER Granter;
+ PXENVBD_BLOCKRING BlockRing;
+
+ ULONG DeviceId;
+ ULONG TargetId;
+ PCHAR Path;
+ PCHAR TargetPath;
+ PCHAR BackendPath;
+ USHORT BackendId;
+
+ BOOLEAN DeviceUsage[4];
+ ULONG64 SectorCount;
+ ULONG SectorSize;
+ ULONG PhysicalSectorSize;
+ ULONG DiskInfo;
+ BOOLEAN Removable;
+ BOOLEAN FeatureBarrier;
+ BOOLEAN FeatureFlush;
+ BOOLEAN FeatureDiscard;
+ BOOLEAN DiscardSecure;
+ ULONG DiscardAlignment;
+ ULONG DiscardGranularity;
+ ULONG FeatureIndirect;
+
+ XENBUS_DEBUG_INTERFACE DebugInterface;
+ XENBUS_SUSPEND_INTERFACE SuspendInterface;
+ XENBUS_STORE_INTERFACE StoreInterface;
+
+ PXENBUS_DEBUG_CALLBACK DebugCallback;
+ PXENBUS_SUSPEND_CALLBACK SuspendCallback;
+
+ PXENVBD_THREAD BackendThread;
+ PXENBUS_STORE_WATCH BackendWatch;
+
+ LIST_ENTRY Fresh;
+ LIST_ENTRY Prepared;
+ LIST_ENTRY Submitted;
+ LIST_ENTRY Shutdown;
+
+ NPAGED_LOOKASIDE_LIST RequestList;
+ NPAGED_LOOKASIDE_LIST SegmentList;
+ NPAGED_LOOKASIDE_LIST IndirectList;
+};
typedef struct _XENVBD_SG_LIST {
// SGList from SRB
@@ -69,182 +135,129 @@ typedef struct _XENVBD_SG_LIST {
ULONG Length;
} XENVBD_SG_LIST, *PXENVBD_SG_LIST;
-#define TARGET_SIGNATURE 'odpX'
+static FORCEINLINE VOID
+SGListInit(
+ IN OUT PXENVBD_SG_LIST SGList,
+ IN PVOID Adapter,
+ IN PSCSI_REQUEST_BLOCK Srb
+ )
+{
+ RtlZeroMemory(SGList, sizeof(XENVBD_SG_LIST));
+ SGList->SGList = StorPortGetScatterGatherList(Adapter, Srb);
+}
-typedef struct _XENVBD_LOOKASIDE {
- KEVENT Empty;
- LONG Used;
- LONG Max;
- ULONG Failed;
- ULONG Size;
- NPAGED_LOOKASIDE_LIST List;
-} XENVBD_LOOKASIDE, *PXENVBD_LOOKASIDE;
+static FORCEINLINE VOID
+SGListGet(
+ IN OUT PXENVBD_SG_LIST SGList
+ )
+{
+ PSTOR_SCATTER_GATHER_ELEMENT SGElement;
+ ULONG Offset;
-struct _XENVBD_TARGET {
- ULONG Signature;
- PXENVBD_ADAPTER Adapter;
- PDEVICE_OBJECT DeviceObject;
- DEVICE_PNP_STATE DevicePnpState;
- DEVICE_PNP_STATE PrevPnpState;
- DEVICE_POWER_STATE DevicePowerState;
- KSPIN_LOCK Lock;
+ ASSERT3U(SGList->Index, <, SGList->SGList->NumberOfElements);
- // Frontend (Ring, includes XenBus interfaces)
- PXENVBD_FRONTEND Frontend;
+ SGElement = &SGList->SGList->List[SGList->Index];
- // State
- LONG Paused;
+ SGList->PhysAddr.QuadPart = SGElement->PhysicalAddress.QuadPart +
SGList->Offset;
+ Offset = (ULONG)(SGList->PhysAddr.QuadPart & (PAGE_SIZE - 1));
+ SGList->PhysLen = __min(PAGE_SIZE - Offset - SGList->Length,
+ SGElement->Length - SGList->Offset);
- // Eject
- BOOLEAN WrittenEjected;
- BOOLEAN EjectRequested;
- BOOLEAN EjectPending;
- BOOLEAN Missing;
- const CHAR* Reason;
-
- // SRBs
- XENVBD_LOOKASIDE RequestList;
- XENVBD_LOOKASIDE SegmentList;
- XENVBD_LOOKASIDE IndirectList;
- XENVBD_QUEUE FreshSrbs;
- XENVBD_QUEUE PreparedReqs;
- XENVBD_QUEUE SubmittedReqs;
- XENVBD_QUEUE ShutdownSrbs;
- ULONG NextTag;
-
- // Stats - SRB Counts by BLKIF_OP_
- ULONG BlkOpRead;
- ULONG BlkOpWrite;
- ULONG BlkOpIndirectRead;
- ULONG BlkOpIndirectWrite;
- ULONG BlkOpBarrier;
- ULONG BlkOpDiscard;
- ULONG BlkOpFlush;
- // Stats - Failures
- ULONG FailedMaps;
- ULONG FailedBounces;
- ULONG FailedGrants;
- // Stats - Segments
- ULONG64 SegsGranted;
- ULONG64 SegsBounced;
-};
+ ASSERT3U(SGList->PhysLen, <=, PAGE_SIZE);
+ ASSERT3U(SGList->Offset, <, SGElement->Length);
-//=============================================================================
-#define TARGET_POOL_TAG 'odPX'
-#define REQUEST_POOL_TAG 'qeRX'
-#define SEGMENT_POOL_TAG 'geSX'
-#define INDIRECT_POOL_TAG 'dnIX'
+ SGList->Length = SGList->PhysLen; // gets reset every time for Granted,
every 1or2 times for Bounced
+ SGList->Offset = SGList->Offset + SGList->PhysLen;
+ if (SGList->Offset >= SGElement->Length) {
+ SGList->Index = SGList->Index + 1;
+ SGList->Offset = 0;
+ }
+}
-__checkReturn
-__drv_allocatesMem(mem)
-__bcount(Size)
-static FORCEINLINE PVOID
-#pragma warning(suppress: 28195)
-__TargetAlloc(
- __in ULONG Size
+static FORCEINLINE BOOLEAN
+SGListNext(
+ IN OUT PXENVBD_SG_LIST SGList,
+ IN ULONG AlignmentMask
)
{
- return __AllocatePoolWithTag(NonPagedPool, Size, TARGET_POOL_TAG);
+ SGList->Length = 0;
+ SGListGet(SGList); // get next PhysAddr and PhysLen
+ return !((SGList->PhysAddr.QuadPart & AlignmentMask) || (SGList->PhysLen &
AlignmentMask));
}
-static FORCEINLINE VOID
-#pragma warning(suppress: 28197)
-__TargetFree(
- __in __drv_freesMem(mem) PVOID Buffer
+static FORCEINLINE PFN_NUMBER
+SGListPfn(
+ IN PXENVBD_SG_LIST SGList
)
{
- if (Buffer)
- __FreePoolWithTag(Buffer, TARGET_POOL_TAG);
+ return (PFN_NUMBER)(SGList->PhysAddr.QuadPart >> PAGE_SHIFT);
}
-//=============================================================================
-// Lookasides
-static FORCEINLINE VOID
-__LookasideInit(
- IN OUT PXENVBD_LOOKASIDE Lookaside,
- IN ULONG Size,
- IN ULONG Tag
+static FORCEINLINE ULONG
+SGListOffset(
+ IN PXENVBD_SG_LIST SGList
)
{
- RtlZeroMemory(Lookaside, sizeof(XENVBD_LOOKASIDE));
- Lookaside->Size = Size;
- KeInitializeEvent(&Lookaside->Empty, SynchronizationEvent, TRUE);
- ExInitializeNPagedLookasideList(&Lookaside->List, NULL, NULL, 0,
- Size, Tag, 0);
+ return (ULONG)(SGList->PhysAddr.QuadPart & (PAGE_SIZE - 1));
}
-static FORCEINLINE VOID
-__LookasideTerm(
- IN PXENVBD_LOOKASIDE Lookaside
+static FORCEINLINE ULONG
+SGListLength(
+ IN PXENVBD_SG_LIST SGList
)
{
- ASSERT3U(Lookaside->Used, ==, 0);
- ExDeleteNPagedLookasideList(&Lookaside->List);
- RtlZeroMemory(Lookaside, sizeof(XENVBD_LOOKASIDE));
+ return SGList->PhysLen;
}
static FORCEINLINE PVOID
-__LookasideAlloc(
- IN PXENVBD_LOOKASIDE Lookaside
+__TargetAllocate(
+ IN ULONG Size
)
{
- LONG Result;
- PVOID Buffer;
-
- Buffer = ExAllocateFromNPagedLookasideList(&Lookaside->List);
- if (Buffer == NULL) {
- ++Lookaside->Failed;
- return NULL;
- }
-
- RtlZeroMemory(Buffer, Lookaside->Size);
- Result = InterlockedIncrement(&Lookaside->Used);
- ASSERT3S(Result, >, 0);
- if (Result > Lookaside->Max)
- Lookaside->Max = Result;
- KeClearEvent(&Lookaside->Empty);
-
+ PVOID Buffer;
+ Buffer = ExAllocatePoolWithTag(NonPagedPool,
+ Size,
+ TARGET_POOL_TAG);
+ if (Buffer)
+ RtlZeroMemory(Buffer, Size);
return Buffer;
}
static FORCEINLINE VOID
-__LookasideFree(
- IN PXENVBD_LOOKASIDE Lookaside,
- IN PVOID Buffer
+__TargetFree(
+ IN PVOID Buffer
)
{
- LONG Result;
+ if (Buffer)
+ ExFreePoolWithTag(Buffer, TARGET_POOL_TAG);
+}
- ExFreeToNPagedLookasideList(&Lookaside->List, Buffer);
- Result = InterlockedDecrement(&Lookaside->Used);
- ASSERT3S(Result, >=, 0);
-
- if (Result == 0) {
- KeSetEvent(&Lookaside->Empty, IO_NO_INCREMENT, FALSE);
- }
+#define TARGET_GET_PROPERTY(_name, _type) \
+_type \
+TargetGet ## _name ## ( \
+ IN PXENVBD_TARGET Target \
+ ) \
+{ \
+ return Target-> ## _name ## ; \
}
-static FORCEINLINE VOID
-__LookasideDebug(
- IN PXENVBD_LOOKASIDE Lookaside,
- IN PXENBUS_DEBUG_INTERFACE Debug,
- IN PCHAR Name
- )
-{
- XENBUS_DEBUG(Printf, Debug,
- "LOOKASIDE: %s: %u / %u (%u failed)\n",
- Name, Lookaside->Used,
- Lookaside->Max, Lookaside->Failed);
+TARGET_GET_PROPERTY(DeviceId, ULONG)
+TARGET_GET_PROPERTY(TargetId, ULONG)
+TARGET_GET_PROPERTY(DeviceObject, PDEVICE_OBJECT)
+TARGET_GET_PROPERTY(Missing, BOOLEAN)
+TARGET_GET_PROPERTY(DevicePnpState, DEVICE_PNP_STATE)
+TARGET_GET_PROPERTY(Adapter, PXENVBD_ADAPTER)
+TARGET_GET_PROPERTY(Granter, PXENVBD_GRANTER)
+TARGET_GET_PROPERTY(Path, PCHAR)
+TARGET_GET_PROPERTY(BackendPath, PCHAR)
+TARGET_GET_PROPERTY(BackendId, USHORT)
+TARGET_GET_PROPERTY(Removable, BOOLEAN)
- Lookaside->Max = Lookaside->Used;
- Lookaside->Failed = 0;
-}
+#undef TARGET_GET_PROPERTY
-//=============================================================================
-// Debug
static FORCEINLINE PCHAR
-__PnpStateName(
- __in DEVICE_PNP_STATE State
+DevicePnpStateName(
+ IN DEVICE_PNP_STATE State
)
{
switch (State) {
@@ -258,294 +271,81 @@ __PnpStateName(
case RemovePending: return "RemovePending";
case SurpriseRemovePending: return "SurpriseRemovePending";
case Deleted: return "Deleted";
- default: return "UNKNOWN";
- }
-}
-
-DECLSPEC_NOINLINE VOID
-TargetDebugCallback(
- __in PXENVBD_TARGET Target,
- __in PXENBUS_DEBUG_INTERFACE DebugInterface
- )
-{
- if (Target == NULL || DebugInterface == NULL)
- return;
- if (Target->Signature != TARGET_SIGNATURE)
- return;
-
- XENBUS_DEBUG(Printf, DebugInterface,
- "TARGET: Adapter 0x%p DeviceObject 0x%p\n",
- Target->Adapter,
- Target->DeviceObject);
- XENBUS_DEBUG(Printf, DebugInterface,
- "TARGET: DevicePnpState %s (%s)\n",
- __PnpStateName(Target->DevicePnpState),
- __PnpStateName(Target->PrevPnpState));
- XENBUS_DEBUG(Printf, DebugInterface,
- "TARGET: DevicePowerState %s\n",
- PowerDeviceStateName(Target->DevicePowerState));
- XENBUS_DEBUG(Printf, DebugInterface,
- "TARGET: %s\n",
- Target->Missing ? Target->Reason : "Not Missing");
-
- XENBUS_DEBUG(Printf, DebugInterface,
- "TARGET: BLKIF_OPs: READ=%u WRITE=%u\n",
- Target->BlkOpRead, Target->BlkOpWrite);
- XENBUS_DEBUG(Printf, DebugInterface,
- "TARGET: BLKIF_OPs: INDIRECT_READ=%u INDIRECT_WRITE=%u\n",
- Target->BlkOpIndirectRead, Target->BlkOpIndirectWrite);
- XENBUS_DEBUG(Printf, DebugInterface,
- "TARGET: BLKIF_OPs: BARRIER=%u DISCARD=%u FLUSH=%u\n",
- Target->BlkOpBarrier, Target->BlkOpDiscard,
Target->BlkOpFlush);
- XENBUS_DEBUG(Printf, DebugInterface,
- "TARGET: Failed: Maps=%u Bounces=%u Grants=%u\n",
- Target->FailedMaps, Target->FailedBounces,
Target->FailedGrants);
- XENBUS_DEBUG(Printf, DebugInterface,
- "TARGET: Segments Granted=%llu Bounced=%llu\n",
- Target->SegsGranted, Target->SegsBounced);
-
- __LookasideDebug(&Target->RequestList, DebugInterface, "REQUESTs");
- __LookasideDebug(&Target->SegmentList, DebugInterface, "SEGMENTs");
- __LookasideDebug(&Target->IndirectList, DebugInterface, "INDIRECTs");
-
- QueueDebugCallback(&Target->FreshSrbs, "Fresh ", DebugInterface);
- QueueDebugCallback(&Target->PreparedReqs, "Prepared ", DebugInterface);
- QueueDebugCallback(&Target->SubmittedReqs, "Submitted", DebugInterface);
- QueueDebugCallback(&Target->ShutdownSrbs, "Shutdown ", DebugInterface);
-
- FrontendDebugCallback(Target->Frontend, DebugInterface);
-
- Target->BlkOpRead = Target->BlkOpWrite = 0;
- Target->BlkOpIndirectRead = Target->BlkOpIndirectWrite = 0;
- Target->BlkOpBarrier = Target->BlkOpDiscard = Target->BlkOpFlush = 0;
- Target->FailedMaps = Target->FailedBounces = Target->FailedGrants = 0;
- Target->SegsGranted = Target->SegsBounced = 0;
-}
-
-//=============================================================================
-// Power States
-__checkReturn
-static FORCEINLINE BOOLEAN
-TargetSetDevicePowerState(
- __in PXENVBD_TARGET Target,
- __in DEVICE_POWER_STATE State
- )
-{
- KIRQL Irql;
- BOOLEAN Changed = FALSE;
-
- KeAcquireSpinLock(&Target->Lock, &Irql);
- if (Target->DevicePowerState != State) {
- Verbose("Target[%d] : POWER %s to %s\n", TargetGetTargetId(Target),
PowerDeviceStateName(Target->DevicePowerState), PowerDeviceStateName(State));
- Target->DevicePowerState = State;
- Changed = TRUE;
- }
- KeReleaseSpinLock(&Target->Lock, Irql);
-
- return Changed;
-}
-
-//=============================================================================
-// PnP States
-FORCEINLINE VOID
-TargetSetMissing(
- __in PXENVBD_TARGET Target,
- __in __nullterminated const CHAR* Reason
- )
-{
- KIRQL Irql;
-
- ASSERT3P(Reason, !=, NULL);
-
- KeAcquireSpinLock(&Target->Lock, &Irql);
- if (Target->Missing) {
- Verbose("Target[%d] : Already MISSING (%s) when trying to set (%s)\n",
TargetGetTargetId(Target), Target->Reason, Reason);
- } else {
- Verbose("Target[%d] : MISSING %s\n", TargetGetTargetId(Target),
Reason);
- Target->Missing = TRUE;
- Target->Reason = Reason;
+ default: return "<UNKNOWN>";
}
- KeReleaseSpinLock(&Target->Lock, Irql);
-}
-
-__checkReturn
-FORCEINLINE BOOLEAN
-TargetIsMissing(
- __in PXENVBD_TARGET Target
- )
-{
- KIRQL Irql;
- BOOLEAN Missing;
-
- KeAcquireSpinLock(&Target->Lock, &Irql);
- Missing = Target->Missing;
- KeReleaseSpinLock(&Target->Lock, Irql);
-
- return Missing;
}
-FORCEINLINE const CHAR*
-TargetMissingReason(
- __in PXENVBD_TARGET Target
+static FORCEINLINE VOID
+TargetRestoreDevicePnpState(
+ IN PXENVBD_TARGET Target
)
{
- KIRQL Irql;
- const CHAR* Reason;
-
- KeAcquireSpinLock(&Target->Lock, &Irql);
- Reason = Target->Reason;
- KeReleaseSpinLock(&Target->Lock, Irql);
-
- return Reason;
+ Verbose("[%u] %s --> %s\n",
+ Target->TargetId,
+ DevicePnpStateName(Target->DevicePnpState),
+ DevicePnpStateName(Target->PrevPnpState));
+ Target->DevicePnpState = Target->PrevPnpState;
}
-FORCEINLINE VOID
+VOID
TargetSetDevicePnpState(
- __in PXENVBD_TARGET Target,
- __in DEVICE_PNP_STATE State
+ IN PXENVBD_TARGET Target,
+ IN DEVICE_PNP_STATE State
)
{
- Verbose("Target[%d] : PNP %s to %s\n",
- TargetGetTargetId(Target),
- __PnpStateName(Target->DevicePnpState),
- __PnpStateName(State));
-
- if (Target->DevicePnpState == Deleted)
- return;
-
+ Verbose("[%u] %s --> %s\n",
+ Target->TargetId,
+ DevicePnpStateName(Target->DevicePnpState),
+ DevicePnpStateName(State));
Target->PrevPnpState = Target->DevicePnpState;
Target->DevicePnpState = State;
}
-
-__checkReturn
-FORCEINLINE DEVICE_PNP_STATE
-TargetGetDevicePnpState(
- __in PXENVBD_TARGET Target
- )
-{
- return Target->DevicePnpState;
-}
-
-static FORCEINLINE VOID
-__TargetRestoreDevicePnpState(
- __in PXENVBD_TARGET Target,
- __in DEVICE_PNP_STATE State
- )
-{
- if (Target->DevicePnpState == State) {
- Verbose("Target[%d] : PNP %s to %s\n", TargetGetTargetId(Target),
__PnpStateName(Target->DevicePnpState), __PnpStateName(Target->PrevPnpState));
- Target->DevicePnpState = Target->PrevPnpState;
- }
-}
-
-//=============================================================================
-// Query Methods
-FORCEINLINE ULONG
-TargetGetTargetId(
- __in PXENVBD_TARGET Target
- )
-{
- ASSERT3P(Target, !=, NULL);
- return FrontendGetTargetId(Target->Frontend);
-}
-
-ULONG
-TargetGetDeviceId(
- __in PXENVBD_TARGET Target
- )
-{
- ASSERT3P(Target, !=, NULL);
- return FrontendGetDeviceId(Target->Frontend);
-}
-
-__checkReturn
-FORCEINLINE PDEVICE_OBJECT
-TargetGetDeviceObject(
- __in PXENVBD_TARGET Target
- )
-{
- ASSERT3P(Target, !=, NULL);
- return Target->DeviceObject;
-}
-
-FORCEINLINE VOID
+VOID
TargetSetDeviceObject(
- __in PXENVBD_TARGET Target,
- __in PDEVICE_OBJECT DeviceObject
+ IN PXENVBD_TARGET Target,
+ IN PDEVICE_OBJECT DeviceObject
)
{
- Verbose("Target[%d] : Setting DeviceObject = 0x%p\n",
TargetGetTargetId(Target), DeviceObject);
-
- ASSERT3P(Target->DeviceObject, ==, NULL);
+ Verbose("[%u] DevObj = 0x%p\n",
+ Target->TargetId,
+ DeviceObject);
Target->DeviceObject = DeviceObject;
}
-__checkReturn
-FORCEINLINE BOOLEAN
-TargetIsPaused(
- __in PXENVBD_TARGET Target
- )
-{
- BOOLEAN Paused;
- KIRQL Irql;
-
- KeAcquireSpinLock(&Target->Lock, &Irql);
- Paused = (Target->Paused > 0);
- KeReleaseSpinLock(&Target->Lock, Irql);
-
- return Paused;
-}
-
-__checkReturn
-FORCEINLINE ULONG
-TargetOutstandingReqs(
- __in PXENVBD_TARGET Target
- )
-{
- return QueueCount(&Target->SubmittedReqs);
-}
-
-__checkReturn
-FORCEINLINE PXENVBD_ADAPTER
-TargetGetAdapter(
- __in PXENVBD_TARGET Target
- )
-{
- return Target->Adapter;
-}
-
-FORCEINLINE ULONG
-TargetSectorSize(
- __in PXENVBD_TARGET Target
+VOID
+TargetSetMissing(
+ IN PXENVBD_TARGET Target,
+ IN const CHAR* Reason
)
{
- return FrontendGetDiskInfo(Target->Frontend)->SectorSize;
+ Verbose("[%u] Missing: %s\n", Target->TargetId, Reason);
+ Target->Missing = TRUE;
}
-//=============================================================================
static PXENVBD_INDIRECT
TargetGetIndirect(
- IN PXENVBD_TARGET Target
+ IN PXENVBD_TARGET Target
)
{
PXENVBD_INDIRECT Indirect;
NTSTATUS status;
- PXENVBD_GRANTER Granter = FrontendGetGranter(Target->Frontend);
- Indirect = __LookasideAlloc(&Target->IndirectList);
+ Indirect = ExAllocateFromNPagedLookasideList(&Target->IndirectList);
if (Indirect == NULL)
goto fail1;
RtlZeroMemory(Indirect, sizeof(XENVBD_INDIRECT));
+ InitializeListHead(&Indirect->ListEntry);
Indirect->Mdl = __AllocatePage();
if (Indirect->Mdl == NULL)
goto fail2;
Indirect->Page = MmGetSystemAddressForMdlSafe(Indirect->Mdl,
NormalPagePriority);
+ ASSERT(Indirect->Page != NULL);
- status = GranterGet(Granter,
+ status = GranterGet(Target->Granter,
MmGetMdlPfnArray(Indirect->Mdl)[0],
TRUE,
&Indirect->Grant);
@@ -557,40 +357,43 @@ TargetGetIndirect(
fail3:
__FreePage(Indirect->Mdl);
fail2:
- __LookasideFree(&Target->IndirectList, Indirect);
+ RtlZeroMemory(Indirect, sizeof(XENVBD_INDIRECT));
+ ExFreeToNPagedLookasideList(&Target->IndirectList, Indirect);
fail1:
return NULL;
}
static VOID
TargetPutIndirect(
- IN PXENVBD_TARGET Target,
- IN PXENVBD_INDIRECT Indirect
+ IN PXENVBD_TARGET Target,
+ IN PXENVBD_INDIRECT Indirect
)
{
- PXENVBD_GRANTER Granter = FrontendGetGranter(Target->Frontend);
-
if (Indirect->Grant)
- GranterPut(Granter, Indirect->Grant);
+ GranterPut(Target->Granter, Indirect->Grant);
+
if (Indirect->Page)
__FreePage(Indirect->Mdl);
RtlZeroMemory(Indirect, sizeof(XENVBD_INDIRECT));
- __LookasideFree(&Target->IndirectList, Indirect);
+ ExFreeToNPagedLookasideList(&Target->IndirectList, Indirect);
}
static PXENVBD_SEGMENT
TargetGetSegment(
- IN PXENVBD_TARGET Target
+ IN PXENVBD_TARGET Target
)
{
- PXENVBD_SEGMENT Segment;
+ PXENVBD_SEGMENT Segment;
- Segment = __LookasideAlloc(&Target->SegmentList);
+ Segment = ExAllocateFromNPagedLookasideList(&Target->SegmentList);
if (Segment == NULL)
goto fail1;
RtlZeroMemory(Segment, sizeof(XENVBD_SEGMENT));
+
+ InitializeListHead(&Segment->ListEntry);
+
return Segment;
fail1:
@@ -599,38 +402,38 @@ fail1:
static VOID
TargetPutSegment(
- IN PXENVBD_TARGET Target,
- IN PXENVBD_SEGMENT Segment
+ IN PXENVBD_TARGET Target,
+ IN PXENVBD_SEGMENT Segment
)
{
- PXENVBD_GRANTER Granter = FrontendGetGranter(Target->Frontend);
-
if (Segment->Grant)
- GranterPut(Granter, Segment->Grant);
+ GranterPut(Target->Granter, Segment->Grant);
+
+ if (Segment->Buffer)
+ MmUnmapLockedPages(Segment->Buffer, &Segment->Mdl);
if (Segment->BufferId)
BufferPut(Segment->BufferId);
- if (Segment->Buffer)
- MmUnmapLockedPages(Segment->Buffer, &Segment->Mdl);
-
RtlZeroMemory(Segment, sizeof(XENVBD_SEGMENT));
- __LookasideFree(&Target->SegmentList, Segment);
+ ExFreeToNPagedLookasideList(&Target->SegmentList, Segment);
}
static PXENVBD_REQUEST
TargetGetRequest(
- IN PXENVBD_TARGET Target
+ IN PXENVBD_TARGET Target
)
{
- PXENVBD_REQUEST Request;
+ PXENVBD_REQUEST Request;
- Request = __LookasideAlloc(&Target->RequestList);
+ Request = ExAllocateFromNPagedLookasideList(&Target->RequestList);
if (Request == NULL)
goto fail1;
RtlZeroMemory(Request, sizeof(XENVBD_REQUEST));
- Request->Id = (ULONG)InterlockedIncrement((PLONG)&Target->NextTag);
+ Request->Id = (ULONG64)(ULONG_PTR)Request;
+
+ InitializeListHead(&Request->ListEntry);
InitializeListHead(&Request->Segments);
InitializeListHead(&Request->Indirects);
@@ -642,1694 +445,2398 @@ fail1:
static VOID
TargetPutRequest(
- IN PXENVBD_TARGET Target,
- IN PXENVBD_REQUEST Request
+ IN PXENVBD_TARGET Target,
+ IN PXENVBD_REQUEST Request
)
{
- PLIST_ENTRY Entry;
-
for (;;) {
- PXENVBD_SEGMENT Segment;
+ PLIST_ENTRY ListEntry;
+ PXENVBD_INDIRECT Indirect;
- Entry = RemoveHeadList(&Request->Segments);
- if (Entry == &Request->Segments)
+ ListEntry = RemoveHeadList(&Request->Indirects);
+ if (ListEntry == &Request->Indirects)
break;
- Segment = CONTAINING_RECORD(Entry, XENVBD_SEGMENT, Entry);
- TargetPutSegment(Target, Segment);
- }
+ Indirect = CONTAINING_RECORD(ListEntry, XENVBD_INDIRECT, ListEntry);
+ TargetPutIndirect(Target, Indirect);
+ }
for (;;) {
- PXENVBD_INDIRECT Indirect;
+ PLIST_ENTRY ListEntry;
+ PXENVBD_SEGMENT Segment;
- Entry = RemoveHeadList(&Request->Indirects);
- if (Entry == &Request->Indirects)
+ ListEntry = RemoveHeadList(&Request->Segments);
+ if (ListEntry == &Request->Segments)
break;
- Indirect = CONTAINING_RECORD(Entry, XENVBD_INDIRECT, Entry);
- TargetPutIndirect(Target, Indirect);
+
+ Segment = CONTAINING_RECORD(ListEntry, XENVBD_SEGMENT, ListEntry);
+ TargetPutSegment(Target, Segment);
}
RtlZeroMemory(Request, sizeof(XENVBD_REQUEST));
- __LookasideFree(&Target->RequestList, Request);
+ ExFreeToNPagedLookasideList(&Target->RequestList, Request);
}
-static FORCEINLINE PXENVBD_REQUEST
-TargetRequestFromTag(
- IN PXENVBD_TARGET Target,
- IN ULONG Tag
+static FORCEINLINE BOOLEAN
+BufferMap(
+ IN PXENVBD_SEGMENT Segment,
+ IN PXENVBD_SG_LIST SGList,
+ IN ULONG Length
)
{
- KIRQL Irql;
- PLIST_ENTRY Entry;
- PXENVBD_QUEUE Queue = &Target->SubmittedReqs;
-
- KeAcquireSpinLock(&Queue->Lock, &Irql);
-
- for (Entry = Queue->List.Flink; Entry != &Queue->List; Entry =
Entry->Flink) {
- PXENVBD_REQUEST Request = CONTAINING_RECORD(Entry, XENVBD_REQUEST,
Entry);
- if (Request->Id == Tag) {
- RemoveEntryList(&Request->Entry);
- --Queue->Current;
- KeReleaseSpinLock(&Queue->Lock, Irql);
- return Request;
- }
+ // map PhysAddr to 1 or 2 pages and lock for VirtAddr
+#pragma warning(push)
+#pragma warning(disable:28145)
+ Segment->Mdl.Next = NULL;
+ Segment->Mdl.Size = (SHORT)(sizeof(MDL) + sizeof(PFN_NUMBER));
+ Segment->Mdl.MdlFlags = MDL_PAGES_LOCKED;
+ Segment->Mdl.Process = NULL;
+ Segment->Mdl.MappedSystemVa = NULL;
+ Segment->Mdl.StartVa = NULL;
+ Segment->Mdl.ByteCount = SGListLength(SGList);
+ Segment->Mdl.ByteOffset = SGListOffset(SGList);
+ Segment->Pfn[0] = SGListPfn(SGList);
+
+ if (Segment->Mdl.ByteCount < Length) {
+ // need part of next page
+ SGListGet(SGList);
+ Segment->Mdl.Size += sizeof(PFN_NUMBER);
+ Segment->Mdl.ByteCount = Segment->Mdl.ByteCount +
SGListLength(SGList);
+ Segment->Pfn[1] = SGListPfn(SGList);
}
+#pragma warning(pop)
- KeReleaseSpinLock(&Queue->Lock, Irql);
- Warning("Target[%d] : Tag %x not found in submitted list (%u items)\n",
- TargetGetTargetId(Target), Tag, QueueCount(Queue));
- return NULL;
-}
+ ASSERT3U(Segment->Mdl.ByteCount, <=, PAGE_SIZE);
+ ASSERT3U(Segment->Mdl.ByteCount, ==, Length);
+
+ Segment->Length = min(Segment->Mdl.ByteCount, PAGE_SIZE);
+ Segment->Buffer = MmMapLockedPagesSpecifyCache(&Segment->Mdl,
+ KernelMode,
+ MmCached,
+ NULL,
+ FALSE,
+ NormalPagePriority);
+ if (Segment->Buffer == NULL)
+ goto fail;
-static FORCEINLINE VOID
-__TargetIncBlkifOpCount(
- __in PXENVBD_TARGET Target,
- __in PXENVBD_REQUEST Request
- )
-{
- switch (Request->Operation) {
- case BLKIF_OP_READ:
- if (Request->NrSegments > BLKIF_MAX_SEGMENTS_PER_REQUEST)
- ++Target->BlkOpIndirectRead;
- else
- ++Target->BlkOpRead;
- break;
- case BLKIF_OP_WRITE:
- if (Request->NrSegments > BLKIF_MAX_SEGMENTS_PER_REQUEST)
- ++Target->BlkOpIndirectWrite;
- else
- ++Target->BlkOpWrite;
- break;
- case BLKIF_OP_WRITE_BARRIER:
- ++Target->BlkOpBarrier;
- break;
- case BLKIF_OP_DISCARD:
- ++Target->BlkOpDiscard;
- break;
- case BLKIF_OP_FLUSH_DISKCACHE:
- ++Target->BlkOpFlush;
- break;
- default:
- ASSERT(FALSE);
- break;
- }
-}
+ ASSERT3P(MmGetMdlPfnArray(&Segment->Mdl)[0], ==, Segment->Pfn[0]);
+ // if only 1 Pfn is used, this triggers an array-out-of-bounds condition!
+ //ASSERT3P(MmGetMdlPfnArray(&Segment->Mdl)[1], ==, Segment->Pfn[1]);
+
+ return TRUE;
-static FORCEINLINE ULONG
-__SectorsPerPage(
- __in ULONG SectorSize
- )
-{
- ASSERT3U(SectorSize, !=, 0);
- return PAGE_SIZE / SectorSize;
+fail:
+ return FALSE;
}
-static FORCEINLINE VOID
-__Operation(
- __in UCHAR CdbOp,
- __out PUCHAR RingOp,
- __out PBOOLEAN ReadOnly
+static BOOLEAN
+TargetPrepareRW(
+ IN PXENVBD_TARGET Target,
+ IN PXENVBD_SRBEXT SrbExt,
+ IN UCHAR Operation
)
{
- 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);
- }
-}
+ PSCSI_REQUEST_BLOCK Srb = SrbExt->Srb;
+ ULONG64 SectorStart = Cdb_LogicalBlock(Srb);
+ ULONG SectorsLeft = Cdb_TransferBlock(Srb);
+ LIST_ENTRY List;
+ XENVBD_SG_LIST SGList;
+ KIRQL Irql;
+ const ULONG SectorSize = Target->SectorSize;
+ const ULONG SectorMask = SectorSize - 1;
+ const ULONG SectorsPerPage = PAGE_SIZE / SectorSize;
-static FORCEINLINE ULONG
-__Offset(
- __in STOR_PHYSICAL_ADDRESS PhysAddr
- )
-{
- return (ULONG)(PhysAddr.QuadPart & (PAGE_SIZE - 1));
-}
+ InitializeListHead(&List);
+ SGListInit(&SGList, TargetGetAdapter(Target), Srb);
-static FORCEINLINE PFN_NUMBER
-__Phys2Pfn(
- __in STOR_PHYSICAL_ADDRESS PhysAddr
- )
-{
- return (PFN_NUMBER)(PhysAddr.QuadPart >> PAGE_SHIFT);
-}
+ // validate SectorStart, SectorsLeft fits in this target (prevent
read/write beyond extents)
-static FORCEINLINE PFN_NUMBER
-__Virt2Pfn(
- __in PVOID VirtAddr
- )
-{
- return (PFN_NUMBER)(MmGetPhysicalAddress(VirtAddr).QuadPart >> PAGE_SHIFT);
-}
+ while (SectorsLeft > 0) {
+ PXENVBD_REQUEST Request;
+ ULONG Index;
+ ULONG MaxSegments;
-static FORCEINLINE MM_PAGE_PRIORITY
-__TargetPriority(
- __in PXENVBD_TARGET Target
- )
-{
- PXENVBD_CAPS Caps = FrontendGetCaps(Target->Frontend);
- if (!(Caps->Paging ||
- Caps->Hibernation ||
- Caps->DumpFile))
- return NormalPagePriority;
+ MaxSegments = Target->FeatureIndirect;
+ MaxSegments = min(MaxSegments, XENVBD_MAX_SEGMENTS_PER_INDIRECT); //
limit to sensible value
+ MaxSegments = max(MaxSegments, BLKIF_MAX_SEGMENTS_PER_REQUEST); //
ensure at least 11
+ ASSERT3U(MaxSegments, >=, BLKIF_MAX_SEGMENTS_PER_REQUEST);
+ ASSERT3U(MaxSegments, <=, XENVBD_MAX_SEGMENTS_PER_INDIRECT);
- return HighPagePriority;
-}
-
-static FORCEINLINE VOID
-SGListGet(
- IN OUT PXENVBD_SG_LIST SGList
- )
-{
- PSTOR_SCATTER_GATHER_ELEMENT SGElement;
-
- ASSERT3U(SGList->Index, <, SGList->SGList->NumberOfElements);
+ Request = TargetGetRequest(Target);
+ if (Request == NULL)
+ goto fail1;
+ InsertTailList(&List, &Request->ListEntry);
+ InterlockedIncrement(&SrbExt->RequestCount);
+
+ Request->SrbExt = SrbExt;
+ Request->Operation = Operation;
+ Request->FirstSector = SectorStart;
+
+ // build segments
+ for (Index = 0; Index < MaxSegments; ++Index) {
+ PXENVBD_SEGMENT Segment;
+ ULONG SectorsNow;
+ PFN_NUMBER Pfn;
+ NTSTATUS status;
+
+ if (SectorsLeft == 0)
+ break;
+
+ Segment = TargetGetSegment(Target);
+ if (Segment == NULL)
+ goto fail2;
+ InsertTailList(&Request->Segments, &Segment->ListEntry);
+ ++Request->NrSegments;
+
+ if (SGListNext(&SGList, SectorMask)) {
+ ASSERT((SGListOffset(&SGList) & SectorMask) == 0);
+
+ Segment->FirstSector = (UCHAR)(SGListOffset(&SGList) /
SectorSize);
+ SectorsNow = min(SectorsLeft, SectorsPerPage -
Segment->FirstSector);
+ Segment->LastSector = (UCHAR)(Segment->FirstSector +
SectorsNow - 1);
+
+ Pfn = SGListPfn(&SGList);
+ } else {
+ ASSERT((SGListOffset(&SGList) & SectorMask) != 0);
+
+ Segment->FirstSector = (UCHAR)0;
+ SectorsNow = min(SectorsLeft, SectorsPerPage);
+ Segment->LastSector = (UCHAR)(SectorsNow - 1);
+
+ if (!BufferMap(Segment, &SGList, SectorsNow * SectorSize))
+ goto fail3;
+
+ if (!BufferGet(Segment, &Segment->BufferId, &Pfn))
+ goto fail4;
+
+ if (Operation == BLKIF_OP_WRITE) {
+ BufferCopyIn(Segment->BufferId,
+ Segment->Buffer,
+ Segment->Length);
+ }
+ }
+
+ status = GranterGet(Target->Granter,
+ Pfn,
+ Operation == BLKIF_OP_WRITE,
+ &Segment->Grant);
+ if (!NT_SUCCESS(status))
+ goto fail5;
+
+ SectorStart += SectorsNow;
+ SectorsLeft -= SectorsNow;
+ }
- SGElement = &SGList->SGList->List[SGList->Index];
+ // build indirects
+ if (MaxSegments > BLKIF_MAX_SEGMENTS_PER_REQUEST) {
+ // round up
+ ULONG NumInd = (Request->NrSegments +
XENVBD_MAX_SEGMENTS_PER_PAGE - 1) /
+ XENVBD_MAX_SEGMENTS_PER_PAGE;
- SGList->PhysAddr.QuadPart = SGElement->PhysicalAddress.QuadPart +
SGList->Offset;
- SGList->PhysLen = __min(PAGE_SIZE - __Offset(SGList->PhysAddr) -
SGList->Length, SGElement->Length - SGList->Offset);
+ ASSERT(NumInd <= BLKIF_MAX_INDIRECT_PAGES_PER_REQUEST);
+ while (NumInd--) {
+ PXENVBD_INDIRECT Indirect;
- ASSERT3U(SGList->PhysLen, <=, PAGE_SIZE);
- ASSERT3U(SGList->Offset, <, SGElement->Length);
+ Indirect = TargetGetIndirect(Target);
+ if (Indirect == NULL)
+ goto fail6;
- SGList->Length = SGList->PhysLen; // gets reset every time for Granted,
every 1or2 times for Bounced
- SGList->Offset = SGList->Offset + SGList->PhysLen;
- if (SGList->Offset >= SGElement->Length) {
- SGList->Index = SGList->Index + 1;
- SGList->Offset = 0;
+ InsertTailList(&Request->Indirects, &Indirect->ListEntry);
+ }
+ }
}
-}
-
-static FORCEINLINE BOOLEAN
-SGListNext(
- IN OUT PXENVBD_SG_LIST SGList,
- IN ULONG AlignmentMask
- )
-{
- SGList->Length = 0;
- SGListGet(SGList); // get next PhysAddr and PhysLen
- return !((SGList->PhysAddr.QuadPart & AlignmentMask) || (SGList->PhysLen &
AlignmentMask));
-}
-static FORCEINLINE BOOLEAN
-MapSegmentBuffer(
- IN PXENVBD_TARGET Target,
- IN PXENVBD_SEGMENT Segment,
- IN PXENVBD_SG_LIST SGList,
- IN ULONG SectorSize,
- IN ULONG SectorsNow
- )
-{
- PMDL Mdl;
+ Srb->SrbStatus = SRB_STATUS_PENDING;
- // map PhysAddr to 1 or 2 pages and lock for VirtAddr
-#pragma warning(push)
-#pragma warning(disable:28145)
- Mdl = &Segment->Mdl;
- 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 = SGList->PhysLen;
- Mdl->ByteOffset = __Offset(SGList->PhysAddr);
- Segment->Pfn[0] = __Phys2Pfn(SGList->PhysAddr);
-
- if (SGList->PhysLen < SectorsNow * SectorSize) {
- SGListGet(SGList);
- Mdl->Size += sizeof(PFN_NUMBER);
- Mdl->ByteCount = Mdl->ByteCount + SGList->PhysLen;
- Segment->Pfn[1] = __Phys2Pfn(SGList->PhysAddr);
- }
-#pragma warning(pop)
+ KeAcquireSpinLock(&Target->QueueLock, &Irql);
+ for (;;) {
+ PLIST_ENTRY ListEntry;
+ PXENVBD_REQUEST Request;
- ASSERT((Mdl->ByteCount & (SectorSize - 1)) == 0);
- ASSERT3U(Mdl->ByteCount, <=, PAGE_SIZE);
- ASSERT3U(SectorsNow, ==, (Mdl->ByteCount / SectorSize));
-
- Segment->Length = __min(Mdl->ByteCount, PAGE_SIZE);
- Segment->Buffer = MmMapLockedPagesSpecifyCache(Mdl, KernelMode,
- MmCached, NULL, FALSE, __TargetPriority(Target));
- if (!Segment->Buffer) {
- goto fail;
+ ListEntry = RemoveHeadList(&List);
+ if (ListEntry == &List)
+ break;
+ Request = CONTAINING_RECORD(ListEntry, XENVBD_REQUEST, ListEntry);
+ InsertTailList(&Target->Prepared, &Request->ListEntry);
}
+ KeReleaseSpinLock(&Target->QueueLock, Irql);
- ASSERT3P(MmGetMdlPfnArray(Mdl)[0], ==, Segment->Pfn[0]);
- ASSERT3P(MmGetMdlPfnArray(Mdl)[1], ==, Segment->Pfn[1]);
-
return TRUE;
-fail:
+fail6:
+fail5:
+fail4:
+fail3:
+fail2:
+fail1:
+ Srb->SrbStatus = SRB_STATUS_ERROR;
+ for (;;) {
+ PLIST_ENTRY ListEntry;
+ PXENVBD_REQUEST Request;
+
+ ListEntry = RemoveHeadList(&List);
+ if (ListEntry == &List)
+ break;
+ Request = CONTAINING_RECORD(ListEntry, XENVBD_REQUEST, ListEntry);
+ TargetPutRequest(Target, Request);
+ }
return FALSE;
}
-static FORCEINLINE VOID
-RequestCopyOutput(
- __in PXENVBD_REQUEST Request
+static BOOLEAN
+TargetPrepareUnmap(
+ IN PXENVBD_TARGET Target,
+ IN PXENVBD_SRBEXT SrbExt
)
{
- PLIST_ENTRY Entry;
-
- if (Request->Operation != BLKIF_OP_READ)
- return;
+ PSCSI_REQUEST_BLOCK Srb = SrbExt->Srb;
+ PUNMAP_LIST_HEADER Unmap = Srb->DataBuffer;
+ ULONG Count;
+ ULONG Index;
+ LIST_ENTRY List;
+ KIRQL Irql;
- for (Entry = Request->Segments.Flink;
- Entry != &Request->Segments;
- Entry = Entry->Flink) {
- PXENVBD_SEGMENT Segment = CONTAINING_RECORD(Entry, XENVBD_SEGMENT,
Entry);
+ InitializeListHead(&List);
+ Count = _byteswap_ushort(*(PUSHORT)Unmap->BlockDescrDataLength) /
+ sizeof(UNMAP_BLOCK_DESCRIPTOR);
- if (Segment->BufferId)
- BufferCopyOut(Segment->BufferId, Segment->Buffer, Segment->Length);
- }
-}
+ for (Index = 0; Index < Count; ++Index) {
+ PUNMAP_BLOCK_DESCRIPTOR Descr = &Unmap->Descriptors[Index];
+ PXENVBD_REQUEST Request;
-static BOOLEAN
-PrepareSegment(
- IN PXENVBD_TARGET Target,
- IN PXENVBD_SEGMENT Segment,
- IN PXENVBD_SG_LIST SGList,
- IN BOOLEAN ReadOnly,
- IN ULONG SectorsLeft,
- OUT PULONG SectorsNow
- )
-{
- PFN_NUMBER Pfn;
- NTSTATUS Status;
- PXENVBD_GRANTER Granter = FrontendGetGranter(Target->Frontend);
- const ULONG SectorSize = TargetSectorSize(Target);
- const ULONG SectorsPerPage = __SectorsPerPage(SectorSize);
-
- if (SGListNext(SGList, SectorSize - 1)) {
- ++Target->SegsGranted;
- // get first sector, last sector and count
- Segment->FirstSector = (UCHAR)((__Offset(SGList->PhysAddr) +
SectorSize - 1) / SectorSize);
- *SectorsNow = __min(SectorsLeft, SectorsPerPage -
Segment->FirstSector);
- Segment->LastSector = (UCHAR)(Segment->FirstSector + *SectorsNow -
1);
- Segment->BufferId = NULL; // granted, ensure its null
- Segment->Buffer = NULL; // granted, ensure its null
- Segment->Length = 0; // granted, ensure its 0
- Pfn = __Phys2Pfn(SGList->PhysAddr);
-
- ASSERT3U((SGList->PhysLen / SectorSize), ==, *SectorsNow);
- ASSERT3U((SGList->PhysLen & (SectorSize - 1)), ==, 0);
- } else {
- ++Target->SegsBounced;
- // get first sector, last sector and count
- Segment->FirstSector = 0;
- *SectorsNow = __min(SectorsLeft, SectorsPerPage);
- Segment->LastSector = (UCHAR)(*SectorsNow - 1);
-
- // map SGList to Virtual Address. Populates Segment->Buffer and
Segment->Length
- if (!MapSegmentBuffer(Target, Segment, SGList, SectorSize,
*SectorsNow)) {
- ++Target->FailedMaps;
+ Request = TargetGetRequest(Target);
+ if (Request == NULL)
goto fail1;
- }
-
- // get a buffer
- if (!BufferGet(Segment, &Segment->BufferId, &Pfn)) {
- ++Target->FailedBounces;
- goto fail2;
- }
+ InsertTailList(&List, &Request->ListEntry);
+ InterlockedIncrement(&SrbExt->RequestCount);
- // copy contents in
- if (ReadOnly) { // Operation == BLKIF_OP_WRITE
- BufferCopyIn(Segment->BufferId, Segment->Buffer, Segment->Length);
- }
+ 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;
}
- // Grant segment's page
- Status = GranterGet(Granter, Pfn, ReadOnly, &Segment->Grant);
- if (!NT_SUCCESS(Status)) {
- ++Target->FailedGrants;
- goto fail3;
+ Srb->SrbStatus = SRB_STATUS_PENDING;
+
+ KeAcquireSpinLock(&Target->QueueLock, &Irql);
+ for (;;) {
+ PLIST_ENTRY ListEntry;
+ PXENVBD_REQUEST Request;
+
+ ListEntry = RemoveHeadList(&List);
+ if (ListEntry == &List)
+ break;
+ Request = CONTAINING_RECORD(ListEntry, XENVBD_REQUEST, ListEntry);
+ InsertTailList(&Target->Prepared, &Request->ListEntry);
}
+ KeReleaseSpinLock(&Target->QueueLock, Irql);
return TRUE;
-fail3:
-fail2:
-fail1:
+fail1:
+ Srb->SrbStatus = SRB_STATUS_ERROR;
+ for (;;) {
+ PLIST_ENTRY ListEntry;
+ PXENVBD_REQUEST Request;
+
+ ListEntry = RemoveHeadList(&List);
+ if (ListEntry == &List)
+ break;
+ Request = CONTAINING_RECORD(ListEntry, XENVBD_REQUEST, ListEntry);
+ TargetPutRequest(Target, Request);
+ }
return FALSE;
}
static BOOLEAN
-PrepareBlkifReadWrite(
- IN PXENVBD_TARGET Target,
- IN PXENVBD_REQUEST Request,
- IN PXENVBD_SG_LIST SGList,
- IN ULONG MaxSegments,
- IN ULONG64 SectorStart,
- IN ULONG SectorsLeft,
- OUT PULONG SectorsDone
+TargetPrepareSync(
+ IN PXENVBD_TARGET Target,
+ IN PXENVBD_SRBEXT SrbExt,
+ IN UCHAR Operation
)
{
- UCHAR Operation;
- BOOLEAN ReadOnly;
- ULONG Index;
- __Operation(Cdb_OperationEx(Request->Srb), &Operation, &ReadOnly);
+ PSCSI_REQUEST_BLOCK Srb = SrbExt->Srb;
+ PXENVBD_REQUEST Request;
+ KIRQL Irql;
- Request->Operation = Operation;
- Request->NrSegments = 0;
- Request->FirstSector = SectorStart;
-
- for (Index = 0;
- Index < MaxSegments &&
- SectorsLeft > 0;
- ++Index) {
- PXENVBD_SEGMENT Segment;
- ULONG SectorsNow;
-
- Segment = TargetGetSegment(Target);
- if (Segment == NULL)
- goto fail1;
+ Srb->SrbStatus = SRB_STATUS_ERROR;
+ Request = TargetGetRequest(Target);
+ if (Request == NULL)
+ return FALSE;
+ InterlockedIncrement(&SrbExt->RequestCount);
- InsertTailList(&Request->Segments, &Segment->Entry);
- ++Request->NrSegments;
+ Request->SrbExt = SrbExt;
+ Request->Operation = Operation;
+ Request->FirstSector = Cdb_LogicalBlock(Srb);
- if (!PrepareSegment(Target,
- Segment,
- SGList,
- ReadOnly,
- SectorsLeft,
- &SectorsNow))
- goto fail2;
+ Srb->SrbStatus = SRB_STATUS_PENDING;
- *SectorsDone += SectorsNow;
- SectorsLeft -= SectorsNow;
- }
- ASSERT3U(Request->NrSegments, >, 0);
- ASSERT3U(Request->NrSegments, <=, MaxSegments);
+ KeAcquireSpinLock(&Target->QueueLock, &Irql);
+ InsertTailList(&Target->Prepared, &Request->ListEntry);
+ KeReleaseSpinLock(&Target->QueueLock, Irql);
return TRUE;
-
-fail2:
-fail1:
- return FALSE;
}
static BOOLEAN
-PrepareBlkifIndirect(
- IN PXENVBD_TARGET Target,
- IN PXENVBD_REQUEST Request
+TargetPrepareRequest(
+ IN PXENVBD_TARGET Target,
+ IN PXENVBD_SRBEXT SrbExt
)
{
- ULONG Index;
- ULONG NrSegments = 0;
+ PSCSI_REQUEST_BLOCK Srb = SrbExt->Srb;
+ UCHAR Operation;
- for (Index = 0;
- Index < BLKIF_MAX_INDIRECT_PAGES_PER_REQUEST &&
- NrSegments < Request->NrSegments;
- ++Index) {
- PXENVBD_INDIRECT Indirect;
+ Operation = Cdb_OperationEx(SrbExt->Srb);
+ switch (Operation) {
+ case SCSIOP_READ:
+ return TargetPrepareRW(Target, SrbExt, BLKIF_OP_READ);
- Indirect = TargetGetIndirect(Target);
- if (Indirect == NULL)
- goto fail1;
- InsertTailList(&Request->Indirects, &Indirect->Entry);
+ case SCSIOP_WRITE:
+ return TargetPrepareRW(Target, SrbExt, BLKIF_OP_WRITE);
- NrSegments += XENVBD_MAX_SEGMENTS_PER_PAGE;
- }
+ case SCSIOP_UNMAP:
+ return TargetPrepareUnmap(Target, SrbExt);
- return TRUE;
+ case SCSIOP_SYNCHRONIZE_CACHE:
+ if (Target->FeatureFlush)
+ return TargetPrepareSync(Target, SrbExt, BLKIF_OP_FLUSH_DISKCACHE);
+ if (Target->FeatureBarrier)
+ return TargetPrepareSync(Target, SrbExt, BLKIF_OP_WRITE_BARRIER);
+
+ // nothing supported - shouldnt really get here, but just complete if
it did
+ Warning("[%u] FLUSH & BARRIER not supported, SCSIOP_SYNCHRONIZE_CACHE
got to Prepare\n",
+ Target->TargetId);
+ Srb->SrbStatus = SRB_STATUS_SUCCESS;
+ AdapterCompleteSrb(Target->Adapter, SrbExt);
+ return TRUE;
-fail1:
+ default:
+ ASSERT(FALSE);
+ break;
+ }
return FALSE;
}
-static FORCEINLINE ULONG
-UseIndirect(
- IN PXENVBD_TARGET Target,
- IN ULONG SectorsLeft
- )
+static FORCEINLINE BOOLEAN
+TargetPrepareFresh(
+ IN PXENVBD_TARGET Target
+ )
{
- const ULONG SectorsPerPage = __SectorsPerPage(TargetSectorSize(Target));
- const ULONG MaxIndirectSegs =
FrontendGetFeatures(Target->Frontend)->Indirect;
+ PXENVBD_SRBEXT SrbExt;
+ PLIST_ENTRY ListEntry;
+ KIRQL Irql;
+
+ KeAcquireSpinLock(&Target->QueueLock, &Irql);
+ ListEntry = RemoveHeadList(&Target->Fresh);
+ if (ListEntry == &Target->Fresh) {
+ KeReleaseSpinLock(&Target->QueueLock, Irql);
+ return FALSE;
+ }
+ KeReleaseSpinLock(&Target->QueueLock, Irql);
+
+ SrbExt = CONTAINING_RECORD(ListEntry, XENVBD_SRBEXT, ListEntry);
- if (MaxIndirectSegs <= BLKIF_MAX_SEGMENTS_PER_REQUEST)
- return BLKIF_MAX_SEGMENTS_PER_REQUEST; // not supported
+ if (TargetPrepareRequest(Target, SrbExt))
+ return TRUE;
- if (SectorsLeft < BLKIF_MAX_SEGMENTS_PER_REQUEST * SectorsPerPage)
- return BLKIF_MAX_SEGMENTS_PER_REQUEST; // first into a single
BLKIF_OP_{READ/WRITE}
+ KeAcquireSpinLock(&Target->QueueLock, &Irql);
+ InsertHeadList(&Target->Fresh, ListEntry);
+ KeReleaseSpinLock(&Target->QueueLock, Irql);
- return MaxIndirectSegs;
+ return FALSE;
}
-static FORCEINLINE ULONG
-TargetQueueRequestList(
- IN PXENVBD_TARGET Target,
- IN PLIST_ENTRY List
+static FORCEINLINE BOOLEAN
+TargetSubmitPrepared(
+ IN PXENVBD_TARGET Target
)
{
- ULONG Count = 0;
for (;;) {
+ PLIST_ENTRY ListEntry;
PXENVBD_REQUEST Request;
- PLIST_ENTRY Entry;
+ KIRQL Irql;
- Entry = RemoveHeadList(List);
- if (Entry == List)
+ KeAcquireSpinLock(&Target->QueueLock, &Irql);
+ ListEntry = RemoveHeadList(&Target->Prepared);
+ if (ListEntry == &Target->Prepared) {
+ KeReleaseSpinLock(&Target->QueueLock, Irql);
break;
+ }
+ Request = CONTAINING_RECORD(ListEntry, XENVBD_REQUEST, ListEntry);
+
+ InsertTailList(&Target->Submitted, ListEntry);
+ KeReleaseSpinLock(&Target->QueueLock, Irql);
- ++Count;
- Request = CONTAINING_RECORD(Entry, XENVBD_REQUEST, Entry);
- __TargetIncBlkifOpCount(Target, Request);
- QueueAppend(&Target->PreparedReqs, &Request->Entry);
+ if (BlockRingSubmit(Target->BlockRing, Request))
+ continue;
+
+ KeAcquireSpinLock(&Target->QueueLock, &Irql);
+ RemoveEntryList(&Request->ListEntry);
+ InsertHeadList(&Target->Prepared, &Request->ListEntry);
+ KeReleaseSpinLock(&Target->QueueLock, Irql);
+
+ return FALSE;
}
- return Count;
+
+ return TRUE;
}
static FORCEINLINE VOID
-TargetCancelRequestList(
- IN PXENVBD_TARGET Target,
- IN PLIST_ENTRY List
+TargetCompleteShutdown(
+ IN PXENVBD_TARGET Target
)
{
+ if (IsListEmpty(&Target->Shutdown))
+ return;
+ if (!IsListEmpty(&Target->Fresh))
+ return;
+ if (!IsListEmpty(&Target->Prepared))
+ return;
+ if (!IsListEmpty(&Target->Shutdown))
+ return;
+
for (;;) {
- PXENVBD_REQUEST Request;
- PLIST_ENTRY Entry;
+ PLIST_ENTRY ListEntry;
+ PXENVBD_SRBEXT SrbExt;
+ KIRQL Irql;
- Entry = RemoveHeadList(List);
- if (Entry == List)
+ KeAcquireSpinLock(&Target->QueueLock, &Irql);
+ ListEntry = RemoveHeadList(&Target->Shutdown);
+ if (ListEntry == &Target->Shutdown) {
+ KeReleaseSpinLock(&Target->QueueLock, Irql);
break;
+ }
+ KeReleaseSpinLock(&Target->QueueLock, Irql);
- Request = CONTAINING_RECORD(Entry, XENVBD_REQUEST, Entry);
- TargetPutRequest(Target, Request);
+ SrbExt = CONTAINING_RECORD(ListEntry, XENVBD_SRBEXT, ListEntry);
+ SrbExt->Srb->SrbStatus = SRB_STATUS_SUCCESS;
+ AdapterCompleteSrb(TargetGetAdapter(Target), SrbExt);
}
}
-__checkReturn
-static BOOLEAN
-PrepareReadWrite(
- __in PXENVBD_TARGET Target,
- __in PSCSI_REQUEST_BLOCK Srb
+VOID
+TargetSubmitRequests(
+ IN PXENVBD_TARGET Target
)
{
- PXENVBD_SRBEXT SrbExt = Srb->SrbExtension;
- ULONG64 SectorStart = Cdb_LogicalBlock(Srb);
- ULONG SectorsLeft = Cdb_TransferBlock(Srb);
- LIST_ENTRY List;
- XENVBD_SG_LIST SGList;
- ULONG DebugCount;
+ for (;;) {
+ // submit all prepared requests (0 or more requests)
+ // return TRUE if submitted 0 or more requests from prepared queue
+ // return FALSE iff ring is full
+ if (!TargetSubmitPrepared(Target))
+ break;
- Srb->SrbStatus = SRB_STATUS_PENDING;
+ // prepare a single SRB (into 1 or more requests)
+ // return TRUE if prepare succeeded
+ // return FALSE if prepare failed or fresh queue empty
+ if (!TargetPrepareFresh(Target))
+ break;
+ }
- InitializeListHead(&List);
- SrbExt->RequestCount = 0;
+ // if no requests/SRBs outstanding, complete any shutdown SRBs
+ TargetCompleteShutdown(Target);
+}
+
+static FORCEINLINE VOID
+TargetDisableFeature(
+ IN PXENVBD_TARGET Target,
+ IN UCHAR Operation
+ )
+{
+ switch (Operation) {
+ case BLKIF_OP_WRITE_BARRIER:
+ Target->FeatureBarrier = FALSE;
+ break;
+ case BLKIF_OP_FLUSH_DISKCACHE:
+ Target->FeatureFlush = FALSE;
+ break;
+ case BLKIF_OP_DISCARD:
+ Target->FeatureDiscard = FALSE;
+ break;
+ default:
+ break;
+ }
+}
- RtlZeroMemory(&SGList, sizeof(SGList));
- SGList.SGList = StorPortGetScatterGatherList(TargetGetAdapter(Target),
Srb);
+VOID
+TargetCompleteResponse(
+ IN PXENVBD_TARGET Target,
+ IN ULONG64 Id,
+ IN SHORT Status
+ )
+{
+ PLIST_ENTRY ListEntry;
+ PXENVBD_REQUEST Request;
+ PXENVBD_SRBEXT SrbExt;
+ PSCSI_REQUEST_BLOCK Srb;
+ KIRQL Irql;
- while (SectorsLeft > 0) {
- ULONG MaxSegments;
- ULONG SectorsDone = 0;
- PXENVBD_REQUEST Request;
+ KeAcquireSpinLock(&Target->QueueLock, &Irql);
+ Request = NULL;
+ for (ListEntry = Target->Submitted.Flink;
+ ListEntry != &Target->Submitted;
+ ListEntry = ListEntry->Flink) {
+ Request = CONTAINING_RECORD(ListEntry, XENVBD_REQUEST, ListEntry);
- Request = TargetGetRequest(Target);
- if (Request == NULL)
- goto fail1;
- InsertTailList(&List, &Request->Entry);
- InterlockedIncrement(&SrbExt->RequestCount);
-
- Request->Srb = Srb;
- MaxSegments = UseIndirect(Target, SectorsLeft);
-
- if (!PrepareBlkifReadWrite(Target,
- Request,
- &SGList,
- MaxSegments,
- SectorStart,
- SectorsLeft,
- &SectorsDone))
- goto fail2;
+ if (Request->Id == Id) {
+ RemoveEntryList(&Request->ListEntry);
- if (MaxSegments > BLKIF_MAX_SEGMENTS_PER_REQUEST) {
- if (!PrepareBlkifIndirect(Target, Request))
- goto fail3;
+ ASSERT3P(Request, ==, (PVOID)(ULONG_PTR)Id);
+ break;
}
- SectorsLeft -= SectorsDone;
- SectorStart += SectorsDone;
+ Request = NULL;
}
+ KeReleaseSpinLock(&Target->QueueLock, Irql);
- DebugCount = TargetQueueRequestList(Target, &List);
- if (DebugCount != (ULONG)SrbExt->RequestCount) {
- Trace("[%u] %d != %u\n", TargetGetTargetId(Target),
SrbExt->RequestCount, DebugCount);
- }
- return TRUE;
+ ASSERT3P(Request, !=, NULL);
+ SrbExt = Request->SrbExt;
+ ASSERT3P(SrbExt, !=, NULL);
+ Srb = SrbExt->Srb;
+ ASSERT3P(Srb, !=, NULL);
-fail3:
-fail2:
-fail1:
- TargetCancelRequestList(Target, &List);
- SrbExt->RequestCount = 0;
- Srb->SrbStatus = SRB_STATUS_ERROR;
- return FALSE;
+ switch (Status) {
+ case BLKIF_RSP_OKAY:
+ if (Request->Operation == BLKIF_OP_READ) {
+ for (ListEntry = Request->Segments.Flink;
+ ListEntry != &Request->Segments;
+ ListEntry = ListEntry->Flink) {
+ PXENVBD_SEGMENT Segment = CONTAINING_RECORD(ListEntry,
XENVBD_SEGMENT, ListEntry);
+
+ if (Segment->BufferId) {
+ ASSERT(Segment->Buffer);
+ ASSERT(Segment->Length);
+ BufferCopyOut(Segment->BufferId,
+ Segment->Buffer,
+ Segment->Length);
+ }
+ }
+ }
+ break;
+ case BLKIF_RSP_EOPNOTSUPP:
+ TargetDisableFeature(Target, Request->Operation);
+ break;
+ case BLKIF_RSP_ERROR:
+ default:
+ Srb->SrbStatus = SRB_STATUS_ERROR;
+ break;
+ }
+
+ TargetPutRequest(Target, Request);
+
+ if (InterlockedDecrement(&SrbExt->RequestCount) != 0)
+ return;
+
+ if (Srb->SrbStatus == SRB_STATUS_PENDING)
+ Srb->SrbStatus = SRB_STATUS_SUCCESS;
+
+ AdapterCompleteSrb(Target->Adapter, SrbExt);
}
-__checkReturn
-static BOOLEAN
-PrepareSyncCache(
- __in PXENVBD_TARGET Target,
- __in PSCSI_REQUEST_BLOCK Srb
+VOID
+TargetReset(
+ IN PXENVBD_TARGET Target
)
{
- PXENVBD_SRBEXT SrbExt = Srb->SrbExtension;
- PXENVBD_REQUEST Request;
- LIST_ENTRY List;
- UCHAR Operation;
- ULONG DebugCount;
+ ULONG Outstanding;
- Srb->SrbStatus = SRB_STATUS_PENDING;
-
- if (FrontendGetDiskInfo(Target->Frontend)->FlushCache)
- Operation = BLKIF_OP_FLUSH_DISKCACHE;
- else
- Operation = BLKIF_OP_WRITE_BARRIER;
+ Verbose("[%u] =====>\n", Target->TargetId);
- InitializeListHead(&List);
- SrbExt->RequestCount = 0;
+ ASSERT3U(KeGetCurrentIrql(), ==, DISPATCH_LEVEL);
- Request = TargetGetRequest(Target);
- if (Request == NULL)
- goto fail1;
- InsertTailList(&List, &Request->Entry);
- InterlockedIncrement(&SrbExt->RequestCount);
+ Trace("polling...\n");
+ Outstanding = BlockRingPoll(Target->BlockRing);
+ Trace("%u requests outstanding\n", Outstanding);
- Request->Srb = Srb;
- Request->Operation = Operation;
- Request->FirstSector = Cdb_LogicalBlock(Srb);
+ Verbose("[%u] <=====\n", Target->TargetId);
+}
- DebugCount = TargetQueueRequestList(Target, &List);
- if (DebugCount != (ULONG)SrbExt->RequestCount) {
- Trace("[%u] %d != %u\n", TargetGetTargetId(Target),
SrbExt->RequestCount, DebugCount);
- }
- return TRUE;
+VOID
+TargetFlush(
+ IN PXENVBD_TARGET Target,
+ IN PXENVBD_SRBEXT SrbExt
+ )
+{
+ KIRQL Irql;
-fail1:
- TargetCancelRequestList(Target, &List);
- SrbExt->RequestCount = 0;
- Srb->SrbStatus = SRB_STATUS_ERROR;
- return FALSE;
+ SrbExt->Srb->SrbStatus = SRB_STATUS_PENDING;
+
+ KeAcquireSpinLock(&Target->QueueLock, &Irql);
+ InsertTailList(&Target->Shutdown, &SrbExt->ListEntry);
+ KeReleaseSpinLock(&Target->QueueLock, Irql);
+
+ BlockRingKick(Target->BlockRing);
}
-__checkReturn
-static BOOLEAN
-PrepareUnmap(
- __in PXENVBD_TARGET Target,
- __in PSCSI_REQUEST_BLOCK Srb
+VOID
+TargetShutdown(
+ IN PXENVBD_TARGET Target,
+ IN PXENVBD_SRBEXT SrbExt
)
{
- PXENVBD_SRBEXT SrbExt = Srb->SrbExtension;
- PUNMAP_LIST_HEADER Unmap = Srb->DataBuffer;
- ULONG Count =
_byteswap_ushort(*(PUSHORT)Unmap->BlockDescrDataLength) /
sizeof(UNMAP_BLOCK_DESCRIPTOR);
- ULONG Index;
- LIST_ENTRY List;
- ULONG DebugCount;
+ KIRQL Irql;
+
+ SrbExt->Srb->SrbStatus = SRB_STATUS_PENDING;
+
+ KeAcquireSpinLock(&Target->QueueLock, &Irql);
+ InsertTailList(&Target->Shutdown, &SrbExt->ListEntry);
+ KeReleaseSpinLock(&Target->QueueLock, Irql);
+
+ BlockRingKick(Target->BlockRing);
+}
+
+VOID
+TargetPrepareSrb(
+ IN PXENVBD_TARGET Target,
+ IN PXENVBD_SRBEXT SrbExt
+ )
+{
+ PSCSI_REQUEST_BLOCK Srb = SrbExt->Srb;
+
+ UNREFERENCED_PARAMETER(Target);
Srb->SrbStatus = SRB_STATUS_PENDING;
+}
- InitializeListHead(&List);
- SrbExt->RequestCount = 0;
+static FORCEINLINE VOID
+TargetQueueSrb(
+ IN PXENVBD_TARGET Target,
+ IN PXENVBD_SRBEXT SrbExt
+ )
+{
+ KIRQL Irql;
- for (Index = 0; Index < Count; ++Index) {
- PUNMAP_BLOCK_DESCRIPTOR Descr = &Unmap->Descriptors[Index];
- PXENVBD_REQUEST Request;
+ SrbExt->Srb->SrbStatus = SRB_STATUS_PENDING;
- Request = TargetGetRequest(Target);
- if (Request == NULL)
- goto fail1;
- InsertTailList(&List, &Request->Entry);
- InterlockedIncrement(&SrbExt->RequestCount);
+ KeAcquireSpinLock(&Target->QueueLock, &Irql);
+ InsertTailList(&Target->Fresh, &SrbExt->ListEntry);
+ KeReleaseSpinLock(&Target->QueueLock, Irql);
- Request->Srb = Srb;
- Request->Operation = BLKIF_OP_DISCARD;
- Request->FirstSector =
_byteswap_uint64(*(PULONG64)Descr->StartingLba);
- Request->NrSectors = _byteswap_ulong(*(PULONG)Descr->LbaCount);
- Request->Flags = 0;
- }
+ BlockRingKick(Target->BlockRing);
+}
- DebugCount = TargetQueueRequestList(Target, &List);
- if (DebugCount != (ULONG)SrbExt->RequestCount) {
- Trace("[%u] %d != %u\n", TargetGetTargetId(Target),
SrbExt->RequestCount, DebugCount);
- }
- return TRUE;
+static FORCEINLINE VOID
+TargetInquiryStd(
+ IN PXENVBD_TARGET Target,
+ IN PXENVBD_SRBEXT SrbExt
+ )
+{
+ PSCSI_REQUEST_BLOCK Srb = SrbExt->Srb;
+ PINQUIRYDATA Data = Srb->DataBuffer;
+
+ UNREFERENCED_PARAMETER(Target);
-fail1:
- TargetCancelRequestList(Target, &List);
- SrbExt->RequestCount = 0;
- Srb->SrbStatus = SRB_STATUS_ERROR;
- return FALSE;
+ Srb->SrbStatus = SRB_STATUS_DATA_OVERRUN;
+ if (Srb->DataTransferLength < sizeof(INQUIRYDATA))
+ return;
+
+ RtlZeroMemory(Data, Srb->DataTransferLength);
+ Data->DeviceType = DIRECT_ACCESS_DEVICE;
+ Data->DeviceTypeQualifier = DEVICE_CONNECTED;
+ Data->Versions = 4;
+ Data->ResponseDataFormat = 2;
+ Data->AdditionalLength = INQUIRYDATABUFFERSIZE - 4;
+ Data->CommandQueue = 1;
+ RtlCopyMemory(Data->VendorId, "XENSRC ", 8);
+ RtlCopyMemory(Data->ProductId, "PVDISK ", 16);
+ RtlCopyMemory(Data->ProductRevisionLevel, "3.0 ", 4);
+
+ Srb->DataTransferLength = sizeof(INQUIRYDATA);
+ Srb->SrbStatus = SRB_STATUS_SUCCESS;
+}
+
+static FORCEINLINE VOID
+TargetInquiry00(
+ IN PXENVBD_TARGET Target,
+ IN PXENVBD_SRBEXT SrbExt
+ )
+{
+ PSCSI_REQUEST_BLOCK Srb = SrbExt->Srb;
+ PUCHAR Data = Srb->DataBuffer;
+
+ UNREFERENCED_PARAMETER(Target);
+
+ Srb->SrbStatus = SRB_STATUS_DATA_OVERRUN;
+ if (Srb->DataTransferLength < 7)
+ return;
+
+ RtlZeroMemory(Data, Srb->DataTransferLength);
+ Data[3] = 3;
+ Data[5] = 0x80;
+ Data[6] = 0x83;
+
+ Srb->DataTransferLength = 7;
+ Srb->SrbStatus = SRB_STATUS_SUCCESS;
}
-//=============================================================================
-// Queue-Related
static FORCEINLINE VOID
-__TargetPauseDataPath(
- __in PXENVBD_TARGET Target,
- __in BOOLEAN Timeout
+TargetInquiry80(
+ IN PXENVBD_TARGET Target,
+ IN PXENVBD_SRBEXT SrbExt
)
{
- KIRQL Irql;
- ULONG Requests;
- ULONG Count = 0;
- PXENVBD_NOTIFIER Notifier = FrontendGetNotifier(Target->Frontend);
- PXENVBD_BLOCKRING BlockRing = FrontendGetBlockRing(Target->Frontend);
+ PSCSI_REQUEST_BLOCK Srb = SrbExt->Srb;
+ PVPD_SERIAL_NUMBER_PAGE Data = Srb->DataBuffer;
+
+ Srb->SrbStatus = SRB_STATUS_DATA_OVERRUN;
+ if (Srb->DataTransferLength < sizeof(VPD_SERIAL_NUMBER_PAGE) + 4)
+ return;
- KeAcquireSpinLock(&Target->Lock, &Irql);
- ++Target->Paused;
- KeReleaseSpinLock(&Target->Lock, Irql);
+ RtlZeroMemory(Data, Srb->DataTransferLength);
+ Data->PageCode = 0x80;
+ Data->PageLength = 4;
+ RtlStringCchPrintfA((PCHAR)Data->SerialNumber, 4, "%04u",
Target->TargetId);
- Requests = QueueCount(&Target->SubmittedReqs);
- KeMemoryBarrier();
+ Srb->DataTransferLength = sizeof(VPD_SERIAL_NUMBER_PAGE) + 4;
+ Srb->SrbStatus = SRB_STATUS_SUCCESS;
+}
- Verbose("Target[%d] : Waiting for %d Submitted requests\n",
TargetGetTargetId(Target), Requests);
+static FORCEINLINE VOID
+TargetInquiry83(
+ IN PXENVBD_TARGET Target,
+ IN PXENVBD_SRBEXT SrbExt
+ )
+{
+ PSCSI_REQUEST_BLOCK Srb = SrbExt->Srb;
+ PVPD_IDENTIFICATION_PAGE Data = Srb->DataBuffer;
+ PVPD_IDENTIFICATION_DESCRIPTOR Descr;
- // poll ring and send event channel notification every 1ms (for up to 3
minutes)
- while (QueueCount(&Target->SubmittedReqs)) {
- if (Timeout && Count > 180000)
- break;
- KeRaiseIrql(DISPATCH_LEVEL, &Irql);
- BlockRingPoll(BlockRing);
- KeLowerIrql(Irql);
- NotifierSend(Notifier); // let backend know it needs to do
some work
- StorPortStallExecution(1000); // 1000 micro-seconds
- ++Count;
+ Srb->SrbStatus = SRB_STATUS_DATA_OVERRUN;
+ if (Srb->DataTransferLength < sizeof(VPD_IDENTIFICATION_PAGE) - 1 +
+ sizeof(VPD_IDENTIFICATION_DESCRIPTOR) + 16)
+ return;
+
+ RtlZeroMemory(Data, Srb->DataTransferLength);
+ Data->PageCode = 0x83;
+ Data->PageLength = sizeof(VPD_IDENTIFICATION_DESCRIPTOR) + 16;
+
+ Descr = (PVPD_IDENTIFICATION_DESCRIPTOR)Data->Descriptors;
+ Descr->CodeSet = VpdCodeSetAscii;
+ Descr->IdentifierType = VpdIdentifierTypeVendorId;
+ Descr->IdentifierLength = 16;
+ RtlStringCbPrintfA((PCHAR)Descr->Identifier,
+ 16,
+ "XEN:%u:%u",
+ Target->DeviceId,
+ Target->TargetId);
+
+ Srb->DataTransferLength = sizeof(VPD_IDENTIFICATION_PAGE) - 1 +
+ sizeof(VPD_IDENTIFICATION_DESCRIPTOR) + 16;
+ Srb->SrbStatus = SRB_STATUS_SUCCESS;
+}
+
+static FORCEINLINE VOID
+TargetInquiry(
+ IN PXENVBD_TARGET Target,
+ IN PXENVBD_SRBEXT SrbExt
+ )
+{
+ if (Cdb_EVPD(SrbExt->Srb)) {
+ switch (Cdb_PageCode(SrbExt->Srb)) {
+ case 0x00: TargetInquiry00(Target, SrbExt); break;
+ case 0x80: TargetInquiry80(Target, SrbExt); break;
+ case 0x83: TargetInquiry83(Target, SrbExt); break;
+ default: SrbExt->Srb->SrbStatus = SRB_STATUS_ERROR; break;
+ }
+ } else {
+ switch (Cdb_PageCode(SrbExt->Srb)) {
+ case 0x00: TargetInquiryStd(Target, SrbExt); break;
+ default: SrbExt->Srb->SrbStatus = SRB_STATUS_ERROR; break;
+ }
}
+}
+
+static FORCEINLINE VOID
+TargetModeSense(
+ IN PXENVBD_TARGET Target,
+ IN PXENVBD_SRBEXT SrbExt
+ )
+{
+ PSCSI_REQUEST_BLOCK Srb = SrbExt->Srb;
+ PMODE_PARAMETER_HEADER Header;
+ ULONG Offset;
+ UCHAR PageCode;
- Verbose("Target[%d] : %u/%u Submitted requests left (%u iterrations)\n",
- TargetGetTargetId(Target), QueueCount(&Target->SubmittedReqs),
Requests, Count);
+ UNREFERENCED_PARAMETER(Target);
- // Abort Fresh SRBs
- for (;;) {
- PXENVBD_SRBEXT SrbExt;
- PLIST_ENTRY ListEntry = QueuePop(&Target->FreshSrbs);
- if (ListEntry == NULL)
- break;
- SrbExt = CONTAINING_RECORD(ListEntry, XENVBD_SRBEXT, ListEntry);
+ Srb->SrbStatus = SRB_STATUS_DATA_OVERRUN;
+ if (Srb->DataTransferLength < sizeof(MODE_PARAMETER_HEADER))
+ return;
+ RtlZeroMemory(Srb->DataBuffer, Srb->DataTransferLength);
- Verbose("Target[%d] : FreshSrb 0x%p -> SCSI_ABORTED\n",
TargetGetTargetId(Target), SrbExt->Srb);
- SrbExt->Srb->SrbStatus = SRB_STATUS_ABORTED;
- SrbExt->Srb->ScsiStatus = 0x40; // SCSI_ABORTED;
- AdapterCompleteSrb(TargetGetAdapter(Target), SrbExt);
+ Header = Srb->DataBuffer;
+ Header->ModeDataLength = sizeof(MODE_PARAMETER_HEADER) - 1;
+
+ Offset = sizeof(MODE_PARAMETER_HEADER);
+ PageCode = Cdb_PageCode(Srb);
+ if (Cdb_Dbd(Srb) == 0 &&
+ Srb->DataTransferLength >= Offset + sizeof(MODE_PARAMETER_BLOCK)) {
+ PMODE_PARAMETER_BLOCK Block = (PMODE_PARAMETER_BLOCK)((PUCHAR)Header
+ Offset);
+
+ // Block is ZEROed
+ UNREFERENCED_PARAMETER(Block);
+
+ Header->BlockDescriptorLength = sizeof(MODE_PARAMETER_BLOCK);
+ Header->ModeDataLength += sizeof(MODE_PARAMETER_BLOCK);
+ Offset += sizeof(MODE_PARAMETER_BLOCK);
}
- // Fail PreparedReqs
- for (;;) {
- PXENVBD_SRBEXT SrbExt;
- PXENVBD_REQUEST Request;
- PLIST_ENTRY Entry = QueuePop(&Target->PreparedReqs);
- if (Entry == NULL)
- break;
- Request = CONTAINING_RECORD(Entry, XENVBD_REQUEST, Entry);
- SrbExt = Request->Srb->SrbExtension;
+ if ((PageCode == MODE_PAGE_CACHING || PageCode == MODE_SENSE_RETURN_ALL) &&
+ Srb->DataTransferLength >= Offset + sizeof(MODE_CACHING_PAGE)) {
+ PMODE_CACHING_PAGE Caching = (PMODE_CACHING_PAGE)((PUCHAR)Header +
Offset);
- Verbose("Target[%d] : PreparedReq 0x%p -> FAILED\n",
TargetGetTargetId(Target), Request);
+ Caching->PageCode = MODE_PAGE_CACHING;
+ Caching->PageLength = sizeof(MODE_CACHING_PAGE);
+ // Caching is ZEROed
- SrbExt->Srb->SrbStatus = SRB_STATUS_ABORTED;
- TargetPutRequest(Target, Request);
+ Header->ModeDataLength += sizeof(MODE_CACHING_PAGE);
+ Offset += sizeof(MODE_CACHING_PAGE);
+ }
- if (InterlockedDecrement(&SrbExt->RequestCount) == 0) {
- SrbExt->Srb->ScsiStatus = 0x40; // SCSI_ABORTED
- AdapterCompleteSrb(TargetGetAdapter(Target), SrbExt);
- }
+ if ((PageCode == MODE_PAGE_FAULT_REPORTING || PageCode ==
MODE_SENSE_RETURN_ALL) &&
+ Srb->DataTransferLength >= Offset + sizeof(MODE_CACHING_PAGE)) {
+ PMODE_INFO_EXCEPTIONS Info = (PMODE_INFO_EXCEPTIONS)((PUCHAR)Header +
Offset);
+
+ Info->PageCode = MODE_PAGE_FAULT_REPORTING;
+ Info->PageLength = sizeof(MODE_INFO_EXCEPTIONS);
+ Info->Dexcpt = 1;
+ // Info is ZEROed
+
+ Header->ModeDataLength += sizeof(MODE_CACHING_PAGE);
+ Offset += sizeof(MODE_CACHING_PAGE);
}
+
+ Srb->DataTransferLength = Offset;
+ Srb->SrbStatus = SRB_STATUS_SUCCESS;
}
static FORCEINLINE VOID
-__TargetUnpauseDataPath(
- __in PXENVBD_TARGET Target
+TargetRequestSense(
+ IN PXENVBD_TARGET Target,
+ IN PXENVBD_SRBEXT SrbExt
)
{
- KIRQL Irql;
+ PSCSI_REQUEST_BLOCK Srb = SrbExt->Srb;
+ PSENSE_DATA Sense = Srb->DataBuffer;
- KeAcquireSpinLock(&Target->Lock, &Irql);
- --Target->Paused;
- KeReleaseSpinLock(&Target->Lock, Irql);
+ UNREFERENCED_PARAMETER(Target);
+
+ Srb->SrbStatus = SRB_STATUS_DATA_OVERRUN;
+ if (Srb->DataTransferLength < sizeof(SENSE_DATA))
+ return;
+ RtlZeroMemory(Srb->DataBuffer, Srb->DataTransferLength);
+
+ Sense->ErrorCode = 0x70;
+ Sense->Valid = 1;
+ Sense->SenseKey = SCSI_SENSE_NO_SENSE;
+ Sense->AdditionalSenseCode = SCSI_ADSENSE_NO_SENSE;
+
+ Srb->DataTransferLength = sizeof(SENSE_DATA);
+ Srb->SrbStatus = SRB_STATUS_SUCCESS;
+}
+
+static FORCEINLINE VOID
+TargetReportLuns(
+ IN PXENVBD_TARGET Target,
+ IN PXENVBD_SRBEXT SrbExt
+ )
+{
+ PSCSI_REQUEST_BLOCK Srb = SrbExt->Srb;
+ ULONG Length;
+ ULONG Offset;
+ ULONG AllocLength = Cdb_AllocationLength(Srb);
+ PUCHAR Buffer = Srb->DataBuffer;
+
+ UNREFERENCED_PARAMETER(Target);
+
+ Srb->SrbStatus = SRB_STATUS_DATA_OVERRUN;
+ if (Srb->DataTransferLength < 8)
+ return;
+ RtlZeroMemory(Srb->DataBuffer, Srb->DataTransferLength);
+
+ Length = 0;
+ Offset = 8;
+
+ if (Offset + 8 <= AllocLength) {
+ Buffer[Offset] = 0;
+ Offset += 8;
+ Length += 8;
+ }
+
+ if (Offset + 8 <= AllocLength) {
+ Buffer[Offset] = XENVBD_MAX_TARGETS;
+ Offset += 8;
+ Length += 8;
+ }
+
+ REVERSE_BYTES(Buffer, &Length);
+
+ Srb->DataTransferLength = __min(Length, AllocLength);
+ Srb->SrbStatus = SRB_STATUS_SUCCESS;
+}
+
+static FORCEINLINE VOID
+TargetReadCapacity(
+ IN PXENVBD_TARGET Target,
+ IN PXENVBD_SRBEXT SrbExt
+ )
+{
+ PSCSI_REQUEST_BLOCK Srb = SrbExt->Srb;
+ PREAD_CAPACITY_DATA Capacity = Srb->DataBuffer;
+ ULONG64 SectorCount = Target->SectorCount;
+ ULONG SectorSize = Target->SectorSize;
+ ULONG LastBlock;
+
+ Srb->SrbStatus = SRB_STATUS_DATA_OVERRUN;
+ if (Srb->DataTransferLength < sizeof(READ_CAPACITY_DATA))
+ return;
+ RtlZeroMemory(Srb->DataBuffer, Srb->DataTransferLength);
+
+ Srb->SrbStatus = SRB_STATUS_ERROR;
+ if (Cdb_PMI(Srb) == 0 && Cdb_LogicalBlock(Srb) != 0)
+ return;
+
+ if (SectorCount == (ULONG)SectorCount)
+ LastBlock = (ULONG)SectorCount - 1;
+ else
+ LastBlock = ~0ul;
+
+ Capacity->LogicalBlockAddress = _byteswap_ulong(LastBlock);
+ Capacity->BytesPerBlock = _byteswap_ulong(SectorSize);
+
+ Srb->DataTransferLength = sizeof(READ_CAPACITY_DATA);
+ Srb->SrbStatus = SRB_STATUS_SUCCESS;
+}
+
+static FORCEINLINE VOID
+TargetReadCapacity16(
+ IN PXENVBD_TARGET Target,
+ IN PXENVBD_SRBEXT SrbExt
+ )
+{
+ PSCSI_REQUEST_BLOCK Srb = SrbExt->Srb;
+ PREAD_CAPACITY16_DATA Capacity = Srb->DataBuffer;
+ ULONG64 SectorCount = Target->SectorCount;
+ ULONG SectorSize = Target->SectorSize;
+ ULONG LogPerPhysExp;
+
+ Srb->SrbStatus = SRB_STATUS_DATA_OVERRUN;
+ if (Srb->DataTransferLength < sizeof(READ_CAPACITY16_DATA))
+ return;
+ RtlZeroMemory(Srb->DataBuffer, Srb->DataTransferLength);
+
+ Srb->SrbStatus = SRB_STATUS_ERROR;
+ if (Cdb_PMI(Srb) == 0 && Cdb_LogicalBlock(Srb) != 0)
+ return;
+
+ if (Target->PhysicalSectorSize == 0)
+ LogPerPhysExp = 0;
+ else if (!_BitScanReverse(&LogPerPhysExp, Target->PhysicalSectorSize /
SectorSize))
+ LogPerPhysExp = 0;
+
+ Capacity->LogicalBlockAddress.QuadPart = _byteswap_uint64(SectorCount -
1);
+ Capacity->BytesPerBlock = _byteswap_ulong(SectorSize);
+ Capacity->LogicalPerPhysicalExponent = (UCHAR)LogPerPhysExp;
+
+ Srb->DataTransferLength = sizeof(READ_CAPACITY16_DATA);
+ Srb->SrbStatus = SRB_STATUS_SUCCESS;
}
static FORCEINLINE BOOLEAN
-TargetPrepareFresh(
- IN PXENVBD_TARGET Target
+TargetCheckSectors(
+ IN PXENVBD_TARGET Target,
+ IN PXENVBD_SRBEXT SrbExt
)
{
- PXENVBD_SRBEXT SrbExt;
- PLIST_ENTRY ListEntry;
+ ULONG64 StartSector = Cdb_LogicalBlock(SrbExt->Srb);
+ ULONG SectorCount = Cdb_TransferBlock(SrbExt->Srb);
- ListEntry = QueuePop(&Target->FreshSrbs);
- if (ListEntry == NULL)
- return FALSE; // fresh queue is empty
+ // prevent read/write beyond the end of the disk
+ if (StartSector >= Target->SectorCount)
+ return FALSE;
+ if (StartSector + SectorCount >= Target->SectorCount)
+ return FALSE;
+ return TRUE;
+}
- SrbExt = CONTAINING_RECORD(ListEntry, XENVBD_SRBEXT, ListEntry);
+VOID
+TargetStartSrb(
+ IN PXENVBD_TARGET Target,
+ IN PXENVBD_SRBEXT SrbExt
+ )
+{
+ PSCSI_REQUEST_BLOCK Srb = SrbExt->Srb;
+ UCHAR Operation;
- switch (Cdb_OperationEx(SrbExt->Srb)) {
+ Operation = Cdb_OperationEx(Srb);
+ switch (Operation) {
case SCSIOP_READ:
case SCSIOP_WRITE:
- if (PrepareReadWrite(Target, SrbExt->Srb))
- return TRUE; // prepared this SRB
+ if (!TargetCheckSectors(Target, SrbExt))
+ Srb->SrbStatus = SRB_STATUS_ERROR;
+ else
+ TargetQueueSrb(Target, SrbExt);
break;
+
+ case SCSIOP_UNMAP:
+ if (Target->FeatureDiscard)
+ TargetQueueSrb(Target, SrbExt);
+ else
+ Srb->SrbStatus = SRB_STATUS_SUCCESS;
+ break;
+
case SCSIOP_SYNCHRONIZE_CACHE:
- if (PrepareSyncCache(Target, SrbExt->Srb))
- return TRUE; // prepared this SRB
+ if (Target->FeatureBarrier || Target->FeatureFlush)
+ TargetQueueSrb(Target, SrbExt);
+ else
+ Srb->SrbStatus = SRB_STATUS_SUCCESS;
break;
- case SCSIOP_UNMAP:
- if (PrepareUnmap(Target, SrbExt->Srb))
- return TRUE; // prepared this SRB
+
+ case SCSIOP_INQUIRY:
+ TargetInquiry(Target, SrbExt);
+ break;
+ case SCSIOP_MODE_SENSE:
+ TargetModeSense(Target, SrbExt);
+ break;
+ case SCSIOP_REQUEST_SENSE:
+ TargetRequestSense(Target, SrbExt);
+ break;
+ case SCSIOP_REPORT_LUNS:
+ TargetReportLuns(Target, SrbExt);
+ break;
+ case SCSIOP_READ_CAPACITY:
+ TargetReadCapacity(Target, SrbExt);
break;
+ case SCSIOP_READ_CAPACITY16:
+ TargetReadCapacity16(Target, SrbExt);
+ break;
+
+ case SCSIOP_MEDIUM_REMOVAL:
+ case SCSIOP_TEST_UNIT_READY:
+ case SCSIOP_RESERVE_UNIT:
+ case SCSIOP_RESERVE_UNIT10:
+ case SCSIOP_RELEASE_UNIT:
+ case SCSIOP_RELEASE_UNIT10:
+ case SCSIOP_VERIFY:
+ case SCSIOP_VERIFY16:
+ case SCSIOP_START_STOP_UNIT:
+ Srb->SrbStatus = SRB_STATUS_SUCCESS;
+ break;
+
default:
- ASSERT(FALSE);
+ Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
break;
}
- QueueUnPop(&Target->FreshSrbs, &SrbExt->ListEntry);
-
- return FALSE; // prepare failed
}
-static FORCEINLINE BOOLEAN
-TargetSubmitPrepared(
- __in PXENVBD_TARGET Target
+static VOID
+TargetStoreReadDiskInfo(
+ IN PXENVBD_TARGET Target
)
{
- PXENVBD_BLOCKRING BlockRing = FrontendGetBlockRing(Target->Frontend);
- if (TargetIsPaused(Target)) {
- if (QueueCount(&Target->PreparedReqs))
- Warning("Target[%d] : Paused, not submitting new requests (%u)\n",
- TargetGetTargetId(Target),
- QueueCount(&Target->PreparedReqs));
- return FALSE;
+ PCHAR Buffer;
+ NTSTATUS status;
+
+ status = XENBUS_STORE(Read,
+ &Target->StoreInterface,
+ NULL,
+ Target->BackendPath,
+ "info",
+ &Buffer);
+ if (NT_SUCCESS(status)) {
+ Target->DiskInfo = strtoul(Buffer, NULL, 10);
+
+ XENBUS_STORE(Free,
+ &Target->StoreInterface,
+ Buffer);
+ }
+
+ status = XENBUS_STORE(Read,
+ &Target->StoreInterface,
+ NULL,
+ Target->BackendPath,
+ "sectors",
+ &Buffer);
+ if (NT_SUCCESS(status)) {
+ Target->SectorCount = _strtoui64(Buffer, NULL, 10);
+
+ XENBUS_STORE(Free,
+ &Target->StoreInterface,
+ Buffer);
+ }
+
+ status = XENBUS_STORE(Read,
+ &Target->StoreInterface,
+ NULL,
+ Target->BackendPath,
+ "sector-size",
+ &Buffer);
+ if (NT_SUCCESS(status)) {
+ Target->SectorSize = strtoul(Buffer, NULL, 10);
+
+ XENBUS_STORE(Free,
+ &Target->StoreInterface,
+ Buffer);
+ }
+
+ status = XENBUS_STORE(Read,
+ &Target->StoreInterface,
+ NULL,
+ Target->BackendPath,
+ "physical-sector-size",
+ &Buffer);
+ if (NT_SUCCESS(status)) {
+ Target->PhysicalSectorSize = strtoul(Buffer, NULL, 10);
+
+ XENBUS_STORE(Free,
+ &Target->StoreInterface,
+ Buffer);
+ } else {
+ Target->PhysicalSectorSize = Target->SectorSize;
}
+}
- for (;;) {
- PXENVBD_REQUEST Request;
- PLIST_ENTRY Entry;
+static VOID
+TargetStoreReadFeatures(
+ IN PXENVBD_TARGET Target
+ )
+{
+ PCHAR Buffer;
+ NTSTATUS status;
- Entry = QueuePop(&Target->PreparedReqs);
- if (Entry == NULL)
- break;
+ status = XENBUS_STORE(Read,
+ &Target->StoreInterface,
+ NULL,
+ Target->BackendPath,
+ "removable",
+ &Buffer);
+ if (NT_SUCCESS(status)) {
+ Target->Removable = (BOOLEAN)strtoul(Buffer, NULL, 2);
+
+ XENBUS_STORE(Free,
+ &Target->StoreInterface,
+ Buffer);
+ }
+
+ status = XENBUS_STORE(Read,
+ &Target->StoreInterface,
+ NULL,
+ Target->BackendPath,
+ "feature-barrier",
+ &Buffer);
+ if (NT_SUCCESS(status)) {
+ Target->FeatureBarrier = (BOOLEAN)strtoul(Buffer, NULL, 2);
+
+ XENBUS_STORE(Free,
+ &Target->StoreInterface,
+ Buffer);
+ }
+
+ status = XENBUS_STORE(Read,
+ &Target->StoreInterface,
+ NULL,
+ Target->BackendPath,
+ "feature-flush-cache",
+ &Buffer);
+ if (NT_SUCCESS(status)) {
+ Target->FeatureFlush = (BOOLEAN)strtoul(Buffer, NULL, 2);
+
+ XENBUS_STORE(Free,
+ &Target->StoreInterface,
+ Buffer);
+ }
+
+ status = XENBUS_STORE(Read,
+ &Target->StoreInterface,
+ NULL,
+ Target->BackendPath,
+ "feature-discard",
+ &Buffer);
+ if (NT_SUCCESS(status)) {
+ Target->FeatureDiscard = (BOOLEAN)strtoul(Buffer, NULL, 2);
+
+ XENBUS_STORE(Free,
+ &Target->StoreInterface,
+ Buffer);
+ }
+
+ status = XENBUS_STORE(Read,
+ &Target->StoreInterface,
+ NULL,
+ Target->BackendPath,
+ "discard-enable",
+ &Buffer);
+ if (NT_SUCCESS(status)) {
+ BOOLEAN Enabled = (BOOLEAN)strtoul(Buffer, NULL, 2);
+ if (!Enabled)
+ Target->FeatureDiscard = FALSE;
+
+ XENBUS_STORE(Free,
+ &Target->StoreInterface,
+ Buffer);
+ }
+
+ status = XENBUS_STORE(Read,
+ &Target->StoreInterface,
+ NULL,
+ Target->BackendPath,
+ "discard-secure",
+ &Buffer);
+ if (NT_SUCCESS(status)) {
+ Target->DiscardSecure = (BOOLEAN)strtoul(Buffer, NULL, 2);
+
+ XENBUS_STORE(Free,
+ &Target->StoreInterface,
+ Buffer);
+ }
+
+ status = XENBUS_STORE(Read,
+ &Target->StoreInterface,
+ NULL,
+ Target->BackendPath,
+ "discard-alignment",
+ &Buffer);
+ if (NT_SUCCESS(status)) {
+ Target->DiscardAlignment = strtoul(Buffer, NULL, 10);
+
+ XENBUS_STORE(Free,
+ &Target->StoreInterface,
+ Buffer);
+ }
+
+ status = XENBUS_STORE(Read,
+ &Target->StoreInterface,
+ NULL,
+ Target->BackendPath,
+ "discard-secure",
+ &Buffer);
+ if (NT_SUCCESS(status)) {
+ Target->DiscardGranularity = strtoul(Buffer, NULL, 10);
+
+ XENBUS_STORE(Free,
+ &Target->StoreInterface,
+ Buffer);
+ }
+
+ status = XENBUS_STORE(Read,
+ &Target->StoreInterface,
+ NULL,
+ Target->BackendPath,
+ "feature-max-indirect-segments",
+ &Buffer);
+ if (NT_SUCCESS(status)) {
+ Target->FeatureIndirect = strtoul(Buffer, NULL, 10);
+
+ XENBUS_STORE(Free,
+ &Target->StoreInterface,
+ Buffer);
+ }
+}
+
+static NTSTATUS
+TargetStoreWrite(
+ IN PXENVBD_TARGET Target,
+ IN PXENBUS_STORE_TRANSACTION Transaction
+ )
+{
+ NTSTATUS status;
+
+ status = XENBUS_STORE(Printf,
+ &Target->StoreInterface,
+ Transaction,
+ Target->Path,
+ "target-id",
+ "%u",
+ Target->TargetId);
+ if (!NT_SUCCESS(status))
+ return status;
+
+ status = XENBUS_STORE(Printf,
+ &Target->StoreInterface,
+ Transaction,
+ Target->Path,
+ "feature-surprise-remove",
+ "%u",
+ TRUE);
+ if (!NT_SUCCESS(status))
+ return status;
+
+ status = XENBUS_STORE(Printf,
+ &Target->StoreInterface,
+ Transaction,
+ Target->Path,
+ "feature-online-resize",
+ "%u",
+ TRUE);
+ if (!NT_SUCCESS(status))
+ return status;
- Request = CONTAINING_RECORD(Entry, XENVBD_REQUEST, Entry);
+ return STATUS_SUCCESS;
+}
- QueueAppend(&Target->SubmittedReqs, &Request->Entry);
- KeMemoryBarrier();
+static NTSTATUS
+TargetWriteTargetPath(
+ IN PXENVBD_TARGET Target
+ )
+{
+ NTSTATUS status;
- if (BlockRingSubmit(BlockRing, Request))
- continue;
+ status = XENBUS_STORE(Printf,
+ &Target->StoreInterface,
+ NULL,
+ Target->TargetPath,
+ "frontend",
+ "%s",
+ Target->Path);
+ if (!NT_SUCCESS(status))
+ goto fail1;
- QueueRemove(&Target->SubmittedReqs, &Request->Entry);
- QueueUnPop(&Target->PreparedReqs, &Request->Entry);
- return FALSE; // ring full
- }
+ status = XENBUS_STORE(Printf,
+ &Target->StoreInterface,
+ NULL,
+ Target->TargetPath,
+ "device",
+ "%u",
+ Target->DeviceId);
+ if (!NT_SUCCESS(status))
+ goto fail2;
- return TRUE;
+ return STATUS_SUCCESS;
+
+fail2:
+ Error("fail2\n");
+fail1:
+ Error("fail1 %08x\n", status);
+ return status;
}
-static FORCEINLINE VOID
-TargetCompleteShutdown(
- __in PXENVBD_TARGET Target
+static VOID
+TargetWaitForBackendStateChange(
+ IN PXENVBD_TARGET Target,
+ OUT XenbusState* State
)
{
- if (QueueCount(&Target->ShutdownSrbs) == 0)
- return;
+ KEVENT Event;
+ PXENBUS_STORE_WATCH Watch;
+ LARGE_INTEGER Start;
+ ULONGLONG TimeDelta;
+ LARGE_INTEGER Timeout;
+ XenbusState Old = *State;
+ NTSTATUS status;
- if (QueueCount(&Target->FreshSrbs) ||
- QueueCount(&Target->PreparedReqs) ||
- QueueCount(&Target->SubmittedReqs))
- return;
+ KeInitializeEvent(&Event, NotificationEvent, FALSE);
- for (;;) {
- PXENVBD_SRBEXT SrbExt;
- PLIST_ENTRY ListEntry = QueuePop(&Target->ShutdownSrbs);
- if (ListEntry == NULL)
- break;
- SrbExt = CONTAINING_RECORD(ListEntry, XENVBD_SRBEXT, ListEntry);
- SrbExt->Srb->SrbStatus = SRB_STATUS_SUCCESS;
- AdapterCompleteSrb(TargetGetAdapter(Target), SrbExt);
+ status = XENBUS_STORE(WatchAdd,
+ &Target->StoreInterface,
+ Target->BackendPath,
+ "state",
+ &Event,
+ &Watch);
+ if (!NT_SUCCESS(status))
+ Watch = NULL;
+
+ KeQuerySystemTime(&Start);
+ TimeDelta = 0;
+
+ Timeout.QuadPart = 0;
+
+ while (*State == Old && TimeDelta < 120000) {
+ PCHAR Buffer;
+ LARGE_INTEGER Now;
+
+ if (Watch != NULL) {
+ ULONG Attempt = 0;
+
+ while (++Attempt < 1000) {
+ status = KeWaitForSingleObject(&Event,
+ Executive,
+ KernelMode,
+ FALSE,
+ &Timeout);
+ if (status != STATUS_TIMEOUT)
+ break;
+
+ // We are waiting for a watch event at DISPATCH_LEVEL so
+ // it is our responsibility to poll the store ring.
+ XENBUS_STORE(Poll,
+ &Target->StoreInterface);
+
+ KeStallExecutionProcessor(1000); // 1ms
+ }
+
+ KeClearEvent(&Event);
+ }
+
+ status = XENBUS_STORE(Read,
+ &Target->StoreInterface,
+ NULL,
+ Target->BackendPath,
+ "state",
+ &Buffer);
+ if (!NT_SUCCESS(status)) {
+ *State = XenbusStateUnknown;
+ } else {
+ *State = (XenbusState)strtol(Buffer, NULL, 10);
+
+ XENBUS_STORE(Free,
+ &Target->StoreInterface,
+ Buffer);
+ }
+
+ KeQuerySystemTime(&Now);
+
+ TimeDelta = (Now.QuadPart - Start.QuadPart) / 10000ull;
}
+
+ if (Watch != NULL)
+ (VOID) XENBUS_STORE(WatchRemove,
+ &Target->StoreInterface,
+ Watch);
}
-static FORCEINLINE PCHAR
-BlkifOperationName(
- IN UCHAR Operation
+static NTSTATUS
+TargetUpdatePath(
+ IN PXENVBD_TARGET Target
)
{
- 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>";
+ ULONG Length;
+ PCHAR Buffer;
+ NTSTATUS status;
+
+ status = XENBUS_STORE(Read,
+ &Target->StoreInterface,
+ NULL,
+ Target->Path,
+ "backend-id",
+ &Buffer);
+ if (NT_SUCCESS(status)) {
+ Target->BackendId = (USHORT)strtoul(Buffer, NULL, 10);
+
+ XENBUS_STORE(Free,
+ &Target->StoreInterface,
+ Buffer);
+ } else {
+ Target->BackendId = 0;
}
+
+ status = XENBUS_STORE(Read,
+ &Target->StoreInterface,
+ NULL,
+ Target->Path,
+ "backend",
+ &Buffer);
+ if (!NT_SUCCESS(status))
+ goto fail1;
+
+ __TargetFree(Target->BackendPath);
+ Target->BackendPath = NULL;
+
+ Length = (ULONG)strlen(Buffer);
+
+ status = STATUS_NO_MEMORY;
+ Target->BackendPath = __TargetAllocate(Length + 1);
+ if (Target->BackendPath == NULL)
+ goto fail2;
+
+ RtlCopyMemory(Target->BackendPath, Buffer, Length);
+
+ XENBUS_STORE(Free,
+ &Target->StoreInterface,
+ Buffer);
+
+ return STATUS_SUCCESS;
+
+fail2:
+ Error("fail2\n");
+ XENBUS_STORE(Free,
+ &Target->StoreInterface,
+ Buffer);
+fail1:
+ Error("fail1 %08x\n", status);
+ return status;
+
}
-VOID
-TargetSubmitRequests(
- __in PXENVBD_TARGET Target
+static NTSTATUS
+TargetClose(
+ IN PXENVBD_TARGET Target
)
{
- for (;;) {
- // submit all prepared requests (0 or more requests)
- // return TRUE if submitted 0 or more requests from prepared queue
- // return FALSE iff ring is full
- if (!TargetSubmitPrepared(Target))
- break;
+ XenbusState State;
+ NTSTATUS status;
- // prepare a single SRB (into 1 or more requests)
- // return TRUE if prepare succeeded
- // return FALSE if prepare failed or fresh queue empty
- if (!TargetPrepareFresh(Target))
- break;
- }
+ Trace("[%u] ----->\n", Target->TargetId);
- // if no requests/SRBs outstanding, complete any shutdown SRBs
- TargetCompleteShutdown(Target);
+ if (Target->BackendWatch)
+ XENBUS_STORE(WatchRemove,
+ &Target->StoreInterface,
+ Target->BackendWatch);
+ Target->BackendWatch = NULL;
+
+ status = TargetUpdatePath(Target);
+ if (!NT_SUCCESS(status))
+ goto fail1;
+
+ State = XenbusStateUnknown;
+ do {
+ TargetWaitForBackendStateChange(Target, &State);
+
+ status = STATUS_UNSUCCESSFUL;
+ if (State == XenbusStateUnknown)
+ goto fail2;
+ } while (State == XenbusStateInitialising);
+
+ while (State != XenbusStateClosing &&
+ State != XenbusStateClosed) {
+ status = XENBUS_STORE(Printf,
+ &Target->StoreInterface,
+ NULL,
+ Target->Path,
+ "state",
+ "%u",
+ (ULONG)XenbusStateClosing);
+ if (!NT_SUCCESS(status))
+ goto fail3;
+
+ TargetWaitForBackendStateChange(Target, &State);
+
+ status = STATUS_UNSUCCESSFUL;
+ if (State == XenbusStateUnknown)
+ goto fail4;
+ }
+
+ while (State != XenbusStateClosed) {
+ status = XENBUS_STORE(Printf,
+ &Target->StoreInterface,
+ NULL,
+ Target->Path,
+ "state",
+ "%u",
+ (ULONG)XenbusStateClosed);
+ if (!NT_SUCCESS(status))
+ goto fail3;
+
+ TargetWaitForBackendStateChange(Target, &State);
+
+ status = STATUS_UNSUCCESSFUL;
+ if (State == XenbusStateUnknown)
+ goto fail4;
+ }
+
+ Trace("[%u] <-----\n", Target->TargetId);
+ return STATUS_SUCCESS;
+
+fail4:
+ Error("fail4\n");
+fail3:
+ Error("fail3\n");
+fail2:
+ Error("fail2\n");
+fail1:
+ Error("fail1 %08x\n", status);
+ return status;
}
-VOID
-TargetCompleteResponse(
- __in PXENVBD_TARGET Target,
- __in ULONG Tag,
- __in SHORT Status
+static NTSTATUS
+TargetPrepare(
+ IN PXENVBD_TARGET Target
)
{
- PXENVBD_REQUEST Request;
- PSCSI_REQUEST_BLOCK Srb;
- PXENVBD_SRBEXT SrbExt;
+ XenbusState State;
+ NTSTATUS status;
- Request = TargetRequestFromTag(Target, Tag);
- if (Request == NULL)
- return;
+ Trace("[%u] ----->\n", Target->TargetId);
+
+ status = TargetUpdatePath(Target);
+ if (!NT_SUCCESS(status))
+ goto fail1;
+
+ status = XENBUS_STORE(WatchAdd,
+ &Target->StoreInterface,
+ NULL,
+ Target->BackendPath,
+ ThreadGetEvent(Target->BackendThread),
+ &Target->BackendWatch);
+ if (!NT_SUCCESS(status))
+ goto fail2;
- Srb = Request->Srb;
- SrbExt = Srb->SrbExtension;
- ASSERT3P(SrbExt, !=, NULL);
+ status = TargetWriteTargetPath(Target);
+ if (!NT_SUCCESS(status))
+ goto fail3;
- switch (Status) {
- case BLKIF_RSP_OKAY:
- RequestCopyOutput(Request);
- break;
+ status = XENBUS_STORE(Printf,
+ &Target->StoreInterface,
+ NULL,
+ Target->Path,
+ "state",
+ "%u",
+ (ULONG)XenbusStateInitialising);
+ if (!NT_SUCCESS(status))
+ goto fail4;
- case BLKIF_RSP_EOPNOTSUPP:
- // Remove appropriate feature support
- FrontendRemoveFeature(Target->Frontend, Request->Operation);
- // Succeed this SRB, subsiquent SRBs will be succeeded instead of
being passed to the backend.
- Srb->SrbStatus = SRB_STATUS_SUCCESS;
- break;
+ State = XenbusStateUnknown;
+ do {
+ TargetWaitForBackendStateChange(Target, &State);
- case BLKIF_RSP_ERROR:
- default:
- Warning("Target[%d] : %s BLKIF_RSP_ERROR (Tag %x)\n",
- TargetGetTargetId(Target),
BlkifOperationName(Request->Operation), Tag);
- Srb->SrbStatus = SRB_STATUS_ERROR;
- break;
- }
+ status = STATUS_UNSUCCESSFUL;
+ if (State == XenbusStateUnknown)
+ goto fail5;
+ } while (State == XenbusStateClosed ||
+ State == XenbusStateInitialising);
- TargetPutRequest(Target, Request);
+ status = STATUS_UNSUCCESSFUL;
+ if (State != XenbusStateInitWait)
+ goto fail6;
- // complete srb
- if (InterlockedDecrement(&SrbExt->RequestCount) == 0) {
- 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
- }
+ Trace("[%u] <-----\n", Target->TargetId);
+ return STATUS_SUCCESS;
- AdapterCompleteSrb(TargetGetAdapter(Target), SrbExt);
- }
+fail6:
+ Error("fail6\n");
+fail5:
+ Error("fail5\n");
+fail4:
+ Error("fail4\n");
+fail3:
+ Error("fail3\n");
+ XENBUS_STORE(WatchRemove,
+ &Target->StoreInterface,
+ Target->BackendWatch);
+ Target->BackendWatch = NULL;
+fail2:
+ Error("fail2\n");
+fail1:
+ Error("fail1 %08x\n", status);
+ return status;
}
-VOID
-TargetPreResume(
- __in PXENVBD_TARGET Target
+static NTSTATUS
+TargetConnect(
+ IN PXENVBD_TARGET Target
)
{
- LIST_ENTRY List;
-
- InitializeListHead(&List);
+ XenbusState State;
+ NTSTATUS status;
- // pop all submitted requests, cleanup and add associated SRB to a list
- for (;;) {
- PXENVBD_SRBEXT SrbExt;
- PXENVBD_REQUEST Request;
- PLIST_ENTRY Entry = QueuePop(&Target->SubmittedReqs);
- if (Entry == NULL)
- break;
- Request = CONTAINING_RECORD(Entry, XENVBD_REQUEST, Entry);
- SrbExt = Request->Srb->SrbExtension;
+ Trace("[%u] ----->\n", Target->TargetId);
- TargetPutRequest(Target, Request);
+ status = GranterConnect(Target->Granter);
+ if (!NT_SUCCESS(status))
+ goto fail1;
- if (InterlockedDecrement(&SrbExt->RequestCount) == 0) {
- InsertTailList(&List, &SrbExt->ListEntry);
- }
- }
+ status = BlockRingConnect(Target->BlockRing);
+ if (!NT_SUCCESS(status))
+ goto fail2;
- // pop all prepared requests, cleanup and add associated SRB to a list
for (;;) {
- PXENVBD_SRBEXT SrbExt;
- PXENVBD_REQUEST Request;
- PLIST_ENTRY Entry = QueuePop(&Target->PreparedReqs);
- if (Entry == NULL)
+ PXENBUS_STORE_TRANSACTION Transaction;
+
+ status = XENBUS_STORE(TransactionStart,
+ &Target->StoreInterface,
+ &Transaction);
+ if (!NT_SUCCESS(status))
break;
- Request = CONTAINING_RECORD(Entry, XENVBD_REQUEST, Entry);
- SrbExt = Request->Srb->SrbExtension;
- TargetPutRequest(Target, Request);
+ status = BlockRingStoreWrite(Target->BlockRing, Transaction);
+ if (!NT_SUCCESS(status))
+ goto abort;
- if (InterlockedDecrement(&SrbExt->RequestCount) == 0) {
- InsertTailList(&List, &SrbExt->ListEntry);
- }
- }
+ status = GranterStoreWrite(Target->Granter, Transaction);
+ if (!NT_SUCCESS(status))
+ goto abort;
- // foreach SRB in list, put on start of FreshSrbs
- for (;;) {
- PXENVBD_SRBEXT SrbExt;
- PLIST_ENTRY ListEntry = RemoveTailList(&List);
- if (ListEntry == &List)
- break;
- SrbExt = CONTAINING_RECORD(ListEntry, XENVBD_SRBEXT, ListEntry);
+ status = TargetStoreWrite(Target, Transaction);
+ if (!NT_SUCCESS(status))
+ goto abort;
+
+ status = XENBUS_STORE(TransactionEnd,
+ &Target->StoreInterface,
+ Transaction,
+ TRUE);
+ if (status == STATUS_RETRY)
+ continue;
+ break;
- QueueUnPop(&Target->FreshSrbs, &SrbExt->ListEntry);
+abort:
+ (VOID) XENBUS_STORE(TransactionEnd,
+ &Target->StoreInterface,
+ Transaction,
+ FALSE);
+ break;
}
+ if (!NT_SUCCESS(status))
+ goto fail3;
- // now the first set of requests popped off submitted list is the next SRB
- // to be popped off the fresh list
-}
+ status = XENBUS_STORE(Printf,
+ &Target->StoreInterface,
+ NULL,
+ Target->Path,
+ "state",
+ "%u",
+ (ULONG)XenbusStateInitialised);
+ if (!NT_SUCCESS(status))
+ goto fail4;
+
+ State = XenbusStateUnknown;
+ do {
+ TargetWaitForBackendStateChange(Target, &State);
+
+ status = STATUS_UNSUCCESSFUL;
+ if (State == XenbusStateUnknown)
+ goto fail5;
+ } while (State == XenbusStateInitWait ||
+ State == XenbusStateInitialising ||
+ State == XenbusStateInitialised);
+
+ status = STATUS_UNSUCCESSFUL;
+ if (State != XenbusStateConnected)
+ goto fail6;
+
+ TargetStoreReadDiskInfo(Target);
+ TargetStoreReadFeatures(Target);
+
+ status = XENBUS_STORE(Printf,
+ &Target->StoreInterface,
+ NULL,
+ Target->Path,
+ "state",
+ "%u",
+ (ULONG)XenbusStateConnected);
+ if (!NT_SUCCESS(status))
+ goto fail7;
-VOID
-TargetPostResume(
- __in PXENVBD_TARGET Target
- )
-{
- KIRQL Irql;
+ Trace("[%u] <-----\n", Target->TargetId);
+ return STATUS_SUCCESS;
- Verbose("Target[%d] : %d Fresh SRBs\n", TargetGetTargetId(Target),
QueueCount(&Target->FreshSrbs));
-
- // clear missing flag
- KeAcquireSpinLock(&Target->Lock, &Irql);
- Verbose("Target[%d] : %s (%s)\n", TargetGetTargetId(Target),
Target->Missing ? "MISSING" : "NOT_MISSING", Target->Reason);
- Target->Missing = FALSE;
- Target->Reason = NULL;
- KeReleaseSpinLock(&Target->Lock, Irql);
+fail7:
+ Error("fail7\n");
+fail6:
+ Error("fail6\n");
+fail5:
+ Error("fail5\n");
+fail4:
+ Error("fali4\n");
+fail3:
+ Error("fail3\n");
+ BlockRingDisconnect(Target->BlockRing);
+fail2:
+ Error("fail2\n");
+ GranterDisconnect(Target->Granter);
+fail1:
+ Error("fail1 %08x\n", status);
+ return status;
}
-//=============================================================================
-// SRBs
-__checkReturn
-static FORCEINLINE BOOLEAN
-__ValidateSectors(
- __in ULONG64 SectorCount,
- __in ULONG64 Start,
- __in ULONG Length
+static VOID
+TargetEnable(
+ IN PXENVBD_TARGET Target
)
{
- // Deal with overflow
- return (Start < SectorCount) && ((Start + Length) <= SectorCount);
-}
+ Trace("[%u] ----->\n", Target->TargetId);
-__checkReturn
-static FORCEINLINE BOOLEAN
-__ValidateSrbBuffer(
- __in PCHAR Caller,
- __in PSCSI_REQUEST_BLOCK Srb,
- __in ULONG MinLength
- )
-{
- if (Srb->DataBuffer == NULL) {
- Error("%s: Srb[0x%p].DataBuffer = NULL\n", Caller, Srb);
- return FALSE;
- }
- if (MinLength) {
- if (Srb->DataTransferLength < MinLength) {
- Error("%s: Srb[0x%p].DataTransferLength < %d\n", Caller, Srb,
MinLength);
- return FALSE;
- }
- } else {
- if (Srb->DataTransferLength == 0) {
- Error("%s: Srb[0x%p].DataTransferLength = 0\n", Caller, Srb);
- return FALSE;
- }
- }
+ GranterEnable(Target->Granter);
+ BlockRingEnable(Target->BlockRing);
- return TRUE;
+ Trace("[%u] <-----\n", Target->TargetId);
}
-static DECLSPEC_NOINLINE VOID
-TargetReadWrite(
- IN PXENVBD_TARGET Target,
- IN PXENVBD_SRBEXT SrbExt
+static VOID
+TargetDisable(
+ IN PXENVBD_TARGET Target
)
{
- PSCSI_REQUEST_BLOCK Srb = SrbExt->Srb;
- PXENVBD_DISKINFO DiskInfo = FrontendGetDiskInfo(Target->Frontend);
- PXENVBD_NOTIFIER Notifier = FrontendGetNotifier(Target->Frontend);
-
- if (FrontendGetCaps(Target->Frontend)->Connected == FALSE) {
- Trace("Target[%d] : Not Ready, fail SRB\n", TargetGetTargetId(Target));
- Srb->ScsiStatus = 0x40; // SCSI_ABORT;
- Srb->SrbStatus = SRB_STATUS_ERROR;
- return;
- }
+ Trace("[%u] ----->\n", Target->TargetId);
- // check valid sectors
- if (!__ValidateSectors(DiskInfo->SectorCount, Cdb_LogicalBlock(Srb),
Cdb_TransferBlock(Srb))) {
- Trace("Target[%d] : Invalid Sector (%d @ %lld < %lld)\n",
TargetGetTargetId(Target), Cdb_TransferBlock(Srb), Cdb_LogicalBlock(Srb),
DiskInfo->SectorCount);
- Srb->ScsiStatus = 0x40; // SCSI_ABORT
- Srb->SrbStatus = SRB_STATUS_ERROR;
- return; // Complete now
- }
+ BlockRingDisable(Target->BlockRing);
+ GranterDisable(Target->Granter);
- QueueAppend(&Target->FreshSrbs, &SrbExt->ListEntry);
- NotifierKick(Notifier);
+ Trace("[%u] <-----\n", Target->TargetId);
}
-static DECLSPEC_NOINLINE VOID
-TargetSyncCache(
- IN PXENVBD_TARGET Target,
- IN PXENVBD_SRBEXT SrbExt
+static VOID
+TargetDisconnect(
+ IN PXENVBD_TARGET Target
)
{
- PSCSI_REQUEST_BLOCK Srb = SrbExt->Srb;
- PXENVBD_NOTIFIER Notifier = FrontendGetNotifier(Target->Frontend);
-
- if (FrontendGetCaps(Target->Frontend)->Connected == FALSE) {
- Trace("Target[%d] : Not Ready, fail SRB\n", TargetGetTargetId(Target));
- Srb->ScsiStatus = 0x40; // SCSI_ABORT;
- Srb->SrbStatus = SRB_STATUS_ERROR;
- return;
- }
+ Trace("[%u] ----->\n", Target->TargetId);
- if (FrontendGetDiskInfo(Target->Frontend)->FlushCache == FALSE &&
- FrontendGetDiskInfo(Target->Frontend)->Barrier == FALSE) {
- Trace("Target[%d] : FLUSH and BARRIER not supported, suppressing\n",
TargetGetTargetId(Target));
- Srb->ScsiStatus = 0x00; // SCSI_GOOD
- Srb->SrbStatus = SRB_STATUS_SUCCESS;
- return;
- }
+ BlockRingDisconnect(Target->BlockRing);
+ GranterDisconnect(Target->Granter);
- QueueAppend(&Target->FreshSrbs, &SrbExt->ListEntry);
- NotifierKick(Notifier);
+ Trace("[%u] <-----\n", Target->TargetId);
}
-static DECLSPEC_NOINLINE VOID
-TargetUnmap(
- IN PXENVBD_TARGET Target,
- IN PXENVBD_SRBEXT SrbExt
+static FORCEINLINE PCHAR
+XenvbdStateName(
+ IN XENVBD_STATE State
)
{
- PSCSI_REQUEST_BLOCK Srb = SrbExt->Srb;
- PXENVBD_NOTIFIER Notifier = FrontendGetNotifier(Target->Frontend);
-
- if (FrontendGetCaps(Target->Frontend)->Connected == FALSE) {
- Trace("Target[%d] : Not Ready, fail SRB\n", TargetGetTargetId(Target));
- Srb->ScsiStatus = 0x40; // SCSI_ABORT;
- Srb->SrbStatus = SRB_STATUS_ERROR;
- return;
- }
-
- if (FrontendGetDiskInfo(Target->Frontend)->Discard == FALSE) {
- Trace("Target[%d] : DISCARD not supported, suppressing\n",
TargetGetTargetId(Target));
- Srb->ScsiStatus = 0x00; // SCSI_GOOD
- Srb->SrbStatus = SRB_STATUS_SUCCESS;
- return;
+ switch (State) {
+ case XENVBD_STATE_INVALID: return "INVALID";
+ case XENVBD_INITIALIZED: return "INITIAIZED";
+ case XENVBD_CLOSING: return "CLOSING";
+ case XENVBD_CLOSED: return "CLOSED";
+ case XENVBD_PREPARED: return "PREPARED";
+ case XENVBD_CONNECTED: return "CONNECTED";
+ case XENVBD_ENABLED: return "ENABLED";
+ default: return "<UNKNOWN>";
}
-
- QueueAppend(&Target->FreshSrbs, &SrbExt->ListEntry);
- NotifierKick(Notifier);
}
-#define MODE_CACHING_PAGE_LENGTH 20
-static DECLSPEC_NOINLINE VOID
-TargetModeSense(
- IN PXENVBD_TARGET Target,
- IN PXENVBD_SRBEXT SrbExt
- )
-{
- PSCSI_REQUEST_BLOCK Srb = SrbExt->Srb;
- PMODE_PARAMETER_HEADER Header = Srb->DataBuffer;
- const UCHAR PageCode = Cdb_PageCode(Srb);
- ULONG LengthLeft = Cdb_AllocationLength(Srb);
- PVOID CurrentPage = Srb->DataBuffer;
+static NTSTATUS
+TargetSetState(
+ IN PXENVBD_TARGET Target,
+ IN XENVBD_STATE State
+ )
+{
+ NTSTATUS status = STATUS_SUCCESS;
+
+ Verbose("[%u] %s -> %s\n",
+ Target->TargetId,
+ XenvbdStateName(Target->State),
+ XenvbdStateName(State));
+
+ ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
+
+ while (NT_SUCCESS(status) && Target->State != State) {
+ switch (Target->State) {
+ case XENVBD_INITIALIZED:
+ switch (State) {
+ case XENVBD_CLOSING:
+ case XENVBD_CLOSED:
+ case XENVBD_PREPARED:
+ case XENVBD_CONNECTED:
+ case XENVBD_ENABLED:
+ status = TargetClose(Target);
+ if (!NT_SUCCESS(status))
+ break;
+ Target->State = XENVBD_CLOSED;
+ break;
+ default:
+ status = STATUS_UNSUCCESSFUL;
+ break;
+ }
+ break;
- UNREFERENCED_PARAMETER(Target);
+ case XENVBD_CLOSING:
+ switch (State) {
+ case XENVBD_INITIALIZED:
+ case XENVBD_CLOSED:
+ case XENVBD_PREPARED:
+ case XENVBD_CONNECTED:
+ case XENVBD_ENABLED:
+ TargetDisconnect(Target);
+ Target->State = XENVBD_CLOSED;
+ break;
+ default:
+ status = STATUS_UNSUCCESSFUL;
+ break;
+ }
+ break;
- RtlZeroMemory(Srb->DataBuffer, Srb->DataTransferLength);
+ case XENVBD_CLOSED:
+ switch (State) {
+ //case XENVBD_INITIALIZING:
+ // Target->State = XENVBD_INITIALISED;
+ // break;
+ case XENVBD_PREPARED:
+ case XENVBD_CONNECTED:
+ case XENVBD_ENABLED:
+ status = TargetPrepare(Target);
+ if (!NT_SUCCESS(status)) {
+ TargetClose(Target);
+ Target->State = XENVBD_CLOSED;
+ break;
+ }
+ Target->State = XENVBD_PREPARED;
+ break;
+ default:
+ status = STATUS_UNSUCCESSFUL;
+ break;
+ }
+ break;
- if (!__ValidateSrbBuffer(__FUNCTION__, Srb, (ULONG)sizeof(struct
_MODE_SENSE))) {
- Srb->ScsiStatus = 0x40;
- Srb->SrbStatus = SRB_STATUS_DATA_OVERRUN;
- Srb->DataTransferLength = 0;
- return;
- }
+ case XENVBD_PREPARED:
+ switch (State) {
+ case XENVBD_CLOSING:
+ case XENVBD_CLOSED:
+ status = TargetClose(Target);
+ if (!NT_SUCCESS(status))
+ break;
+ Target->State = XENVBD_CLOSED;
+ break;
+ case XENVBD_CONNECTED:
+ case XENVBD_ENABLED:
+ status = TargetConnect(Target);
+ if (!NT_SUCCESS(status)) {
+ TargetClose(Target);
+ Target->State = XENVBD_CLOSED;
+ break;
+ }
+ Target->State = XENVBD_CONNECTED;
+ break;
+ default:
+ status = STATUS_UNSUCCESSFUL;
+ break;
+ }
+ break;
- // TODO : CDROM requires more ModePage entries
- // Header
- Header->ModeDataLength = sizeof(MODE_PARAMETER_HEADER) - 1;
- Header->MediumType = 0;
- Header->DeviceSpecificParameter = 0;
- Header->BlockDescriptorLength = 0;
- LengthLeft -= sizeof(MODE_PARAMETER_HEADER);
- CurrentPage = ((PUCHAR)CurrentPage + sizeof(MODE_PARAMETER_HEADER));
-
- // Fill in Block Parameters (if Specified and space)
- // when the DBD (Disable Block Descriptor) is set, ignore the block page
- if (Cdb_Dbd(Srb) == 0 &&
- LengthLeft >= sizeof(MODE_PARAMETER_BLOCK)) {
- PMODE_PARAMETER_BLOCK Block = (PMODE_PARAMETER_BLOCK)CurrentPage;
- // Fill in BlockParams
- Block->DensityCode = 0;
- Block->NumberOfBlocks[0] = 0;
- Block->NumberOfBlocks[1] = 0;
- Block->NumberOfBlocks[2] = 0;
- Block->BlockLength[0] = 0;
- Block->BlockLength[1] = 0;
- Block->BlockLength[2] = 0;
+ case XENVBD_CONNECTED:
+ switch (State) {
+ case XENVBD_ENABLED:
+ TargetEnable(Target);
+ Target->State = XENVBD_ENABLED;
+ break;
+ case XENVBD_CLOSING:
+ case XENVBD_CLOSED:
+ status = TargetClose(Target);
+ if (!NT_SUCCESS(status))
+ break;
+ Target->State = XENVBD_CLOSING;
+ break;
+ default:
+ status = STATUS_UNSUCCESSFUL;
+ break;
+ }
+ break;
- Header->BlockDescriptorLength = sizeof(MODE_PARAMETER_BLOCK);
- Header->ModeDataLength += sizeof(MODE_PARAMETER_BLOCK);
- LengthLeft -= sizeof(MODE_PARAMETER_BLOCK);
- CurrentPage = ((PUCHAR)CurrentPage + sizeof(MODE_PARAMETER_BLOCK));
- }
+ case XENVBD_ENABLED:
+ switch (State) {
+ case XENVBD_CLOSING:
+ case XENVBD_CLOSED:
+ case XENVBD_CONNECTED:
+ TargetDisable(Target);
+ Target->State = XENVBD_CONNECTED;
+ break;
+ default:
+ status = STATUS_UNSUCCESSFUL;
+ break;
+ }
+ break;
- // Fill in Cache Parameters (if Specified and space)
- if ((PageCode == MODE_PAGE_CACHING || PageCode == MODE_SENSE_RETURN_ALL) &&
- LengthLeft >= MODE_CACHING_PAGE_LENGTH) {
- PMODE_CACHING_PAGE Caching = (PMODE_CACHING_PAGE)CurrentPage;
- // Fill in CachingParams
- Caching->PageCode = MODE_PAGE_CACHING;
- Caching->PageSavable = 0;
- Caching->PageLength = MODE_CACHING_PAGE_LENGTH;
- Caching->ReadDisableCache = 0;
- Caching->MultiplicationFactor = 0;
- Caching->WriteCacheEnable =
FrontendGetDiskInfo(Target->Frontend)->FlushCache ? 1 : 0;
- Caching->WriteRetensionPriority = 0;
- Caching->ReadRetensionPriority = 0;
- Caching->DisablePrefetchTransfer[0] = 0;
- Caching->DisablePrefetchTransfer[1] = 0;
- Caching->MinimumPrefetch[0] = 0;
- Caching->MinimumPrefetch[1] = 0;
- Caching->MaximumPrefetch[0] = 0;
- Caching->MaximumPrefetch[1] = 0;
- Caching->MaximumPrefetchCeiling[0] = 0;
- Caching->MaximumPrefetchCeiling[1] = 0;
-
- Header->ModeDataLength += MODE_CACHING_PAGE_LENGTH;
- LengthLeft -= MODE_CACHING_PAGE_LENGTH;
- CurrentPage = ((PUCHAR)CurrentPage + MODE_CACHING_PAGE_LENGTH);
+ default:
+ status = STATUS_UNSUCCESSFUL;
+ break;
+ }
}
- // Fill in Informational Exception Parameters (if Specified and space)
- if ((PageCode == MODE_PAGE_FAULT_REPORTING || PageCode ==
MODE_SENSE_RETURN_ALL) &&
- LengthLeft >= sizeof(MODE_INFO_EXCEPTIONS)) {
- PMODE_INFO_EXCEPTIONS Exceptions = (PMODE_INFO_EXCEPTIONS)CurrentPage;
- // Fill in Exceptions
- Exceptions->PageCode = MODE_PAGE_FAULT_REPORTING;
- Exceptions->PSBit = 0;
- Exceptions->PageLength = sizeof(MODE_INFO_EXCEPTIONS);
- Exceptions->Flags = 0;
- Exceptions->Dexcpt = 1; // disabled
- Exceptions->ReportMethod = 0;
- Exceptions->IntervalTimer[0] = 0;
- Exceptions->IntervalTimer[1] = 0;
- Exceptions->IntervalTimer[2] = 0;
- Exceptions->IntervalTimer[3] = 0;
- Exceptions->ReportCount[0] = 0;
- Exceptions->ReportCount[1] = 0;
- Exceptions->ReportCount[2] = 0;
- Exceptions->ReportCount[3] = 0;
-
- Header->ModeDataLength += sizeof(MODE_INFO_EXCEPTIONS);
- LengthLeft -= sizeof(MODE_INFO_EXCEPTIONS);
- CurrentPage = ((PUCHAR)CurrentPage + sizeof(MODE_INFO_EXCEPTIONS));
- }
+ Verbose("[%u] in state %s\n",
+ Target->TargetId,
+ XenvbdStateName(Target->State));
- // Finish this SRB
- Srb->SrbStatus = SRB_STATUS_SUCCESS;
- Srb->DataTransferLength = __min(Cdb_AllocationLength(Srb),
(ULONG)(Header->ModeDataLength + 1));
+ return status;
}
-static DECLSPEC_NOINLINE VOID
-TargetRequestSense(
- IN PXENVBD_TARGET Target,
- IN PXENVBD_SRBEXT SrbExt
+static FORCEINLINE NTSTATUS
+__TargetD3ToD0(
+ IN PXENVBD_TARGET Target
)
{
- PSCSI_REQUEST_BLOCK Srb = SrbExt->Srb;
- PSENSE_DATA Sense = Srb->DataBuffer;
+ NTSTATUS status;
- UNREFERENCED_PARAMETER(Target);
+ status = XENBUS_STORE(Acquire, &Target->StoreInterface);
+ if (!NT_SUCCESS(status))
+ goto fail1;
- if (!__ValidateSrbBuffer(__FUNCTION__, Srb, (ULONG)sizeof(SENSE_DATA))) {
- Srb->ScsiStatus = 0x40;
- Srb->SrbStatus = SRB_STATUS_DATA_OVERRUN;
- return;
- }
+ status = TargetSetState(Target, XENVBD_ENABLED);
+ if (!NT_SUCCESS(status))
+ goto fail2;
- RtlZeroMemory(Sense, sizeof(SENSE_DATA));
+ return STATUS_SUCCESS;
- Sense->ErrorCode = 0x70;
- Sense->Valid = 1;
- Sense->AdditionalSenseCodeQualifier = 0;
- Sense->SenseKey = SCSI_SENSE_NO_SENSE;
- Sense->AdditionalSenseCode = SCSI_ADSENSE_NO_SENSE;
- Srb->DataTransferLength = sizeof(SENSE_DATA);
- Srb->SrbStatus = SRB_STATUS_SUCCESS;
+fail2:
+ Error("fail2\n");
+ XENBUS_STORE(Release, &Target->StoreInterface);
+fail1:
+ Error("fail1 %08x\n", status);
+ return status;
}
-static DECLSPEC_NOINLINE VOID
-TargetReportLuns(
- IN PXENVBD_TARGET Target,
- IN PXENVBD_SRBEXT SrbExt
+static FORCEINLINE VOID
+__TargetD0ToD3(
+ IN PXENVBD_TARGET Target
)
{
- PSCSI_REQUEST_BLOCK Srb = SrbExt->Srb;
- ULONG Length;
- ULONG Offset;
- ULONG AllocLength = Cdb_AllocationLength(Srb);
- PUCHAR Buffer = Srb->DataBuffer;
-
- UNREFERENCED_PARAMETER(Target);
+ TargetSetState(Target, XENVBD_CLOSED);
- if (!__ValidateSrbBuffer(__FUNCTION__, Srb, 8)) {
- Srb->ScsiStatus = 0x40;
- Srb->SrbStatus = SRB_STATUS_DATA_OVERRUN;
- Srb->DataTransferLength = 0;
- return;
- }
+ XENBUS_STORE(Release, &Target->StoreInterface);
+}
- RtlZeroMemory(Buffer, AllocLength);
+static DECLSPEC_NOINLINE VOID
+TargetSuspendCallback(
+ IN PVOID Context
+ )
+{
+ PXENVBD_TARGET Target = Context;
+ LIST_ENTRY List;
+ NTSTATUS status;
- Length = 0;
- Offset = 8;
+ // Any outstanding requests are going to cause problems...
+ // Submitted requests are lost
+ // Prepared requests will need re-preparing (different grant/backend)
+ // Fresh SRBs will be ok
+ InitializeListHead(&List);
+ for (;;) {
+ PLIST_ENTRY ListEntry;
+ PXENVBD_REQUEST Request;
+ PXENVBD_SRBEXT SrbExt;
- if (Offset + 8 <= AllocLength) {
- Buffer[Offset] = 0;
- Offset += 8;
- Length += 8;
- }
+ ListEntry = RemoveHeadList(&Target->Submitted);
+ if (ListEntry == &Target->Submitted)
+ break;
+ Request = CONTAINING_RECORD(ListEntry, XENVBD_REQUEST, ListEntry);
+ SrbExt = Request->SrbExt;
- if (Offset + 8 <= AllocLength) {
- Buffer[Offset] = XENVBD_MAX_TARGETS;
- Offset += 8;
- Length += 8;
+ TargetPutRequest(Target, Request);
+ if (InterlockedDecrement(&SrbExt->RequestCount) == 0) {
+ SrbExt->Srb->SrbStatus = SRB_STATUS_ABORTED;
+ AdapterCompleteSrb(Target->Adapter, SrbExt);
+ }
}
+ for (;;) {
+ PLIST_ENTRY ListEntry;
+ PXENVBD_REQUEST Request;
+ PXENVBD_SRBEXT SrbExt;
- REVERSE_BYTES(Buffer, &Length);
-
- Srb->DataTransferLength = __min(Length, AllocLength);
- Srb->SrbStatus = SRB_STATUS_SUCCESS;
-}
+ ListEntry = RemoveHeadList(&Target->Prepared);
+ if (ListEntry == &Target->Prepared)
+ break;
+ Request = CONTAINING_RECORD(ListEntry, XENVBD_REQUEST, ListEntry);
+ SrbExt = Request->SrbExt;
-static DECLSPEC_NOINLINE VOID
-TargetReadCapacity(
- IN PXENVBD_TARGET Target,
- IN PXENVBD_SRBEXT SrbExt
- )
-{
- PSCSI_REQUEST_BLOCK Srb = SrbExt->Srb;
- PREAD_CAPACITY_DATA Capacity = Srb->DataBuffer;
- PXENVBD_DISKINFO DiskInfo = FrontendGetDiskInfo(Target->Frontend);
- ULONG64 SectorCount;
- ULONG SectorSize;
- ULONG LastBlock;
-
- if (Cdb_PMI(Srb) == 0 && Cdb_LogicalBlock(Srb) != 0) {
- Srb->ScsiStatus = 0x02; // CHECK_CONDITION
- return;
+ TargetPutRequest(Target, Request);
+ if (InterlockedDecrement(&SrbExt->RequestCount) == 0) {
+ InsertHeadList(&List, &SrbExt->ListEntry);
+ }
}
-
- SectorCount = DiskInfo->SectorCount;
- SectorSize = DiskInfo->SectorSize;
+ for (;;) {
+ PLIST_ENTRY ListEntry;
- if (SectorCount == (ULONG)SectorCount)
- LastBlock = (ULONG)SectorCount - 1;
- else
- LastBlock = ~(ULONG)0;
+ ListEntry = RemoveHeadList(&List);
+ if (ListEntry == &List)
+ break;
- if (Capacity) {
- Capacity->LogicalBlockAddress = _byteswap_ulong(LastBlock);
- Capacity->BytesPerBlock = _byteswap_ulong(SectorSize);
+ InsertHeadList(&Target->Fresh, ListEntry);
}
- Srb->SrbStatus = SRB_STATUS_SUCCESS;
+ __TargetD0ToD3(Target);
+
+ status = __TargetD3ToD0(Target);
+ ASSERT(NT_SUCCESS(status));
}
static DECLSPEC_NOINLINE VOID
-TargetReadCapacity16(
- IN PXENVBD_TARGET Target,
- IN PXENVBD_SRBEXT SrbExt
+TargetDebugCallback(
+ IN PVOID Context,
+ IN BOOLEAN Crashing
)
-{
- PSCSI_REQUEST_BLOCK Srb = SrbExt->Srb;
- PREAD_CAPACITY16_DATA Capacity = Srb->DataBuffer;
- PXENVBD_DISKINFO DiskInfo = FrontendGetDiskInfo(Target->Frontend);
- ULONG64 SectorCount;
- ULONG SectorSize;
- ULONG PhysSectorSize;
- ULONG LogicalPerPhysical;
- ULONG LogicalPerPhysicalExponent;
-
- if (Cdb_PMI(Srb) == 0 && Cdb_LogicalBlock(Srb) != 0) {
- Srb->ScsiStatus = 0x02; // CHECK_CONDITION
- return;
- }
-
- SectorCount = DiskInfo->SectorCount;
- SectorSize = DiskInfo->SectorSize;
- PhysSectorSize = DiskInfo->PhysSectorSize;
+{
+ PXENVBD_TARGET Target = Context;
- LogicalPerPhysical = PhysSectorSize / SectorSize;
+ UNREFERENCED_PARAMETER(Crashing);
- if (!_BitScanReverse(&LogicalPerPhysicalExponent, LogicalPerPhysical))
- LogicalPerPhysicalExponent = 0;
+ XENBUS_DEBUG(Printf,
+ &Target->DebugInterface,
+ "Adapter: 0x%p DeviceObject: 0x%p\n",
+ Target->Adapter,
+ Target->DeviceObject);
- if (Capacity) {
- Capacity->LogicalBlockAddress.QuadPart = _byteswap_uint64(SectorCount
- 1);
- Capacity->BytesPerBlock = _byteswap_ulong(SectorSize);
- Capacity->LogicalPerPhysicalExponent =
(UCHAR)LogicalPerPhysicalExponent;
- }
+ XENBUS_DEBUG(Printf,
+ &Target->DebugInterface,
+ "TargetI: %u DeviceId: %u BackendId: %u\n",
+ Target->TargetId,
+ Target->DeviceId,
+ Target->BackendId);
+
+ XENBUS_DEBUG(Printf,
+ &Target->DebugInterface,
+ "Path: %s\n",
+ Target->Path);
+
+ XENBUS_DEBUG(Printf,
+ &Target->DebugInterface,
+ "BackendPath: %s\n",
+ Target->BackendPath ? Target->BackendPath : "NULL");
+
+ XENBUS_DEBUG(Printf,
+ &Target->DebugInterface,
+ "TargetPath: %s\n",
+ Target->TargetPath);
+
+ XENBUS_DEBUG(Printf,
+ &Target->DebugInterface,
+ "Features: %s%s%s%s%s\n",
+ Target->Removable ? "REMOVABLE " : "",
+ Target->FeatureBarrier ? "BARRIER " : "",
+ Target->FeatureDiscard ? "DISCARD " : "",
+ Target->FeatureFlush ? "FLUSH " : "",
+ Target->FeatureIndirect ? "INDIRECT " : "");
+
+ if (Target->FeatureDiscard) {
+ XENBUS_DEBUG(Printf,
+ &Target->DebugInterface,
+ "DISCARD: %s%u @ %u\n",
+ Target->DiscardSecure ? "SECURE " : "",
+ Target->DiscardAlignment,
+ Target->DiscardGranularity);
+ }
+
+ if (Target->FeatureIndirect) {
+ XENBUS_DEBUG(Printf,
+ &Target->DebugInterface,
+ "INDIRECT: %u MaxSegsPerInd\n",
+ Target->FeatureIndirect);
+ }
+
+ XENBUS_DEBUG(Printf,
+ &Target->DebugInterface,
+ "%llu sectors @ %u (%u) %08x\n",
+ Target->SectorCount,
+ Target->SectorSize,
+ Target->PhysicalSectorSize,
+ Target->DiskInfo);
+}
+
+static DECLSPEC_NOINLINE NTSTATUS
+TargetBackendThread(
+ IN PXENVBD_THREAD Self,
+ IN PVOID Context
+ )
+{
+ PXENVBD_TARGET Target = Context;
+ PKEVENT Event = ThreadGetEvent(Self);
+ LARGE_INTEGER Start;
+ LARGE_INTEGER Now;
+
+ KeQuerySystemTime(&Start);
+ for (;;) {
+ PCHAR Buffer;
+ NTSTATUS status;
+ KIRQL Irql;
+ BOOLEAN Online = TRUE;
+
+ (VOID) KeWaitForSingleObject(Event,
+ Executive,
+ KernelMode,
+ FALSE,
+ NULL);
+ if (ThreadIsAlerted(Self))
+ break;
- Srb->SrbStatus = SRB_STATUS_SUCCESS;
-}
+ KeQuerySystemTime(&Now);
+ // Rate limit checking to once a second
+ if ((Now.QuadPart - Start.QuadPart) < 10000000ull)
+ continue;
+ Start.QuadPart = Now.QuadPart;
-static FORCEINLINE VOID
-__TargetQueueShutdown(
- IN PXENVBD_TARGET Target,
- IN PXENVBD_SRBEXT SrbExt
- )
-{
- PXENVBD_NOTIFIER Notifier = FrontendGetNotifier(Target->Frontend);
+ KeAcquireSpinLock(&Target->StateLock, &Irql);
+ if (Target->DevicePowerState != PowerDeviceD0) {
+ KeReleaseSpinLock(&Target->StateLock, Irql);
+ continue;
+ }
+ KeReleaseSpinLock(&Target->StateLock, Irql);
+
+ TargetStoreReadDiskInfo(Target);
+
+ status = XENBUS_STORE(Read,
+ &Target->StoreInterface,
+ NULL,
+ Target->BackendPath,
+ "online",
+ &Buffer);
+ if (NT_SUCCESS(status)) {
+ Online = (BOOLEAN)strtoul(Buffer, NULL, 2);
+
+ XENBUS_STORE(Free,
+ &Target->StoreInterface,
+ Buffer);
+ }
- QueueAppend(&Target->ShutdownSrbs, &SrbExt->ListEntry);
- NotifierKick(Notifier);
+ if (!Online) {
+ // eject!
+ TargetSetMissing(Target, "Ejecting");
+ AdapterTargetListChanged(TargetGetAdapter(Target));
+ }
+ }
- SrbExt->Srb->SrbStatus = SRB_STATUS_PENDING;
+ return STATUS_SUCCESS;
}
-VOID
-TargetReset(
+NTSTATUS
+TargetD3ToD0(
IN PXENVBD_TARGET Target
)
{
+ KIRQL Irql;
+ NTSTATUS status;
+
+ if (Target->DevicePowerState == PowerDeviceD0)
+ return STATUS_SUCCESS;
+
Verbose("[%u] =====>\n",
- TargetGetTargetId(Target));
+ Target->TargetId);
- __TargetPauseDataPath(Target, TRUE);
+ status = XENBUS_DEBUG(Acquire, &Target->DebugInterface);
+ if (!NT_SUCCESS(status))
+ goto fail1;
- if (QueueCount(&Target->SubmittedReqs)) {
- Error("Target[%d] : backend has %u outstanding requests after a
TargetReset\n",
- TargetGetTargetId(Target), QueueCount(&Target->SubmittedReqs));
- }
+ status = XENBUS_SUSPEND(Acquire, &Target->SuspendInterface);
+ if (!NT_SUCCESS(status))
+ goto fail2;
- __TargetUnpauseDataPath(Target);
+ status = XENBUS_DEBUG(Register,
+ &Target->DebugInterface,
+ __MODULE__,
+ TargetDebugCallback,
+ Target,
+ &Target->DebugCallback);
+ if (!NT_SUCCESS(status))
+ goto fail3;
- Verbose("[%u] <=====\n",
- TargetGetTargetId(Target));
-}
+ status = XENBUS_SUSPEND(Register,
+ &Target->SuspendInterface,
+ SUSPEND_CALLBACK_LATE,
+ TargetSuspendCallback,
+ Target,
+ &Target->SuspendCallback);
+ if (!NT_SUCCESS(status))
+ goto fail4;
-VOID
-TargetPrepareSrb(
- IN PXENVBD_TARGET Target,
- IN PXENVBD_SRBEXT SrbExt
- )
-{
- PSCSI_REQUEST_BLOCK Srb = SrbExt->Srb;
+ KeAcquireSpinLock(&Target->StateLock, &Irql);
+ status = __TargetD3ToD0(Target);
+ KeReleaseSpinLock(&Target->StateLock, Irql);
+ if (!NT_SUCCESS(status))
+ goto fail5;
- SrbExt->Srb->SrbStatus = SRB_STATUS_NO_DEVICE;
- if (TargetIsMissing(Target))
- return;
+ Target->DevicePowerState = PowerDeviceD0;
+ Verbose("[%u] <=====\n",
+ Target->TargetId);
+ return STATUS_SUCCESS;
- Srb->SrbStatus = SRB_STATUS_PENDING;
+fail5:
+ Error("fail5\n");
+ XENBUS_SUSPEND(Deregister,
+ &Target->SuspendInterface,
+ Target->SuspendCallback);
+ Target->SuspendCallback = NULL;
+fail4:
+ Error("fail4\n");
+ XENBUS_DEBUG(Deregister,
+ &Target->DebugInterface,
+ Target->DebugCallback);
+ Target->DebugCallback = NULL;
+fail3:
+ Error("fail3\n");
+ XENBUS_SUSPEND(Release,
+ &Target->SuspendInterface);
+fail2:
+ Error("fail2\n");
+ XENBUS_DEBUG(Release,
+ &Target->DebugInterface);
+fail1:
+ Error("fail1 %08x\n", status);
+ return status;
}
VOID
-TargetStartSrb(
- IN PXENVBD_TARGET Target,
- IN PXENVBD_SRBEXT SrbExt
+TargetD0ToD3(
+ IN PXENVBD_TARGET Target
)
{
- const UCHAR Operation = Cdb_OperationEx(SrbExt->Srb);
- PXENVBD_DISKINFO DiskInfo = FrontendGetDiskInfo(Target->Frontend);
+ KIRQL Irql;
- if (DiskInfo->DiskInfo & VDISK_READONLY) {
- Trace("Target[%d] : (%08x) Read-Only, fail SRB (%02x:%s)\n",
TargetGetTargetId(Target),
- DiskInfo->DiskInfo, Operation, Cdb_OperationName(Operation));
- SrbExt->Srb->ScsiStatus = 0x40; // SCSI_ABORT
- SrbExt->Srb->SrbStatus = SRB_STATUS_ERROR;
+ if (Target->DevicePowerState == PowerDeviceD3)
return;
- }
-
- switch (Operation) {
- case SCSIOP_READ:
- TargetReadWrite(Target, SrbExt);
- case SCSIOP_WRITE:
- TargetReadWrite(Target, SrbExt);
- break;
-
- case SCSIOP_SYNCHRONIZE_CACHE:
- TargetSyncCache(Target, SrbExt);
- break;
+ Verbose("[%u] =====>\n",
+ Target->TargetId);
+ Target->DevicePowerState = PowerDeviceD3;
- case SCSIOP_UNMAP:
- TargetUnmap(Target, SrbExt);
- break;
+ KeAcquireSpinLock(&Target->StateLock, &Irql);
+ __TargetD0ToD3(Target);
+ KeReleaseSpinLock(&Target->StateLock, Irql);
- case SCSIOP_INQUIRY:
- if (!StorPortSetDeviceQueueDepth(TargetGetAdapter(Target),
- 0,
- (UCHAR)TargetGetTargetId(Target),
- 0,
- XENVBD_MAX_QUEUE_DEPTH))
- Verbose("Target[%d] : Failed to set queue depth\n",
- TargetGetTargetId(Target));
- PdoInquiry(TargetGetTargetId(Target),
FrontendGetInquiry(Target->Frontend), SrbExt->Srb);
- break;
- case SCSIOP_MODE_SENSE:
- TargetModeSense(Target, SrbExt);
- break;
- case SCSIOP_REQUEST_SENSE:
- TargetRequestSense(Target, SrbExt);
- break;
- case SCSIOP_REPORT_LUNS:
- TargetReportLuns(Target, SrbExt);
- break;
- case SCSIOP_READ_CAPACITY:
- TargetReadCapacity(Target, SrbExt);
- break;
- case SCSIOP_READ_CAPACITY16:
- TargetReadCapacity16(Target, SrbExt);
- break;
+ XENBUS_SUSPEND(Deregister,
+ &Target->SuspendInterface,
+ Target->SuspendCallback);
+ Target->SuspendCallback = NULL;
- case SCSIOP_MEDIUM_REMOVAL:
- case SCSIOP_TEST_UNIT_READY:
- case SCSIOP_RESERVE_UNIT:
- case SCSIOP_RESERVE_UNIT10:
- case SCSIOP_RELEASE_UNIT:
- case SCSIOP_RELEASE_UNIT10:
- case SCSIOP_VERIFY:
- case SCSIOP_VERIFY16:
- case SCSIOP_START_STOP_UNIT:
- SrbExt->Srb->SrbStatus = SRB_STATUS_SUCCESS;
- break;
+ XENBUS_DEBUG(Deregister,
+ &Target->DebugInterface,
+ Target->DebugCallback);
+ Target->DebugCallback = NULL;
- default:
- Trace("Target[%d] : Unsupported CDB (%02x:%s)\n",
- TargetGetTargetId(Target),
- Operation,
- Cdb_OperationName(Operation));
- SrbExt->Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
- break;
- }
-}
+ XENBUS_SUSPEND(Release,
+ &Target->SuspendInterface);
-VOID
-TargetFlush(
- IN PXENVBD_TARGET Target,
- IN PXENVBD_SRBEXT SrbExt
- )
-{
- __TargetQueueShutdown(Target, SrbExt);
-}
+ XENBUS_DEBUG(Release,
+ &Target->DebugInterface);
-VOID
-TargetShutdown(
- IN PXENVBD_TARGET Target,
- IN PXENVBD_SRBEXT SrbExt
- )
-{
- __TargetQueueShutdown(Target, SrbExt);
+ Verbose("[%u] <=====\n",
+ Target->TargetId);
}
-VOID
-TargetSrbPnp(
- __in PXENVBD_TARGET Target,
- __in PSCSI_PNP_REQUEST_BLOCK Srb
+static FORCEINLINE PCHAR
+__DeviceUsageName(
+ IN ULONG Index
)
{
- switch (Srb->PnPAction) {
- case StorQueryCapabilities: {
- PSTOR_DEVICE_CAPABILITIES DeviceCaps = Srb->DataBuffer;
- PXENVBD_CAPS Caps = FrontendGetCaps(Target->Frontend);
-
- if (Caps->Removable)
- DeviceCaps->Removable = 1;
- if (Caps->Removable)
- DeviceCaps->EjectSupported = 1;
- if (Caps->SurpriseRemovable)
- DeviceCaps->SurpriseRemovalOK = 1;
-
- DeviceCaps->UniqueID = 1;
-
- } break;
-
- default:
- break;
+ switch (Index) {
+ case DeviceUsageTypeUndefined: return NULL;
+ case DeviceUsageTypePaging: return "paging";
+ case DeviceUsageTypeHibernation: return "hibernation";
+ case DeviceUsageTypeDumpFile: return "dump";
+ default: return NULL;
}
}
-//=============================================================================
-// PnP Handler
static FORCEINLINE VOID
__TargetDeviceUsageNotification(
- __in PXENVBD_TARGET Target,
- __in PIRP Irp
+ IN PXENVBD_TARGET Target,
+ IN PIRP Irp
)
{
PIO_STACK_LOCATION StackLocation;
+ ULONG Index;
BOOLEAN Value;
- DEVICE_USAGE_NOTIFICATION_TYPE Type;
- PXENVBD_CAPS Caps = FrontendGetCaps(Target->Frontend);
StackLocation = IoGetCurrentIrpStackLocation(Irp);
Value = StackLocation->Parameters.UsageNotification.InPath;
- Type = StackLocation->Parameters.UsageNotification.Type;
-
- switch (Type) {
- case DeviceUsageTypePaging:
- if (Caps->Paging == Value)
- return;
- Caps->Paging = Value;
- break;
-
- case DeviceUsageTypeHibernation:
- if (Caps->Hibernation == Value)
- return;
- Caps->Hibernation = Value;
- break;
-
- case DeviceUsageTypeDumpFile:
- if (Caps->DumpFile == Value)
- return;
- Caps->DumpFile = Value;
- break;
+ Index = (ULONG)StackLocation->Parameters.UsageNotification.Type;
- default:
+ if (__DeviceUsageName(Index) == NULL)
+ return;
+ if (Target->DeviceUsage[Index] == Value)
return;
- }
- FrontendWriteUsage(Target->Frontend);
-}
-
-static FORCEINLINE VOID
-__TargetCheckEjectPending(
- __in PXENVBD_TARGET Target
- )
-{
- KIRQL Irql;
- BOOLEAN EjectPending = FALSE;
-
- KeAcquireSpinLock(&Target->Lock, &Irql);
- if (Target->EjectPending) {
- EjectPending = TRUE;
- Target->EjectPending = FALSE;
- Target->EjectRequested = TRUE;
- }
- KeReleaseSpinLock(&Target->Lock, Irql);
-
- if (EjectPending) {
- Verbose("Target[%d] : IoRequestDeviceEject(0x%p)\n",
TargetGetTargetId(Target), Target->DeviceObject);
- IoRequestDeviceEject(Target->DeviceObject);
- }
-}
-
-static FORCEINLINE VOID
-__TargetCheckEjectFailed(
- __in PXENVBD_TARGET Target
- )
-{
- KIRQL Irql;
- BOOLEAN EjectFailed = FALSE;
-
- KeAcquireSpinLock(&Target->Lock, &Irql);
- if (Target->EjectRequested) {
- EjectFailed = TRUE;
- Target->EjectRequested = FALSE;
- }
- KeReleaseSpinLock(&Target->Lock, Irql);
-
- if (EjectFailed) {
- Error("Target[%d] : Unplug failed due to open handle(s)!\n",
TargetGetTargetId(Target));
- FrontendStoreWriteFrontend(Target->Frontend, "error", "Unplug failed
due to open handle(s)!");
- }
-}
-
-static FORCEINLINE VOID
-__TargetRemoveDevice(
- __in PXENVBD_TARGET Target
- )
-{
- TargetD0ToD3(Target);
- switch (TargetGetDevicePnpState(Target)) {
- case SurpriseRemovePending:
- TargetSetMissing(Target, "Surprise Remove");
- TargetSetDevicePnpState(Target, Deleted);
- AdapterTargetListChanged(TargetGetAdapter(Target));
- break;
+ Target->DeviceUsage[Index] = Value;
- default:
- TargetSetMissing(Target, "Removed");
- TargetSetDevicePnpState(Target, Deleted);
- AdapterTargetListChanged(TargetGetAdapter(Target));
- break;
- }
-}
+ Verbose("[%u] %s %s\n",
+ Target->TargetId,
+ Value ? "ADDING" : "REMOVING",
+ __DeviceUsageName(Index));
-static FORCEINLINE VOID
-__TargetEject(
- __in PXENVBD_TARGET Target
- )
-{
- TargetSetMissing(Target, "Ejected");
- TargetSetDevicePnpState(Target, Deleted);
- AdapterTargetListChanged(TargetGetAdapter(Target));
+ (VOID) XENBUS_STORE(Printf,
+ &Target->StoreInterface,
+ NULL,
+ Target->TargetPath,
+ __DeviceUsageName(Index),
+ "%u",
+ Value);
}
-__checkReturn
NTSTATUS
TargetDispatchPnp(
- __in PXENVBD_TARGET Target,
- __in PDEVICE_OBJECT DeviceObject,
- __in PIRP Irp
+ IN PXENVBD_TARGET Target,
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp
)
{
- PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
-
- __TargetCheckEjectPending(Target);
-
- switch (Stack->MinorFunction) {
+ PIO_STACK_LOCATION StackLocation;
+
+ StackLocation = IoGetCurrentIrpStackLocation(Irp);
+ switch (StackLocation->MinorFunction) {
case IRP_MN_START_DEVICE:
(VOID) TargetD3ToD0(Target);
TargetSetDevicePnpState(Target, Started);
@@ -2340,7 +2847,7 @@ TargetDispatchPnp(
break;
case IRP_MN_CANCEL_STOP_DEVICE:
- __TargetRestoreDevicePnpState(Target, StopPending);
+ TargetRestoreDevicePnpState(Target);
break;
case IRP_MN_STOP_DEVICE:
@@ -2353,8 +2860,8 @@ TargetDispatchPnp(
break;
case IRP_MN_CANCEL_REMOVE_DEVICE:
- __TargetCheckEjectFailed(Target);
- __TargetRestoreDevicePnpState(Target, RemovePending);
+ // Should write something to Xenstore to indicate the VETO on
deviceeject
+ TargetRestoreDevicePnpState(Target);
break;
case IRP_MN_SURPRISE_REMOVAL:
@@ -2362,11 +2869,16 @@ TargetDispatchPnp(
break;
case IRP_MN_REMOVE_DEVICE:
- __TargetRemoveDevice(Target);
+ TargetD0ToD3(Target);
+ TargetSetMissing(Target, DevicePnpStateName(Target->DevicePnpState));
+ TargetSetDevicePnpState(Target, Deleted);
+ AdapterTargetListChanged(TargetGetAdapter(Target));
break;
case IRP_MN_EJECT:
- __TargetEject(Target);
+ TargetSetMissing(Target, "Ejected");
+ TargetSetDevicePnpState(Target, Deleted);
+ AdapterTargetListChanged(TargetGetAdapter(Target));
break;
case IRP_MN_DEVICE_USAGE_NOTIFICATION:
@@ -2376,114 +2888,15 @@ TargetDispatchPnp(
default:
break;
}
- return DriverDispatchPnp(DeviceObject, Irp);
-}
-
-__drv_maxIRQL(DISPATCH_LEVEL)
-VOID
-TargetIssueDeviceEject(
- __in PXENVBD_TARGET Target,
- __in __nullterminated const CHAR* Reason
- )
-{
- KIRQL Irql;
- BOOLEAN DoEject = FALSE;
-
- KeAcquireSpinLock(&Target->Lock, &Irql);
- if (Target->DeviceObject) {
- DoEject = TRUE;
- Target->EjectRequested = TRUE;
- } else {
- Target->EjectPending = TRUE;
- }
- KeReleaseSpinLock(&Target->Lock, Irql);
-
- Verbose("Target[%d] : Ejecting (%s - %s)\n", TargetGetTargetId(Target),
DoEject ? "Now" : "Next PnP IRP", Reason);
- if (!Target->WrittenEjected) {
- Target->WrittenEjected = TRUE;
- FrontendStoreWriteFrontend(Target->Frontend, "ejected", "1");
- }
- if (DoEject) {
- Verbose("Target[%d] : IoRequestDeviceEject(0x%p)\n",
TargetGetTargetId(Target), Target->DeviceObject);
- IoRequestDeviceEject(Target->DeviceObject);
- } else {
- Verbose("Target[%d] : Triggering BusChangeDetected to detect
device\n", TargetGetTargetId(Target));
- AdapterTargetListChanged(TargetGetAdapter(Target));
- }
-}
-
-__checkReturn
-NTSTATUS
-TargetD3ToD0(
- __in PXENVBD_TARGET Target
- )
-{
- NTSTATUS Status;
- const ULONG TargetId = TargetGetTargetId(Target);
-
- if (!TargetSetDevicePowerState(Target, PowerDeviceD0))
- return STATUS_SUCCESS;
-
- Trace("Target[%d] @ (%d) =====>\n", TargetId, KeGetCurrentIrql());
- Verbose("Target[%d] : D3->D0\n", TargetId);
-
- // power up frontend
- Status = FrontendD3ToD0(Target->Frontend);
- if (!NT_SUCCESS(Status))
- goto fail1;
-
- // connect frontend
- Status = FrontendSetState(Target->Frontend, XENVBD_ENABLED);
- if (!NT_SUCCESS(Status))
- goto fail2;
- __TargetUnpauseDataPath(Target);
-
- Trace("Target[%d] @ (%d) <=====\n", TargetId, KeGetCurrentIrql());
- return STATUS_SUCCESS;
-
-fail2:
- Error("Fail2\n");
- FrontendD0ToD3(Target->Frontend);
-
-fail1:
- Error("Fail1 (%08x)\n", Status);
-
- Target->DevicePowerState = PowerDeviceD3;
-
- return Status;
-}
-
-VOID
-TargetD0ToD3(
- __in PXENVBD_TARGET Target
- )
-{
- const ULONG TargetId = TargetGetTargetId(Target);
-
- if (!TargetSetDevicePowerState(Target, PowerDeviceD3))
- return;
-
- Trace("Target[%d] @ (%d) =====>\n", TargetId, KeGetCurrentIrql());
- Verbose("Target[%d] : D0->D3\n", TargetId);
-
- // close frontend
- __TargetPauseDataPath(Target, FALSE);
- (VOID) FrontendSetState(Target->Frontend, XENVBD_CLOSED);
- ASSERT3U(QueueCount(&Target->SubmittedReqs), ==, 0);
-
- // power down frontend
- FrontendD0ToD3(Target->Frontend);
- Trace("Target[%d] @ (%d) <=====\n", TargetId, KeGetCurrentIrql());
+ return DriverDispatchPnp(DeviceObject, Irp);
}
static FORCEINLINE ULONG
__ParseVbd(
- IN PCHAR DeviceIdStr
+ IN ULONG DeviceId
)
-{
- ULONG DeviceId = strtoul(DeviceIdStr, NULL, 10);
-
+{
ASSERT3U((DeviceId & ~((1 << 29) - 1)), ==, 0);
if (DeviceId & (1 << 28))
@@ -2504,140 +2917,235 @@ __ParseVbd(
}
}
-__checkReturn
NTSTATUS
TargetCreate(
- __in PXENVBD_ADAPTER Adapter,
- __in __nullterminated PCHAR DeviceId,
- OUT PXENVBD_TARGET* _Target
+ IN PXENVBD_ADAPTER Adapter,
+ IN PANSI_STRING Device,
+ OUT PXENVBD_TARGET* _Target
)
{
- NTSTATUS Status;
- PXENVBD_TARGET Target;
- ULONG TargetId;
+ PXENVBD_TARGET Target;
+ ULONG DeviceId;
+ ULONG TargetId;
+ ULONG Size;
+ NTSTATUS status;
+ DeviceId = strtoul(Device->Buffer, NULL, 10);
TargetId = __ParseVbd(DeviceId);
if (TargetId >= XENVBD_MAX_TARGETS)
return STATUS_RETRY;
-
if (AdapterIsTargetEmulated(Adapter, TargetId))
return STATUS_RETRY;
- Trace("Target[%d] @ (%d) =====>\n", TargetId, KeGetCurrentIrql());
+ Verbose("[%u] =====> %s\n", TargetId, Device->Buffer);
- Status = STATUS_INSUFFICIENT_RESOURCES;
-#pragma warning(suppress: 6014)
- Target = __TargetAlloc(sizeof(XENVBD_TARGET));
- if (!Target)
+ status = STATUS_NO_MEMORY;
+ Target = __TargetAllocate(sizeof(XENVBD_TARGET));
+ if (Target == NULL)
goto fail1;
- Verbose("Target[%d] : Creating\n", TargetId);
- Target->Signature = TARGET_SIGNATURE;
- Target->Adapter = Adapter;
- Target->DeviceObject = NULL; // filled in later
- Target->Paused = 1; // Paused until D3->D0 transition
- Target->DevicePnpState = Present;
+ Target->Adapter = Adapter;
+ Target->DeviceObject = NULL; // filled in later
+ Target->DevicePnpState = Present;
Target->DevicePowerState = PowerDeviceD3;
-
- KeInitializeSpinLock(&Target->Lock);
- QueueInit(&Target->FreshSrbs);
- QueueInit(&Target->PreparedReqs);
- QueueInit(&Target->SubmittedReqs);
- QueueInit(&Target->ShutdownSrbs);
- __LookasideInit(&Target->RequestList, sizeof(XENVBD_REQUEST),
REQUEST_POOL_TAG);
- __LookasideInit(&Target->SegmentList, sizeof(XENVBD_SEGMENT),
SEGMENT_POOL_TAG);
- __LookasideInit(&Target->IndirectList, sizeof(XENVBD_INDIRECT),
INDIRECT_POOL_TAG);
-
- Status = FrontendCreate(Target, DeviceId, TargetId, &Target->Frontend);
- if (!NT_SUCCESS(Status))
+ Target->DeviceId = DeviceId;
+ Target->TargetId = TargetId;
+ Target->State = XENVBD_INITIALIZED;
+ Target->BackendId = DOMID_INVALID;
+ KeInitializeSpinLock(&Target->StateLock);
+ KeInitializeSpinLock(&Target->QueueLock);
+
+ AdapterGetDebugInterface(Adapter, &Target->DebugInterface);
+ AdapterGetStoreInterface(Adapter, &Target->StoreInterface);
+ AdapterGetSuspendInterface(Adapter, &Target->SuspendInterface);
+
+ status = STATUS_NO_MEMORY;
+ Size = sizeof("device/vbd/") + Device->Length + 1;
+ Target->Path = __TargetAllocate(Size);
+ if (Target->Path == NULL)
goto fail2;
- Status = TargetD3ToD0(Target);
- if (!NT_SUCCESS(Status))
+ status = RtlStringCbPrintfA(Target->Path,
+ Size,
+ "device/vbd/%s",
+ Device->Buffer);
+ if (!NT_SUCCESS(status))
goto fail3;
- *_Target = Target;
+ status = STATUS_NO_MEMORY;
+ Size = sizeof("data/scsi/target/XXXX") + 1;
+ Target->TargetPath = __TargetAllocate(Size);
+ if (Target->TargetPath == NULL)
+ goto fail4;
- Verbose("Target[%d] : Created (%s)\n", TargetId, Target);
- Trace("Target[%d] @ (%d) <=====\n", TargetId, KeGetCurrentIrql());
+ status = RtlStringCbPrintfA(Target->TargetPath,
+ Size,
+ "data/scsi/target/%u",
+ TargetId);
+ if (!NT_SUCCESS(status))
+ goto fail5;
+
+ status = GranterCreate(Target, &Target->Granter);
+ if (!NT_SUCCESS(status))
+ goto fail6;
+
+ status = BlockRingCreate(Target, &Target->BlockRing);
+ if (!NT_SUCCESS(status))
+ goto fail7;
+
+ status = ThreadCreate(TargetBackendThread,
+ Target,
+ &Target->BackendThread);
+ if (!NT_SUCCESS(status))
+ goto fail8;
+
+ InitializeListHead(&Target->Fresh);
+ InitializeListHead(&Target->Prepared);
+ InitializeListHead(&Target->Submitted);
+ InitializeListHead(&Target->Shutdown);
+
+ ExInitializeNPagedLookasideList(&Target->RequestList,
+ NULL,
+ NULL,
+ 0,
+ sizeof(XENVBD_REQUEST),
+ REQUEST_POOL_TAG,
+ 0);
+ ExInitializeNPagedLookasideList(&Target->SegmentList,
+ NULL,
+ NULL,
+ 0,
+ sizeof(XENVBD_SEGMENT),
+ SEGMENT_POOL_TAG,
+ 0);
+ ExInitializeNPagedLookasideList(&Target->IndirectList,
+ NULL,
+ NULL,
+ 0,
+ sizeof(XENVBD_INDIRECT),
+ INDIRECT_POOL_TAG,
+ 0);
+
+ status = TargetD3ToD0(Target);
+ if (!NT_SUCCESS(status))
+ goto fail9;
+
+ Verbose("[%u] <=====\n", TargetId);
+ *_Target = Target;
return STATUS_SUCCESS;
+fail9:
+ Error("fail9\n");
+
+ ExDeleteNPagedLookasideList(&Target->RequestList);
+ ExDeleteNPagedLookasideList(&Target->SegmentList);
+ ExDeleteNPagedLookasideList(&Target->IndirectList);
+
+ RtlZeroMemory(&Target->Fresh, sizeof(LIST_ENTRY));
+ RtlZeroMemory(&Target->Prepared, sizeof(LIST_ENTRY));
+ RtlZeroMemory(&Target->Submitted, sizeof(LIST_ENTRY));
+ RtlZeroMemory(&Target->Shutdown, sizeof(LIST_ENTRY));
+
+ ThreadAlert(Target->BackendThread);
+ ThreadJoin(Target->BackendThread);
+ Target->BackendThread = NULL;
+fail8:
+ Error("fail8\n");
+ BlockRingDestroy(Target->BlockRing);
+ Target->BlockRing = NULL;
+fail7:
+ Error("fail7\n");
+ GranterDestroy(Target->Granter);
+ Target->Granter = NULL;
+fail6:
+ Error("fail6\n");
+fail5:
+ Error("fail5\n");
+ __TargetFree(Target->TargetPath);
+ Target->TargetPath = NULL;
+fail4:
+ Error("fail4\n");
fail3:
- Error("Fail3\n");
- FrontendDestroy(Target->Frontend);
- Target->Frontend = NULL;
-
+ Error("fail3\n");
+ __TargetFree(Target->Path);
+ Target->Path = NULL;
fail2:
- Error("Fail2\n");
- __LookasideTerm(&Target->IndirectList);
- __LookasideTerm(&Target->SegmentList);
- __LookasideTerm(&Target->RequestList);
+ Error("fail2\n");
+ RtlZeroMemory(&Target->DebugInterface, sizeof(XENBUS_DEBUG_INTERFACE));
+ RtlZeroMemory(&Target->StoreInterface, sizeof(XENBUS_STORE_INTERFACE));
+ RtlZeroMemory(&Target->SuspendInterface, sizeof(XENBUS_SUSPEND_INTERFACE));
+
+ Target->Adapter = NULL;
+ Target->DeviceObject = NULL; // filled in later
+ Target->DevicePnpState = 0;
+ Target->DevicePowerState = 0;
+ Target->DeviceId = 0;
+ Target->TargetId = 0;
+ Target->State = 0;
+ Target->BackendId = 0;
+ RtlZeroMemory(&Target->QueueLock, sizeof(KSPIN_LOCK));
+ RtlZeroMemory(&Target->StateLock, sizeof(KSPIN_LOCK));
+
+ ASSERT(IsZeroMemory(Target, sizeof(XENVBD_TARGET)));
__TargetFree(Target);
-
fail1:
- Error("Fail1 (%08x)\n", Status);
- return Status;
+ Error("fail1 %08x\n", status);
+ return status;
}
VOID
TargetDestroy(
- __in PXENVBD_TARGET Target
+ IN PXENVBD_TARGET Target
)
{
- const ULONG TargetId = TargetGetTargetId(Target);
- PVOID Objects[3];
- PKWAIT_BLOCK WaitBlock;
+ ASSERT(IsListEmpty(&Target->Fresh));
+ ASSERT(IsListEmpty(&Target->Prepared));
+ ASSERT(IsListEmpty(&Target->Submitted));
+ ASSERT(IsListEmpty(&Target->Shutdown));
- Trace("Target[%d] @ (%d) =====>\n", TargetId, KeGetCurrentIrql());
- Verbose("Target[%d] : Destroying\n", TargetId);
+ ExDeleteNPagedLookasideList(&Target->RequestList);
+ ExDeleteNPagedLookasideList(&Target->SegmentList);
+ ExDeleteNPagedLookasideList(&Target->IndirectList);
- ASSERT3U(Target->Signature, ==, TARGET_SIGNATURE);
+ RtlZeroMemory(&Target->Fresh, sizeof(LIST_ENTRY));
+ RtlZeroMemory(&Target->Prepared, sizeof(LIST_ENTRY));
+ RtlZeroMemory(&Target->Submitted, sizeof(LIST_ENTRY));
+ RtlZeroMemory(&Target->Shutdown, sizeof(LIST_ENTRY));
- TargetD0ToD3(Target);
+ ThreadAlert(Target->BackendThread);
+ ThreadJoin(Target->BackendThread);
+ Target->BackendThread = NULL;
- Verbose("Target[%d] : RequestListUsed %d\n", TargetId,
Target->RequestList.Used);
- Objects[0] = &Target->RequestList.Empty;
- Objects[1] = &Target->SegmentList.Empty;
- Objects[2] = &Target->IndirectList.Empty;
+ BlockRingDestroy(Target->BlockRing);
+ Target->BlockRing = NULL;
- WaitBlock = (PKWAIT_BLOCK)__TargetAlloc(sizeof(KWAIT_BLOCK) *
ARRAYSIZE(Objects));
- if (WaitBlock == NULL) {
- ULONG Index;
+ GranterDestroy(Target->Granter);
+ Target->Granter = NULL;
- Error("Unable to allocate resources for KWAIT_BLOCK\n");
+ __TargetFree(Target->BackendPath);
+ Target->BackendPath = NULL;
- for (Index = 0; Index < ARRAYSIZE(Objects); Index++)
- KeWaitForSingleObject(Objects[Index],
- Executive,
- KernelMode,
- FALSE,
- NULL);
- } else {
- KeWaitForMultipleObjects(ARRAYSIZE(Objects),
- Objects,
- WaitAll,
- Executive,
- KernelMode,
- FALSE,
- NULL,
- WaitBlock);
-#pragma prefast(suppress:6102)
- __TargetFree(WaitBlock);
- }
+ __TargetFree(Target->TargetPath);
+ Target->TargetPath = NULL;
- ASSERT3U(TargetGetDevicePnpState(Target), ==, Deleted);
+ __TargetFree(Target->Path);
+ Target->Path = NULL;
- FrontendDestroy(Target->Frontend);
- Target->Frontend = NULL;
+ RtlZeroMemory(&Target->DebugInterface, sizeof(XENBUS_DEBUG_INTERFACE));
+ RtlZeroMemory(&Target->StoreInterface, sizeof(XENBUS_STORE_INTERFACE));
+ RtlZeroMemory(&Target->SuspendInterface, sizeof(XENBUS_SUSPEND_INTERFACE));
- __LookasideTerm(&Target->IndirectList);
- __LookasideTerm(&Target->SegmentList);
- __LookasideTerm(&Target->RequestList);
+ Target->Adapter = NULL;
+ Target->DeviceObject = NULL; // filled in later
+ Target->DevicePnpState = 0;
+ Target->DevicePowerState = 0;
+ Target->DeviceId = 0;
+ Target->TargetId = 0;
+ Target->State = 0;
+ Target->BackendId = 0;
+ RtlZeroMemory(&Target->QueueLock, sizeof(KSPIN_LOCK));
+ RtlZeroMemory(&Target->StateLock, sizeof(KSPIN_LOCK));
- ASSERT3U(Target->Signature, ==, TARGET_SIGNATURE);
- RtlZeroMemory(Target, sizeof(XENVBD_TARGET));
+ ASSERT(IsZeroMemory(Target, sizeof(XENVBD_TARGET)));
__TargetFree(Target);
-
- Verbose("Target[%d] : Destroyed\n", TargetId);
- Trace("Target[%d] @ (%d) <=====\n", TargetId, KeGetCurrentIrql());
}
diff --git a/src/xenvbd/target.h b/src/xenvbd/target.h
index 86f57fd..43660dd 100644
--- a/src/xenvbd/target.h
+++ b/src/xenvbd/target.h
@@ -36,197 +36,117 @@
typedef struct _XENVBD_TARGET XENVBD_TARGET, *PXENVBD_TARGET;
-#include "adapter.h"
-#include "srbext.h"
#include "types.h"
-#include <debug_interface.h>
-
-extern VOID
-TargetDebugCallback(
- __in PXENVBD_TARGET Target,
- __in PXENBUS_DEBUG_INTERFACE Debug
- );
-
-// Creation/Deletion
-__checkReturn
-extern NTSTATUS
-TargetCreate(
- __in PXENVBD_ADAPTER Adapter,
- __in __nullterminated PCHAR DeviceId,
- OUT PXENVBD_TARGET* _Target
- );
-
-extern VOID
-TargetDestroy(
- __in PXENVBD_TARGET Target
- );
-
-__checkReturn
-extern NTSTATUS
-TargetD3ToD0(
- __in PXENVBD_TARGET Target
- );
-
-extern VOID
-TargetD0ToD3(
- __in PXENVBD_TARGET Target
- );
-
-// PnP States
-extern VOID
-TargetSetMissing(
- __in PXENVBD_TARGET Target,
- __in __nullterminated const CHAR* Reason
- );
+#include "srbext.h"
+#include "adapter.h"
+#include "granter.h"
-__checkReturn
-extern BOOLEAN
-TargetIsMissing(
- __in PXENVBD_TARGET Target
+#define TARGET_GET_PROPERTY(_name, _type) \
+extern _type \
+TargetGet ## _name ## ( \
+ IN PXENVBD_TARGET Target \
);
-extern const CHAR*
-TargetMissingReason(
- __in PXENVBD_TARGET Target
- );
+TARGET_GET_PROPERTY(DeviceId, ULONG)
+TARGET_GET_PROPERTY(TargetId, ULONG)
+TARGET_GET_PROPERTY(DeviceObject, PDEVICE_OBJECT)
+TARGET_GET_PROPERTY(Missing, BOOLEAN)
+TARGET_GET_PROPERTY(DevicePnpState, DEVICE_PNP_STATE)
+TARGET_GET_PROPERTY(Adapter, PXENVBD_ADAPTER)
+TARGET_GET_PROPERTY(Granter, PXENVBD_GRANTER)
+TARGET_GET_PROPERTY(Path, PCHAR)
+TARGET_GET_PROPERTY(BackendPath, PCHAR)
+TARGET_GET_PROPERTY(BackendId, USHORT)
+TARGET_GET_PROPERTY(Removable, BOOLEAN)
-__checkReturn
-extern BOOLEAN
-TargetIsEmulatedUnplugged(
- __in PXENVBD_TARGET Target
- );
+#undef TARGET_GET_PROPERTY
extern VOID
TargetSetDevicePnpState(
- __in PXENVBD_TARGET Target,
- __in DEVICE_PNP_STATE State
- );
-
-__checkReturn
-extern DEVICE_PNP_STATE
-TargetGetDevicePnpState(
- __in PXENVBD_TARGET Target
- );
-
-// Query Methods
-extern ULONG
-TargetGetTargetId(
- __in PXENVBD_TARGET Target
- );
-
-extern ULONG
-TargetGetDeviceId(
- __in PXENVBD_TARGET Target
- );
-
-__checkReturn
-extern PDEVICE_OBJECT
-TargetGetDeviceObject(
- __in PXENVBD_TARGET Target
+ IN PXENVBD_TARGET Target,
+ IN DEVICE_PNP_STATE State
);
extern VOID
TargetSetDeviceObject(
- __in PXENVBD_TARGET Target,
- __in PDEVICE_OBJECT DeviceObject
- );
-
-__checkReturn
-extern BOOLEAN
-TargetIsPaused(
- __in PXENVBD_TARGET Target
- );
-
-__checkReturn
-extern ULONG
-TargetOutstandingReqs(
- __in PXENVBD_TARGET Target
+ IN PXENVBD_TARGET Target,
+ IN PDEVICE_OBJECT DeviceObject
);
-__checkReturn
-extern PXENVBD_ADAPTER
-TargetGetAdapter(
- __in PXENVBD_TARGET Target
+extern VOID
+TargetSetMissing(
+ IN PXENVBD_TARGET Target,
+ IN const CHAR* Reason
);
-extern ULONG
-TargetSectorSize(
- __in PXENVBD_TARGET Target
+extern NTSTATUS
+TargetCreate(
+ IN PXENVBD_ADAPTER Adapter,
+ IN PANSI_STRING Device,
+ OUT PXENVBD_TARGET* _Target
);
-// Queue-Related
extern VOID
-TargetSubmitRequests(
- __in PXENVBD_TARGET Target
+TargetDestroy(
+ IN PXENVBD_TARGET Target
);
-extern VOID
-TargetCompleteResponse(
- __in PXENVBD_TARGET Target,
- __in ULONG Tag,
- __in SHORT Status
+extern NTSTATUS
+TargetD3ToD0(
+ IN PXENVBD_TARGET Target
);
extern VOID
-TargetPreResume(
- __in PXENVBD_TARGET Target
+TargetD0ToD3(
+ IN PXENVBD_TARGET Target
);
-extern VOID
-TargetPostResume(
- __in PXENVBD_TARGET Target
+extern NTSTATUS
+TargetDispatchPnp(
+ IN PXENVBD_TARGET Target,
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp
);
-// StorPort Methods
extern VOID
TargetReset(
IN PXENVBD_TARGET Target
);
extern VOID
-TargetPrepareSrb(
+TargetFlush(
IN PXENVBD_TARGET Target,
IN PXENVBD_SRBEXT SrbExt
);
extern VOID
-TargetStartSrb(
+TargetShutdown(
IN PXENVBD_TARGET Target,
IN PXENVBD_SRBEXT SrbExt
);
extern VOID
-TargetFlush(
+TargetPrepareSrb(
IN PXENVBD_TARGET Target,
IN PXENVBD_SRBEXT SrbExt
);
extern VOID
-TargetShutdown(
+TargetStartSrb(
IN PXENVBD_TARGET Target,
IN PXENVBD_SRBEXT SrbExt
);
extern VOID
-TargetSrbPnp(
- __in PXENVBD_TARGET Target,
- __in PSCSI_PNP_REQUEST_BLOCK Srb
- );
-
-// PnP Handler
-__checkReturn
-extern NTSTATUS
-TargetDispatchPnp(
- __in PXENVBD_TARGET Target,
- __in PDEVICE_OBJECT DeviceObject,
- __in PIRP Irp
+TargetSubmitRequests(
+ IN PXENVBD_TARGET Target
);
-__drv_maxIRQL(DISPATCH_LEVEL)
extern VOID
-TargetIssueDeviceEject(
- __in PXENVBD_TARGET Target,
- __in __nullterminated const CHAR* Reason
+TargetCompleteResponse(
+ IN PXENVBD_TARGET Target,
+ IN ULONG64 Id,
+ IN SHORT Status
);
#endif // _XENVBD_TARGET_H
diff --git a/vs2012/xenvbd/xenvbd.vcxproj b/vs2012/xenvbd/xenvbd.vcxproj
index 04aff7c..993310d 100644
--- a/vs2012/xenvbd/xenvbd.vcxproj
+++ b/vs2012/xenvbd/xenvbd.vcxproj
@@ -76,12 +76,8 @@
<ClCompile Include="../../src/xenvbd/driver.c" />
<ClCompile Include="../../src/xenvbd/registry.c" />
<ClCompile Include="../../src/xenvbd/adapter.c" />
- <ClCompile Include="../../src/xenvbd/frontend.c" />
<ClCompile Include="../../src/xenvbd/target.c" />
- <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/granter.c" />
</ItemGroup>
diff --git a/vs2013/xenvbd/xenvbd.vcxproj b/vs2013/xenvbd/xenvbd.vcxproj
index 4dc5bb5..19d5a40 100644
--- a/vs2013/xenvbd/xenvbd.vcxproj
+++ b/vs2013/xenvbd/xenvbd.vcxproj
@@ -104,12 +104,8 @@
<ClCompile Include="../../src/xenvbd/driver.c" />
<ClCompile Include="../../src/xenvbd/registry.c" />
<ClCompile Include="../../src/xenvbd/adapter.c" />
- <ClCompile Include="../../src/xenvbd/frontend.c" />
<ClCompile Include="../../src/xenvbd/target.c" />
- <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/granter.c" />
</ItemGroup>
diff --git a/vs2015/xenvbd/xenvbd.vcxproj b/vs2015/xenvbd/xenvbd.vcxproj
index 4ae5159..f93ed7d 100644
--- a/vs2015/xenvbd/xenvbd.vcxproj
+++ b/vs2015/xenvbd/xenvbd.vcxproj
@@ -68,12 +68,8 @@
<ClCompile Include="../../src/xenvbd/driver.c" />
<ClCompile Include="../../src/xenvbd/registry.c" />
<ClCompile Include="../../src/xenvbd/adapter.c" />
- <ClCompile Include="../../src/xenvbd/frontend.c" />
<ClCompile Include="../../src/xenvbd/target.c" />
- <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/granter.c" />
</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 |