[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[win-pv-devel] [PATCH 4/9] Rework enumeration code to work at PASSIVE_LEVEL



There should be no need to hold a lock whilst enumerating devices, as the
insertion and removal of Pdos is already locked. This allows more 
operations to be called during creation/deletion of Pdos

Signed-off-by: Owen Smith <owen.smith@xxxxxxxxxx>
---
 src/xenvbd/fdo.c | 151 ++++++++++++++++++++++++-------------------------------
 1 file changed, 67 insertions(+), 84 deletions(-)

diff --git a/src/xenvbd/fdo.c b/src/xenvbd/fdo.c
index 939fb47..dadf395 100644
--- a/src/xenvbd/fdo.c
+++ b/src/xenvbd/fdo.c
@@ -90,8 +90,9 @@ struct _XENVBD_FDO {
     PXENVBD_PDO                 Targets[XENVBD_MAX_TARGETS];
 
     // Target Enumeration
-    PXENVBD_THREAD              RescanThread;
-    PXENBUS_STORE_WATCH         RescanWatch;
+    PXENVBD_THREAD              ScanThread;
+    KEVENT                      ScanEvent;
+    PXENBUS_STORE_WATCH         ScanWatch;
     PXENVBD_THREAD              FrontendThread;
 
     // Statistics
@@ -123,6 +124,21 @@ __FdoSetDevicePowerState(
     return Changed;
 }
 
+static FORCEINLINE DEVICE_POWER_STATE
+__FdoGetDevicePowerState(
+    __in PXENVBD_FDO                Fdo
+    )
+{
+    KIRQL               Irql;
+    DEVICE_POWER_STATE  State;
+
+    KeAcquireSpinLock(&Fdo->Lock, &Irql);
+    State = Fdo->DevicePower;
+    KeReleaseSpinLock(&Fdo->Lock, Irql);
+
+    return State;
+}
+
 __checkReturn
 static FORCEINLINE PXENVBD_PDO
 __FdoGetPdoAlways(
@@ -637,48 +653,29 @@ __FdoEnumerate(
         *NeedInvalidate |= (NT_SUCCESS(Status)) ? TRUE : FALSE;
     }
 }
-__drv_requiresIRQL(DISPATCH_LEVEL)
 static DECLSPEC_NOINLINE VOID
 FdoScanTargets(
-    __in    PXENVBD_FDO Fdo,
-    __out   PBOOLEAN    NeedInvalidate,
-    __out   PBOOLEAN    NeedReboot
+    __in    PXENVBD_FDO Fdo
     )
 {
     NTSTATUS        Status;
     PCHAR           Buffer;
+    BOOLEAN         NeedInvalidate;
+    BOOLEAN         NeedReboot;
 
-    Trace("====>\n");
     Status = XENBUS_STORE(Directory, &Fdo->Store, NULL, "device", 
FdoEnum(Fdo), &Buffer);
-    if (NT_SUCCESS(Status)) {
-        __FdoEnumerate(Fdo, Buffer, NeedInvalidate, NeedReboot);
-        XENBUS_STORE(Free, &Fdo->Store, Buffer);
-    } else {
-        *NeedInvalidate = FALSE;
-        *NeedReboot = FALSE;
-    }
-    Trace("<====\n");
-}
+    if (!NT_SUCCESS(Status))
+        return;
 
-static DECLSPEC_NOINLINE VOID
-FdoLogTargets(
-    __in PCHAR                       Caller,
-    __in PXENVBD_FDO                 Fdo
-    )
-{
-    ULONG   TargetId;
+    __FdoEnumerate(Fdo, Buffer, &NeedInvalidate, &NeedReboot);
+    XENBUS_STORE(Free, &Fdo->Store, Buffer);
 
-    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);
-        }
+    if (NeedInvalidate) {
+        StorPortNotification(BusChangeDetected, Fdo, 0);
+    }
+    if (NeedReboot) {
+        DriverNotifyInstaller();
     }
-    Verbose("%s <===\n", Caller);
 }
 
 __checkReturn
@@ -689,33 +686,27 @@ FdoScan(
     )
 {
     PXENVBD_FDO     Fdo = Context;
+    PKEVENT         Event = ThreadGetEvent(Thread);
 
     for (;;) {
-        KIRQL   Irql;
-        BOOLEAN NeedInvalidate;
-        BOOLEAN NeedReboot;
-        
-        if (!ThreadWait(Thread))
-            break;
-        
-        KeAcquireSpinLock(&Fdo->Lock, &Irql);
-        if (Fdo->DevicePower != PowerDeviceD0) {
-            KeReleaseSpinLock(&Fdo->Lock, Irql);
-            continue;
-        }
-        
-        FdoScanTargets(Fdo, &NeedInvalidate, &NeedReboot);
+        Trace("waiting...\n");
 
-        KeReleaseSpinLock(&Fdo->Lock, Irql);
+        (VOID) KeWaitForSingleObject(Event,
+                                     Executive,
+                                     KernelMode,
+                                     FALSE,
+                                     NULL);
+        KeClearEvent(Event);
 
-        if (NeedInvalidate) {
-            FdoLogTargets("ScanThread", Fdo);
-            StorPortNotification(BusChangeDetected, Fdo, 0);
-        }
+        if (ThreadIsAlerted(Thread))
+            break;
+
+        if (__FdoGetDevicePowerState(Fdo) == PowerDeviceD0)
+            FdoScanTargets(Fdo);
 
-        if (NeedReboot)
-            DriverNotifyInstaller();
+        KeSetEvent(&Fdo->ScanEvent, IO_NO_INCREMENT, FALSE);
     }
+    KeSetEvent(&Fdo->ScanEvent, IO_NO_INCREMENT, FALSE);
 
     return STATUS_SUCCESS;
 }
