Commit 1d7d2a9d authored by Paolo Bonzini's avatar Paolo Bonzini
Browse files

nbd: accept URIs



The URI syntax is consistent with the Gluster syntax.  Export names
are specified in the path, preceded by one or more (otherwise unused)
slashes.

Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
parent d04b0bbb
Loading
Loading
Loading
Loading
+97 −1
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@

#include "qemu-common.h"
#include "nbd.h"
#include "uri.h"
#include "block_int.h"
#include "module.h"
#include "qemu_socket.h"
@@ -69,6 +70,69 @@ typedef struct BDRVNBDState {
    char *export_name; /* An NBD server may export several devices */
} BDRVNBDState;

static int nbd_parse_uri(BDRVNBDState *s, const char *filename)
{
    URI *uri;
    const char *p;
    QueryParams *qp = NULL;
    int ret = 0;

    uri = uri_parse(filename);
    if (!uri) {
        return -EINVAL;
    }

    /* transport */
    if (!strcmp(uri->scheme, "nbd")) {
        s->is_unix = false;
    } else if (!strcmp(uri->scheme, "nbd+tcp")) {
        s->is_unix = false;
    } else if (!strcmp(uri->scheme, "nbd+unix")) {
        s->is_unix = true;
    } else {
        ret = -EINVAL;
        goto out;
    }

    p = uri->path ? uri->path : "/";
    p += strspn(p, "/");
    if (p[0]) {
        s->export_name = g_strdup(p);
    }

    qp = query_params_parse(uri->query);
    if (qp->n > 1 || (s->is_unix && !qp->n) || (!s->is_unix && qp->n)) {
        ret = -EINVAL;
        goto out;
    }

    if (s->is_unix) {
        /* nbd+unix:///export?socket=path */
        if (uri->server || uri->port || strcmp(qp->p[0].name, "socket")) {
            ret = -EINVAL;
            goto out;
        }
        s->host_spec = g_strdup(qp->p[0].value);
    } else {
        /* nbd[+tcp]://host:port/export */
        if (!uri->server) {
            ret = -EINVAL;
            goto out;
        }
        if (!uri->port) {
            uri->port = NBD_DEFAULT_PORT;
        }
        s->host_spec = g_strdup_printf("%s:%d", uri->server, uri->port);
    }

out:
    if (qp) {
        query_params_free(qp);
    }
    uri_free(uri);
    return ret;
}

static int nbd_config(BDRVNBDState *s, const char *filename)
{
    char *file;
@@ -77,6 +141,10 @@ static int nbd_config(BDRVNBDState *s, const char *filename)
    const char *unixpath;
    int err = -EINVAL;

    if (strstr(filename, "://")) {
        return nbd_parse_uri(s, filename);
    }

    file = g_strdup(filename);

    export_name = strstr(file, EN_OPTSTR);
@@ -495,6 +563,33 @@ static int64_t nbd_getlength(BlockDriverState *bs)

static BlockDriver bdrv_nbd = {
    .format_name         = "nbd",
    .protocol_name       = "nbd",
    .instance_size       = sizeof(BDRVNBDState),
    .bdrv_file_open      = nbd_open,
    .bdrv_co_readv       = nbd_co_readv,
    .bdrv_co_writev      = nbd_co_writev,
    .bdrv_close          = nbd_close,
    .bdrv_co_flush_to_os = nbd_co_flush,
    .bdrv_co_discard     = nbd_co_discard,
    .bdrv_getlength      = nbd_getlength,
};

static BlockDriver bdrv_nbd_tcp = {
    .format_name         = "nbd",
    .protocol_name       = "nbd+tcp",
    .instance_size       = sizeof(BDRVNBDState),
    .bdrv_file_open      = nbd_open,
    .bdrv_co_readv       = nbd_co_readv,
    .bdrv_co_writev      = nbd_co_writev,
    .bdrv_close          = nbd_close,
    .bdrv_co_flush_to_os = nbd_co_flush,
    .bdrv_co_discard     = nbd_co_discard,
    .bdrv_getlength      = nbd_getlength,
};

static BlockDriver bdrv_nbd_unix = {
    .format_name         = "nbd",
    .protocol_name       = "nbd+unix",
    .instance_size       = sizeof(BDRVNBDState),
    .bdrv_file_open      = nbd_open,
    .bdrv_co_readv       = nbd_co_readv,
@@ -503,12 +598,13 @@ static BlockDriver bdrv_nbd = {
    .bdrv_co_flush_to_os = nbd_co_flush,
    .bdrv_co_discard     = nbd_co_discard,
    .bdrv_getlength      = nbd_getlength,
    .protocol_name       = "nbd",
};

static void bdrv_nbd_init(void)
{
    bdrv_register(&bdrv_nbd);
    bdrv_register(&bdrv_nbd_tcp);
    bdrv_register(&bdrv_nbd_unix);
}

block_init(bdrv_nbd_init);
+17 −8
Original line number Diff line number Diff line
@@ -610,14 +610,14 @@ QEMU can access directly to block device exported using the Network Block Device
protocol.

@example
qemu-system-i386 linux.img -hdb nbd:my_nbd_server.mydomain.org:1024
qemu-system-i386 linux.img -hdb nbd://my_nbd_server.mydomain.org:1024/
@end example

If the NBD server is located on the same host, you can use an unix socket instead
of an inet socket:

@example
qemu-system-i386 linux.img -hdb nbd:unix:/tmp/my_socket
qemu-system-i386 linux.img -hdb nbd+unix://?socket=/tmp/my_socket
@end example

In this case, the block device must be exported using qemu-nbd:
@@ -631,17 +631,26 @@ The use of qemu-nbd allows to share a disk between several guests:
qemu-nbd --socket=/tmp/my_socket --share=2 my_disk.qcow2
@end example

@noindent
and then you can use it with two guests:
@example
qemu-system-i386 linux1.img -hdb nbd:unix:/tmp/my_socket
qemu-system-i386 linux2.img -hdb nbd:unix:/tmp/my_socket
qemu-system-i386 linux1.img -hdb nbd+unix://?socket=/tmp/my_socket
qemu-system-i386 linux2.img -hdb nbd+unix://?socket=/tmp/my_socket
@end example

If the nbd-server uses named exports (since NBD 2.9.18), you must use the
"exportname" option:
If the nbd-server uses named exports (supported since NBD 2.9.18, or with QEMU's
own embedded NBD server), you must specify an export name in the URI:
@example
qemu-system-i386 -cdrom nbd:localhost:exportname=debian-500-ppc-netinst
qemu-system-i386 -cdrom nbd:localhost:exportname=openSUSE-11.1-ppc-netinst
qemu-system-i386 -cdrom nbd://localhost/debian-500-ppc-netinst
qemu-system-i386 -cdrom nbd://localhost/openSUSE-11.1-ppc-netinst
@end example

The URI syntax for NBD is supported since QEMU 1.3.  An alternative syntax is
also available.  Here are some example of the older syntax:
@example
qemu-system-i386 linux.img -hdb nbd:my_nbd_server.mydomain.org:1024
qemu-system-i386 linux2.img -hdb nbd:unix:/tmp/my_socket
qemu-system-i386 -cdrom nbd:localhost:10809:exportname=debian-500-ppc-netinst
@end example

@node disk_images_sheepdog