[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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.