[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


 


Rackspace

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