[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [win-pv-devel] [PATCH 4/4] Re-work frontend xenbus state handling code
Any time the xenbus state transitions through XenbusStateClosed (6) then it's possible for the toolstack to tear down the vif, regardless of whether the state transition was initialiated by the backend going offline or the frontend being disabled at the same time the backend happens to go offline. It's important, therefore, that the frontend code allows for this and always requests PDO ejection if the backend does go away (even if a new immediately appears). Signed-off-by: Paul Durrant <paul.durrant@xxxxxxxxxx> --- src/xenvif/fdo.c | 39 +-- src/xenvif/frontend.c | 809 ++++++++++++++++++++++++-------------------------- src/xenvif/frontend.h | 2 +- src/xenvif/pdo.c | 160 +++++----- src/xenvif/pdo.h | 10 +- 5 files changed, 492 insertions(+), 528 deletions(-) diff --git a/src/xenvif/fdo.c b/src/xenvif/fdo.c index 3f6713b..b903b09 100644 --- a/src/xenvif/fdo.c +++ b/src/xenvif/fdo.c @@ -766,20 +766,22 @@ __FdoEnumerate( } } - if (Missing && - !PdoIsMissing(Pdo) && - !PdoIsEjectRequested(Pdo) && - PdoGetDevicePnpState(Pdo) != Deleted) { - PdoSetMissing(Pdo, "device disappeared"); - - // If the PDO has not yet been enumerated then we can go ahead - // and mark it as deleted, otherwise we need to notify PnP manager and - // wait for the REMOVE_DEVICE IRP. - if (PdoGetDevicePnpState(Pdo) == Present) { - PdoSetDevicePnpState(Pdo, Deleted); - PdoDestroy(Pdo); - } else { - NeedInvalidate = TRUE; + if (!PdoIsMissing(Pdo) && PdoGetDevicePnpState(Pdo) != Deleted) { + if (PdoIsEjectRequested(Pdo)) { + IoRequestDeviceEject(PdoGetDeviceObject(Pdo)); + } else if (Missing) { + PdoSetMissing(Pdo, "device disappeared"); + + // If the PDO has not yet been enumerated then we can + // go ahead and mark it as deleted, otherwise we need + // to notify PnP manager and wait for the REMOVE_DEVICE + // IRP. + if (PdoGetDevicePnpState(Pdo) == Present) { + PdoSetDevicePnpState(Pdo, Deleted); + PdoDestroy(Pdo); + } else { + NeedInvalidate = TRUE; + } } } @@ -1611,6 +1613,11 @@ FdoQueryDeviceRelations( goto done; } + KeClearEvent(&Fdo->ScanEvent); + ThreadWake(Fdo->ScanThread); + + Trace("waiting for scan thread\n"); + (VOID) KeWaitForSingleObject(&Fdo->ScanEvent, Executive, KernelMode, @@ -1643,10 +1650,6 @@ FdoQueryDeviceRelations( ASSERT3U(Dx->Type, ==, PHYSICAL_DEVICE_OBJECT); - if (PdoGetDevicePnpState(Pdo) == Deleted && - !PdoIsMissing(Pdo)) - PdoSetMissing(Pdo, "surprise remove"); - if (PdoIsMissing(Pdo)) continue; diff --git a/src/xenvif/frontend.c b/src/xenvif/frontend.c index 51cf906..ce04bbf 100644 --- a/src/xenvif/frontend.c +++ b/src/xenvif/frontend.c @@ -61,9 +61,11 @@ struct _XENVIF_FRONTEND { PCHAR Path; PCHAR Prefix; XENVIF_FRONTEND_STATE State; + BOOLEAN Online; KSPIN_LOCK Lock; PXENVIF_THREAD MibThread; PXENVIF_THREAD EjectThread; + KEVENT EjectEvent; PCHAR BackendPath; USHORT BackendDomain; @@ -96,6 +98,7 @@ FrontendStateName( return #_State; switch (State) { + _STATE_NAME(UNKNOWN); _STATE_NAME(CLOSED); _STATE_NAME(PREPARED); _STATE_NAME(CONNECTED); @@ -312,6 +315,42 @@ DEFINE_FRONTEND_GET_FUNCTION(Mac, PXENVIF_MAC) DEFINE_FRONTEND_GET_FUNCTION(Transmitter, PXENVIF_TRANSMITTER) DEFINE_FRONTEND_GET_FUNCTION(Receiver, PXENVIF_RECEIVER) +static BOOLEAN +FrontendIsOnline( + IN PXENVIF_FRONTEND Frontend + ) +{ + return Frontend->Online; +} + +static BOOLEAN +FrontendIsBackendOnline( + IN PXENVIF_FRONTEND Frontend + ) +{ + PCHAR Buffer; + BOOLEAN Online; + NTSTATUS status; + + status = XENBUS_STORE(Read, + &Frontend->StoreInterface, + NULL, + __FrontendGetBackendPath(Frontend), + "online", + &Buffer); + if (!NT_SUCCESS(status)) { + Online = FALSE; + } else { + Online = (BOOLEAN)strtol(Buffer, NULL, 2); + + XENBUS_STORE(Free, + &Frontend->StoreInterface, + Buffer); + } + + return Online; +} + static DECLSPEC_NOINLINE NTSTATUS FrontendEject( IN PXENVIF_THREAD Self, @@ -326,11 +365,7 @@ FrontendEject( Event = ThreadGetEvent(Self); for (;;) { - BOOLEAN Online; - XenbusState State; - ULONG Attempt; - KIRQL Irql; - NTSTATUS status; + KIRQL Irql; KeWaitForSingleObject(Event, Executive, @@ -345,91 +380,24 @@ FrontendEject( KeAcquireSpinLock(&Frontend->Lock, &Irql); // It is not safe to use interfaces before this point - if (Frontend->State == FRONTEND_CLOSED) { - KeReleaseSpinLock(&Frontend->Lock, Irql); - continue; - } - - Online = TRUE; - State = XenbusStateUnknown; - - Attempt = 0; - for (;;) { - PXENBUS_STORE_TRANSACTION Transaction; - PCHAR Buffer; - - status = STATUS_UNSUCCESSFUL; - if (__FrontendGetBackendPath(Frontend) == NULL) - break; - - status = XENBUS_STORE(TransactionStart, - &Frontend->StoreInterface, - &Transaction); - if (!NT_SUCCESS(status)) - break; - - status = XENBUS_STORE(Read, - &Frontend->StoreInterface, - Transaction, - __FrontendGetBackendPath(Frontend), - "online", - &Buffer); - if (!NT_SUCCESS(status)) - goto abort; - - Online = (BOOLEAN)strtol(Buffer, NULL, 2); - - XENBUS_STORE(Free, - &Frontend->StoreInterface, - Buffer); - - status = XENBUS_STORE(Read, - &Frontend->StoreInterface, - Transaction, - __FrontendGetBackendPath(Frontend), - "state", - &Buffer); - if (!NT_SUCCESS(status)) - goto abort; - - State = (XenbusState)strtol(Buffer, NULL, 10); - - XENBUS_STORE(Free, - &Frontend->StoreInterface, - Buffer); - - status = XENBUS_STORE(TransactionEnd, - &Frontend->StoreInterface, - Transaction, - TRUE); - if (status != STATUS_RETRY || ++Attempt > 10) - break; - - continue; - -abort: - (VOID) XENBUS_STORE(TransactionEnd, - &Frontend->StoreInterface, - Transaction, - FALSE); - break; - } - - if (!NT_SUCCESS(status)) { - Online = TRUE; - State = XenbusStateUnknown; - } + if (Frontend->State == FRONTEND_UNKNOWN || + Frontend->State == FRONTEND_CLOSED) + goto loop; - if (!Online && State == XenbusStateClosing) { - Info("%s: requesting device eject\n", - __FrontendGetPath(Frontend)); + if (!FrontendIsOnline(Frontend)) + goto loop; - PdoRequestEject(Frontend->Pdo); - } + if (!FrontendIsBackendOnline(Frontend)) + PdoRequestEject(__FrontendGetPdo(Frontend)); +loop: KeReleaseSpinLock(&Frontend->Lock, Irql); + + KeSetEvent(&Frontend->EjectEvent, IO_NO_INCREMENT, FALSE); } + KeSetEvent(&Frontend->EjectEvent, IO_NO_INCREMENT, FALSE); + Trace("%s: <====\n", __FrontendGetPath(Frontend)); return STATUS_SUCCESS; @@ -555,7 +523,7 @@ FrontendProcessAddressTable( *AddressTable = NULL; *AddressCount = 0; - Luid = PdoGetLuid(Frontend->Pdo); + Luid = PdoGetLuid(__FrontendGetPdo(Frontend)); for (Index = 0; Index < MibTable->NumEntries; Index++) { PMIB_UNICASTIPADDRESS_ROW Row = &MibTable->Table[Index]; @@ -874,33 +842,140 @@ fail1: return status; } -static NTSTATUS -FrontendWaitForStateChange( +static VOID +FrontendSetOnline( + IN PXENVIF_FRONTEND Frontend + ) +{ + Trace("====>\n"); + + Frontend->Online = TRUE; + + Trace("<====\n"); +} + +static VOID +FrontendSetOffline( + IN PXENVIF_FRONTEND Frontend + ) +{ + Trace("====>\n"); + + Frontend->Online = FALSE; + PdoRequestEject(__FrontendGetPdo(Frontend)); + + Trace("<====\n"); +} + +static VOID +FrontendSetXenbusState( IN PXENVIF_FRONTEND Frontend, - IN PCHAR Path, - IN XenbusState *State + IN XenbusState State + ) +{ + BOOLEAN Online; + + Trace("%s: ====> %s\n", + __FrontendGetPath(Frontend), + XenbusStateName(State)); + + ASSERT(FrontendIsOnline(Frontend)); + + Online = !PdoIsEjectRequested(__FrontendGetPdo(Frontend)) && + FrontendIsBackendOnline(Frontend); + + (VOID) XENBUS_STORE(Printf, + &Frontend->StoreInterface, + NULL, + __FrontendGetPath(Frontend), + "state", + "%u", + State); + + if (State == XenbusStateClosed && !Online) + FrontendSetOffline(Frontend); + + Trace("%s: <==== %s\n", + __FrontendGetPath(Frontend), + XenbusStateName(State)); +} + +static NTSTATUS +FrontendAcquireBackend( + IN PXENVIF_FRONTEND Frontend ) { - KEVENT Event; - PXENBUS_STORE_WATCH Watch; - LARGE_INTEGER Start; - ULONGLONG TimeDelta; - LARGE_INTEGER Timeout; - XenbusState Old = *State; + PCHAR Buffer; NTSTATUS status; - Trace("%s: ====> (%s)\n", Path, XenbusStateName(*State)); + Trace("=====>\n"); + + status = XENBUS_STORE(Read, + &Frontend->StoreInterface, + NULL, + __FrontendGetPath(Frontend), + "backend", + &Buffer); + if (!NT_SUCCESS(status)) + goto fail1; + + Frontend->BackendPath = Buffer; + + status = XENBUS_STORE(Read, + &Frontend->StoreInterface, + NULL, + __FrontendGetPath(Frontend), + "backend-id", + &Buffer); + if (!NT_SUCCESS(status)) { + Frontend->BackendDomain = 0; + } else { + Frontend->BackendDomain = (USHORT)strtol(Buffer, NULL, 10); + + XENBUS_STORE(Free, + &Frontend->StoreInterface, + Buffer); + } + + return STATUS_SUCCESS; + +fail1: + Error("fail1 (%08x)\n", status); + + Trace("<====\n"); + return status; +} + +static VOID +FrontendWaitForBackendXenbusStateChange( + IN PXENVIF_FRONTEND Frontend, + IN OUT XenbusState *State + ) +{ + KEVENT Event; + PXENBUS_STORE_WATCH Watch; + LARGE_INTEGER Start; + ULONGLONG TimeDelta; + LARGE_INTEGER Timeout; + XenbusState Old = *State; + NTSTATUS status; + + Trace("%s: ====> %s\n", + __FrontendGetBackendPath(Frontend), + XenbusStateName(*State)); + + ASSERT(FrontendIsOnline(Frontend)); KeInitializeEvent(&Event, NotificationEvent, FALSE); status = XENBUS_STORE(WatchAdd, &Frontend->StoreInterface, - Path, + __FrontendGetBackendPath(Frontend), "state", &Event, &Watch); if (!NT_SUCCESS(status)) - goto fail1; + Watch = NULL; KeQuerySystemTime(&Start); TimeDelta = 0; @@ -908,40 +983,39 @@ FrontendWaitForStateChange( Timeout.QuadPart = 0; while (*State == Old && TimeDelta < 120000) { - ULONG Attempt; PCHAR Buffer; LARGE_INTEGER Now; - Attempt = 0; - while (++Attempt < 1000) { - status = KeWaitForSingleObject(&Event, - Executive, - KernelMode, - FALSE, - &Timeout); - if (status != STATUS_TIMEOUT) - break; + if (Watch != NULL) { + ULONG Attempt = 0; - // We are waiting for a watch event at DISPATCH_LEVEL so - // it is our responsibility to poll the store ring. - XENBUS_STORE(Poll, - &Frontend->StoreInterface); + while (++Attempt < 1000) { + status = KeWaitForSingleObject(&Event, + Executive, + KernelMode, + FALSE, + &Timeout); + if (status != STATUS_TIMEOUT) + break; - KeStallExecutionProcessor(1000); // 1ms - } + // We are waiting for a watch event at DISPATCH_LEVEL so + // it is our responsibility to poll the store ring. + XENBUS_STORE(Poll, + &Frontend->StoreInterface); + + KeStallExecutionProcessor(1000); // 1ms + } - KeClearEvent(&Event); + KeClearEvent(&Event); + } status = XENBUS_STORE(Read, &Frontend->StoreInterface, NULL, - Path, + __FrontendGetBackendPath(Frontend), "state", &Buffer); if (!NT_SUCCESS(status)) { - if (status != STATUS_OBJECT_NAME_NOT_FOUND) - goto fail2; - *State = XenbusStateUnknown; } else { *State = (XenbusState)strtol(Buffer, NULL, 10); @@ -956,45 +1030,44 @@ FrontendWaitForStateChange( TimeDelta = (Now.QuadPart - Start.QuadPart) / 10000ull; } - status = STATUS_UNSUCCESSFUL; - if (*State == Old) - goto fail3; - - (VOID) XENBUS_STORE(WatchRemove, - &Frontend->StoreInterface, - Watch); + if (Watch != NULL) + (VOID) XENBUS_STORE(WatchRemove, + &Frontend->StoreInterface, + Watch); - Trace("%s: <==== (%s)\n", Path, XenbusStateName(*State)); + Trace("%s: <==== (%s)\n", + __FrontendGetBackendPath(Frontend), + XenbusStateName(*State)); +} - return STATUS_SUCCESS; +static VOID +FrontendReleaseBackend( + IN PXENVIF_FRONTEND Frontend + ) +{ + Trace("=====>\n"); -fail3: - Error("fail3\n"); + ASSERT(Frontend->BackendDomain != DOMID_INVALID); + ASSERT(Frontend->BackendPath != NULL); -fail2: - Error("fail2\n"); + Frontend->BackendDomain = DOMID_INVALID; - (VOID) XENBUS_STORE(WatchRemove, - &Frontend->StoreInterface, - Watch); + XENBUS_STORE(Free, + &Frontend->StoreInterface, + Frontend->BackendPath); + Frontend->BackendPath = NULL; -fail1: - Error("fail1 (%08x)\n", status); - - return status; + Trace("<=====\n"); } -static NTSTATUS +static VOID FrontendClose( - IN PXENVIF_FRONTEND Frontend, - IN BOOLEAN Force + IN PXENVIF_FRONTEND Frontend ) { - PCHAR Path; XenbusState State; - NTSTATUS status; - Trace("====>\n"); + Trace("====> %s\n"); ASSERT(Frontend->Watch != NULL); (VOID) XENBUS_STORE(WatchRemove, @@ -1002,87 +1075,44 @@ FrontendClose( Frontend->Watch); Frontend->Watch = NULL; - // Release cached information about the backend - ASSERT(Frontend->BackendPath != NULL); - XENBUS_STORE(Free, - &Frontend->StoreInterface, - Frontend->BackendPath); - Frontend->BackendPath = NULL; + State = XenbusStateUnknown; + while (State != XenbusStateClosed) { + if (!FrontendIsOnline(Frontend)) + break; - Frontend->BackendDomain = DOMID_INVALID; + FrontendWaitForBackendXenbusStateChange(Frontend, + &State); - if (Force) - goto done; + switch (State) { + case XenbusStateUnknown: + FrontendSetOffline(Frontend); + break; - status = XENBUS_STORE(Read, - &Frontend->StoreInterface, - NULL, - __FrontendGetPath(Frontend), - "backend", - &Path); - if (!NT_SUCCESS(status)) - goto fail1; + case XenbusStateConnected: + case XenbusStateInitWait: + FrontendSetXenbusState(Frontend, + XenbusStateClosing); + break; - State = XenbusStateInitialising; - status = FrontendWaitForStateChange(Frontend, Path, &State); - if (!NT_SUCCESS(status)) - goto fail2; + case XenbusStateClosing: + FrontendSetXenbusState(Frontend, + XenbusStateClosed); + break; - while (State != XenbusStateClosing && - State != XenbusStateClosed && - State != XenbusStateUnknown) { - (VOID) XENBUS_STORE(Printf, - &Frontend->StoreInterface, - NULL, - __FrontendGetPath(Frontend), - "state", - "%u", - XenbusStateClosing); - status = FrontendWaitForStateChange(Frontend, Path, &State); - if (!NT_SUCCESS(status)) - goto fail2; - } + case XenbusStateClosed: + break; - while (State != XenbusStateClosed && - State != XenbusStateUnknown) { - (VOID) XENBUS_STORE(Printf, - &Frontend->StoreInterface, - NULL, - __FrontendGetPath(Frontend), - "state", - "%u", - XenbusStateClosed); - status = FrontendWaitForStateChange(Frontend, Path, &State); - if (!NT_SUCCESS(status)) - goto fail3; + default: + ASSERT(FALSE); + break; + } } - XENBUS_STORE(Free, - &Frontend->StoreInterface, - Path); + FrontendReleaseBackend(Frontend); -done: XENBUS_STORE(Release, &Frontend->StoreInterface); Trace("<====\n"); - return STATUS_SUCCESS; - -fail3: - Error("fail3\n"); - -fail2: - Error("fail2\n"); - - XENBUS_STORE(Free, - &Frontend->StoreInterface, - Path); - -fail1: - Error("fail1 (%08x)\n", status); - - XENBUS_STORE(Release, &Frontend->StoreInterface); - - return status; } static NTSTATUS @@ -1090,9 +1120,7 @@ FrontendPrepare( IN PXENVIF_FRONTEND Frontend ) { - PCHAR Path; XenbusState State; - PCHAR Buffer; NTSTATUS status; Trace("====>\n"); @@ -1101,97 +1129,48 @@ FrontendPrepare( if (!NT_SUCCESS(status)) goto fail1; - status = XENBUS_STORE(Read, - &Frontend->StoreInterface, - NULL, - __FrontendGetPath(Frontend), - "backend", - &Path); + FrontendSetOnline(Frontend); + + status = FrontendAcquireBackend(Frontend); if (!NT_SUCCESS(status)) goto fail2; State = XenbusStateUnknown; - status = FrontendWaitForStateChange(Frontend, Path, &State); - if (!NT_SUCCESS(status)) - goto fail3; + while (State != XenbusStateInitWait) { + if (!FrontendIsOnline(Frontend)) + break; - while (State == XenbusStateConnected) { - (VOID) XENBUS_STORE(Printf, - &Frontend->StoreInterface, - NULL, - __FrontendGetPath(Frontend), - "state", - "%u", - XenbusStateClosing); - status = FrontendWaitForStateChange(Frontend, Path, &State); - if (!NT_SUCCESS(status)) - goto fail4; - } + FrontendWaitForBackendXenbusStateChange(Frontend, + &State); - while (State == XenbusStateClosing) { - (VOID) XENBUS_STORE(Printf, - &Frontend->StoreInterface, - NULL, - __FrontendGetPath(Frontend), - "state", - "%u", - XenbusStateClosed); - status = FrontendWaitForStateChange(Frontend, Path, &State); - if (!NT_SUCCESS(status)) - goto fail5; - } + status = STATUS_SUCCESS; + switch (State) { + case XenbusStateUnknown: + FrontendSetOffline(Frontend); + break; - while (State != XenbusStateClosed && - State != XenbusStateInitialising && - State != XenbusStateInitWait && - State != XenbusStateUnknown) { - status = FrontendWaitForStateChange(Frontend, Path, &State); - if (!NT_SUCCESS(status)) - goto fail6; - } + case XenbusStateClosed: + FrontendSetXenbusState(Frontend, + XenbusStateInitialising); + break; - status = STATUS_UNSUCCESSFUL; - if (State == XenbusStateUnknown) - goto fail7; + case XenbusStateClosing: + FrontendSetXenbusState(Frontend, + XenbusStateClosed); + break; - status = XENBUS_STORE(Printf, - &Frontend->StoreInterface, - NULL, - __FrontendGetPath(Frontend), - "state", - "%u", - XenbusStateInitialising); - if (!NT_SUCCESS(status)) - goto fail8; + case XenbusStateInitWait: + break; - while (State == XenbusStateClosed || - State == XenbusStateInitialising) { - status = FrontendWaitForStateChange(Frontend, Path, &State); - if (!NT_SUCCESS(status)) - goto fail9; + default: + ASSERT(FALSE); + break; + } } status = STATUS_UNSUCCESSFUL; if (State != XenbusStateInitWait) - goto fail10; - - Frontend->BackendPath = Path; - - status = XENBUS_STORE(Read, - &Frontend->StoreInterface, - NULL, - __FrontendGetPath(Frontend), - "backend-id", - &Buffer); - if (!NT_SUCCESS(status)) { - Frontend->BackendDomain = 0; - } else { - Frontend->BackendDomain = (USHORT)strtol(Buffer, NULL, 10); - - XENBUS_STORE(Free, - &Frontend->StoreInterface, - Buffer); - } + goto fail3; status = XENBUS_STORE(WatchAdd, &Frontend->StoreInterface, @@ -1200,47 +1179,24 @@ FrontendPrepare( ThreadGetEvent(Frontend->EjectThread), &Frontend->Watch); if (!NT_SUCCESS(status)) - goto fail11; + goto fail4; Trace("<====\n"); return STATUS_SUCCESS; -fail11: - Error("fail11\n"); - - Frontend->BackendDomain = DOMID_INVALID; - Frontend->BackendPath = NULL; - -fail10: - Error("fail10\n"); - -fail9: - Error("fail9\n"); - -fail8: - Error("fail8\n"); - -fail7: - Error("fail7\n"); - -fail6: - Error("fail6\n"); - -fail5: - Error("fail5\n"); - fail4: Error("fail4\n"); fail3: Error("fail3\n"); - XENBUS_STORE(Free, - &Frontend->StoreInterface, - Path); + FrontendReleaseBackend(Frontend); + fail2: Error("fail2\n"); + FrontendSetOffline(Frontend); + XENBUS_STORE(Release, &Frontend->StoreInterface); fail1: @@ -1423,7 +1379,6 @@ FrontendConnect( IN PXENVIF_FRONTEND Frontend ) { - PCHAR Path = __FrontendGetBackendPath(Frontend); XenbusState State; ULONG Attempt; NTSTATUS status; @@ -1514,36 +1469,49 @@ abort: if (!NT_SUCCESS(status)) goto fail7; - status = XENBUS_STORE(Printf, - &Frontend->StoreInterface, - NULL, - __FrontendGetPath(Frontend), - "state", - "%u", - XenbusStateConnected); - if (!NT_SUCCESS(status)) - goto fail8; + State = XenbusStateUnknown; + while (State != XenbusStateConnected) { + if (!FrontendIsOnline(Frontend)) + break; - State = XenbusStateInitWait; - status = FrontendWaitForStateChange(Frontend, Path, &State); - if (!NT_SUCCESS(status)) - goto fail9; + FrontendWaitForBackendXenbusStateChange(Frontend, + &State); + + status = STATUS_SUCCESS; + switch (State) { + case XenbusStateUnknown: + FrontendSetOffline(Frontend); + break; + + case XenbusStateInitWait: + case XenbusStateInitialised: + FrontendSetXenbusState(Frontend, + XenbusStateConnected); + break; + + case XenbusStateClosing: + FrontendSetXenbusState(Frontend, + XenbusStateClosed); + break; + + case XenbusStateConnected: + break; + + default: + ASSERT(FALSE); + break; + } + } status = STATUS_UNSUCCESSFUL; if (State != XenbusStateConnected) - goto fail10; + goto fail8; ThreadWake(Frontend->MibThread); Trace("<====\n"); return STATUS_SUCCESS; -fail10: - Error("fail10\n"); - -fail9: - Error("fail9\n"); - fail8: Error("fail8\n"); @@ -1693,6 +1661,26 @@ FrontendSetState( NTSTATUS status; switch (Frontend->State) { + case FRONTEND_UNKNOWN: + switch (State) { + case FRONTEND_CLOSED: + case FRONTEND_PREPARED: + case FRONTEND_CONNECTED: + case FRONTEND_ENABLED: + status = FrontendPrepare(Frontend); + if (NT_SUCCESS(status)) { + Frontend->State = FRONTEND_PREPARED; + } else { + Failed = TRUE; + } + break; + + default: + ASSERT(FALSE); + break; + } + break; + case FRONTEND_CLOSED: switch (State) { case FRONTEND_PREPARED: @@ -1706,6 +1694,10 @@ FrontendSetState( } break; + case FRONTEND_UNKNOWN: + Frontend->State = FRONTEND_UNKNOWN; + break; + default: ASSERT(FALSE); break; @@ -1720,25 +1712,17 @@ FrontendSetState( if (NT_SUCCESS(status)) { Frontend->State = FRONTEND_CONNECTED; } else { - status = FrontendClose(Frontend, FALSE); - if (NT_SUCCESS(status)) - Frontend->State = FRONTEND_CLOSED; - else - Frontend->State = FRONTEND_STATE_INVALID; + FrontendClose(Frontend); + Frontend->State = FRONTEND_CLOSED; Failed = TRUE; } break; case FRONTEND_CLOSED: - status = FrontendClose(Frontend, FALSE); - if (NT_SUCCESS(status)) { - Frontend->State = FRONTEND_CLOSED; - } else { - Frontend->State = FRONTEND_STATE_INVALID; - Failed = TRUE; - } - + case FRONTEND_UNKNOWN: + FrontendClose(Frontend); + Frontend->State = FRONTEND_CLOSED; break; default: @@ -1754,11 +1738,8 @@ FrontendSetState( if (NT_SUCCESS(status)) { Frontend->State = FRONTEND_ENABLED; } else { - status = FrontendClose(Frontend, FALSE); - if (NT_SUCCESS(status)) - Frontend->State = FRONTEND_CLOSED; - else - Frontend->State = FRONTEND_STATE_INVALID; + FrontendClose(Frontend); + Frontend->State = FRONTEND_CLOSED; FrontendDisconnect(Frontend); Failed = TRUE; @@ -1767,16 +1748,11 @@ FrontendSetState( case FRONTEND_PREPARED: case FRONTEND_CLOSED: - status = FrontendClose(Frontend, FALSE); - if (NT_SUCCESS(status)) { - Frontend->State = FRONTEND_CLOSED; - } else { - Frontend->State = FRONTEND_STATE_INVALID; - Failed = TRUE; - } + case FRONTEND_UNKNOWN: + FrontendClose(Frontend); + Frontend->State = FRONTEND_CLOSED; FrontendDisconnect(Frontend); - break; default: @@ -1790,6 +1766,7 @@ FrontendSetState( case FRONTEND_CONNECTED: case FRONTEND_PREPARED: case FRONTEND_CLOSED: + case FRONTEND_UNKNOWN: FrontendDisable(Frontend); Frontend->State = FRONTEND_CONNECTED; break; @@ -1800,10 +1777,6 @@ FrontendSetState( } break; - case FRONTEND_STATE_INVALID: - Failed = TRUE; - break; - default: ASSERT(FALSE); break; @@ -1821,34 +1794,15 @@ FrontendSetState( return (!Failed) ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL; } -static FORCEINLINE NTSTATUS +static FORCEINLINE VOID __FrontendResume( IN PXENVIF_FRONTEND Frontend ) { - NTSTATUS status; - ASSERT3U(KeGetCurrentIrql(), ==, DISPATCH_LEVEL); - status = FrontendSetState(Frontend, FRONTEND_PREPARED); - if (!NT_SUCCESS(status)) - goto fail1; - - status = FrontendSetState(Frontend, FRONTEND_CLOSED); - if (!NT_SUCCESS(status)) - goto fail2; - - return STATUS_SUCCESS; - -fail2: - Error("fail2\n"); - - Frontend->State = FRONTEND_CLOSED; - -fail1: - Error("fail1 (%08x)\n", status); - - return status; + ASSERT3U(Frontend->State, ==, FRONTEND_UNKNOWN); + (VOID) FrontendSetState(Frontend, FRONTEND_CLOSED); } static FORCEINLINE VOID @@ -1856,9 +1810,9 @@ __FrontendSuspend( IN PXENVIF_FRONTEND Frontend ) { - UNREFERENCED_PARAMETER(Frontend); - ASSERT3U(KeGetCurrentIrql(), ==, DISPATCH_LEVEL); + + (VOID) FrontendSetState(Frontend, FRONTEND_UNKNOWN); } static DECLSPEC_NOINLINE VOID @@ -1867,12 +1821,9 @@ FrontendSuspendCallbackLate( ) { PXENVIF_FRONTEND Frontend = Argument; - NTSTATUS status; __FrontendSuspend(Frontend); - - status = __FrontendResume(Frontend); - ASSERT(NT_SUCCESS(status)); + __FrontendResume(Frontend); } NTSTATUS @@ -1891,9 +1842,7 @@ FrontendResume( if (!NT_SUCCESS(status)) goto fail1; - status = __FrontendResume(Frontend); - if (!NT_SUCCESS(status)) - goto fail2; + __FrontendResume(Frontend); status = XENBUS_SUSPEND(Register, &Frontend->SuspendInterface, @@ -1902,22 +1851,30 @@ FrontendResume( Frontend, &Frontend->SuspendCallbackLate); if (!NT_SUCCESS(status)) - goto fail3; + goto fail2; KeLowerIrql(Irql); + KeClearEvent(&Frontend->EjectEvent); + ThreadWake(Frontend->EjectThread); + + Trace("waiting for eject thread\n"); + + (VOID) KeWaitForSingleObject(&Frontend->EjectEvent, + Executive, + KernelMode, + FALSE, + NULL); + Trace("<====\n"); return STATUS_SUCCESS; -fail3: - Error("fail3\n"); - - __FrontendSuspend(Frontend); - fail2: Error("fail2\n"); + __FrontendSuspend(Frontend); + XENBUS_SUSPEND(Release, &Frontend->SuspendInterface); fail1: @@ -1950,6 +1907,17 @@ FrontendSuspend( KeLowerIrql(Irql); + KeClearEvent(&Frontend->EjectEvent); + ThreadWake(Frontend->EjectThread); + + Trace("waiting for eject thread\n"); + + (VOID) KeWaitForSingleObject(&Frontend->EjectEvent, + Executive, + KernelMode, + FALSE, + NULL); + Trace("<====\n"); } @@ -2012,7 +1980,7 @@ FrontendInitialize( KeInitializeSpinLock(&(*Frontend)->Lock); - (*Frontend)->State = FRONTEND_CLOSED; + (*Frontend)->Online = TRUE; FdoGetDebugInterface(PdoGetFdo(Pdo), &(*Frontend)->DebugInterface); FdoGetSuspendInterface(PdoGetFdo(Pdo), &(*Frontend)->SuspendInterface); @@ -2032,6 +2000,8 @@ FrontendInitialize( if (!NT_SUCCESS(status)) goto fail8; + KeInitializeEvent(&(*Frontend)->EjectEvent, NotificationEvent, FALSE); + status = ThreadCreate(FrontendEject, *Frontend, &(*Frontend)->EjectThread); if (!NT_SUCCESS(status)) goto fail9; @@ -2054,6 +2024,8 @@ fail10: fail9: Error("fail9\n"); + RtlZeroMemory(&(*Frontend)->EjectEvent, sizeof (KEVENT)); + TransmitterTeardown(__FrontendGetTransmitter(*Frontend)); (*Frontend)->Transmitter = NULL; @@ -2083,7 +2055,7 @@ fail6: RtlZeroMemory(&(*Frontend)->DebugInterface, sizeof (XENBUS_DEBUG_INTERFACE)); - (*Frontend)->State = FRONTEND_STATE_INVALID; + (*Frontend)->Online = FALSE; RtlZeroMemory(&(*Frontend)->Lock, sizeof (KSPIN_LOCK)); @@ -2128,16 +2100,7 @@ FrontendTeardown( ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL); - ASSERT(Frontend->State != FRONTEND_ENABLED); - ASSERT(Frontend->State != FRONTEND_CONNECTED); - - if (Frontend->State == FRONTEND_PREPARED) { - (VOID) FrontendClose(Frontend, TRUE); - Frontend->State = FRONTEND_CLOSED; - } - - ASSERT(Frontend->State == FRONTEND_CLOSED || - Frontend->State == FRONTEND_STATE_INVALID); + ASSERT(Frontend->State == FRONTEND_UNKNOWN); ThreadAlert(Frontend->MibThread); ThreadJoin(Frontend->MibThread); @@ -2147,6 +2110,8 @@ FrontendTeardown( ThreadJoin(Frontend->EjectThread); Frontend->EjectThread = NULL; + RtlZeroMemory(&Frontend->EjectEvent, sizeof (KEVENT)); + TransmitterTeardown(__FrontendGetTransmitter(Frontend)); Frontend->Transmitter = NULL; @@ -2167,7 +2132,7 @@ FrontendTeardown( RtlZeroMemory(&Frontend->DebugInterface, sizeof (XENBUS_DEBUG_INTERFACE)); - Frontend->State = FRONTEND_STATE_INVALID; + Frontend->Online = FALSE; RtlZeroMemory(&Frontend->Lock, sizeof (KSPIN_LOCK)); diff --git a/src/xenvif/frontend.h b/src/xenvif/frontend.h index 1673fac..374e9b4 100644 --- a/src/xenvif/frontend.h +++ b/src/xenvif/frontend.h @@ -48,7 +48,7 @@ typedef struct _XENVIF_FRONTEND XENVIF_FRONTEND, *PXENVIF_FRONTEND; typedef enum _XENVIF_FRONTEND_STATE { - FRONTEND_STATE_INVALID, + FRONTEND_UNKNOWN, FRONTEND_CLOSED, FRONTEND_PREPARED, FRONTEND_CONNECTED, diff --git a/src/xenvif/pdo.c b/src/xenvif/pdo.c index dc7eacd..5b6e085 100644 --- a/src/xenvif/pdo.c +++ b/src/xenvif/pdo.c @@ -70,8 +70,7 @@ struct _XENVIF_PDO { PXENVIF_FDO Fdo; BOOLEAN Missing; const CHAR *Reason; - BOOLEAN EjectRequested; - KSPIN_LOCK EjectLock; + LONG Eject; UNICODE_STRING ContainerID; @@ -241,55 +240,20 @@ PdoIsMissing( return __PdoIsMissing(Pdo); } -static FORCEINLINE VOID -__PdoSetEjectRequested( - IN PXENVIF_PDO Pdo - ) -{ - KIRQL Irql; - - KeAcquireSpinLock(&Pdo->EjectLock, &Irql); - Pdo->EjectRequested = TRUE; - KeReleaseSpinLock(&Pdo->EjectLock, Irql); -} - -static FORCEINLINE BOOLEAN -__PdoClearEjectRequested( - IN PXENVIF_PDO Pdo - ) -{ - KIRQL Irql; - BOOLEAN EjectRequested; - - KeAcquireSpinLock(&Pdo->EjectLock, &Irql); - EjectRequested = Pdo->EjectRequested; - Pdo->EjectRequested = FALSE; - KeReleaseSpinLock(&Pdo->EjectLock, Irql); - - return EjectRequested; -} - -static FORCEINLINE BOOLEAN -__PdoIsEjectRequested( +static FORCEINLINE PXENVIF_FDO +__PdoGetFdo( IN PXENVIF_PDO Pdo ) { - KIRQL Irql; - BOOLEAN EjectRequested; - - KeAcquireSpinLock(&Pdo->EjectLock, &Irql); - EjectRequested = Pdo->EjectRequested; - KeReleaseSpinLock(&Pdo->EjectLock, Irql); - - return EjectRequested; + return Pdo->Fdo; } -BOOLEAN -PdoIsEjectRequested( +PXENVIF_FDO +PdoGetFdo( IN PXENVIF_PDO Pdo ) { - return __PdoIsEjectRequested(Pdo); + return __PdoGetFdo(Pdo); } static FORCEINLINE VOID @@ -326,6 +290,59 @@ PdoGetName( return __PdoGetName(Pdo); } +static FORCEINLINE BOOLEAN +__PdoSetEjectRequested( + IN PXENVIF_PDO Pdo + ) +{ + return (InterlockedBitTestAndSet(&Pdo->Eject, 0) == 0) ? TRUE : FALSE; +} + +VOID +PdoRequestEject( + IN PXENVIF_PDO Pdo + ) +{ + PXENVIF_DX Dx = Pdo->Dx; + PDEVICE_OBJECT PhysicalDeviceObject = Dx->DeviceObject; + PXENVIF_FDO Fdo = __PdoGetFdo(Pdo); + + if (!__PdoSetEjectRequested(Pdo)) + return; + + Info("%p (%s)\n", + PhysicalDeviceObject, + __PdoGetName(Pdo)); + + IoInvalidateDeviceRelations(FdoGetPhysicalDeviceObject(Fdo), + BusRelations); +} + +static FORCEINLINE BOOLEAN +__PdoClearEjectRequested( + IN PXENVIF_PDO Pdo + ) +{ + return (InterlockedBitTestAndReset(&Pdo->Eject, 0) != 0) ? TRUE : FALSE; +} + +static FORCEINLINE BOOLEAN +__PdoIsEjectRequested( + IN PXENVIF_PDO Pdo + ) +{ + KeMemoryBarrier(); + return (Pdo->Eject & 1) ? TRUE : FALSE; +} + +BOOLEAN +PdoIsEjectRequested( + IN PXENVIF_PDO Pdo + ) +{ + return __PdoIsEjectRequested(Pdo); +} + // {2A597D5E-8864-4428-A110-F568F316D4E4} DEFINE_GUID(GUID_CONTAINER_ID_NAME_SPACE, 0x2a597d5e, 0x8864, 0x4428, 0xa1, 0x10, 0xf5, 0x68, 0xf3, 0x16, 0xd4, 0xe4); @@ -511,22 +528,6 @@ fail1: #define MAXTEXTLEN 1024 -static FORCEINLINE PXENVIF_FDO -__PdoGetFdo( - IN PXENVIF_PDO Pdo - ) -{ - return Pdo->Fdo; -} - -PXENVIF_FDO -PdoGetFdo( - IN PXENVIF_PDO Pdo - ) -{ - return __PdoGetFdo(Pdo); -} - static NTSTATUS PdoAddRevision( IN PXENVIF_PDO Pdo, @@ -1018,15 +1019,6 @@ PdoGetBusData( Length); } -VOID -PdoRequestEject( - IN PXENVIF_PDO Pdo - ) -{ - __PdoSetEjectRequested(Pdo); - IoRequestDeviceEject(__PdoGetDeviceObject(Pdo)); -} - static FORCEINLINE NTSTATUS __PdoD3ToD0( IN PXENVIF_PDO Pdo @@ -1474,17 +1466,17 @@ done: FdoAcquireMutex(Fdo); - if (__PdoIsMissing(Pdo) || - __PdoGetDevicePnpState(Pdo) == SurpriseRemovePending) + if (__PdoIsMissing(Pdo)) { + DEVICE_PNP_STATE State = __PdoGetDevicePnpState(Pdo); + __PdoSetDevicePnpState(Pdo, Deleted); - else - __PdoSetDevicePnpState(Pdo, Enumerated); - if (__PdoIsMissing(Pdo)) { - if (__PdoGetDevicePnpState(Pdo) == Deleted) + if (State == SurpriseRemovePending) PdoDestroy(Pdo); else NeedInvalidate = TRUE; + } else { + __PdoSetDevicePnpState(Pdo, Enumerated); } FdoReleaseMutex(Fdo); @@ -2088,17 +2080,16 @@ PdoEject( Trace("%s\n", __PdoGetName(Pdo)); - __PdoClearEjectRequested(Pdo); - FdoAcquireMutex(Fdo); __PdoSetDevicePnpState(Pdo, Deleted); __PdoSetMissing(Pdo, "device ejected"); - PdoDestroy(Pdo); - FdoReleaseMutex(Fdo); + IoInvalidateDeviceRelations(FdoGetPhysicalDeviceObject(Fdo), + BusRelations); + status = STATUS_SUCCESS; Irp->IoStatus.Status = status; @@ -2648,12 +2639,14 @@ PdoCreate( Dx->Pdo = Pdo; - KeInitializeSpinLock(&Pdo->EjectLock); - status = FdoAddPhysicalDeviceObject(Fdo, Pdo); if (!NT_SUCCESS(status)) goto fail11; + status = STATUS_UNSUCCESSFUL; + if (__PdoIsEjectRequested(Pdo)) + goto fail12; + for (Index = 0; Index < Pdo->Count; Index++) { Info("%p (%s %08X)\n", PhysicalDeviceObject, @@ -2664,11 +2657,15 @@ PdoCreate( PhysicalDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; return STATUS_SUCCESS; +fail12: + Error("fail12\n"); + + FdoRemovePhysicalDeviceObject(Fdo, Pdo); + fail11: Error("fail11\n"); (VOID) __PdoClearEjectRequested(Pdo); - RtlZeroMemory(&Pdo->EjectLock, sizeof (KSPIN_LOCK)); Dx->Pdo = NULL; @@ -2771,7 +2768,6 @@ PdoDestroy( FdoRemovePhysicalDeviceObject(Fdo, Pdo); (VOID) __PdoClearEjectRequested(Pdo); - RtlZeroMemory(&Pdo->EjectLock, sizeof (KSPIN_LOCK)); Dx->Pdo = NULL; diff --git a/src/xenvif/pdo.h b/src/xenvif/pdo.h index 13dbe81..be05125 100644 --- a/src/xenvif/pdo.h +++ b/src/xenvif/pdo.h @@ -61,6 +61,11 @@ PdoIsMissing( IN PXENVIF_PDO Pdo ); +extern VOID +PdoRequestEject( + IN PXENVIF_PDO Pdo + ); + extern BOOLEAN PdoIsEjectRequested( IN PXENVIF_PDO Pdo @@ -203,11 +208,6 @@ PdoGetVifInterface( IN PXENVIF_PDO Pdo ); -extern VOID -PdoRequestEject( - IN PXENVIF_PDO Pdo - ); - extern NTSTATUS PdoDispatch( IN PXENVIF_PDO Pdo, -- 2.1.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 |