@@ -1258,13 +1249,13 @@ __FdoD3ToD0(
 
     (VOID) FdoSetDistribution(Fdo);
 
-    ASSERT3P(Fdo->RescanWatch, ==, NULL);
+    ASSERT3P(Fdo->ScanWatch, ==, NULL);
     Status = XENBUS_STORE(WatchAdd,
                           &Fdo->Store,
                           "device",
                           FdoEnum(Fdo),
-                          ThreadGetEvent(Fdo->RescanThread),
-                          &Fdo->RescanWatch);
+                          ThreadGetEvent(Fdo->ScanThread),
+                          &Fdo->ScanWatch);
     if (!NT_SUCCESS(Status))
         goto fail1;
 
@@ -1300,8 +1291,8 @@ __FdoD0ToD3(
 
     (VOID) XENBUS_STORE(WatchRemove,
                         &Fdo->Store,
-                        Fdo->RescanWatch);
-    Fdo->RescanWatch = NULL;
+                        Fdo->ScanWatch);
+    Fdo->ScanWatch = NULL;
 
     FdoClearDistribution(Fdo);
 
@@ -1539,6 +1530,7 @@ __FdoInitialize(
     KeInitializeSpinLock(&Fdo->TargetLock);
     KeInitializeSpinLock(&Fdo->Lock);
     KeInitializeEvent(&Fdo->RemoveEvent, SynchronizationEvent, FALSE);
+    KeInitializeEvent(&Fdo->ScanEvent, SynchronizationEvent, FALSE);
 
     Fdo->ReferenceCount = 1;
     Fdo->Signature = FDO_SIGNATURE;
@@ -1559,7 +1551,7 @@ __FdoInitialize(
         goto fail2;
 
     // start enum thread
-    Status = ThreadCreate(FdoScan, Fdo, &Fdo->RescanThread);
+    Status = ThreadCreate(FdoScan, Fdo, &Fdo->ScanThread);
     if (!NT_SUCCESS(Status))
         goto fail3;
 
@@ -1588,9 +1580,9 @@ fail5:
     Fdo->FrontendThread = NULL;
 fail4:
     Error("fail4\n");
-    ThreadAlert(Fdo->RescanThread);
-    ThreadJoin(Fdo->RescanThread);
-    Fdo->RescanThread = NULL;
+    ThreadAlert(Fdo->ScanThread);
+    ThreadJoin(Fdo->ScanThread);
+    Fdo->ScanThread = NULL;
 fail3:
     Error("fail3\n");
     __FdoZeroInterfaces(Fdo);
@@ -1634,9 +1626,9 @@ __FdoTerminate(
     Fdo->FrontendThread = NULL;
 
     // stop enum thread
-    ThreadAlert(Fdo->RescanThread);
-    ThreadJoin(Fdo->RescanThread);
-    Fdo->RescanThread = NULL;
+    ThreadAlert(Fdo->ScanThread);
+    ThreadJoin(Fdo->ScanThread);
+    Fdo->ScanThread = NULL;
 
     // clear device objects
     Fdo->DeviceObject = NULL;
@@ -1669,6 +1661,7 @@ __FdoTerminate(
     RtlZeroMemory(&Fdo->Enumerator, sizeof(ANSI_STRING));
     RtlZeroMemory(&Fdo->TargetLock, sizeof(KSPIN_LOCK));
     RtlZeroMemory(&Fdo->Lock, sizeof(KSPIN_LOCK));
+    RtlZeroMemory(&Fdo->ScanEvent, sizeof(KEVENT));
     RtlZeroMemory(&Fdo->RemoveEvent, sizeof(KEVENT));
     __FdoZeroInterfaces(Fdo);
 
@@ -2035,26 +2028,16 @@ FdoDispatchPnp(
 
     case IRP_MN_QUERY_DEVICE_RELATIONS:
         if (Stack->Parameters.QueryDeviceRelations.Type == BusRelations) {
-            KIRQL   Irql;
-            BOOLEAN NeedInvalidate;
-            BOOLEAN NeedReboot;
-
-            KeAcquireSpinLock(&Fdo->Lock, &Irql);
-
-            if (Fdo->DevicePower == PowerDeviceD0) {
-                FdoScanTargets(Fdo, &NeedInvalidate, &NeedReboot);
-            } else {
-                NeedInvalidate = FALSE;
-                NeedReboot = FALSE;
-            }
-
-            KeReleaseSpinLock(&Fdo->Lock, Irql);
+            KeClearEvent(&Fdo->ScanEvent);
+            ThreadWake(Fdo->ScanThread);
 
-            if (NeedInvalidate)
-                FdoLogTargets("QUERY_RELATIONS", Fdo);
+            Trace("waiting for scan thread\n");
 
-            if (NeedReboot)
-                DriverNotifyInstaller();
+            (VOID) KeWaitForSingleObject(&Fdo->ScanEvent,
+                                         Executive,
+                                         KernelMode,
+                                         FALSE,
+                                         NULL);
         }
         FdoDereference(Fdo);
         break;
-- 
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®.