sheepdog: add support for connecting to unix domain socket

This patch adds support for a unix domain socket for a connection
between qemu and local sheepdog server.  You can use the unix domain
socket with the following syntax:

 $ qemu sheepdog+unix:///<vdiname>?socket=<socket path>[#snapid]

Signed-off-by: MORITA Kazutaka <morita.kazutaka@lab.ntt.co.jp>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
MORITA Kazutaka 2013-02-22 12:39:53 +09:00 committed by Stefan Hajnoczi
parent 25af257d21
commit 1b8bbb46e7
3 changed files with 77 additions and 13 deletions

View File

@ -299,6 +299,7 @@ typedef struct BDRVSheepdogState {
uint32_t cache_flags; uint32_t cache_flags;
char *host_spec; char *host_spec;
bool is_unix;
int fd; int fd;
CoMutex lock; CoMutex lock;
@ -451,7 +452,18 @@ static int connect_to_sdog(BDRVSheepdogState *s)
int fd; int fd;
Error *err = NULL; Error *err = NULL;
fd = inet_connect(s->host_spec, &err); if (s->is_unix) {
fd = unix_connect(s->host_spec, &err);
} else {
fd = inet_connect(s->host_spec, &err);
if (err == NULL) {
int ret = socket_set_nodelay(fd);
if (ret < 0) {
error_report("%s", strerror(errno));
}
}
}
if (err != NULL) { if (err != NULL) {
qerror_report_err(err); qerror_report_err(err);
@ -757,7 +769,7 @@ static int aio_flush_request(void *opaque)
*/ */
static int get_sheep_fd(BDRVSheepdogState *s) static int get_sheep_fd(BDRVSheepdogState *s)
{ {
int ret, fd; int fd;
fd = connect_to_sdog(s); fd = connect_to_sdog(s);
if (fd < 0) { if (fd < 0) {
@ -766,13 +778,6 @@ static int get_sheep_fd(BDRVSheepdogState *s)
socket_set_nonblock(fd); socket_set_nonblock(fd);
ret = socket_set_nodelay(fd);
if (ret) {
error_report("%s", strerror(errno));
closesocket(fd);
return -errno;
}
qemu_aio_set_fd_handler(fd, co_read_response, NULL, aio_flush_request, s); qemu_aio_set_fd_handler(fd, co_read_response, NULL, aio_flush_request, s);
return fd; return fd;
} }
@ -789,15 +794,42 @@ static int sd_parse_uri(BDRVSheepdogState *s, const char *filename,
return -EINVAL; return -EINVAL;
} }
/* transport */
if (!strcmp(uri->scheme, "sheepdog")) {
s->is_unix = false;
} else if (!strcmp(uri->scheme, "sheepdog+tcp")) {
s->is_unix = false;
} else if (!strcmp(uri->scheme, "sheepdog+unix")) {
s->is_unix = true;
} else {
ret = -EINVAL;
goto out;
}
if (uri->path == NULL || !strcmp(uri->path, "/")) { if (uri->path == NULL || !strcmp(uri->path, "/")) {
ret = -EINVAL; ret = -EINVAL;
goto out; goto out;
} }
pstrcpy(vdi, SD_MAX_VDI_LEN, uri->path + 1); pstrcpy(vdi, SD_MAX_VDI_LEN, uri->path + 1);
/* sheepdog[+tcp]://[host:port]/vdiname */ qp = query_params_parse(uri->query);
s->host_spec = g_strdup_printf("%s:%d", uri->server ?: SD_DEFAULT_ADDR, if (qp->n > 1 || (s->is_unix && !qp->n) || (!s->is_unix && qp->n)) {
uri->port ?: SD_DEFAULT_PORT); ret = -EINVAL;
goto out;
}
if (s->is_unix) {
/* sheepdog+unix:///vdiname?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 {
/* sheepdog[+tcp]://[host:port]/vdiname */
s->host_spec = g_strdup_printf("%s:%d", uri->server ?: SD_DEFAULT_ADDR,
uri->port ?: SD_DEFAULT_PORT);
}
/* snapshot tag */ /* snapshot tag */
if (uri->fragment) { if (uri->fragment) {
@ -2098,9 +2130,35 @@ static BlockDriver bdrv_sheepdog_tcp = {
.create_options = sd_create_options, .create_options = sd_create_options,
}; };
static BlockDriver bdrv_sheepdog_unix = {
.format_name = "sheepdog",
.protocol_name = "sheepdog+unix",
.instance_size = sizeof(BDRVSheepdogState),
.bdrv_file_open = sd_open,
.bdrv_close = sd_close,
.bdrv_create = sd_create,
.bdrv_getlength = sd_getlength,
.bdrv_truncate = sd_truncate,
.bdrv_co_readv = sd_co_readv,
.bdrv_co_writev = sd_co_writev,
.bdrv_co_flush_to_disk = sd_co_flush_to_disk,
.bdrv_snapshot_create = sd_snapshot_create,
.bdrv_snapshot_goto = sd_snapshot_goto,
.bdrv_snapshot_delete = sd_snapshot_delete,
.bdrv_snapshot_list = sd_snapshot_list,
.bdrv_save_vmstate = sd_save_vmstate,
.bdrv_load_vmstate = sd_load_vmstate,
.create_options = sd_create_options,
};
static void bdrv_sheepdog_init(void) static void bdrv_sheepdog_init(void)
{ {
bdrv_register(&bdrv_sheepdog); bdrv_register(&bdrv_sheepdog);
bdrv_register(&bdrv_sheepdog_tcp); bdrv_register(&bdrv_sheepdog_tcp);
bdrv_register(&bdrv_sheepdog_unix);
} }
block_init(bdrv_sheepdog_init); block_init(bdrv_sheepdog_init);

View File

@ -865,6 +865,12 @@ qemu-img create -b sheepdog:///@var{base}#@var{tag} sheepdog:///@var{image}
where @var{base} is a image name of the source snapshot and @var{tag} where @var{base} is a image name of the source snapshot and @var{tag}
is its tag name. is its tag name.
You can use an unix socket instead of an inet socket:
@example
qemu-system-i386 sheepdog+unix:///@var{image}?socket=@var{path}
@end example
If the Sheepdog daemon doesn't run on the local host, you need to If the Sheepdog daemon doesn't run on the local host, you need to
specify one of the Sheepdog servers to connect to. specify one of the Sheepdog servers to connect to.
@example @example

View File

@ -2100,7 +2100,7 @@ devices.
Syntax for specifying a sheepdog device Syntax for specifying a sheepdog device
@example @example
sheepdog[+tcp]://[host:port]/vdiname[#snapid|#tag] sheepdog[+tcp|+unix]://[host:port]/vdiname[?socket=path][#snapid|#tag]
@end example @end example
Example Example