Esempio n. 1
0
static VOID
close_frontend(struct scsifilt *sf, SUSPEND_TOKEN token)
{
    XENBUS_STATE frontend_state;
    XENBUS_STATE backend_state;
    NTSTATUS status;

    TraceNotice(("target %d: closing frontend...\n", sf->target_id));

    // Get initial frontend state
    status = xenbus_read_state(XBT_NIL, sf->frontend_path, "state", &frontend_state);
    if (!NT_SUCCESS(status))
        frontend_state = null_XENBUS_STATE();

    // Wait for the backend to stabilise
    backend_state = null_XENBUS_STATE();
    do {
        backend_state = XenbusWaitForBackendStateChange(sf->backend_path, backend_state,
                                                        NULL, token);
    } while (same_XENBUS_STATE(backend_state, XENBUS_STATE_INITIALISING));

    TraceVerbose(("%s: target %d: backend state = %s, frontend state = %s\n",
                  __FUNCTION__, sf->target_id,
                  XenbusStateName(backend_state),
                  XenbusStateName(frontend_state)));

    frontend_state = XENBUS_STATE_CLOSING;
    while (!same_XENBUS_STATE(backend_state, XENBUS_STATE_CLOSING) &&
           !same_XENBUS_STATE(backend_state, XENBUS_STATE_CLOSED) &&
           !is_null_XENBUS_STATE(backend_state)) {
        xenbus_change_state(XBT_NIL, sf->frontend_path, "state", frontend_state);
        backend_state = XenbusWaitForBackendStateChange(sf->backend_path, backend_state,
                                                        NULL, token);
    }

    TraceVerbose(("%s: target %d: backend state = %s, frontend state = %s\n",
                  __FUNCTION__, sf->target_id,
                  XenbusStateName(backend_state),
                  XenbusStateName(frontend_state)));

    frontend_state = XENBUS_STATE_CLOSED;
    while (!same_XENBUS_STATE(backend_state, XENBUS_STATE_CLOSED) &&
           !is_null_XENBUS_STATE(backend_state)) {
        xenbus_change_state(XBT_NIL, sf->frontend_path, "state", frontend_state);
        backend_state = XenbusWaitForBackendStateChange(sf->backend_path, backend_state,
                                                        NULL, token);
    }

    TraceVerbose(("%s: target %d: backend state = %s, frontend state = %s\n",
                  __FUNCTION__, sf->target_id,
                  XenbusStateName(backend_state),
                  XenbusStateName(frontend_state)));

    TraceNotice(("target %d: backend closed\n", sf->target_id));
}
Esempio n. 2
0
VOID
XenLowerDisonnectBackend(
    PXEN_LOWER XenLower)
{
    SUSPEND_TOKEN token;
    XENBUS_STATE festate;
    XENBUS_STATE bestate;

    if (strlen(XenLower->BackendPath) == 0)
    {
        TraceError((__FUNCTION__ ": shutting down an adapter %s which wasn't properly created?\n",
            XenLower->FrontendPath));
        return;        
    }

    // Give disconnect a go even if by some chance we cannot get a token.
    token = EvtchnAllocateSuspendToken("xenvusb-disconnect");

    // Wait for the backend to stabilise before we close it
    bestate = null_XENBUS_STATE();
    do {
        bestate = XenbusWaitForBackendStateChange(XenLower->BackendPath,
            bestate, NULL, null_SUSPEND_TOKEN());
    } while (same_XENBUS_STATE(bestate, XENBUS_STATE_INITIALISING));

    // Now close the frontend
    festate = XENBUS_STATE_CLOSING;
    while (!same_XENBUS_STATE(bestate, XENBUS_STATE_CLOSING) &&
           !same_XENBUS_STATE(bestate, XENBUS_STATE_CLOSED) &&
           !is_null_XENBUS_STATE(bestate))
    {
        xenbus_change_state(XBT_NIL, XenLower->FrontendPath, "state", festate);
        bestate = XenbusWaitForBackendStateChange(XenLower->BackendPath,
            bestate, NULL, null_SUSPEND_TOKEN());
    }

    festate = XENBUS_STATE_CLOSED;
    while (!same_XENBUS_STATE(bestate, XENBUS_STATE_CLOSED) &&
           !is_null_XENBUS_STATE(bestate))
    {
        xenbus_change_state(XBT_NIL, XenLower->FrontendPath, "state", festate);
        bestate = XenbusWaitForBackendStateChange(XenLower->BackendPath,
            bestate, NULL, null_SUSPEND_TOKEN());
    }

    // Unhook this here since there will be no reconnecting at this point.
    if (XenLower->LateSuspendHandler)
    {
        EvtchnUnregisterSuspendHandler(XenLower->LateSuspendHandler);
        XenLower->LateSuspendHandler = NULL;
    }

    // Clear the XenLower->BackendPath which sort of indicates shutdown or
    // not properly initialized.

    // --XT-- keep backend path, useful on resume to check whether device was
    //        unplugged during suspend
    // memset(&XenLower->BackendPath[0], 0, XEN_LOWER_MAX_PATH);

    if (!is_null_SUSPEND_TOKEN(token))
    {
        EvtchnReleaseSuspendToken(token);
    }
}
Esempio n. 3
0
static NTSTATUS
XenLowerConnectBackendInternal(
    PXEN_LOWER XenLower,
    SUSPEND_TOKEN Token)
{
    NTSTATUS status = STATUS_SUCCESS;
    XENBUS_STATE state;
    xenbus_transaction_t xbt;
    PCHAR fepath;

    if (is_null_EVTCHN_PORT(XenLower->EvtchnPort))
    {
        TraceError((__FUNCTION__ ": no event channel port, this routine must be called after event channel initialization\n"));
        return STATUS_UNSUCCESSFUL;
    }

    //---------------------------Backend Wait Ready-------------------------------//
    //
    // Wait for backend to get ready for initialization.
    //

    status = xenbus_change_state(XBT_NIL,
        XenLower->FrontendPath,
        "state",
        XENBUS_STATE_INITIALISING);
    if (!NT_SUCCESS(status))
    {
        TraceWarning((__FUNCTION__
            ": Failed to change front end state to XENBUS_STATE_INITIALISING(%d) status: 0x%x\n",
            XENBUS_STATE_INITIALISING, status));
        // Go on, best effort, chin up
    }

    TraceInfo((__FUNCTION__
        ": Front end state set to XENBUS_STATE_INITIALISING(%d)\n",
        XENBUS_STATE_INITIALISING));

    state = null_XENBUS_STATE();
    for ( ; ; )
    {
        // Turns out suspend tokens are not even used.
        state = XenbusWaitForBackendStateChange(XenLower->BackendPath,
            state, NULL, Token);

        if (same_XENBUS_STATE(state, XENBUS_STATE_INITWAIT))
        {
            break;
        }

        if (same_XENBUS_STATE(state, XENBUS_STATE_CLOSING) ||
            is_null_XENBUS_STATE(state))
        {
            TraceError((__FUNCTION__ ": backend '%s' went away before we could connect to it?\n",
                XenLower->BackendPath));

            status = STATUS_UNSUCCESSFUL;
            break;
        }
    }

    if (status != STATUS_SUCCESS)
    {
        return status;
    }

    TraceInfo((__FUNCTION__
        ": Back end state went to XENBUS_STATE_INITWAIT(%d)\n",
        XENBUS_STATE_INITWAIT));
    
    //----------------------------Backend Connect---------------------------------//    

    //
    // Communicate configuration to backend.
    //

    fepath = XenLower->FrontendPath;
    do {
        xenbus_transaction_start(&xbt);
        xenbus_write_grant_ref(xbt, fepath, "ring-ref", XenLower->SringGrantRef);
        xenbus_write_evtchn_port(xbt, fepath, "event-channel", XenLower->EvtchnPort);
        xenbus_change_state(xbt, fepath, "state", XENBUS_STATE_CONNECTED);
        status = xenbus_transaction_end(xbt, 0);
    } while (status == STATUS_RETRY);

    if (status != STATUS_SUCCESS)
    {
        TraceError((__FUNCTION__ ": failed to configure xenstore frontend values.\n"));
        return STATUS_UNSUCCESSFUL;
    }

    TraceInfo((__FUNCTION__
        ": Front end state set to XENBUS_STATE_CONNECTED(%d)\n",
        XENBUS_STATE_CONNECTED));

    //
    // Wait for backend to accept configuration and complete initialization.
    //

    state = null_XENBUS_STATE();
    for ( ; ; )
    {
        state = XenbusWaitForBackendStateChange(XenLower->BackendPath,
            state, NULL, Token);

        if (is_null_XENBUS_STATE(state) ||
            same_XENBUS_STATE(state, XENBUS_STATE_CLOSING) ||
            same_XENBUS_STATE(state, XENBUS_STATE_CLOSED))
        {

            TraceError((__FUNCTION__ ": Failed to connected '%s' <-> '%s' backend state: %d\n",
                XenLower->FrontendPath,
                XenLower->BackendPath,
                state));

            status = STATUS_UNSUCCESSFUL;
            break;
        }

        if (same_XENBUS_STATE(state, XENBUS_STATE_CONNECTED))
        {
            TraceNotice((__FUNCTION__ ": Connected '%s' <-> '%s' \n",
                XenLower->FrontendPath,
                XenLower->BackendPath));
            TraceInfo((__FUNCTION__
                ": Back end final state went to XENBUS_STATE_CONNECTED(%d)\n",
                XENBUS_STATE_CONNECTED));
            break;
        }
    }

    return status;
}
Esempio n. 4
0
/* We've bound the scsifilt instance to a xenvbd instance, and we've
   disconnected xenvbd from the shared ring.  Connect scsifilt. */
