예제 #1
0
파일: nbd-client.c 프로젝트: Aakriti/qemu
static void nbd_teardown_connection(NbdClientSession *client)
{
    struct nbd_request request = {
        .type = NBD_CMD_DISC,
        .from = 0,
        .len = 0
    };

    nbd_send_request(client->sock, &request);

    /* finish any pending coroutines */
    shutdown(client->sock, 2);
    nbd_recv_coroutines_enter_all(client);

    qemu_aio_set_fd_handler(client->sock, NULL, NULL, NULL);
    closesocket(client->sock);
    client->sock = -1;
}

void nbd_client_session_close(NbdClientSession *client)
{
    if (!client->bs) {
        return;
    }

    nbd_teardown_connection(client);
    client->bs = NULL;
}

int nbd_client_session_init(NbdClientSession *client, BlockDriverState *bs,
    int sock, const char *export)
{
    int ret;

    /* NBD handshake */
    logout("session init %s\n", export);
    qemu_set_block(sock);
    ret = nbd_receive_negotiate(sock, export,
                                &client->nbdflags, &client->size,
                                &client->blocksize);
    if (ret < 0) {
        logout("Failed to negotiate with the NBD server\n");
        closesocket(sock);
        return ret;
    }

    qemu_co_mutex_init(&client->send_mutex);
    qemu_co_mutex_init(&client->free_sema);
    client->bs = bs;
    client->sock = sock;

    /* Now that we're connected, set the socket to be non-blocking and
     * kick the reply mechanism.  */
    qemu_set_nonblock(sock);
    qemu_aio_set_fd_handler(sock, nbd_reply_ready, NULL, client);

    logout("Established connection with NBD server\n");
    return 0;
}
예제 #2
0
파일: nbd.c 프로젝트: AsherBond/qemu-kvm-mq
static void nbd_close(BlockDriverState *bs)
{
    BDRVNBDState *s = bs->opaque;
    g_free(s->export_name);
    g_free(s->host_spec);

    nbd_teardown_connection(bs);
}
예제 #3
0
파일: nbd-client.c 프로젝트: twnkl/qemu
void nbd_client_close(BlockDriverState *bs)
{
    NBDClientSession *client = nbd_get_client_session(bs);
    NBDRequest request = { .type = NBD_CMD_DISC };

    if (client->ioc == NULL) {
        return;
    }

    nbd_send_request(client->ioc, &request);

    nbd_teardown_connection(bs);
}
예제 #4
0
void nbd_client_close(BlockDriverState *bs)
{
    NbdClientSession *client = nbd_get_client_session(bs);
    struct nbd_request request = {
        .type = NBD_CMD_DISC,
        .from = 0,
        .len = 0
    };

    if (client->sock == -1) {
        return;
    }

    nbd_send_request(client->sock, &request);

    nbd_teardown_connection(bs);
}

int nbd_client_init(BlockDriverState *bs, int sock, const char *export,
                    Error **errp)
{
    NbdClientSession *client = nbd_get_client_session(bs);
    int ret;

    /* NBD handshake */
    logout("session init %s\n", export);
    qemu_set_block(sock);
    ret = nbd_receive_negotiate(sock, export,
                                &client->nbdflags, &client->size,
                                &client->blocksize, errp);
    if (ret < 0) {
        logout("Failed to negotiate with the NBD server\n");
        closesocket(sock);
        return ret;
    }

    qemu_co_mutex_init(&client->send_mutex);
    qemu_co_mutex_init(&client->free_sema);
    client->sock = sock;

    /* Now that we're connected, set the socket to be non-blocking and
     * kick the reply mechanism.  */
    qemu_set_nonblock(sock);
    nbd_client_attach_aio_context(bs, bdrv_get_aio_context(bs));

    logout("Established connection with NBD server\n");
    return 0;
}
예제 #5
0
static void nbd_reply_ready(void *opaque)
{
    BlockDriverState *bs = opaque;
    NbdClientSession *s = nbd_get_client_session(bs);
    uint64_t i;
    int ret;

    if (!s->ioc) { /* Already closed */
        return;
    }

    if (s->reply.handle == 0) {
        /* No reply already in flight.  Fetch a header.  It is possible
         * that another thread has done the same thing in parallel, so
         * the socket is not readable anymore.
         */
        ret = nbd_receive_reply(s->ioc, &s->reply);
        if (ret == -EAGAIN) {
            return;
        }
        if (ret < 0) {
            s->reply.handle = 0;
            goto fail;
        }
    }

    /* There's no need for a mutex on the receive side, because the
     * handler acts as a synchronization point and ensures that only
     * one coroutine is called until the reply finishes.  */
    i = HANDLE_TO_INDEX(s, s->reply.handle);
    if (i >= MAX_NBD_REQUESTS) {
        goto fail;
    }

    if (s->recv_coroutine[i]) {
        qemu_coroutine_enter(s->recv_coroutine[i], NULL);
        return;
    }

fail:
    nbd_teardown_connection(bs);
}
예제 #6
0
void nbd_client_close(BlockDriverState *bs)
{
    NbdClientSession *client = nbd_get_client_session(bs);
    struct nbd_request request = {
        .type = NBD_CMD_DISC,
        .from = 0,
        .len = 0
    };

    if (client->ioc == NULL) {
        return;
    }

    nbd_send_request(client->ioc, &request);

    nbd_teardown_connection(bs);
}

int nbd_client_init(BlockDriverState *bs,
                    QIOChannelSocket *sioc,
                    const char *export,
                    QCryptoTLSCreds *tlscreds,
                    const char *hostname,
                    Error **errp)
{
    NbdClientSession *client = nbd_get_client_session(bs);
    int ret;

    /* NBD handshake */
    logout("session init %s\n", export);
    qio_channel_set_blocking(QIO_CHANNEL(sioc), true, NULL);

    ret = nbd_receive_negotiate(QIO_CHANNEL(sioc), export,
                                &client->nbdflags,
                                tlscreds, hostname,
                                &client->ioc,
                                &client->size, errp);
    if (ret < 0) {
        logout("Failed to negotiate with the NBD server\n");
        return ret;
    }

    qemu_co_mutex_init(&client->send_mutex);
    qemu_co_mutex_init(&client->free_sema);
    client->sioc = sioc;
    object_ref(OBJECT(client->sioc));

    if (!client->ioc) {
        client->ioc = QIO_CHANNEL(sioc);
        object_ref(OBJECT(client->ioc));
    }

    /* Now that we're connected, set the socket to be non-blocking and
     * kick the reply mechanism.  */
    qio_channel_set_blocking(QIO_CHANNEL(sioc), false, NULL);

    nbd_client_attach_aio_context(bs, bdrv_get_aio_context(bs));

    logout("Established connection with NBD server\n");
    return 0;
}