Skip to content

Commit

Permalink
nbd: Keep hostname and port separate
Browse files Browse the repository at this point in the history
The NBD block supports an URL syntax, for which a URL parser returns
separate hostname and port fields. It also supports the traditional qemu
syntax encoded in a filename. Until now, after parsing the URL to get
each piece of information, a new string is built to be fed to socket
functions.

Instead of building a string in the URL case that is immediately parsed
again, parse the string in both cases and use the QemuOpts interface to
qemu-sockets.c.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
  • Loading branch information
kevmw committed Mar 22, 2013
1 parent e62be88 commit f17c90b
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 12 deletions.
49 changes: 40 additions & 9 deletions block/nbd.c
Expand Up @@ -66,7 +66,10 @@ typedef struct BDRVNBDState {
struct nbd_reply reply;

int is_unix;
char *host_spec;
char *unix_path;

InetSocketAddress *inet_addr;

char *export_name; /* An NBD server may export several devices */
} BDRVNBDState;

Expand Down Expand Up @@ -112,7 +115,7 @@ static int nbd_parse_uri(BDRVNBDState *s, const char *filename)
ret = -EINVAL;
goto out;
}
s->host_spec = g_strdup(qp->p[0].value);
s->unix_path = g_strdup(qp->p[0].value);
} else {
/* nbd[+tcp]://host:port/export */
if (!uri->server) {
Expand All @@ -122,7 +125,12 @@ static int nbd_parse_uri(BDRVNBDState *s, const char *filename)
if (!uri->port) {
uri->port = NBD_DEFAULT_PORT;
}
s->host_spec = g_strdup_printf("%s:%d", uri->server, uri->port);

s->inet_addr = g_new0(InetSocketAddress, 1);
*s->inet_addr = (InetSocketAddress) {
.host = g_strdup(uri->server),
.port = g_strdup_printf("%d", uri->port),
};
}

out:
Expand All @@ -140,6 +148,7 @@ static int nbd_config(BDRVNBDState *s, const char *filename)
const char *host_spec;
const char *unixpath;
int err = -EINVAL;
Error *local_err = NULL;

if (strstr(filename, "://")) {
return nbd_parse_uri(s, filename);
Expand All @@ -165,10 +174,15 @@ static int nbd_config(BDRVNBDState *s, const char *filename)
/* are we a UNIX or TCP socket? */
if (strstart(host_spec, "unix:", &unixpath)) {
s->is_unix = true;
s->host_spec = g_strdup(unixpath);
s->unix_path = g_strdup(unixpath);
} else {
s->is_unix = false;
s->host_spec = g_strdup(host_spec);
s->inet_addr = inet_parse(host_spec, &local_err);
if (local_err != NULL) {
qerror_report_err(local_err);
error_free(local_err);
goto out;
}
}

err = 0;
Expand All @@ -177,7 +191,8 @@ static int nbd_config(BDRVNBDState *s, const char *filename)
g_free(file);
if (err != 0) {
g_free(s->export_name);
g_free(s->host_spec);
g_free(s->unix_path);
qapi_free_InetSocketAddress(s->inet_addr);
}
return err;
}
Expand Down Expand Up @@ -328,9 +343,24 @@ static int nbd_establish_connection(BlockDriverState *bs)
size_t blocksize;

if (s->is_unix) {
sock = unix_socket_outgoing(s->host_spec);
sock = unix_socket_outgoing(s->unix_path);
} else {
sock = tcp_socket_outgoing_spec(s->host_spec);
QemuOpts *opts = qemu_opts_create_nofail(&socket_optslist);

qemu_opt_set(opts, "host", s->inet_addr->host);
qemu_opt_set(opts, "port", s->inet_addr->port);
if (s->inet_addr->has_to) {
qemu_opt_set_number(opts, "to", s->inet_addr->to);
}
if (s->inet_addr->has_ipv4) {
qemu_opt_set_number(opts, "ipv4", s->inet_addr->ipv4);
}
if (s->inet_addr->has_ipv6) {
qemu_opt_set_number(opts, "ipv6", s->inet_addr->ipv6);
}

sock = tcp_socket_outgoing_opts(opts);
qemu_opts_del(opts);
}

/* Failed to establish connection */
Expand Down Expand Up @@ -550,7 +580,8 @@ static void nbd_close(BlockDriverState *bs)
{
BDRVNBDState *s = bs->opaque;
g_free(s->export_name);
g_free(s->host_spec);
g_free(s->unix_path);
qapi_free_InetSocketAddress(s->inet_addr);

nbd_teardown_connection(bs);
}
Expand Down
2 changes: 2 additions & 0 deletions include/block/nbd.h
Expand Up @@ -22,6 +22,7 @@
#include <sys/types.h>

#include "qemu-common.h"
#include "qemu/option.h"

struct nbd_request {
uint32_t magic;
Expand Down Expand Up @@ -64,6 +65,7 @@ int tcp_socket_outgoing(const char *address, uint16_t port);
int tcp_socket_incoming(const char *address, uint16_t port);
int tcp_socket_outgoing_spec(const char *address_and_port);
int tcp_socket_incoming_spec(const char *address_and_port);
int tcp_socket_outgoing_opts(QemuOpts *opts);
int unix_socket_outgoing(const char *path);
int unix_socket_incoming(const char *path);

Expand Down
1 change: 1 addition & 0 deletions include/qemu/sockets.h
Expand Up @@ -47,6 +47,7 @@ int recv_all(int fd, void *buf, int len1, bool single_read);
*/
typedef void NonBlockingConnectHandler(int fd, void *opaque);

InetSocketAddress *inet_parse(const char *str, Error **errp);
int inet_listen_opts(QemuOpts *opts, int port_offset, Error **errp);
int inet_listen(const char *str, char *ostr, int olen,
int socktype, int port_offset, Error **errp);
Expand Down
12 changes: 12 additions & 0 deletions nbd.c
Expand Up @@ -218,6 +218,18 @@ int tcp_socket_outgoing_spec(const char *address_and_port)
return fd;
}

int tcp_socket_outgoing_opts(QemuOpts *opts)
{
Error *local_err = NULL;
int fd = inet_connect_opts(opts, &local_err, NULL, NULL);
if (local_err != NULL) {
qerror_report_err(local_err);
error_free(local_err);
}

return fd;
}

int tcp_socket_incoming(const char *address, uint16_t port)
{
char address_and_port[128];
Expand Down
6 changes: 3 additions & 3 deletions util/qemu-sockets.c
Expand Up @@ -485,7 +485,7 @@ int inet_dgram_opts(QemuOpts *opts, Error **errp)
}

/* compatibility wrapper */
static InetSocketAddress *inet_parse(const char *str, Error **errp)
InetSocketAddress *inet_parse(const char *str, Error **errp)
{
InetSocketAddress *addr;
const char *optstr, *h;
Expand Down Expand Up @@ -555,7 +555,7 @@ static InetSocketAddress *inet_parse(const char *str, Error **errp)
return NULL;
}

static void inet_addr_to_opts(QemuOpts *opts, InetSocketAddress *addr)
static void inet_addr_to_opts(QemuOpts *opts, const InetSocketAddress *addr)
{
bool ipv4 = addr->ipv4 || !addr->has_ipv4;
bool ipv6 = addr->ipv6 || !addr->has_ipv6;
Expand Down Expand Up @@ -622,7 +622,7 @@ int inet_connect(const char *str, Error **errp)

addr = inet_parse(str, errp);
if (addr != NULL) {
opts = qemu_opts_create_nofail(&dummy_opts);
opts = qemu_opts_create_nofail(&socket_optslist);
inet_addr_to_opts(opts, addr);
qapi_free_InetSocketAddress(addr);
sock = inet_connect_opts(opts, errp, NULL, NULL);
Expand Down

0 comments on commit f17c90b

Please sign in to comment.