NTSTATUS
connect_scsifilt_with_token(struct scsifilt *sf, SUSPEND_TOKEN token)
{
    XENBUS_STATE state;
    blkif_sring_t *ring_shared;
    NTSTATUS status;
    KIRQL irql;

    if (sf->backend_path != NULL) {
        TraceVerbose(("Releasing old backend path (%p)\n", sf->backend_path));

        XmFreeMemory(sf->backend_path);
        sf->backend_path = NULL;
    }

    if (sf->ring_shared != NULL) {
        TraceVerbose(("Releasing old shared ring (%p)\n", sf->ring_shared));

        XmFreeMemory(sf->ring_shared);
        sf->ring_shared = NULL;
        sf->ring.sring = NULL;
    }

    find_backend_handle(sf);

    status = STATUS_UNSUCCESSFUL;
    sf->backend_path = get_backend_path(sf, token);
    if (sf->backend_path == NULL)
        goto fail1;

    sf->target_resume(sf->target_id, token);

    if (sf->stopped) {
        sf->target_start(sf->target_id, sf->backend_path, token);
        sf->stopped = FALSE;
    }

    state = XenbusWaitForBackendStateChange(sf->backend_path,
                                            null_XENBUS_STATE(),
                                            NULL,
                                            token);
    if (!same_XENBUS_STATE(state, XENBUS_STATE_INITWAIT))
        goto fail2;

    probe_backend_capabilities(sf);

    status = STATUS_NO_MEMORY;
    ring_shared = XmAllocateZeroedMemory(PAGE_SIZE << sf->ring_order);
    if (ring_shared == NULL)
        goto fail3;

    KeAcquireSpinLock(&sf->ring_lock, &irql);
    sf->ring_shared = ring_shared;
    SHARED_RING_INIT(sf->ring_shared);
    FRONT_RING_INIT(&sf->ring, sf->ring_shared, PAGE_SIZE << sf->ring_order);
    KeReleaseSpinLock(&sf->ring_lock, irql);

    grant_ring(sf);

    status = open_evtchn(sf);
    if (!NT_SUCCESS(status))
        goto fail4;

    do {
        xenbus_transaction_t xbt;

        xenbus_transaction_start(&xbt);

        xenbus_write_evtchn_port(xbt,
                                 sf->frontend_path,
                                 "event-channel",
                                 sf->evtchn_port);

        if (sf->single_page) {
            XM_ASSERT3U(sf->ring_order, ==, 0);

            TraceNotice(("%s: using single page handshake\n", sf->frontend_path));

            /* single page handshake */
            xenbus_write_grant_ref(xbt,
                                   sf->frontend_path,
                                   "ring-ref",
                                   sf->ring_gref[0]);
        } else {
            int i;

            TraceNotice(("%s: using multi-page handshake\n", sf->frontend_path));

            xenbus_printf(xbt, sf->frontend_path, "ring-page-order", "%u",
                          sf->ring_order);

            for (i = 0; i < (1 << sf->ring_order); i++) {
                char buffer[10];

                Xmsnprintf(buffer, sizeof(buffer), "ring-ref%1u", i);
                xenbus_write_grant_ref(xbt, sf->frontend_path, buffer,
                                       sf->ring_gref[i]);
            }
        }

        xenbus_printf(xbt, sf->frontend_path, "protocol", "x86_32-abi");
        xenbus_write_feature_flag(xbt, sf->frontend_path, "feature-surprise-remove",
                                  TRUE);
        xenbus_write_feature_flag(xbt, sf->frontend_path, "feature-online-resize",
                                  TRUE);
        xenbus_change_state(xbt, sf->frontend_path, "state",
                            XENBUS_STATE_INITIALISED);

        status = xenbus_transaction_end(xbt, 0);
    } while (status == STATUS_RETRY);
Esempio n. 5
0
/* Returns STATUS_SUCCESS on success, STATUS_OBJECT_NAME_NOT_FOUND if
   we race, or some other STATUS_ on error. */
static NTSTATUS
set_fe_state_careful(struct scsifilt *sf, XENBUS_STATE state)
{
    return xenbus_change_state(XBT_NIL, sf->frontend_path, "state", state);
}
Esempio n. 6
0
static NTSTATUS
V4vAddDevice(PDRIVER_OBJECT driverObject, PDEVICE_OBJECT pdo)
{
    NTSTATUS          status = STATUS_SUCCESS;
    UNICODE_STRING    deviceName;
    PDEVICE_OBJECT    fdo = NULL;
    PXENV4V_EXTENSION pde = NULL;
    LONG              val;
    BOOLEAN           symlink = FALSE;
    LARGE_INTEGER     seed;
    WCHAR            *szSddl = NULL;
    UNICODE_STRING    sddlString;
    CHAR             *szFpath = NULL;

    TraceVerbose(("====> '%s'.\n", __FUNCTION__));

    // We only allow one instance of this device type. If more than on pdo is created we need
    val = InterlockedCompareExchange(&g_deviceCreated, 1, 0);
    if (val != 0) {
        TraceWarning(("cannot instantiate more that one v4v device node.\n"));
        return STATUS_UNSUCCESSFUL;
    }

    do {
        // Create our device
        RtlInitUnicodeString(&deviceName, V4V_DEVICE_NAME);
        szSddl = g_win5Sddl;
        RtlInitUnicodeString(&sddlString, szSddl);

        status = 
            IoCreateDeviceSecure(driverObject,
                                 sizeof(XENV4V_EXTENSION),
                                 &deviceName,
                                 FILE_DEVICE_UNKNOWN,
                                 FILE_DEVICE_SECURE_OPEN,
                                 FALSE,
                                 &sddlString,
                                 (LPCGUID)&GUID_SD_XENV4V_CONTROL_OBJECT,
                                 &fdo);
        if (!NT_SUCCESS(status)) {
            TraceError(("failed to create device object - error: 0x%x\n", status));
            fdo = NULL;
            break;
        }

        pde = (PXENV4V_EXTENSION)fdo->DeviceExtension;
        RtlZeroMemory(pde, sizeof(XENV4V_EXTENSION));
        RtlStringCchCopyW(pde->symbolicLinkText, XENV4V_SYM_NAME_LEN, V4V_SYMBOLIC_NAME);
        RtlInitUnicodeString(&pde->symbolicLink, pde->symbolicLinkText);

        // Create our symbolic link
        status = IoCreateSymbolicLink(&pde->symbolicLink, &deviceName);
        if (!NT_SUCCESS(status)) {
            TraceError(("failed to create symbolic - error: 0x%x\n", status));
            break;
        }
        symlink = TRUE;       

        // Get our xenstore path
        szFpath = xenbus_find_frontend(pdo);
        if (szFpath == NULL) {
            status = STATUS_NO_SUCH_DEVICE;
            TraceError(("failed to locate XenStore front end path\n"));
            break;
        }

        // Setup the extension
        pde->magic = XENV4V_MAGIC;
        pde->pdo = pdo;
        pde->fdo = fdo;
        IoInitializeRemoveLock(&pde->removeLock, 'v4vx', 0, 0);
        pde->frontendPath = szFpath;
        szFpath = NULL;
        pde->state = XENV4V_DEV_STOPPED; // wait for start
        pde->lastPoState = PowerSystemWorking;
        pde->virqPort = null_EVTCHN_PORT();
        KeInitializeDpc(&pde->virqDpc, V4vVirqNotifyDpc, fdo);
        KeInitializeSpinLock(&pde->virqLock);
        KeInitializeSpinLock(&pde->dpcLock);
        KeInitializeTimerEx(&pde->timer, NotificationTimer);
        KeInitializeDpc(&pde->timerDpc,
                        V4vConnectTimerDpc,
                        fdo);
        KeInitializeSpinLock(&pde->timerLock);
        pde->timerCounter = 0;
        InitializeListHead(&pde->contextList);
        KeInitializeSpinLock(&pde->contextLock);
        pde->contextCount = 0;
        InitializeListHead(&pde->ringList);
        KeInitializeSpinLock(&pde->ringLock);
        InitializeListHead(&pde->pendingIrpQueue);
        pde->pendingIrpCount = 0;
        KeInitializeSpinLock(&pde->queueLock);
        IoCsqInitializeEx(&pde->csqObject,
                          V4vCsqInsertIrpEx,
                          V4vCsqRemoveIrp,
                          V4vCsqPeekNextIrp,
                          V4vCsqAcquireLock,
                          V4vCsqReleaseLock,
                          V4vCsqCompleteCanceledIrp);
        InitializeListHead(&pde->destList);
        pde->destCount = 0;
        ExInitializeNPagedLookasideList(&pde->destLookasideList,
                                        NULL,
                                        NULL,
                                        0,
                                        sizeof(XENV4V_DESTINATION),
                                        XENV4V_TAG,
                                        0);
        KeQueryTickCount(&seed);
        pde->seed = seed.u.LowPart;

        // Now attach us to the stack
        pde->ldo = IoAttachDeviceToDeviceStack(fdo, pdo);
        if (pde->ldo == NULL) {
            TraceError(("failed to attach device to stack - error: 0x%x\n", status));
            status = STATUS_NO_SUCH_DEVICE;
            break;
        }

        // Use direct IO and let the IO manager directly map user buffers; clear the init flag
        fdo->Flags |= DO_DIRECT_IO;
        fdo->Flags &= ~DO_DEVICE_INITIALIZING;        

        // Made it here, go to connected state to be consistent
        xenbus_change_state(XBT_NIL, pde->frontendPath, "state", XENBUS_STATE_CONNECTED);
    } while (FALSE);

    if (!NT_SUCCESS(status)) {
        if (fdo != NULL) {         
            if ((pde != NULL)&&(pde->ldo != NULL)) {
                IoDetachDevice(pde->ldo);
            }
            if (szFpath != NULL) {
                XmFreeMemory(szFpath);
            }
            if (symlink) {
                IoDeleteSymbolicLink(&pde->symbolicLink);
            }
            IoDeleteDevice(fdo);
        }
    }

    TraceVerbose(("<==== '%s'.\n", __FUNCTION__));

    return status;
}
Esempio n. 7
0
static NTSTATUS NTAPI
V4vDispatchPnP(PDEVICE_OBJECT fdo, PIRP irp)
{
    NTSTATUS           status = STATUS_SUCCESS;
    PIO_STACK_LOCATION isl = IoGetCurrentIrpStackLocation(irp);
    PXENV4V_EXTENSION  pde = V4vGetDeviceExtension(fdo);
    KEVENT             kev;

    TraceVerbose(("====> '%s'.\n", __FUNCTION__));

    TraceVerbose((" =PnP= 0x%x\n", isl->MinorFunction));

    status = IoAcquireRemoveLock(&pde->removeLock, irp);
    if (!NT_SUCCESS(status)) {
        TraceError(("failed to acquire IO lock - error: 0x%x\n", status));
        return V4vSimpleCompleteIrp(irp, status);
    }

    switch (isl->MinorFunction) {
    case IRP_MN_START_DEVICE:
        KeInitializeEvent(&kev, NotificationEvent, FALSE);
        // Send the start down and wait for it to complete
        IoCopyCurrentIrpStackLocationToNext(irp);
        IoSetCompletionRoutine(irp, V4vStartDeviceIoCompletion, &kev, TRUE, TRUE, TRUE);
        status = IoCallDriver(pde->ldo, irp);
        if (status == STATUS_PENDING) {
            // Wait for everything underneath us to complete
            TraceVerbose(("Device start waiting for lower device.\n"));
            KeWaitForSingleObject(&kev, Executive, KernelMode, FALSE, NULL);
            TraceVerbose(("Device start wait finished.\n"));
        }

        status = irp->IoStatus.Status;
        if (!NT_SUCCESS(status)) {
            TraceError(("Failed to start lower drivers: %x.\n", status));
            IoCompleteRequest(irp, IO_NO_INCREMENT);
            break;
        }

        status = STATUS_SUCCESS;

        // Connect our interrupt (ec).
        status = V4vInitializeEventChannel(fdo);
        if (NT_SUCCESS(status)) {
            InterlockedExchange(&pde->state, XENV4V_DEV_STARTED);
        }
        else {
            TraceError(("failed to initialize event channel - error: 0x%x\n", status));
        }

        irp->IoStatus.Status = status;
        IoCompleteRequest(irp, IO_NO_INCREMENT);
        break;
    case IRP_MN_STOP_DEVICE:
        // Stop our device's IO processing
        V4vStopDevice(fdo, pde);

        // Pass it down
        irp->IoStatus.Status = STATUS_SUCCESS;
        IoSkipCurrentIrpStackLocation(irp);
        status = IoCallDriver(pde->ldo, irp);
        break;        
    case IRP_MN_REMOVE_DEVICE:
        // Stop our device's IO processing
        V4vStopDevice(fdo, pde);

        // Cleanup anything here that locks for IO
        IoReleaseRemoveLockAndWait(&pde->removeLock, irp);

        // Pass it down first
        IoSkipCurrentIrpStackLocation(irp);
        status = IoCallDriver(pde->ldo, irp);

        // Then detach and cleanup our device
        xenbus_change_state(XBT_NIL, pde->frontendPath, "state", XENBUS_STATE_CLOSED);
        IoDetachDevice(pde->ldo);
        ExDeleteNPagedLookasideList(&pde->destLookasideList);
        XmFreeMemory(pde->frontendPath);
        IoDeleteSymbolicLink(&pde->symbolicLink);
        IoDeleteDevice(fdo);
        InterlockedAnd(&g_deviceCreated, 0);
        return status;
    default:
        // Pass it down
        TraceVerbose(("IRP_MJ_PNP MinorFunction %d passed down\n", isl->MinorFunction));
        IoSkipCurrentIrpStackLocation(irp);
        status = IoCallDriver(pde->ldo, irp);
    };

    // Everybody but REMOVE
    IoReleaseRemoveLock(&pde->removeLock, irp); 

    TraceVerbose(("<==== '%s'.\n", __FUNCTION__));

    return status;
}