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

[XENBUS PATCH v2 2/7] xenfilt: Add Xenbus device precedence mechanism



Define registry values in xenfilt\Parameters with the names being
compatible IDs and values being numeric precedences.

The Xenbus device with the highest precedence should always be activated
over devices with lower precedence, ignoring Active* values.

If a device is force-activated, get its IDs directly instead of via
Active* values.

Signed-off-by: Tu Dinh <ngoc-tu.dinh@xxxxxxxxxx>
---
 src/xenfilt/driver.c | 35 ++++++++++++++++++++
 src/xenfilt/driver.h |  7 ++++
 src/xenfilt/fdo.c    | 25 +++++++++++++-
 src/xenfilt/pdo.c    | 79 ++++++++++++++++++++++++++++++++++++--------
 src/xenfilt/pdo.h    | 10 +++++-
 5 files changed, 141 insertions(+), 15 deletions(-)

diff --git a/src/xenfilt/driver.c b/src/xenfilt/driver.c
index 16e4deb..8f39b8d 100644
--- a/src/xenfilt/driver.c
+++ b/src/xenfilt/driver.c
@@ -279,6 +279,41 @@ DriverGetActive(
     return __DriverGetActive(Key, Value);
 }
 
+_On_failure_(_Post_satisfies_(*Value == 0))
+NTSTATUS
+DriverGetPrecedence(
+    _In_ PCSTR      Id,
+    _Out_ PULONG    Value
+    )
+{
+    HANDLE          ParametersKey;
+    NTSTATUS        status;
+
+    status = RegistryOpenParametersKey(KEY_READ, &ParametersKey);
+    if (!NT_SUCCESS(status))
+        goto fail1;
+
+    status = RegistryQueryDwordValue(ParametersKey,
+                                     (PSTR)Id,
+                                     Value);
+    if (!NT_SUCCESS(status))
+        goto fail2;
+
+    Info("%s found precedence %04lx\n", Id, *Value);
+
+    RegistryCloseKey(ParametersKey);
+
+    return STATUS_SUCCESS;
+
+fail2:
+    RegistryCloseKey(ParametersKey);
+
+fail1:
+    *Value = 0;
+
+    return status;
+}
+
 static BOOLEAN
 DriverIsActivePresent(
     VOID
diff --git a/src/xenfilt/driver.h b/src/xenfilt/driver.h
index 9c703c1..01ab5b7 100644
--- a/src/xenfilt/driver.h
+++ b/src/xenfilt/driver.h
@@ -54,6 +54,13 @@ DriverGetActive(
     _Outptr_result_z_ PSTR  *Value
     );
 
+_On_failure_(_Post_satisfies_(*Value == 0))
+extern NTSTATUS
+DriverGetPrecedence(
+    _In_ PCSTR      Id,
+    _Out_ PULONG    Value
+    );
+
 typedef enum _XENFILT_FILTER_STATE {
     XENFILT_FILTER_ENABLED = 0,
     XENFILT_FILTER_PENDING,
diff --git a/src/xenfilt/fdo.c b/src/xenfilt/fdo.c
index 594da4a..250f1ab 100644
--- a/src/xenfilt/fdo.c
+++ b/src/xenfilt/fdo.c
@@ -404,6 +404,8 @@ FdoEnumerate(
     ULONG                   Count;
     PLIST_ENTRY             ListEntry;
     ULONG                   Index;
+    ULONG                   ActiveIndex;
+    ULONG                   Precedence;
     NTSTATUS                status;
 
     Count = Relations->Count;
@@ -458,11 +460,32 @@ FdoEnumerate(
         ListEntry = Next;
     }
 
+    ActiveIndex = Precedence = 0;
+    for (Index = 0; Index < Count; Index++) {
+        ULONG   ThisPrecedence;
+
+        if (PhysicalDeviceObject[Index] != NULL) {
+            status = PdoGetPrecedence(PhysicalDeviceObject[Index],
+                                      &ThisPrecedence);
+            if (ThisPrecedence > Precedence) {
+                ActiveIndex = Index;
+                Precedence = ThisPrecedence;
+            }
+        }
+    }
+
     // Walk the list and create PDO filters for any new devices
     for (Index = 0; Index < Count; Index++) {
 #pragma warning(suppress:6385)  // Reading invalid data from 
'PhysicalDeviceObject'
         if (PhysicalDeviceObject[Index] != NULL) {
-            (VOID) PdoCreate(Fdo, PhysicalDeviceObject[Index], Fdo->Type);
+            LONG    ForceActivate = 0;
+
+            if (Precedence > 0)
+                ForceActivate = Index == ActiveIndex ? 1 : -1;
+            (VOID) PdoCreate(Fdo,
+                             PhysicalDeviceObject[Index],
+                             Fdo->Type,
+                             ForceActivate);
             ObDereferenceObject(PhysicalDeviceObject[Index]);
         }
     }
diff --git a/src/xenfilt/pdo.c b/src/xenfilt/pdo.c
index 4f40c4f..48ae3a3 100644
--- a/src/xenfilt/pdo.c
+++ b/src/xenfilt/pdo.c
@@ -249,7 +249,8 @@ __PdoGetFdo(
 
 static NTSTATUS
 PdoSetDeviceInformation(
-    _In_ PXENFILT_PDO   Pdo
+    _In_ PXENFILT_PDO   Pdo,
+    _In_ LONG           ForceActivate
     )
 {
     PXENFILT_DX         Dx = Pdo->Dx;
@@ -265,19 +266,23 @@ PdoSetDeviceInformation(
     if (!NT_SUCCESS(status))
         goto fail1;
 
-    status = DriverGetActive("DeviceID",
-                             &ActiveDeviceID);
-    if (NT_SUCCESS(status)) {
-        Pdo->Active = (_stricmp(DeviceID, ActiveDeviceID) == 0) ?
-                      TRUE :
-                      FALSE;
-
-        ExFreePool(ActiveDeviceID);
+    if (ForceActivate) {
+        Pdo->Active = ForceActivate > 0;
     } else {
-        Pdo->Active = FALSE;
+        status = DriverGetActive("DeviceID",
+                                &ActiveDeviceID);
+        if (NT_SUCCESS(status)) {
+            Pdo->Active = (_stricmp(DeviceID, ActiveDeviceID) == 0) ?
+                        TRUE :
+                        FALSE;
+
+            ExFreePool(ActiveDeviceID);
+        } else {
+            Pdo->Active = FALSE;
+        }
     }
 
-    if (Pdo->Active) {
+    if (Pdo->Active && !ForceActivate) {
         status = DriverGetActive("InstanceID",
                                  &InstanceID);
         if (!NT_SUCCESS(status))
@@ -1618,11 +1623,59 @@ PdoSuspend(
     UNREFERENCED_PARAMETER(Pdo);
 }
 
+_On_failure_(_Post_satisfies_(*Precedence == 0))
+NTSTATUS
+PdoGetPrecedence(
+    _In_ PDEVICE_OBJECT PhysicalDeviceObject,
+    _Out_ PULONG        Precedence
+    )
+{
+    PSTR                CompatibleIDs;
+    ULONG               Index;
+    NTSTATUS            status;
+
+    status = DriverQueryId(PhysicalDeviceObject,
+                           BusQueryCompatibleIDs,
+                           &CompatibleIDs);
+    if (!NT_SUCCESS(status))
+        goto fail1;
+
+    Index = 0;
+
+    do {
+        ULONG           Length;
+
+        Length = (ULONG)strlen(&CompatibleIDs[Index]);
+        if (Length == 0)
+            break;
+
+        status = DriverGetPrecedence(&CompatibleIDs[Index],
+                                     Precedence);
+        if (NT_SUCCESS(status))
+            goto done;
+
+        Index += Length + 1;
+    } while (1);
+
+    *Precedence = 0;
+
+done:
+    ExFreePool(CompatibleIDs);
+
+    return STATUS_SUCCESS;
+
+fail1:
+    *Precedence = 0;
+
+    return status;
+}
+
 NTSTATUS
 PdoCreate(
     _In_ PXENFILT_FDO                   Fdo,
     _In_ PDEVICE_OBJECT                 PhysicalDeviceObject,
-    _In_ XENFILT_EMULATED_OBJECT_TYPE   Type
+    _In_ XENFILT_EMULATED_OBJECT_TYPE   Type,
+    _In_ LONG                           ForceActivate
     )
 {
     PDEVICE_OBJECT                      LowerDeviceObject;
@@ -1680,7 +1733,7 @@ PdoCreate(
     Pdo->LowerDeviceObject = LowerDeviceObject;
     Pdo->Type = Type;
 
-    status = PdoSetDeviceInformation(Pdo);
+    status = PdoSetDeviceInformation(Pdo, ForceActivate);
     if (!NT_SUCCESS(status))
         goto fail4;
 
diff --git a/src/xenfilt/pdo.h b/src/xenfilt/pdo.h
index 85bc07f..75a1412 100644
--- a/src/xenfilt/pdo.h
+++ b/src/xenfilt/pdo.h
@@ -78,11 +78,19 @@ PdoGetDeviceObject(
     _In_ PXENFILT_PDO   Pdo
     );
 
+_On_failure_(_Post_satisfies_(*Precedence == 0))
+extern NTSTATUS
+PdoGetPrecedence(
+    _In_ PDEVICE_OBJECT PhysicalDeviceObject,
+    _Out_ PULONG        Precedence
+    );
+
 extern NTSTATUS
 PdoCreate(
     _In_ PXENFILT_FDO                   Fdo,
     _In_ PDEVICE_OBJECT                 PhysicalDeviceObject,
-    _In_ XENFILT_EMULATED_OBJECT_TYPE   Type
+    _In_ XENFILT_EMULATED_OBJECT_TYPE   Type,
+    _In_ LONG                           ForceActivate
     );
 
 extern VOID
-- 
2.50.1.windows.1



Ngoc Tu Dinh | Vates XCP-ng Developer

XCP-ng & Xen Orchestra - Vates solutions

web: https://vates.tech




 


Rackspace

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