Patchwork [v3,5/5] sheepdog: add support for connecting to unix domain socket

login
register
mail settings
Submitter MORITA Kazutaka
Date Jan. 29, 2013, 12:11 a.m.
Message ID <1359418264-29524-6-git-send-email-morita.kazutaka@lab.ntt.co.jp>
Download mbox | patch
Permalink /patch/216402/
State New
Headers show

Comments

MORITA Kazutaka - Jan. 29, 2013, 12:11 a.m.
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 path>[#snapid]

Signed-off-by: MORITA Kazutaka <morita.kazutaka@lab.ntt.co.jp>
---
 block/sheepdog.c |   82 ++++++++++++++++++++++++++++++++++++++++++++++--------
 qemu-doc.texi    |    6 ++++
 qemu-options.hx  |    2 +-
 3 files changed, 77 insertions(+), 13 deletions(-)
Paolo Bonzini - Jan. 29, 2013, 8:25 a.m.
Il 29/01/2013 01:11, MORITA Kazutaka ha scritto:
> 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 path>[#snapid]

Should be "?socket=<socket path>".

Otherwise, the patches look good.  Thanks!

Paolo

> 
> Signed-off-by: MORITA Kazutaka <morita.kazutaka@lab.ntt.co.jp>
> ---
>  block/sheepdog.c |   82 ++++++++++++++++++++++++++++++++++++++++++++++--------
>  qemu-doc.texi    |    6 ++++
>  qemu-options.hx  |    2 +-
>  3 files changed, 77 insertions(+), 13 deletions(-)
> 
> diff --git a/block/sheepdog.c b/block/sheepdog.c
> index f35de36..eb7713a 100644
> --- a/block/sheepdog.c
> +++ b/block/sheepdog.c
> @@ -299,6 +299,7 @@ typedef struct BDRVSheepdogState {
>      uint32_t cache_flags;
>  
>      char *host_spec;
> +    bool is_unix;
>      int fd;
>  
>      CoMutex lock;
> @@ -451,7 +452,18 @@ static int connect_to_sdog(BDRVSheepdogState *s)
>      int fd;
>      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) {
>          qerror_report_err(err);
> @@ -757,7 +769,7 @@ static int aio_flush_request(void *opaque)
>   */
>  static int get_sheep_fd(BDRVSheepdogState *s)
>  {
> -    int ret, fd;
> +    int fd;
>  
>      fd = connect_to_sdog(s);
>      if (fd < 0) {
> @@ -766,13 +778,6 @@ static int get_sheep_fd(BDRVSheepdogState *s)
>  
>      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);
>      return fd;
>  }
> @@ -789,15 +794,42 @@ static int sd_parse_uri(BDRVSheepdogState *s, const char *filename,
>          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, "/")) {
>          ret = -EINVAL;
>          goto out;
>      }
>      pstrcpy(vdi, SD_MAX_VDI_LEN, uri->path + 1);
>  
> -    /* sheepdog[+tcp]://[host:port]/vdiname */
> -    s->host_spec = g_strdup_printf("%s:%d", uri->server ?: SD_DEFAULT_ADDR,
> -                                   uri->port ?: SD_DEFAULT_PORT);
> +    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) {
> +        /* 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 */
>      if (uri->fragment) {
> @@ -2097,9 +2129,35 @@ static BlockDriver bdrv_sheepdog_tcp = {
>      .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)
>  {
>      bdrv_register(&bdrv_sheepdog);
>      bdrv_register(&bdrv_sheepdog_tcp);
> +    bdrv_register(&bdrv_sheepdog_unix);
>  }
>  block_init(bdrv_sheepdog_init);
> diff --git a/qemu-doc.texi b/qemu-doc.texi
> index d4eb5eb..9f41589 100644
> --- a/qemu-doc.texi
> +++ b/qemu-doc.texi
> @@ -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}
>  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
>  specify one of the Sheepdog servers to connect to.
>  @example
> diff --git a/qemu-options.hx b/qemu-options.hx
> index 09e3b9e..20b9f84 100644
> --- a/qemu-options.hx
> +++ b/qemu-options.hx
> @@ -2069,7 +2069,7 @@ devices.
>  
>  Syntax for specifying a sheepdog device
>  @example
> -sheepdog[+tcp]://[host:port]/vdiname[#snapid|#tag]
> +sheepdog[+tcp|+unix]://[host:port]/vdiname[?socket=path][#snapid|#tag]
>  @end example
>  
>  Example
>
MORITA Kazutaka - Jan. 29, 2013, 8:53 a.m.
At Tue, 29 Jan 2013 09:25:13 +0100,
Paolo Bonzini wrote:
> 
> Il 29/01/2013 01:11, MORITA Kazutaka ha scritto:
> > 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 path>[#snapid]
> 
> Should be "?socket=<socket path>".

Oops, I'll send v4, thanks!

Kazutaka

Patch

diff --git a/block/sheepdog.c b/block/sheepdog.c
index f35de36..eb7713a 100644
--- a/block/sheepdog.c
+++ b/block/sheepdog.c
@@ -299,6 +299,7 @@  typedef struct BDRVSheepdogState {
     uint32_t cache_flags;
 
     char *host_spec;
+    bool is_unix;
     int fd;
 
     CoMutex lock;
@@ -451,7 +452,18 @@  static int connect_to_sdog(BDRVSheepdogState *s)
     int fd;
     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) {
         qerror_report_err(err);
@@ -757,7 +769,7 @@  static int aio_flush_request(void *opaque)
  */
 static int get_sheep_fd(BDRVSheepdogState *s)
 {
-    int ret, fd;
+    int fd;
 
     fd = connect_to_sdog(s);
     if (fd < 0) {
@@ -766,13 +778,6 @@  static int get_sheep_fd(BDRVSheepdogState *s)
 
     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);
     return fd;
 }
@@ -789,15 +794,42 @@  static int sd_parse_uri(BDRVSheepdogState *s, const char *filename,
         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, "/")) {
         ret = -EINVAL;
         goto out;
     }
     pstrcpy(vdi, SD_MAX_VDI_LEN, uri->path + 1);
 
-    /* sheepdog[+tcp]://[host:port]/vdiname */
-    s->host_spec = g_strdup_printf("%s:%d", uri->server ?: SD_DEFAULT_ADDR,
-                                   uri->port ?: SD_DEFAULT_PORT);
+    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) {
+        /* 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 */
     if (uri->fragment) {
@@ -2097,9 +2129,35 @@  static BlockDriver bdrv_sheepdog_tcp = {
     .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)
 {
     bdrv_register(&bdrv_sheepdog);
     bdrv_register(&bdrv_sheepdog_tcp);
+    bdrv_register(&bdrv_sheepdog_unix);
 }
 block_init(bdrv_sheepdog_init);
diff --git a/qemu-doc.texi b/qemu-doc.texi
index d4eb5eb..9f41589 100644
--- a/qemu-doc.texi
+++ b/qemu-doc.texi
@@ -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}
 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
 specify one of the Sheepdog servers to connect to.
 @example
diff --git a/qemu-options.hx b/qemu-options.hx
index 09e3b9e..20b9f84 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -2069,7 +2069,7 @@  devices.
 
 Syntax for specifying a sheepdog device
 @example
-sheepdog[+tcp]://[host:port]/vdiname[#snapid|#tag]
+sheepdog[+tcp|+unix]://[host:port]/vdiname[?socket=path][#snapid|#tag]
 @end example
 
 Example