[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [win-pv-devel] [PATCH] Make sure unplug and reboot is requested at the right time
Because the installation of XENNET now steals the stack binding of any corresponding emulated NIC, should that NIC re-appear (which it may if the unplug key is cleared from the registry for some reason) then Windows will not attempt to start the PV NIC. This means that the code to check for aliasing emulated device and request unplug and reboot is never executed. This patch re-works the code to perform the checks at PDO creation time, which is unaffected by the new XENNET installation behaviour. Signed-off-by: Paul Durrant <paul.durrant@xxxxxxxxxx> --- src/xenvif/pdo.c | 276 +++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 187 insertions(+), 89 deletions(-) diff --git a/src/xenvif/pdo.c b/src/xenvif/pdo.c index 33a75ae..d4c1962 100644 --- a/src/xenvif/pdo.c +++ b/src/xenvif/pdo.c @@ -97,6 +97,7 @@ struct _XENVIF_PDO { PXENVIF_VIF_CONTEXT VifContext; XENVIF_VIF_INTERFACE VifInterface; + BOOLEAN HasDriver; BOOLEAN HasAlias; }; @@ -1199,8 +1200,8 @@ PdoUnplugRequest( { NTSTATUS status; - ASSERT3U(Pdo->UnplugRequested, !=, Make); - Pdo->UnplugRequested = Make; + if (Pdo->UnplugRequested == Make) + return; status = XENBUS_UNPLUG(Acquire, &Pdo->UnplugInterface); if (!NT_SUCCESS(status)) @@ -1212,6 +1213,8 @@ PdoUnplugRequest( Make); XENBUS_UNPLUG(Release, &Pdo->UnplugInterface); + + Pdo->UnplugRequested = Make; } static DECLSPEC_NOINLINE NTSTATUS @@ -1220,17 +1223,16 @@ PdoStartDevice( IN PIRP Irp ) { - NTSTATUS (*__GetIfTable2)(PMIB_IF_TABLE2 *); - VOID (*__FreeMibTable)(PVOID); - PMIB_IF_TABLE2 Table; - ULONG Index; - PMIB_IF_ROW2 Row; PIO_STACK_LOCATION StackLocation; NTSTATUS status; status = STATUS_UNSUCCESSFUL; - if (Pdo->HasAlias) + if (Pdo->HasAlias) { + PdoUnplugRequest(Pdo, TRUE); + DriverRequestReboot(); + goto fail1; + } if (DriverSafeMode()) goto fail2; @@ -1249,95 +1251,20 @@ PdoStartDevice( if (!NT_SUCCESS(status)) goto fail5; - status = LinkGetRoutineAddress("netio.sys", - "GetIfTable2", - (PVOID *)&__GetIfTable2); - if (!NT_SUCCESS(status)) - goto fail6; - - status = LinkGetRoutineAddress("netio.sys", - "FreeMibTable", - (PVOID *)&__FreeMibTable); - if (!NT_SUCCESS(status)) - goto fail7; - - status = __GetIfTable2(&Table); - if (!NT_SUCCESS(status)) - goto fail8; - - // - // Look for a network interface with the same permanent address - // that is already up. If there is one then it must be an - // aliasing emulated device, so save its settings. - // - for (Index = 0; Index < Table->NumEntries; Index++) { - Row = &Table->Table[Index]; - - Trace("%s: checking %ws (%ws)\n", - __PdoGetName(Pdo), - Row->Alias, - Row->Description); - - if (!Row->InterfaceAndOperStatusFlags.ConnectorPresent) - continue; - - if (Row->PhysicalAddressLength != sizeof (ETHERNET_ADDRESS)) - continue; - - if (memcmp(Row->PermanentPhysicalAddress, - __PdoGetPermanentAddress(Pdo), - sizeof (ETHERNET_ADDRESS)) != 0) - continue; - - if (Row->OperStatus != IfOperStatusUp) - continue; - - Pdo->HasAlias = TRUE; - } - - if (Pdo->HasAlias) { - PdoUnplugRequest(Pdo, TRUE); - - status = STATUS_UNSUCCESSFUL; - goto fail9; - } - StackLocation = IoGetCurrentIrpStackLocation(Irp); status = PdoD3ToD0(Pdo); if (!NT_SUCCESS(status)) - goto fail10; - - PdoUnplugRequest(Pdo, TRUE); + goto fail6; __PdoSetDevicePnpState(Pdo, Started); Irp->IoStatus.Status = STATUS_SUCCESS; IoCompleteRequest(Irp, IO_NO_INCREMENT); - __FreeMibTable(Table); return STATUS_SUCCESS; -fail10: - Error("fail10\n"); - - __FreeMibTable(Table); - - goto fail6; - -fail9: - Error("fail9\n"); - - DriverRequestReboot(); - __FreeMibTable(Table); - -fail8: - Error("fail8\n"); - -fail7: - Error("fail7\n"); - fail6: Error("fail6\n"); @@ -1415,8 +1342,6 @@ PdoStopDevice( if (__PdoGetDevicePowerState(Pdo) != PowerDeviceD0) goto done; - PdoUnplugRequest(Pdo, FALSE); - PdoD0ToD3(Pdo); done: @@ -1506,8 +1431,6 @@ PdoRemoveDevice( if (__PdoGetDevicePowerState(Pdo) != PowerDeviceD0) goto done; - PdoUnplugRequest(Pdo, FALSE); - PdoD0ToD3(Pdo); done: @@ -2625,6 +2548,156 @@ PdoSuspend( FrontendSuspend(__PdoGetFrontend(Pdo)); } +#define ENUM_KEY(_Driver) \ + "\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Enum\\" ## _Driver + +static FORCEINLINE NTSTATUS +__PdoCheckForDriver( + IN PXENVIF_PDO Pdo + ) +{ + HANDLE EnumKey; + ULONG Index; + PXENVIF_PDO_REVISION Revision; + CHAR HardwareKeyName[MAXNAMELEN]; + HANDLE HardwareKey; + PANSI_STRING Ansi; + NTSTATUS status; + + status = RegistryOpenSubKey(NULL, + ENUM_KEY(__MODULE__), + KEY_READ, + &EnumKey); + if (!NT_SUCCESS(status)) + goto fail1; + + Index = ARRAYSIZE(PdoRevision) - 1; + Revision = &PdoRevision[Index]; + + status = RtlStringCbPrintfA(HardwareKeyName, + MAXNAMELEN, + "VEN_%s&DEV_NET&REV_%08X\\%s", + __PdoGetVendorName(Pdo), + Revision->Number, + __PdoGetName(Pdo)); + ASSERT(NT_SUCCESS(status)); + + status = RegistryOpenSubKey(EnumKey, + HardwareKeyName, + KEY_READ, + &HardwareKey); + if (!NT_SUCCESS(status)) + goto fail2; + + status = RegistryQuerySzValue(HardwareKey, + "Driver", + NULL, + &Ansi); + if (NT_SUCCESS(status)) { + Info("Driver = %Z\n", &Ansi[0]); + RegistryFreeSzValue(Ansi); + + Pdo->HasDriver = TRUE; + } else if (status != STATUS_OBJECT_NAME_NOT_FOUND) { + goto fail3; + } + + RegistryCloseKey(HardwareKey); + + RegistryCloseKey(EnumKey); + + return 0; + +fail3: + Error("fail3\n"); + + RegistryCloseKey(HardwareKey); + +fail2: + Error("fail2\n"); + + RegistryCloseKey(EnumKey); + +fail1: + Error("fail1 (%08x)\n", status); + + return status; +} + +static FORCEINLINE NTSTATUS +__PdoCheckForAlias( + IN PXENVIF_PDO Pdo + ) +{ + NTSTATUS (*__GetIfTable2)(PMIB_IF_TABLE2 *); + VOID (*__FreeMibTable)(PVOID); + PMIB_IF_TABLE2 Table; + ULONG Index; + NTSTATUS status; + + status = LinkGetRoutineAddress("netio.sys", + "GetIfTable2", + (PVOID *)&__GetIfTable2); + if (!NT_SUCCESS(status)) + goto fail1; + + status = LinkGetRoutineAddress("netio.sys", + "FreeMibTable", + (PVOID *)&__FreeMibTable); + if (!NT_SUCCESS(status)) + goto fail2; + + status = __GetIfTable2(&Table); + if (!NT_SUCCESS(status)) + goto fail3; + + // + // Look for a network interface with the same permanent address + // that is already up. If there is one then it must be an + // aliasing emulated device, so save its settings. + // + for (Index = 0; Index < Table->NumEntries; Index++) { + PMIB_IF_ROW2 Row = &Table->Table[Index]; + + Trace("%s: checking %ws (%ws)\n", + __PdoGetName(Pdo), + Row->Alias, + Row->Description); + + if (!Row->InterfaceAndOperStatusFlags.ConnectorPresent) + continue; + + if (Row->PhysicalAddressLength != sizeof (ETHERNET_ADDRESS)) + continue; + + if (memcmp(Row->PermanentPhysicalAddress, + __PdoGetPermanentAddress(Pdo), + sizeof (ETHERNET_ADDRESS)) != 0) + continue; + + if (Row->OperStatus != IfOperStatusUp) + continue; + + Pdo->HasAlias = TRUE; + break; + } + + __FreeMibTable(Table); + + return 0; + +fail3: + Error("fail3\n"); + +fail2: + Error("fail2\n"); + +fail1: + Error("fail1 (%08x)\n", status); + + return status; +} + NTSTATUS PdoCreate( IN PXENVIF_FDO Fdo, @@ -2709,6 +2782,21 @@ PdoCreate( if (__PdoIsEjectRequested(Pdo)) goto fail11; + status = __PdoCheckForAlias(Pdo); + if (!NT_SUCCESS(status)) + goto fail12; + + status = __PdoCheckForDriver(Pdo); + if (!NT_SUCCESS(status)) + goto fail13; + + if (Pdo->HasDriver) { + PdoUnplugRequest(Pdo, TRUE); + + if (Pdo->HasAlias) + DriverRequestReboot(); + } + Info("%p (%s)\n", PhysicalDeviceObject, __PdoGetName(Pdo)); @@ -2718,6 +2806,14 @@ PdoCreate( PhysicalDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; return STATUS_SUCCESS; +fail13: + Error("fail13\n"); + + Pdo->HasAlias = FALSE; + +fail12: + Error("fail12\n"); + fail11: Error("fail11\n"); @@ -2806,7 +2902,9 @@ PdoDestroy( ASSERT3U(__PdoGetDevicePnpState(Pdo), ==, Deleted); - Pdo->UnplugRequested = FALSE; + PdoUnplugRequest(Pdo, FALSE); + + Pdo->HasDriver = FALSE; Pdo->HasAlias = FALSE; ASSERT(__PdoIsMissing(Pdo)); -- 2.1.1 _______________________________________________ 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 |