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: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
Paolo Bonzini 2012-11-04 13:04:24 +01:00
parent d04b0bbbc9
commit 1d7d2a9d21
2 changed files with 114 additions and 9 deletions

View file

@ -28,6 +28,7 @@
#include "qemu-common.h" #include "qemu-common.h"
#include "nbd.h" #include "nbd.h"
#include "uri.h"
#include "block_int.h" #include "block_int.h"
#include "module.h" #include "module.h"
#include "qemu_socket.h" #include "qemu_socket.h"
@ -69,6 +70,69 @@ typedef struct BDRVNBDState {
char *export_name; /* An NBD server may export several devices */ char *export_name; /* An NBD server may export several devices */
} BDRVNBDState; } 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) static int nbd_config(BDRVNBDState *s, const char *filename)
{ {
char *file; char *file;
@ -77,6 +141,10 @@ static int nbd_config(BDRVNBDState *s, const char *filename)
const char *unixpath; const char *unixpath;
int err = -EINVAL; int err = -EINVAL;
if (strstr(filename, "://")) {
return nbd_parse_uri(s, filename);
}
file = g_strdup(filename); file = g_strdup(filename);
export_name = strstr(file, EN_OPTSTR); export_name = strstr(file, EN_OPTSTR);
@ -495,6 +563,33 @@ static int64_t nbd_getlength(BlockDriverState *bs)
static BlockDriver bdrv_nbd = { static BlockDriver bdrv_nbd = {
.format_name = "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), .instance_size = sizeof(BDRVNBDState),
.bdrv_file_open = nbd_open, .bdrv_file_open = nbd_open,
.bdrv_co_readv = nbd_co_readv, .bdrv_co_readv = nbd_co_readv,
@ -503,12 +598,13 @@ static BlockDriver bdrv_nbd = {
.bdrv_co_flush_to_os = nbd_co_flush, .bdrv_co_flush_to_os = nbd_co_flush,
.bdrv_co_discard = nbd_co_discard, .bdrv_co_discard = nbd_co_discard,
.bdrv_getlength = nbd_getlength, .bdrv_getlength = nbd_getlength,
.protocol_name = "nbd",
}; };
static void bdrv_nbd_init(void) static void bdrv_nbd_init(void)
{ {
bdrv_register(&bdrv_nbd); bdrv_register(&bdrv_nbd);
bdrv_register(&bdrv_nbd_tcp);
bdrv_register(&bdrv_nbd_unix);
} }
block_init(bdrv_nbd_init); block_init(bdrv_nbd_init);

View file

@ -610,14 +610,14 @@ QEMU can access directly to block device exported using the Network Block Device
protocol. protocol.
@example @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 @end example
If the NBD server is located on the same host, you can use an unix socket instead If the NBD server is located on the same host, you can use an unix socket instead
of an inet socket: of an inet socket:
@example @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 @end example
In this case, the block device must be exported using qemu-nbd: 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 qemu-nbd --socket=/tmp/my_socket --share=2 my_disk.qcow2
@end example @end example
@noindent
and then you can use it with two guests: and then you can use it with two guests:
@example @example
qemu-system-i386 linux1.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:/tmp/my_socket qemu-system-i386 linux2.img -hdb nbd+unix://?socket=/tmp/my_socket
@end example @end example
If the nbd-server uses named exports (since NBD 2.9.18), you must use the If the nbd-server uses named exports (supported since NBD 2.9.18, or with QEMU's
"exportname" option: own embedded NBD server), you must specify an export name in the URI:
@example @example
qemu-system-i386 -cdrom nbd:localhost:exportname=debian-500-ppc-netinst qemu-system-i386 -cdrom nbd://localhost/debian-500-ppc-netinst
qemu-system-i386 -cdrom nbd:localhost:exportname=openSUSE-11.1-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 @end example
@node disk_images_sheepdog @node disk_images_sheepdog