[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [win-pv-devel] [PATCH 03/03] Use list of targets
Replace target array with target list Remove Pdo reference count and remove event Destroy Pdo in response to Remove Irp Signed-off-by: Owen Smith <owen.smith@xxxxxxxxxx> --- src/xenvbd/fdo.c | 176 +++++++++++++++++++++++++++---------------------------- src/xenvbd/fdo.h | 8 +-- src/xenvbd/pdo.c | 109 ++++++++++------------------------ src/xenvbd/pdo.h | 8 ++- 4 files changed, 126 insertions(+), 175 deletions(-) diff --git a/src/xenvbd/fdo.c b/src/xenvbd/fdo.c index df3e9ff..526c6c9 100644 --- a/src/xenvbd/fdo.c +++ b/src/xenvbd/fdo.c @@ -84,7 +84,7 @@ struct _XENVBD_FDO { // Targets KSPIN_LOCK TargetLock; - PXENVBD_PDO Targets[XENVBD_MAX_TARGETS]; + LIST_ENTRY Targets; // Target Enumeration PXENVBD_THREAD RescanThread; @@ -124,48 +124,36 @@ __FdoSetDevicePowerState( __checkReturn static FORCEINLINE PXENVBD_PDO -__FdoGetPdoAlways( +___FdoGetPdo( __in PXENVBD_FDO Fdo, __in ULONG TargetId, __in PCHAR Caller ) { - PXENVBD_PDO Pdo; KIRQL Irql; + PLIST_ENTRY ListEntry; ASSERT3U(TargetId, <, XENVBD_MAX_TARGETS); KeAcquireSpinLock(&Fdo->TargetLock, &Irql); - Pdo = Fdo->Targets[TargetId]; - if (Pdo) { - __PdoReference(Pdo, Caller); - } - KeReleaseSpinLock(&Fdo->TargetLock, Irql); - - return Pdo; -} + for (ListEntry = Fdo->Targets.Flink; + ListEntry != &Fdo->Targets; + ListEntry = ListEntry->Flink) { + PXENVBD_PDO Pdo = PdoFromListEntry(ListEntry); -__checkReturn -static FORCEINLINE PXENVBD_PDO -___FdoGetPdo( - __in PXENVBD_FDO Fdo, - __in ULONG TargetId, - __in PCHAR Caller - ) -{ - PXENVBD_PDO Pdo = NULL; - KIRQL Irql; + if (PdoIsMissing(Pdo)) + continue; + if (PdoGetTargetId(Pdo) != TargetId) + continue; - ASSERT3U(TargetId, <, XENVBD_MAX_TARGETS); + __PdoReference(Pdo, Caller); + KeReleaseSpinLock(&Fdo->TargetLock, Irql); - KeAcquireSpinLock(&Fdo->TargetLock, &Irql); - if (Fdo->Targets[TargetId] && - __PdoReference(Fdo->Targets[TargetId], Caller) > 0) { - Pdo = Fdo->Targets[TargetId]; + return Pdo; } KeReleaseSpinLock(&Fdo->TargetLock, Irql); - return Pdo; + return NULL; } #define __FdoGetPdo(f, t) ___FdoGetPdo(f, t, __FUNCTION__) @@ -209,52 +197,54 @@ __FdoDereference( } return Result; } +static FORCEINLINE BOOLEAN +ListContains( + IN PLIST_ENTRY Head, + IN PLIST_ENTRY Find + ) +{ + PLIST_ENTRY ListEntry; + + for (ListEntry = Head->Flink; + ListEntry != Head; + ListEntry = ListEntry->Flink) { + if (ListEntry == Find) + return TRUE; + } + + return FALSE; +} + BOOLEAN FdoLinkPdo( - __in PXENVBD_FDO Fdo, - __in PXENVBD_PDO Pdo + IN PXENVBD_FDO Fdo, + IN PLIST_ENTRY ListEntry ) { KIRQL Irql; - PXENVBD_PDO Current; - BOOLEAN Result = FALSE; - ULONG TargetId = PdoGetTargetId(Pdo); KeAcquireSpinLock(&Fdo->TargetLock, &Irql); - Current = Fdo->Targets[TargetId]; - if (Fdo->Targets[TargetId] == NULL) { - Fdo->Targets[TargetId] = Pdo; - Result = TRUE; - } + InsertTailList(&Fdo->Targets, ListEntry); KeReleaseSpinLock(&Fdo->TargetLock, Irql); - if (!Result) { - Warning("Target[%d] : Current 0x%p, New 0x%p\n", TargetId, Current, Pdo); - } - return Result; + return TRUE; } BOOLEAN FdoUnlinkPdo( - __in PXENVBD_FDO Fdo, - __in PXENVBD_PDO Pdo + IN PXENVBD_FDO Fdo, + IN PLIST_ENTRY ListEntry ) { KIRQL Irql; - PXENVBD_PDO Current; BOOLEAN Result = FALSE; - ULONG TargetId = PdoGetTargetId(Pdo); KeAcquireSpinLock(&Fdo->TargetLock, &Irql); - Current = Fdo->Targets[TargetId]; - if (Fdo->Targets[TargetId] == Pdo) { - Fdo->Targets[TargetId] = NULL; + if (ListContains(&Fdo->Targets, ListEntry)) { Result = TRUE; } + RemoveEntryList(ListEntry); KeReleaseSpinLock(&Fdo->TargetLock, Irql); - if (!Result) { - Warning("Target[%d] : Current 0x%p, Expected 0x%p\n", TargetId, Current, Pdo); - } return Result; } @@ -357,7 +347,7 @@ FdoDebugCallback( ) { PXENVBD_FDO Fdo = Context; - ULONG TargetId; + PLIST_ENTRY ListEntry; if (Fdo == NULL || Fdo->DebugCallback == NULL) return; @@ -388,22 +378,22 @@ FdoDebugCallback( BufferDebugCallback(&Fdo->Debug); - for (TargetId = 0; TargetId < XENVBD_MAX_TARGETS; ++TargetId) { + for (ListEntry = Fdo->Targets.Flink; + ListEntry != &Fdo->Targets; + ListEntry = ListEntry->Flink) { // no need to use __FdoGetPdo (which is locked at DISPATCH) as called at HIGH_LEVEL - PXENVBD_PDO Pdo = Fdo->Targets[TargetId]; - if (Pdo == NULL) - continue; + PXENVBD_PDO Pdo = PdoFromListEntry(ListEntry); XENBUS_DEBUG(Printf, &Fdo->Debug, "FDO: ====> Target[%-3d] : 0x%p\n", - TargetId, Pdo); + PdoGetTargetId(Pdo), Pdo); // call Target's debug callback directly PdoDebugCallback(Pdo, &Fdo->Debug); XENBUS_DEBUG(Printf, &Fdo->Debug, "FDO: <==== Target[%-3d] : 0x%p\n", - TargetId, Pdo); + PdoGetTargetId(Pdo), Pdo); } Fdo->MaximumSrbs = Fdo->CurrentSrbs; @@ -715,19 +697,26 @@ FdoLogTargets( __in PXENVBD_FDO Fdo ) { - ULONG TargetId; + PLIST_ENTRY ListEntry; + KIRQL Irql; + KeAcquireSpinLock(&Fdo->TargetLock, &Irql); Verbose("%s ===>\n", Caller); - for (TargetId = 0; TargetId < XENVBD_MAX_TARGETS; ++TargetId) { - PXENVBD_PDO Pdo = __FdoGetPdoAlways(Fdo, TargetId, __FUNCTION__); - if (Pdo) { - const CHAR* Reason = PdoMissingReason(Pdo); - Verbose("%s : Target[%d] = 0x%p %s\n", Caller, TargetId, Pdo, - (Reason != NULL) ? Reason : "(present)"); - PdoDereference(Pdo); - } + for (ListEntry = Fdo->Targets.Flink; + ListEntry != &Fdo->Targets; + ListEntry = ListEntry->Flink) { + PXENVBD_PDO Pdo = PdoFromListEntry(ListEntry); + + const CHAR* Reason = PdoMissingReason(Pdo); + Verbose("%s : Target[%d] = 0x%p (0x%p) %s\n", + Caller, + PdoGetTargetId(Pdo), + Pdo, + PdoGetDeviceObject(Pdo), + (Reason != NULL) ? Reason : "(present)"); } Verbose("%s <===\n", Caller); + KeReleaseSpinLock(&Fdo->TargetLock, Irql); } __checkReturn @@ -1226,6 +1215,7 @@ __FdoInitialize( ASSERT3U(KeGetCurrentIrql(), <=, DISPATCH_LEVEL); // initialize the memory Fdo->DevicePower = PowerDeviceD3; + InitializeListHead(&Fdo->Targets); KeInitializeSpinLock(&Fdo->TargetLock); KeInitializeSpinLock(&Fdo->Lock); KeInitializeEvent(&Fdo->RemoveEvent, SynchronizationEvent, FALSE); @@ -1299,8 +1289,6 @@ __FdoTerminate( __in PXENVBD_FDO Fdo ) { - ULONG TargetId; - Trace("=====> (%d)\n", KeGetCurrentIrql()); DriverUnlinkFdo(Fdo); @@ -1334,18 +1322,22 @@ __FdoTerminate( Fdo->LowerDeviceObject = NULL; // delete targets - for (TargetId = 0; TargetId < XENVBD_MAX_TARGETS; ++TargetId) { - PXENVBD_PDO Pdo = __FdoGetPdoAlways(Fdo, TargetId, __FUNCTION__); - if (Pdo) { - // Pdo may not be in Deleted state yet, force it as Fdo is terminating - if (PdoGetDevicePnpState(Pdo) != Deleted) - PdoSetDevicePnpState(Pdo, Deleted); - // update missing (for debug output more than anything else - PdoSetMissing(Pdo, "FdoTerminate"); - // drop ref-count acquired in __FdoGetPdo *before* destroying Pdo - PdoDereference(Pdo); - PdoDestroy(Pdo); - } + for (;;) { + PLIST_ENTRY ListEntry; + PXENVBD_PDO Pdo; + + ListEntry = RemoveHeadList(&Fdo->Targets); + if (ListEntry == &Fdo->Targets) + break; + + Pdo = PdoFromListEntry(ListEntry); + + // Pdo may not be in Deleted state yet, force it as Fdo is terminating + if (PdoGetDevicePnpState(Pdo) != Deleted) + PdoSetDevicePnpState(Pdo, Deleted); + // update missing (for debug output more than anything else + PdoSetMissing(Pdo, "FdoTerminate"); + PdoDestroy(Pdo, FALSE); } // cleanup memory @@ -1358,6 +1350,7 @@ __FdoTerminate( Fdo->CurrentSrbs = Fdo->MaximumSrbs = Fdo->TotalSrbs = 0; RtlZeroMemory(&Fdo->Enumerator, sizeof(ANSI_STRING)); RtlZeroMemory(&Fdo->TargetLock, sizeof(KSPIN_LOCK)); + RtlZeroMemory(&Fdo->Targets, sizeof(LIST_ENTRY)); RtlZeroMemory(&Fdo->Lock, sizeof(KSPIN_LOCK)); RtlZeroMemory(&Fdo->RemoveEvent, sizeof(KEVENT)); __FdoZeroInterfaces(Fdo); diff --git a/src/xenvbd/fdo.h b/src/xenvbd/fdo.h index fcb5803..0b31bdd 100644 --- a/src/xenvbd/fdo.h +++ b/src/xenvbd/fdo.h @@ -64,14 +64,14 @@ __FdoDereference( // Link PDOs extern BOOLEAN FdoLinkPdo( - __in PXENVBD_FDO Fdo, - __in PXENVBD_PDO Pdo + IN PXENVBD_FDO Fdo, + IN PLIST_ENTRY ListEntry ); extern BOOLEAN FdoUnlinkPdo( - __in PXENVBD_FDO Fdo, - __in PXENVBD_PDO Pdo + IN PXENVBD_FDO Fdo, + IN PLIST_ENTRY ListEntry ); // Query Methods __checkReturn diff --git a/src/xenvbd/pdo.c b/src/xenvbd/pdo.c index 76b0112..bd822db 100644 --- a/src/xenvbd/pdo.c +++ b/src/xenvbd/pdo.c @@ -60,8 +60,6 @@ typedef struct _XENVBD_SG_LIST { ULONG Length; } XENVBD_SG_LIST, *PXENVBD_SG_LIST; -#define PDO_SIGNATURE 'odpX' - typedef struct _XENVBD_LOOKASIDE { KEVENT Empty; LONG Used; @@ -72,11 +70,9 @@ typedef struct _XENVBD_LOOKASIDE { } XENVBD_LOOKASIDE, *PXENVBD_LOOKASIDE; struct _XENVBD_PDO { - ULONG Signature; + LIST_ENTRY ListEntry; PXENVBD_FDO Fdo; PDEVICE_OBJECT DeviceObject; - KEVENT RemoveEvent; - LONG ReferenceCount; DEVICE_PNP_STATE DevicePnpState; DEVICE_PNP_STATE PrevPnpState; DEVICE_POWER_STATE DevicePowerState; @@ -123,6 +119,14 @@ struct _XENVBD_PDO { ULONG64 SegsBounced; }; +PXENVBD_PDO +PdoFromListEntry( + IN PLIST_ENTRY ListEntry + ) +{ + return CONTAINING_RECORD(ListEntry, XENVBD_PDO, ListEntry); +} + //============================================================================= #define PDO_POOL_TAG 'odPX' #define REQUEST_POOL_TAG 'qeRX' @@ -267,17 +271,12 @@ PdoDebugCallback( { if (Pdo == NULL || DebugInterface == NULL) return; - if (Pdo->Signature != PDO_SIGNATURE) - return; XENBUS_DEBUG(Printf, DebugInterface, "PDO: Fdo 0x%p DeviceObject 0x%p\n", Pdo->Fdo, Pdo->DeviceObject); XENBUS_DEBUG(Printf, DebugInterface, - "PDO: ReferenceCount %d\n", - Pdo->ReferenceCount); - XENBUS_DEBUG(Printf, DebugInterface, "PDO: DevicePnpState %s (%s)\n", __PnpStateName(Pdo->DevicePnpState), __PnpStateName(Pdo->PrevPnpState)); @@ -516,11 +515,8 @@ PdoCreate( goto fail1; Verbose("Target[%d] : Creating (%s)\n", TargetId, EmulatedUnplugged ? "PV" : "Emulated"); - Pdo->Signature = PDO_SIGNATURE; Pdo->Fdo = Fdo; Pdo->DeviceObject = NULL; // filled in later - KeInitializeEvent(&Pdo->RemoveEvent, SynchronizationEvent, FALSE); - Pdo->ReferenceCount = 1; Pdo->Paused = 1; // Paused until D3->D0 transition Pdo->DevicePnpState = Present; Pdo->DevicePowerState = PowerDeviceD3; @@ -545,7 +541,8 @@ PdoCreate( if (!NT_SUCCESS(Status)) goto fail3; - if (!FdoLinkPdo(Fdo, Pdo)) + InitializeListHead(&Pdo->ListEntry); + if (!FdoLinkPdo(Fdo, &Pdo->ListEntry)) goto fail4; Verbose("Target[%d] : Created (%s)\n", TargetId, EmulatedUnplugged ? "PV" : "Emulated"); @@ -575,57 +572,24 @@ fail1: VOID PdoDestroy( - __in PXENVBD_PDO Pdo + __in PXENVBD_PDO Pdo, + __in BOOLEAN Unlink ) { const ULONG TargetId = PdoGetTargetId(Pdo); - PVOID Objects[4]; - PKWAIT_BLOCK WaitBlock; Trace("Target[%d] @ (%d) =====>\n", TargetId, KeGetCurrentIrql()); Verbose("Target[%d] : Destroying\n", TargetId); - ASSERT3U(Pdo->Signature, ==, PDO_SIGNATURE); - if (!FdoUnlinkPdo(PdoGetFdo(Pdo), Pdo)) { - Error("Target[%d] : PDO 0x%p not linked to FDO 0x%p\n", TargetId, Pdo, PdoGetFdo(Pdo)); + if (Unlink) { + if (!FdoUnlinkPdo(PdoGetFdo(Pdo), &Pdo->ListEntry)) { + Error("Target[%d] : PDO 0x%p not linked to FDO 0x%p\n", TargetId, Pdo, PdoGetFdo(Pdo)); + } } PdoD0ToD3(Pdo); PdoDereference(Pdo); // drop initial ref count - // Wait for ReferenceCount == 0 and RequestListUsed == 0 - Verbose("Target[%d] : ReferenceCount %d, RequestListUsed %d\n", TargetId, Pdo->ReferenceCount, Pdo->RequestList.Used); - Objects[0] = &Pdo->RemoveEvent; - Objects[1] = &Pdo->RequestList.Empty; - Objects[2] = &Pdo->SegmentList.Empty; - Objects[3] = &Pdo->IndirectList.Empty; - - WaitBlock = (PKWAIT_BLOCK)__PdoAlloc(sizeof(KWAIT_BLOCK) * ARRAYSIZE(Objects)); - if (WaitBlock == NULL) { - ULONG Index; - - Error("Unable to allocate resources for KWAIT_BLOCK\n"); - - 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) - __PdoFree(WaitBlock); - } - - ASSERT3S(Pdo->ReferenceCount, ==, 0); ASSERT3U(PdoGetDevicePnpState(Pdo), ==, Deleted); __LookasideTerm(&Pdo->IndirectList); @@ -635,7 +599,6 @@ PdoDestroy( FrontendDestroy(Pdo->Frontend); Pdo->Frontend = NULL; - ASSERT3U(Pdo->Signature, ==, PDO_SIGNATURE); RtlZeroMemory(Pdo, sizeof(XENVBD_PDO)); __PdoFree(Pdo); @@ -730,20 +693,9 @@ __PdoReference( __in PCHAR Caller ) { - LONG Result; - - ASSERT3P(Pdo, !=, NULL); - Result = InterlockedIncrement(&Pdo->ReferenceCount); - ASSERTREFCOUNT(Result, >, 0, Caller); - - if (Result == 1) { - Result = InterlockedDecrement(&Pdo->ReferenceCount); - Error("Target[%d] : %s: Attempting to take reference of removed PDO from %d\n", PdoGetTargetId(Pdo), Caller, Result); - return 0; - } else { - ASSERTREFCOUNT(Result, >, 1, Caller); - return Result; - } + UNREFERENCED_PARAMETER(Pdo); + UNREFERENCED_PARAMETER(Caller); + return 1; } FORCEINLINE LONG @@ -752,17 +704,9 @@ __PdoDereference( __in PCHAR Caller ) { - LONG Result; - - ASSERT3P(Pdo, !=, NULL); - Result = InterlockedDecrement(&Pdo->ReferenceCount); - ASSERTREFCOUNT(Result, >=, 0, Caller); - - if (Result == 0) { - Verbose("Final ReferenceCount dropped, Target[%d] able to be removed\n", PdoGetTargetId(Pdo)); - KeSetEvent(&Pdo->RemoveEvent, IO_NO_INCREMENT, FALSE); - } - return Result; + UNREFERENCED_PARAMETER(Pdo); + UNREFERENCED_PARAMETER(Caller); + return 1; } //============================================================================= @@ -2544,12 +2488,19 @@ __PdoRemoveDevice( PdoSetMissing(Pdo, "Surprise Remove"); PdoSetDevicePnpState(Pdo, Deleted); StorPortNotification(BusChangeDetected, PdoGetFdo(Pdo), 0); + + PdoDereference(Pdo); + PdoDestroy(Pdo, TRUE); break; + case RemovePending: case Enumerated: PdoSetMissing(Pdo, "Removed"); PdoSetDevicePnpState(Pdo, Deleted); StorPortNotification(BusChangeDetected, PdoGetFdo(Pdo), 0); + + PdoDereference(Pdo); + PdoDestroy(Pdo, TRUE); break; default: diff --git a/src/xenvbd/pdo.h b/src/xenvbd/pdo.h index c5e81ab..333aca8 100644 --- a/src/xenvbd/pdo.h +++ b/src/xenvbd/pdo.h @@ -42,6 +42,11 @@ typedef struct _XENVBD_PDO XENVBD_PDO, *PXENVBD_PDO; #include "types.h" #include <debug_interface.h> +extern PXENVBD_PDO +PdoFromListEntry( + IN PLIST_ENTRY ListEntry + ); + extern VOID PdoDebugCallback( __in PXENVBD_PDO Pdo, @@ -62,7 +67,8 @@ PdoCreate( extern VOID PdoDestroy( - __in PXENVBD_PDO Pdo + __in PXENVBD_PDO Pdo, + __in BOOLEAN Unlink ); __checkReturn -- 1.9.4.msysgit.1 _______________________________________________ win-pv-devel mailing list win-pv-devel@xxxxxxxxxxxxxxxxxxxx http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |