diff mbox

[v20,4/5] block/gluster: using new qapi schema

Message ID 1468947453-5433-5-git-send-email-prasanna.kalever@redhat.com (mailing list archive)
State New, archived
Headers show

Commit Message

Prasanna Kumar Kalever July 19, 2016, 4:57 p.m. UTC
this patch adds 'GlusterServer' related schema in qapi/block-core.json

Signed-off-by: Prasanna Kumar Kalever <prasanna.kalever@redhat.com>
---
 block/gluster.c      | 115 +++++++++++++++++++++++++++++----------------------
 qapi/block-core.json |  68 +++++++++++++++++++++++++++---
 2 files changed, 128 insertions(+), 55 deletions(-)

Comments

Markus Armbruster July 19, 2016, 5:30 p.m. UTC | #1
Prasanna Kumar Kalever <prasanna.kalever@redhat.com> writes:

> this patch adds 'GlusterServer' related schema in qapi/block-core.json
>
> Signed-off-by: Prasanna Kumar Kalever <prasanna.kalever@redhat.com>
> ---
>  block/gluster.c      | 115 +++++++++++++++++++++++++++++----------------------
>  qapi/block-core.json |  68 +++++++++++++++++++++++++++---
>  2 files changed, 128 insertions(+), 55 deletions(-)
>
> diff --git a/block/gluster.c b/block/gluster.c
> index 8a54ad4..c4ca59e 100644
> --- a/block/gluster.c
> +++ b/block/gluster.c
> @@ -16,6 +16,7 @@
>  
>  #define GLUSTER_OPT_FILENAME        "filename"
>  #define GLUSTER_OPT_DEBUG           "debug"
> +#define GLUSTER_DEFAULT_PORT        24007
>  #define GLUSTER_DEBUG_DEFAULT       4
>  #define GLUSTER_DEBUG_MAX           9
>  
> @@ -40,15 +41,6 @@ typedef struct BDRVGlusterReopenState {
>      struct glfs_fd *fd;
>  } BDRVGlusterReopenState;
>  
> -typedef struct GlusterConf {
> -    char *host;
> -    int port;
> -    char *volume;
> -    char *path;
> -    char *transport;
> -    int debug_level;
> -} GlusterConf;
> -
>  
>  static QemuOptsList qemu_gluster_create_opts = {
>      .name = "qemu-gluster-create-opts",
> @@ -92,18 +84,7 @@ static QemuOptsList runtime_opts = {
>  };
>  
>  
> -static void qemu_gluster_gconf_free(GlusterConf *gconf)
> -{
> -    if (gconf) {
> -        g_free(gconf->host);
> -        g_free(gconf->volume);
> -        g_free(gconf->path);
> -        g_free(gconf->transport);
> -        g_free(gconf);
> -    }
> -}
> -
> -static int parse_volume_options(GlusterConf *gconf, char *path)
> +static int parse_volume_options(BlockdevOptionsGluster *gconf, char *path)
>  {
>      char *p, *q;
>  
> @@ -160,8 +141,10 @@ static int parse_volume_options(GlusterConf *gconf, char *path)
>   * file=gluster+tcp://host.domain.com:24007/testvol/dir/a.img
>   * file=gluster+unix:///testvol/dir/a.img?socket=/tmp/glusterd.socket
>   */
> -static int qemu_gluster_parseuri(GlusterConf *gconf, const char *filename)
> +static int qemu_gluster_parse_uri(BlockdevOptionsGluster *gconf,
> +                                  const char *filename)
>  {
> +    GlusterServer *gsconf;
>      URI *uri;
>      QueryParams *qp = NULL;
>      bool is_unix = false;
> @@ -172,16 +155,18 @@ static int qemu_gluster_parseuri(GlusterConf *gconf, const char *filename)
>          return -EINVAL;
>      }
>  
> +    gconf->server = gsconf = g_new0(GlusterServer, 1);
> +
>      /* transport */
>      if (!uri->scheme || !strcmp(uri->scheme, "gluster")) {
> -        gconf->transport = g_strdup("tcp");
> +        gsconf->type = GLUSTER_TRANSPORT_TCP;
>      } else if (!strcmp(uri->scheme, "gluster+tcp")) {
> -        gconf->transport = g_strdup("tcp");
> +        gsconf->type = GLUSTER_TRANSPORT_TCP;
>      } else if (!strcmp(uri->scheme, "gluster+unix")) {
> -        gconf->transport = g_strdup("unix");
> +        gsconf->type = GLUSTER_TRANSPORT_UNIX;
>          is_unix = true;
>      } else if (!strcmp(uri->scheme, "gluster+rdma")) {
> -        gconf->transport = g_strdup("tcp");
> +        gsconf->type = GLUSTER_TRANSPORT_TCP;
>          error_report("Warning: rdma feature is not supported falling "
>                       "back to tcp");
>      } else {
> @@ -209,10 +194,14 @@ static int qemu_gluster_parseuri(GlusterConf *gconf, const char *filename)
>              ret = -EINVAL;
>              goto out;
>          }
> -        gconf->host = g_strdup(qp->p[0].value);
> +        gsconf->u.q_unix.path = g_strdup(qp->p[0].value);
>      } else {
> -        gconf->host = g_strdup(uri->server ? uri->server : "localhost");
> -        gconf->port = uri->port;
> +        gsconf->u.tcp.host = g_strdup(uri->server ? uri->server : "localhost");
> +        if (uri->port) {
> +            gsconf->u.tcp.port = g_strdup_printf("%d", uri->port);
> +        } else {
> +            gsconf->u.tcp.port = g_strdup_printf("%d", GLUSTER_DEFAULT_PORT);
> +        }

I'd prefer something like

            gsconf->u.tcp.port = g_strdup_printf("%d",
                                                 uri->has_port ? uri->port
                                                 : GLUSTER_DEFAULT_PORT);

or with a new variable port:

            port = uri->has_port ? uri->port : GLUSTER_DEFAULT_PORT;
            gsconf->u.tcp.port = g_strdup_printf("%d", port);

Not worth a respin now, we can take it as is.

>      }
>  
>  out:
> @@ -223,17 +212,18 @@ out:
>      return ret;
>  }
>  
> -static struct glfs *qemu_gluster_init(GlusterConf *gconf, const char *filename,
> -                                      Error **errp)
> +static struct glfs *qemu_gluster_init(BlockdevOptionsGluster *gconf,
> +                                      const char *filename, Error **errp)
>  {
>      struct glfs *glfs = NULL;
>      int ret;
>      int old_errno;
>  
> -    ret = qemu_gluster_parseuri(gconf, filename);
> +    ret = qemu_gluster_parse_uri(gconf, filename);
>      if (ret < 0) {
> -        error_setg(errp, "Usage: file=gluster[+transport]://[host[:port]]/"
> -                         "volume/path[?socket=...]");
> +        error_setg(errp, "Invalid URI");
> +        error_append_hint(errp, "Usage: file=gluster[+transport]://"
> +                                "[host[:port]]/volume/path[?socket=...]\n");
>          errno = -ret;
>          goto out;
>      }
> @@ -243,8 +233,16 @@ static struct glfs *qemu_gluster_init(GlusterConf *gconf, const char *filename,
>          goto out;
>      }
>  
> -    ret = glfs_set_volfile_server(glfs, gconf->transport, gconf->host,
> -            gconf->port);
> +    if (gconf->server->type == GLUSTER_TRANSPORT_UNIX) {
> +        ret = glfs_set_volfile_server(glfs,
> +                                      GlusterTransport_lookup[gconf->server->type],
> +                                      gconf->server->u.q_unix.path, 0);
> +    } else {
> +        ret = glfs_set_volfile_server(glfs,
> +                                      GlusterTransport_lookup[gconf->server->type],
> +                                      gconf->server->u.tcp.host,
> +                                      atoi(gconf->server->u.tcp.port));

atoi() is okay, because its argument can only come from
qemu_gluster_parse_uri(), so atoi() can't fail.  It'll become wrong when
the argument comes from a QMP client.

> +    }
>      if (ret < 0) {
>          goto out;
>      }
> @@ -256,15 +254,22 @@ static struct glfs *qemu_gluster_init(GlusterConf *gconf, const char *filename,
>  
>      ret = glfs_init(glfs);
>      if (ret) {
> -        error_setg_errno(errp, errno,
> -                         "Gluster connection failed for host=%s port=%d "
> -                         "volume=%s path=%s transport=%s", gconf->host,
> -                         gconf->port, gconf->volume, gconf->path,
> -                         gconf->transport);
> +        if (gconf->server->type == GLUSTER_TRANSPORT_UNIX) {
> +            error_setg(errp,
> +                       "Gluster connection for volume %s, path %s failed on "
> +                       "socket %s ", gconf->volume, gconf->path,
> +                       gconf->server->u.q_unix.path);
> +        } else {
> +            error_setg(errp,
> +                       "Gluster connection for volume %s, path %s failed on "
> +                       "host  %s and port %s ", gconf->volume, gconf->path,
> +                       gconf->server->u.tcp.host, gconf->server->u.tcp.port);
> +        }
>  
>          /* glfs_init sometimes doesn't set errno although docs suggest that */
> -        if (errno == 0)
> +        if (errno == 0) {
>              errno = EINVAL;
> +        }
>  
>          goto out;
>      }
> @@ -352,7 +357,7 @@ static int qemu_gluster_open(BlockDriverState *bs,  QDict *options,
>      BDRVGlusterState *s = bs->opaque;
>      int open_flags = 0;
>      int ret = 0;
> -    GlusterConf *gconf = g_new0(GlusterConf, 1);
> +    BlockdevOptionsGluster *gconf = NULL;
>      QemuOpts *opts;
>      Error *local_err = NULL;
>      const char *filename;
> @@ -375,7 +380,9 @@ static int qemu_gluster_open(BlockDriverState *bs,  QDict *options,
>          s->debug_level = GLUSTER_DEBUG_MAX;
>      }
>  
> +    gconf = g_new0(BlockdevOptionsGluster, 1);
>      gconf->debug_level = s->debug_level;
> +    gconf->has_debug_level = true;
>      s->glfs = qemu_gluster_init(gconf, filename, errp);
>      if (!s->glfs) {
>          ret = -errno;
> @@ -410,7 +417,9 @@ static int qemu_gluster_open(BlockDriverState *bs,  QDict *options,
>  
>  out:
>      qemu_opts_del(opts);
> -    qemu_gluster_gconf_free(gconf);
> +    if (gconf) {
> +        qapi_free_BlockdevOptionsGluster(gconf);
> +    }
>      if (!ret) {
>          return ret;
>      }
> @@ -429,7 +438,7 @@ static int qemu_gluster_reopen_prepare(BDRVReopenState *state,
>      int ret = 0;
>      BDRVGlusterState *s;
>      BDRVGlusterReopenState *reop_s;
> -    GlusterConf *gconf = NULL;
> +    BlockdevOptionsGluster *gconf;
>      int open_flags = 0;
>  
>      assert(state != NULL);
> @@ -442,9 +451,9 @@ static int qemu_gluster_reopen_prepare(BDRVReopenState *state,
>  
>      qemu_gluster_parse_flags(state->flags, &open_flags);
>  
> -    gconf = g_new0(GlusterConf, 1);
> -
> +    gconf = g_new0(BlockdevOptionsGluster, 1);
>      gconf->debug_level = s->debug_level;
> +    gconf->has_debug_level = true;
>      reop_s->glfs = qemu_gluster_init(gconf, state->bs->filename, errp);
>      if (reop_s->glfs == NULL) {
>          ret = -errno;
> @@ -470,7 +479,9 @@ static int qemu_gluster_reopen_prepare(BDRVReopenState *state,
>  
>  exit:
>      /* state->opaque will be freed in either the _abort or _commit */
> -    qemu_gluster_gconf_free(gconf);
> +    if (gconf) {
> +        qapi_free_BlockdevOptionsGluster(gconf);
> +    }
>      return ret;
>  }
>  
> @@ -572,14 +583,15 @@ static inline int qemu_gluster_zerofill(struct glfs_fd *fd, int64_t offset,
>  static int qemu_gluster_create(const char *filename,
>                                 QemuOpts *opts, Error **errp)
>  {
> +    BlockdevOptionsGluster *gconf;
>      struct glfs *glfs;
>      struct glfs_fd *fd;
>      int ret = 0;
>      int prealloc = 0;
>      int64_t total_size = 0;
>      char *tmp = NULL;
> -    GlusterConf *gconf = g_new0(GlusterConf, 1);
>  
> +    gconf = g_new0(BlockdevOptionsGluster, 1);
>      gconf->debug_level = qemu_opt_get_number_del(opts, GLUSTER_OPT_DEBUG,
>                                                   GLUSTER_DEBUG_DEFAULT);
>      if (gconf->debug_level < 0) {
> @@ -587,6 +599,7 @@ static int qemu_gluster_create(const char *filename,
>      } else if (gconf->debug_level > GLUSTER_DEBUG_MAX) {
>          gconf->debug_level = GLUSTER_DEBUG_MAX;
>      }
> +    gconf->has_debug_level = true;
>  
>      glfs = qemu_gluster_init(gconf, filename, errp);
>      if (!glfs) {
> @@ -628,7 +641,9 @@ static int qemu_gluster_create(const char *filename,
>      }
>  out:
>      g_free(tmp);
> -    qemu_gluster_gconf_free(gconf);
> +    if (gconf) {
> +        qapi_free_BlockdevOptionsGluster(gconf);
> +    }
>      if (glfs) {
>          glfs_fini(glfs);
>      }
> diff --git a/qapi/block-core.json b/qapi/block-core.json
> index a7fdb28..1fa0674 100644
> --- a/qapi/block-core.json
> +++ b/qapi/block-core.json
> @@ -1658,13 +1658,14 @@
>  # @host_device, @host_cdrom: Since 2.1
>  #
>  # Since: 2.0
> +# @gluster: Since 2.7
>  ##
>  { 'enum': 'BlockdevDriver',
>    'data': [ 'archipelago', 'blkdebug', 'blkverify', 'bochs', 'cloop',
> -            'dmg', 'file', 'ftp', 'ftps', 'host_cdrom', 'host_device',
> -            'http', 'https', 'luks', 'null-aio', 'null-co', 'parallels',
> -            'qcow', 'qcow2', 'qed', 'quorum', 'raw', 'tftp', 'vdi', 'vhdx',
> -            'vmdk', 'vpc', 'vvfat' ] }
> +            'dmg', 'file', 'ftp', 'ftps', 'gluster', 'host_cdrom',
> +            'host_device', 'http', 'https', 'luks', 'null-aio', 'null-co',
> +            'parallels', 'qcow', 'qcow2', 'qed', 'quorum', 'raw', 'tftp',
> +            'vdi', 'vhdx', 'vmdk', 'vpc', 'vvfat' ] }
>  
>  ##
>  # @BlockdevOptionsFile
> @@ -2057,6 +2058,63 @@
>              '*read-pattern': 'QuorumReadPattern' } }
>  
>  ##
> +# @GlusterTransport
> +#
> +# An enumeration of Gluster transport type
> +#
> +# @tcp:   TCP   - Transmission Control Protocol
> +#
> +# @unix:  UNIX  - Unix domain socket
> +#
> +# Since: 2.7
> +##
> +{ 'enum': 'GlusterTransport',
> +  'data': [ 'unix', 'tcp' ] }
> +
> +
> +##
> +# @GlusterServer
> +#
> +# Captures the address of a socket
> +#
> +# Details for connecting to a gluster server
> +#
> +# @type:       Transport type used for gluster connection
> +#
> +# @unix:       socket file
> +#
> +# @tcp:        host address and port number
> +#
> +# Since: 2.7
> +##
> +{ 'union': 'GlusterServer',
> +  'base': { 'type': 'GlusterTransport' },
> +  'discriminator': 'type',
> +  'data': { 'unix': 'UnixSocketAddress',
> +            'tcp': 'InetSocketAddress' } }

We might want to add comments describing the relationship to
SocketAddress, but that can be done on top.

> +
> +##
> +# @BlockdevOptionsGluster
> +#
> +# Driver specific block device options for Gluster
> +#
> +# @volume:      name of gluster volume where VM image resides
> +#
> +# @path:        absolute path to image file in gluster volume
> +#
> +# @server:      gluster server description
> +#
> +# @debug_level: #optional libgfapi log level (default '4' which is Error)
> +#
> +# Since: 2.7
> +##
> +{ 'struct': 'BlockdevOptionsGluster',
> +  'data': { 'volume': 'str',
> +            'path': 'str',
> +            'server': 'GlusterServer',
> +            '*debug_level': 'int' } }
> +
> +##
>  # @BlockdevOptions
>  #
>  # Options for creating a block device.  Many options are available for all
> @@ -2119,7 +2177,7 @@
>        'file':       'BlockdevOptionsFile',
>        'ftp':        'BlockdevOptionsFile',
>        'ftps':       'BlockdevOptionsFile',
> -# TODO gluster: Wait for structured options
> +      'gluster':    'BlockdevOptionsGluster',
>        'host_cdrom': 'BlockdevOptionsFile',
>        'host_device':'BlockdevOptionsFile',
>        'http':       'BlockdevOptionsFile',

Reviewed-by: Markus Armbruster <armbru@redhat.com>
Markus Armbruster July 19, 2016, 5:37 p.m. UTC | #2
One more thing...

Prasanna Kumar Kalever <prasanna.kalever@redhat.com> writes:

> this patch adds 'GlusterServer' related schema in qapi/block-core.json
>
> Signed-off-by: Prasanna Kumar Kalever <prasanna.kalever@redhat.com>
> ---
>  block/gluster.c      | 115 +++++++++++++++++++++++++++++----------------------
>  qapi/block-core.json |  68 +++++++++++++++++++++++++++---
>  2 files changed, 128 insertions(+), 55 deletions(-)
>
> diff --git a/block/gluster.c b/block/gluster.c
> index 8a54ad4..c4ca59e 100644
> --- a/block/gluster.c
> +++ b/block/gluster.c
[...]
> @@ -628,7 +641,9 @@ static int qemu_gluster_create(const char *filename,
>      }
>  out:
>      g_free(tmp);
> -    qemu_gluster_gconf_free(gconf);
> +    if (gconf) {
> +        qapi_free_BlockdevOptionsGluster(gconf);
> +    }

qapi_free_FOO(NULL) is safe.  Let's drop the conditional.  Could be done
on commit, or as a follow-up cleanup.

>      if (glfs) {
>          glfs_fini(glfs);
>      }
[...]

R-by stands.
Eric Blake July 19, 2016, 6:38 p.m. UTC | #3
On 07/19/2016 10:57 AM, Prasanna Kumar Kalever wrote:
> this patch adds 'GlusterServer' related schema in qapi/block-core.json
> 
> Signed-off-by: Prasanna Kumar Kalever <prasanna.kalever@redhat.com>
> ---
>  block/gluster.c      | 115 +++++++++++++++++++++++++++++----------------------
>  qapi/block-core.json |  68 +++++++++++++++++++++++++++---
>  2 files changed, 128 insertions(+), 55 deletions(-)
> 

> @@ -256,15 +254,22 @@ static struct glfs *qemu_gluster_init(GlusterConf *gconf, const char *filename,
>  
>      ret = glfs_init(glfs);
>      if (ret) {
> -        error_setg_errno(errp, errno,
> -                         "Gluster connection failed for host=%s port=%d "
> -                         "volume=%s path=%s transport=%s", gconf->host,
> -                         gconf->port, gconf->volume, gconf->path,
> -                         gconf->transport);
> +        if (gconf->server->type == GLUSTER_TRANSPORT_UNIX) {
> +            error_setg(errp,
> +                       "Gluster connection for volume %s, path %s failed on "
> +                       "socket %s ", gconf->volume, gconf->path,
> +                       gconf->server->u.q_unix.path);
> +        } else {
> +            error_setg(errp,
> +                       "Gluster connection for volume %s, path %s failed on "
> +                       "host  %s and port %s ", gconf->volume, gconf->path,
> +                       gconf->server->u.tcp.host, gconf->server->u.tcp.port);
> +        }

You are throwing away the errno information that used to be reported
here.  Is that intentional?

>  
>          /* glfs_init sometimes doesn't set errno although docs suggest that */
> -        if (errno == 0)
> +        if (errno == 0) {
>              errno = EINVAL;
> +        }

Pre-existing, but this is too late for messing with errno.  You are not
guaranteed that errno is unchanged by error_setg_errno().  You aren't
even guaranteed that errno == 0 after glfs_init() if it wasn't 0 before
entry.  You probably want a separate patch that reorders this to:

errno = 0;
ret = glfs_init(glfs);
if (ret) {
    if (!errno) {
        errno = EINVAL;
    }
    error_setg...

> +++ b/qapi/block-core.json
> @@ -1658,13 +1658,14 @@
>  # @host_device, @host_cdrom: Since 2.1
>  #
>  # Since: 2.0
> +# @gluster: Since 2.7

I would stick this line a bit earlier:

# @host_device, @host_cdrom: Since 2.1
# @gluster: Since 2.7
#
# Since: 2.0

> @@ -2057,6 +2058,63 @@
>              '*read-pattern': 'QuorumReadPattern' } }
>  
>  ##
> +# @GlusterTransport
> +#
> +# An enumeration of Gluster transport type

Maybe s/type/types/

> +#
> +# @tcp:   TCP   - Transmission Control Protocol
> +#
> +# @unix:  UNIX  - Unix domain socket
> +#
> +# Since: 2.7
> +##
> +{ 'enum': 'GlusterTransport',
> +  'data': [ 'unix', 'tcp' ] }
> +
> +
> +##
> +# @GlusterServer
> +#
> +# Captures the address of a socket
> +#
> +# Details for connecting to a gluster server
> +#
> +# @type:       Transport type used for gluster connection
> +#
> +# @unix:       socket file
> +#
> +# @tcp:        host address and port number
> +#
> +# Since: 2.7
> +##
> +{ 'union': 'GlusterServer',
> +  'base': { 'type': 'GlusterTransport' },
> +  'discriminator': 'type',
> +  'data': { 'unix': 'UnixSocketAddress',
> +            'tcp': 'InetSocketAddress' } }
> +
> +##
> +# @BlockdevOptionsGluster
> +#
> +# Driver specific block device options for Gluster
> +#
> +# @volume:      name of gluster volume where VM image resides
> +#
> +# @path:        absolute path to image file in gluster volume
> +#
> +# @server:      gluster server description
> +#
> +# @debug_level: #optional libgfapi log level (default '4' which is Error)

s/debug_level/debug-level/ - all new QAPI interfaces should prefer '-'
over '_' (the generated C code is the same, though)

> +#
> +# Since: 2.7
> +##
> +{ 'struct': 'BlockdevOptionsGluster',
> +  'data': { 'volume': 'str',
> +            'path': 'str',
> +            'server': 'GlusterServer',
> +            '*debug_level': 'int' } }
> +
> +##
>  # @BlockdevOptions
>  #
>  # Options for creating a block device.  Many options are available for all
> @@ -2119,7 +2177,7 @@
>        'file':       'BlockdevOptionsFile',
>        'ftp':        'BlockdevOptionsFile',
>        'ftps':       'BlockdevOptionsFile',
> -# TODO gluster: Wait for structured options
> +      'gluster':    'BlockdevOptionsGluster',
>        'host_cdrom': 'BlockdevOptionsFile',
>        'host_device':'BlockdevOptionsFile',
>        'http':       'BlockdevOptionsFile',
> 

Between my findings and Markus', it's up to the maintainer whether to
take this as-is and then fix up the problems with a followup patch, or
whether we need a v21.

Reviewed-by: Eric Blake <eblake@redhat.com>
Jeff Cody July 19, 2016, 8:39 p.m. UTC | #4
On Tue, Jul 19, 2016 at 10:27:32PM +0530, Prasanna Kumar Kalever wrote:
> this patch adds 'GlusterServer' related schema in qapi/block-core.json
> 
> Signed-off-by: Prasanna Kumar Kalever <prasanna.kalever@redhat.com>
> ---
>  block/gluster.c      | 115 +++++++++++++++++++++++++++++----------------------
>  qapi/block-core.json |  68 +++++++++++++++++++++++++++---
>  2 files changed, 128 insertions(+), 55 deletions(-)
> 
> diff --git a/block/gluster.c b/block/gluster.c
> index 8a54ad4..c4ca59e 100644
> --- a/block/gluster.c
> +++ b/block/gluster.c
> @@ -16,6 +16,7 @@
>  
>  #define GLUSTER_OPT_FILENAME        "filename"
>  #define GLUSTER_OPT_DEBUG           "debug"
> +#define GLUSTER_DEFAULT_PORT        24007
>  #define GLUSTER_DEBUG_DEFAULT       4
>  #define GLUSTER_DEBUG_MAX           9
>  
> @@ -40,15 +41,6 @@ typedef struct BDRVGlusterReopenState {
>      struct glfs_fd *fd;
>  } BDRVGlusterReopenState;
>  
> -typedef struct GlusterConf {
> -    char *host;
> -    int port;
> -    char *volume;
> -    char *path;
> -    char *transport;
> -    int debug_level;
> -} GlusterConf;
> -
>  
>  static QemuOptsList qemu_gluster_create_opts = {
>      .name = "qemu-gluster-create-opts",
> @@ -92,18 +84,7 @@ static QemuOptsList runtime_opts = {
>  };
>  
>  
> -static void qemu_gluster_gconf_free(GlusterConf *gconf)
> -{
> -    if (gconf) {
> -        g_free(gconf->host);
> -        g_free(gconf->volume);
> -        g_free(gconf->path);
> -        g_free(gconf->transport);
> -        g_free(gconf);
> -    }
> -}
> -
> -static int parse_volume_options(GlusterConf *gconf, char *path)
> +static int parse_volume_options(BlockdevOptionsGluster *gconf, char *path)
>  {
>      char *p, *q;
>  
> @@ -160,8 +141,10 @@ static int parse_volume_options(GlusterConf *gconf, char *path)
>   * file=gluster+tcp://host.domain.com:24007/testvol/dir/a.img
>   * file=gluster+unix:///testvol/dir/a.img?socket=/tmp/glusterd.socket
>   */
> -static int qemu_gluster_parseuri(GlusterConf *gconf, const char *filename)
> +static int qemu_gluster_parse_uri(BlockdevOptionsGluster *gconf,
> +                                  const char *filename)
>  {
> +    GlusterServer *gsconf;
>      URI *uri;
>      QueryParams *qp = NULL;
>      bool is_unix = false;
> @@ -172,16 +155,18 @@ static int qemu_gluster_parseuri(GlusterConf *gconf, const char *filename)
>          return -EINVAL;
>      }
>  
> +    gconf->server = gsconf = g_new0(GlusterServer, 1);
> +
>      /* transport */
>      if (!uri->scheme || !strcmp(uri->scheme, "gluster")) {
> -        gconf->transport = g_strdup("tcp");
> +        gsconf->type = GLUSTER_TRANSPORT_TCP;
>      } else if (!strcmp(uri->scheme, "gluster+tcp")) {
> -        gconf->transport = g_strdup("tcp");
> +        gsconf->type = GLUSTER_TRANSPORT_TCP;
>      } else if (!strcmp(uri->scheme, "gluster+unix")) {
> -        gconf->transport = g_strdup("unix");
> +        gsconf->type = GLUSTER_TRANSPORT_UNIX;
>          is_unix = true;
>      } else if (!strcmp(uri->scheme, "gluster+rdma")) {
> -        gconf->transport = g_strdup("tcp");
> +        gsconf->type = GLUSTER_TRANSPORT_TCP;
>          error_report("Warning: rdma feature is not supported falling "
>                       "back to tcp");
>      } else {
> @@ -209,10 +194,14 @@ static int qemu_gluster_parseuri(GlusterConf *gconf, const char *filename)
>              ret = -EINVAL;
>              goto out;
>          }
> -        gconf->host = g_strdup(qp->p[0].value);
> +        gsconf->u.q_unix.path = g_strdup(qp->p[0].value);
>      } else {
> -        gconf->host = g_strdup(uri->server ? uri->server : "localhost");
> -        gconf->port = uri->port;
> +        gsconf->u.tcp.host = g_strdup(uri->server ? uri->server : "localhost");
> +        if (uri->port) {
> +            gsconf->u.tcp.port = g_strdup_printf("%d", uri->port);
> +        } else {
> +            gsconf->u.tcp.port = g_strdup_printf("%d", GLUSTER_DEFAULT_PORT);
> +        }
>      }
>  
>  out:
> @@ -223,17 +212,18 @@ out:
>      return ret;
>  }
>  
> -static struct glfs *qemu_gluster_init(GlusterConf *gconf, const char *filename,
> -                                      Error **errp)
> +static struct glfs *qemu_gluster_init(BlockdevOptionsGluster *gconf,
> +                                      const char *filename, Error **errp)
>  {
>      struct glfs *glfs = NULL;
>      int ret;
>      int old_errno;
>  
> -    ret = qemu_gluster_parseuri(gconf, filename);
> +    ret = qemu_gluster_parse_uri(gconf, filename);
>      if (ret < 0) {
> -        error_setg(errp, "Usage: file=gluster[+transport]://[host[:port]]/"
> -                         "volume/path[?socket=...]");
> +        error_setg(errp, "Invalid URI");
> +        error_append_hint(errp, "Usage: file=gluster[+transport]://"
> +                                "[host[:port]]/volume/path[?socket=...]\n");
>          errno = -ret;
>          goto out;
>      }
> @@ -243,8 +233,16 @@ static struct glfs *qemu_gluster_init(GlusterConf *gconf, const char *filename,
>          goto out;
>      }
>  
> -    ret = glfs_set_volfile_server(glfs, gconf->transport, gconf->host,
> -            gconf->port);
> +    if (gconf->server->type == GLUSTER_TRANSPORT_UNIX) {
> +        ret = glfs_set_volfile_server(glfs,
> +                                      GlusterTransport_lookup[gconf->server->type],

Formatting issue found by checkpatch; exceeds 80 char.  Will fix on commit,
no need for respin.

> +                                      gconf->server->u.q_unix.path, 0);
> +    } else {
> +        ret = glfs_set_volfile_server(glfs,
> +                                      GlusterTransport_lookup[gconf->server->type],

Formatting issue found by checkpatch; exceeds 80 char.  Will fix on commit,
no need for respin.


> +                                      gconf->server->u.tcp.host,
> +                                      atoi(gconf->server->u.tcp.port));
> +    }
>      if (ret < 0) {
>          goto out;
>      }
> @@ -256,15 +254,22 @@ static struct glfs *qemu_gluster_init(GlusterConf *gconf, const char *filename,
>  
>      ret = glfs_init(glfs);
>      if (ret) {
> -        error_setg_errno(errp, errno,
> -                         "Gluster connection failed for host=%s port=%d "
> -                         "volume=%s path=%s transport=%s", gconf->host,
> -                         gconf->port, gconf->volume, gconf->path,
> -                         gconf->transport);
> +        if (gconf->server->type == GLUSTER_TRANSPORT_UNIX) {
> +            error_setg(errp,
> +                       "Gluster connection for volume %s, path %s failed on "
> +                       "socket %s ", gconf->volume, gconf->path,
> +                       gconf->server->u.q_unix.path);
> +        } else {
> +            error_setg(errp,
> +                       "Gluster connection for volume %s, path %s failed on "
> +                       "host  %s and port %s ", gconf->volume, gconf->path,
> +                       gconf->server->u.tcp.host, gconf->server->u.tcp.port);
> +        }
>  
>          /* glfs_init sometimes doesn't set errno although docs suggest that */
> -        if (errno == 0)
> +        if (errno == 0) {
>              errno = EINVAL;
> +        }

Eric pointed out the errno risk here; as this is pre-existing, nothing to
hold up this patch (can be fixed in later patch).

>  
>          goto out;
>      }
> @@ -352,7 +357,7 @@ static int qemu_gluster_open(BlockDriverState *bs,  QDict *options,
>      BDRVGlusterState *s = bs->opaque;
>      int open_flags = 0;
>      int ret = 0;
> -    GlusterConf *gconf = g_new0(GlusterConf, 1);
> +    BlockdevOptionsGluster *gconf = NULL;
>      QemuOpts *opts;
>      Error *local_err = NULL;
>      const char *filename;
> @@ -375,7 +380,9 @@ static int qemu_gluster_open(BlockDriverState *bs,  QDict *options,
>          s->debug_level = GLUSTER_DEBUG_MAX;
>      }
>  
> +    gconf = g_new0(BlockdevOptionsGluster, 1);
>      gconf->debug_level = s->debug_level;
> +    gconf->has_debug_level = true;
>      s->glfs = qemu_gluster_init(gconf, filename, errp);
>      if (!s->glfs) {
>          ret = -errno;
> @@ -410,7 +417,9 @@ static int qemu_gluster_open(BlockDriverState *bs,  QDict *options,
>  
>  out:
>      qemu_opts_del(opts);
> -    qemu_gluster_gconf_free(gconf);
> +    if (gconf) {
> +        qapi_free_BlockdevOptionsGluster(gconf);
> +    }

Per Markus's suggestion, will remove conditional on commit.

>      if (!ret) {
>          return ret;
>      }
> @@ -429,7 +438,7 @@ static int qemu_gluster_reopen_prepare(BDRVReopenState *state,
>      int ret = 0;
>      BDRVGlusterState *s;
>      BDRVGlusterReopenState *reop_s;
> -    GlusterConf *gconf = NULL;
> +    BlockdevOptionsGluster *gconf;
>      int open_flags = 0;
>  
>      assert(state != NULL);
> @@ -442,9 +451,9 @@ static int qemu_gluster_reopen_prepare(BDRVReopenState *state,
>  
>      qemu_gluster_parse_flags(state->flags, &open_flags);
>  
> -    gconf = g_new0(GlusterConf, 1);
> -
> +    gconf = g_new0(BlockdevOptionsGluster, 1);
>      gconf->debug_level = s->debug_level;
> +    gconf->has_debug_level = true;
>      reop_s->glfs = qemu_gluster_init(gconf, state->bs->filename, errp);
>      if (reop_s->glfs == NULL) {
>          ret = -errno;
> @@ -470,7 +479,9 @@ static int qemu_gluster_reopen_prepare(BDRVReopenState *state,
>  
>  exit:
>      /* state->opaque will be freed in either the _abort or _commit */
> -    qemu_gluster_gconf_free(gconf);
> +    if (gconf) {
> +        qapi_free_BlockdevOptionsGluster(gconf);
> +    }

Here too.

>      return ret;
>  }
>  
> @@ -572,14 +583,15 @@ static inline int qemu_gluster_zerofill(struct glfs_fd *fd, int64_t offset,
>  static int qemu_gluster_create(const char *filename,
>                                 QemuOpts *opts, Error **errp)
>  {
> +    BlockdevOptionsGluster *gconf;
>      struct glfs *glfs;
>      struct glfs_fd *fd;
>      int ret = 0;
>      int prealloc = 0;
>      int64_t total_size = 0;
>      char *tmp = NULL;
> -    GlusterConf *gconf = g_new0(GlusterConf, 1);
>  
> +    gconf = g_new0(BlockdevOptionsGluster, 1);
>      gconf->debug_level = qemu_opt_get_number_del(opts, GLUSTER_OPT_DEBUG,
>                                                   GLUSTER_DEBUG_DEFAULT);
>      if (gconf->debug_level < 0) {
> @@ -587,6 +599,7 @@ static int qemu_gluster_create(const char *filename,
>      } else if (gconf->debug_level > GLUSTER_DEBUG_MAX) {
>          gconf->debug_level = GLUSTER_DEBUG_MAX;
>      }
> +    gconf->has_debug_level = true;
>  
>      glfs = qemu_gluster_init(gconf, filename, errp);
>      if (!glfs) {
> @@ -628,7 +641,9 @@ static int qemu_gluster_create(const char *filename,
>      }
>  out:
>      g_free(tmp);
> -    qemu_gluster_gconf_free(gconf);
> +    if (gconf) {
> +        qapi_free_BlockdevOptionsGluster(gconf);
> +    }
>      if (glfs) {
>          glfs_fini(glfs);
>      }
> diff --git a/qapi/block-core.json b/qapi/block-core.json
> index a7fdb28..1fa0674 100644
> --- a/qapi/block-core.json
> +++ b/qapi/block-core.json
> @@ -1658,13 +1658,14 @@
>  # @host_device, @host_cdrom: Since 2.1
>  #
>  # Since: 2.0
> +# @gluster: Since 2.7
>  ##
>  { 'enum': 'BlockdevDriver',
>    'data': [ 'archipelago', 'blkdebug', 'blkverify', 'bochs', 'cloop',
> -            'dmg', 'file', 'ftp', 'ftps', 'host_cdrom', 'host_device',
> -            'http', 'https', 'luks', 'null-aio', 'null-co', 'parallels',
> -            'qcow', 'qcow2', 'qed', 'quorum', 'raw', 'tftp', 'vdi', 'vhdx',
> -            'vmdk', 'vpc', 'vvfat' ] }
> +            'dmg', 'file', 'ftp', 'ftps', 'gluster', 'host_cdrom',
> +            'host_device', 'http', 'https', 'luks', 'null-aio', 'null-co',
> +            'parallels', 'qcow', 'qcow2', 'qed', 'quorum', 'raw', 'tftp',
> +            'vdi', 'vhdx', 'vmdk', 'vpc', 'vvfat' ] }
>  
>  ##
>  # @BlockdevOptionsFile
> @@ -2057,6 +2058,63 @@
>              '*read-pattern': 'QuorumReadPattern' } }
>  
>  ##
> +# @GlusterTransport
> +#
> +# An enumeration of Gluster transport type
> +#
> +# @tcp:   TCP   - Transmission Control Protocol
> +#
> +# @unix:  UNIX  - Unix domain socket
> +#
> +# Since: 2.7
> +##
> +{ 'enum': 'GlusterTransport',
> +  'data': [ 'unix', 'tcp' ] }
> +
> +
> +##
> +# @GlusterServer
> +#
> +# Captures the address of a socket
> +#
> +# Details for connecting to a gluster server
> +#
> +# @type:       Transport type used for gluster connection
> +#
> +# @unix:       socket file
> +#
> +# @tcp:        host address and port number
> +#
> +# Since: 2.7
> +##
> +{ 'union': 'GlusterServer',
> +  'base': { 'type': 'GlusterTransport' },
> +  'discriminator': 'type',
> +  'data': { 'unix': 'UnixSocketAddress',
> +            'tcp': 'InetSocketAddress' } }
> +
> +##
> +# @BlockdevOptionsGluster
> +#
> +# Driver specific block device options for Gluster
> +#
> +# @volume:      name of gluster volume where VM image resides
> +#
> +# @path:        absolute path to image file in gluster volume
> +#
> +# @server:      gluster server description
> +#
> +# @debug_level: #optional libgfapi log level (default '4' which is Error)
> +#

Per Eric's suggestion, will change this to debug-level on commit.

> +# Since: 2.7
> +##
> +{ 'struct': 'BlockdevOptionsGluster',
> +  'data': { 'volume': 'str',
> +            'path': 'str',
> +            'server': 'GlusterServer',
> +            '*debug_level': 'int' } }
> +
> +##
>  # @BlockdevOptions
>  #
>  # Options for creating a block device.  Many options are available for all
> @@ -2119,7 +2177,7 @@
>        'file':       'BlockdevOptionsFile',
>        'ftp':        'BlockdevOptionsFile',
>        'ftps':       'BlockdevOptionsFile',
> -# TODO gluster: Wait for structured options
> +      'gluster':    'BlockdevOptionsGluster',
>        'host_cdrom': 'BlockdevOptionsFile',
>        'host_device':'BlockdevOptionsFile',
>        'http':       'BlockdevOptionsFile',
> -- 
> 2.7.4
>

After fix-ups:

Reviewed-by: Jeff Cody <jcody@redhat.com>
Jeff Cody July 19, 2016, 9:31 p.m. UTC | #5
On Tue, Jul 19, 2016 at 04:39:39PM -0400, Jeff Cody wrote:
> On Tue, Jul 19, 2016 at 10:27:32PM +0530, Prasanna Kumar Kalever wrote:
> > this patch adds 'GlusterServer' related schema in qapi/block-core.json
> > 
> > Signed-off-by: Prasanna Kumar Kalever <prasanna.kalever@redhat.com>
> > ---
> >  block/gluster.c      | 115 +++++++++++++++++++++++++++++----------------------
> >  qapi/block-core.json |  68 +++++++++++++++++++++++++++---
> >  2 files changed, 128 insertions(+), 55 deletions(-)
> > 
> > diff --git a/block/gluster.c b/block/gluster.c
> > index 8a54ad4..c4ca59e 100644
> > --- a/block/gluster.c
> > +++ b/block/gluster.c
> > @@ -16,6 +16,7 @@
> >  
> >  #define GLUSTER_OPT_FILENAME        "filename"
> >  #define GLUSTER_OPT_DEBUG           "debug"
> > +#define GLUSTER_DEFAULT_PORT        24007
> >  #define GLUSTER_DEBUG_DEFAULT       4
> >  #define GLUSTER_DEBUG_MAX           9
> >  
> > @@ -40,15 +41,6 @@ typedef struct BDRVGlusterReopenState {
> >      struct glfs_fd *fd;
> >  } BDRVGlusterReopenState;
> >  
> > -typedef struct GlusterConf {
> > -    char *host;
> > -    int port;
> > -    char *volume;
> > -    char *path;
> > -    char *transport;
> > -    int debug_level;
> > -} GlusterConf;
> > -
> >  
> >  static QemuOptsList qemu_gluster_create_opts = {
> >      .name = "qemu-gluster-create-opts",
> > @@ -92,18 +84,7 @@ static QemuOptsList runtime_opts = {
> >  };
> >  
> >  
> > -static void qemu_gluster_gconf_free(GlusterConf *gconf)
> > -{
> > -    if (gconf) {
> > -        g_free(gconf->host);
> > -        g_free(gconf->volume);
> > -        g_free(gconf->path);
> > -        g_free(gconf->transport);
> > -        g_free(gconf);
> > -    }
> > -}
> > -
> > -static int parse_volume_options(GlusterConf *gconf, char *path)
> > +static int parse_volume_options(BlockdevOptionsGluster *gconf, char *path)
> >  {
> >      char *p, *q;
> >  
> > @@ -160,8 +141,10 @@ static int parse_volume_options(GlusterConf *gconf, char *path)
> >   * file=gluster+tcp://host.domain.com:24007/testvol/dir/a.img
> >   * file=gluster+unix:///testvol/dir/a.img?socket=/tmp/glusterd.socket
> >   */
> > -static int qemu_gluster_parseuri(GlusterConf *gconf, const char *filename)
> > +static int qemu_gluster_parse_uri(BlockdevOptionsGluster *gconf,
> > +                                  const char *filename)
> >  {
> > +    GlusterServer *gsconf;
> >      URI *uri;
> >      QueryParams *qp = NULL;
> >      bool is_unix = false;
> > @@ -172,16 +155,18 @@ static int qemu_gluster_parseuri(GlusterConf *gconf, const char *filename)
> >          return -EINVAL;
> >      }
> >  
> > +    gconf->server = gsconf = g_new0(GlusterServer, 1);
> > +
> >      /* transport */
> >      if (!uri->scheme || !strcmp(uri->scheme, "gluster")) {
> > -        gconf->transport = g_strdup("tcp");
> > +        gsconf->type = GLUSTER_TRANSPORT_TCP;
> >      } else if (!strcmp(uri->scheme, "gluster+tcp")) {
> > -        gconf->transport = g_strdup("tcp");
> > +        gsconf->type = GLUSTER_TRANSPORT_TCP;
> >      } else if (!strcmp(uri->scheme, "gluster+unix")) {
> > -        gconf->transport = g_strdup("unix");
> > +        gsconf->type = GLUSTER_TRANSPORT_UNIX;
> >          is_unix = true;
> >      } else if (!strcmp(uri->scheme, "gluster+rdma")) {
> > -        gconf->transport = g_strdup("tcp");
> > +        gsconf->type = GLUSTER_TRANSPORT_TCP;
> >          error_report("Warning: rdma feature is not supported falling "
> >                       "back to tcp");
> >      } else {
> > @@ -209,10 +194,14 @@ static int qemu_gluster_parseuri(GlusterConf *gconf, const char *filename)
> >              ret = -EINVAL;
> >              goto out;
> >          }
> > -        gconf->host = g_strdup(qp->p[0].value);
> > +        gsconf->u.q_unix.path = g_strdup(qp->p[0].value);
> >      } else {
> > -        gconf->host = g_strdup(uri->server ? uri->server : "localhost");
> > -        gconf->port = uri->port;
> > +        gsconf->u.tcp.host = g_strdup(uri->server ? uri->server : "localhost");
> > +        if (uri->port) {
> > +            gsconf->u.tcp.port = g_strdup_printf("%d", uri->port);
> > +        } else {
> > +            gsconf->u.tcp.port = g_strdup_printf("%d", GLUSTER_DEFAULT_PORT);
> > +        }
> >      }
> >  
> >  out:
> > @@ -223,17 +212,18 @@ out:
> >      return ret;
> >  }
> >  
> > -static struct glfs *qemu_gluster_init(GlusterConf *gconf, const char *filename,
> > -                                      Error **errp)
> > +static struct glfs *qemu_gluster_init(BlockdevOptionsGluster *gconf,
> > +                                      const char *filename, Error **errp)
> >  {
> >      struct glfs *glfs = NULL;
> >      int ret;
> >      int old_errno;
> >  
> > -    ret = qemu_gluster_parseuri(gconf, filename);
> > +    ret = qemu_gluster_parse_uri(gconf, filename);
> >      if (ret < 0) {
> > -        error_setg(errp, "Usage: file=gluster[+transport]://[host[:port]]/"
> > -                         "volume/path[?socket=...]");
> > +        error_setg(errp, "Invalid URI");
> > +        error_append_hint(errp, "Usage: file=gluster[+transport]://"
> > +                                "[host[:port]]/volume/path[?socket=...]\n");
> >          errno = -ret;
> >          goto out;
> >      }
> > @@ -243,8 +233,16 @@ static struct glfs *qemu_gluster_init(GlusterConf *gconf, const char *filename,
> >          goto out;
> >      }
> >  
> > -    ret = glfs_set_volfile_server(glfs, gconf->transport, gconf->host,
> > -            gconf->port);
> > +    if (gconf->server->type == GLUSTER_TRANSPORT_UNIX) {
> > +        ret = glfs_set_volfile_server(glfs,
> > +                                      GlusterTransport_lookup[gconf->server->type],
> 
> Formatting issue found by checkpatch; exceeds 80 char.  Will fix on commit,
> no need for respin.
> 
> > +                                      gconf->server->u.q_unix.path, 0);
> > +    } else {
> > +        ret = glfs_set_volfile_server(glfs,
> > +                                      GlusterTransport_lookup[gconf->server->type],
> 
> Formatting issue found by checkpatch; exceeds 80 char.  Will fix on commit,
> no need for respin.
> 
> 
> > +                                      gconf->server->u.tcp.host,
> > +                                      atoi(gconf->server->u.tcp.port));
> > +    }
> >      if (ret < 0) {
> >          goto out;
> >      }
> > @@ -256,15 +254,22 @@ static struct glfs *qemu_gluster_init(GlusterConf *gconf, const char *filename,
> >  
> >      ret = glfs_init(glfs);
> >      if (ret) {
> > -        error_setg_errno(errp, errno,
> > -                         "Gluster connection failed for host=%s port=%d "
> > -                         "volume=%s path=%s transport=%s", gconf->host,
> > -                         gconf->port, gconf->volume, gconf->path,
> > -                         gconf->transport);
> > +        if (gconf->server->type == GLUSTER_TRANSPORT_UNIX) {
> > +            error_setg(errp,
> > +                       "Gluster connection for volume %s, path %s failed on "
> > +                       "socket %s ", gconf->volume, gconf->path,
> > +                       gconf->server->u.q_unix.path);
> > +        } else {
> > +            error_setg(errp,
> > +                       "Gluster connection for volume %s, path %s failed on "
> > +                       "host  %s and port %s ", gconf->volume, gconf->path,
> > +                       gconf->server->u.tcp.host, gconf->server->u.tcp.port);
> > +        }
> >  
> >          /* glfs_init sometimes doesn't set errno although docs suggest that */
> > -        if (errno == 0)
> > +        if (errno == 0) {
> >              errno = EINVAL;
> > +        }
> 
> Eric pointed out the errno risk here; as this is pre-existing, nothing to
> hold up this patch (can be fixed in later patch).
> 
> >  
> >          goto out;
> >      }
> > @@ -352,7 +357,7 @@ static int qemu_gluster_open(BlockDriverState *bs,  QDict *options,
> >      BDRVGlusterState *s = bs->opaque;
> >      int open_flags = 0;
> >      int ret = 0;
> > -    GlusterConf *gconf = g_new0(GlusterConf, 1);
> > +    BlockdevOptionsGluster *gconf = NULL;
> >      QemuOpts *opts;
> >      Error *local_err = NULL;
> >      const char *filename;
> > @@ -375,7 +380,9 @@ static int qemu_gluster_open(BlockDriverState *bs,  QDict *options,
> >          s->debug_level = GLUSTER_DEBUG_MAX;
> >      }
> >  
> > +    gconf = g_new0(BlockdevOptionsGluster, 1);
> >      gconf->debug_level = s->debug_level;
> > +    gconf->has_debug_level = true;
> >      s->glfs = qemu_gluster_init(gconf, filename, errp);
> >      if (!s->glfs) {
> >          ret = -errno;
> > @@ -410,7 +417,9 @@ static int qemu_gluster_open(BlockDriverState *bs,  QDict *options,
> >  
> >  out:
> >      qemu_opts_del(opts);
> > -    qemu_gluster_gconf_free(gconf);
> > +    if (gconf) {
> > +        qapi_free_BlockdevOptionsGluster(gconf);
> > +    }
> 
> Per Markus's suggestion, will remove conditional on commit.
> 
> >      if (!ret) {
> >          return ret;
> >      }
> > @@ -429,7 +438,7 @@ static int qemu_gluster_reopen_prepare(BDRVReopenState *state,
> >      int ret = 0;
> >      BDRVGlusterState *s;
> >      BDRVGlusterReopenState *reop_s;
> > -    GlusterConf *gconf = NULL;
> > +    BlockdevOptionsGluster *gconf;
> >      int open_flags = 0;
> >  
> >      assert(state != NULL);
> > @@ -442,9 +451,9 @@ static int qemu_gluster_reopen_prepare(BDRVReopenState *state,
> >  
> >      qemu_gluster_parse_flags(state->flags, &open_flags);
> >  
> > -    gconf = g_new0(GlusterConf, 1);
> > -
> > +    gconf = g_new0(BlockdevOptionsGluster, 1);
> >      gconf->debug_level = s->debug_level;
> > +    gconf->has_debug_level = true;
> >      reop_s->glfs = qemu_gluster_init(gconf, state->bs->filename, errp);
> >      if (reop_s->glfs == NULL) {
> >          ret = -errno;
> > @@ -470,7 +479,9 @@ static int qemu_gluster_reopen_prepare(BDRVReopenState *state,
> >  
> >  exit:
> >      /* state->opaque will be freed in either the _abort or _commit */
> > -    qemu_gluster_gconf_free(gconf);
> > +    if (gconf) {
> > +        qapi_free_BlockdevOptionsGluster(gconf);
> > +    }
> 
> Here too.
> 
> >      return ret;
> >  }
> >  
> > @@ -572,14 +583,15 @@ static inline int qemu_gluster_zerofill(struct glfs_fd *fd, int64_t offset,
> >  static int qemu_gluster_create(const char *filename,
> >                                 QemuOpts *opts, Error **errp)
> >  {
> > +    BlockdevOptionsGluster *gconf;
> >      struct glfs *glfs;
> >      struct glfs_fd *fd;
> >      int ret = 0;
> >      int prealloc = 0;
> >      int64_t total_size = 0;
> >      char *tmp = NULL;
> > -    GlusterConf *gconf = g_new0(GlusterConf, 1);
> >  
> > +    gconf = g_new0(BlockdevOptionsGluster, 1);
> >      gconf->debug_level = qemu_opt_get_number_del(opts, GLUSTER_OPT_DEBUG,
> >                                                   GLUSTER_DEBUG_DEFAULT);
> >      if (gconf->debug_level < 0) {
> > @@ -587,6 +599,7 @@ static int qemu_gluster_create(const char *filename,
> >      } else if (gconf->debug_level > GLUSTER_DEBUG_MAX) {
> >          gconf->debug_level = GLUSTER_DEBUG_MAX;
> >      }
> > +    gconf->has_debug_level = true;
> >  
> >      glfs = qemu_gluster_init(gconf, filename, errp);
> >      if (!glfs) {
> > @@ -628,7 +641,9 @@ static int qemu_gluster_create(const char *filename,
> >      }
> >  out:
> >      g_free(tmp);
> > -    qemu_gluster_gconf_free(gconf);
> > +    if (gconf) {
> > +        qapi_free_BlockdevOptionsGluster(gconf);
> > +    }

I almost missed this one; will remove this conditional as well.

> >      if (glfs) {
> >          glfs_fini(glfs);
> >      }
> > diff --git a/qapi/block-core.json b/qapi/block-core.json
> > index a7fdb28..1fa0674 100644
> > --- a/qapi/block-core.json
> > +++ b/qapi/block-core.json
> > @@ -1658,13 +1658,14 @@
> >  # @host_device, @host_cdrom: Since 2.1
> >  #
> >  # Since: 2.0
> > +# @gluster: Since 2.7
> >  ##
> >  { 'enum': 'BlockdevDriver',
> >    'data': [ 'archipelago', 'blkdebug', 'blkverify', 'bochs', 'cloop',
> > -            'dmg', 'file', 'ftp', 'ftps', 'host_cdrom', 'host_device',
> > -            'http', 'https', 'luks', 'null-aio', 'null-co', 'parallels',
> > -            'qcow', 'qcow2', 'qed', 'quorum', 'raw', 'tftp', 'vdi', 'vhdx',
> > -            'vmdk', 'vpc', 'vvfat' ] }
> > +            'dmg', 'file', 'ftp', 'ftps', 'gluster', 'host_cdrom',
> > +            'host_device', 'http', 'https', 'luks', 'null-aio', 'null-co',
> > +            'parallels', 'qcow', 'qcow2', 'qed', 'quorum', 'raw', 'tftp',
> > +            'vdi', 'vhdx', 'vmdk', 'vpc', 'vvfat' ] }
> >  
> >  ##
> >  # @BlockdevOptionsFile
> > @@ -2057,6 +2058,63 @@
> >              '*read-pattern': 'QuorumReadPattern' } }
> >  
> >  ##
> > +# @GlusterTransport
> > +#
> > +# An enumeration of Gluster transport type
> > +#
> > +# @tcp:   TCP   - Transmission Control Protocol
> > +#
> > +# @unix:  UNIX  - Unix domain socket
> > +#
> > +# Since: 2.7
> > +##
> > +{ 'enum': 'GlusterTransport',
> > +  'data': [ 'unix', 'tcp' ] }
> > +
> > +
> > +##
> > +# @GlusterServer
> > +#
> > +# Captures the address of a socket
> > +#
> > +# Details for connecting to a gluster server
> > +#
> > +# @type:       Transport type used for gluster connection
> > +#
> > +# @unix:       socket file
> > +#
> > +# @tcp:        host address and port number
> > +#
> > +# Since: 2.7
> > +##
> > +{ 'union': 'GlusterServer',
> > +  'base': { 'type': 'GlusterTransport' },
> > +  'discriminator': 'type',
> > +  'data': { 'unix': 'UnixSocketAddress',
> > +            'tcp': 'InetSocketAddress' } }
> > +
> > +##
> > +# @BlockdevOptionsGluster
> > +#
> > +# Driver specific block device options for Gluster
> > +#
> > +# @volume:      name of gluster volume where VM image resides
> > +#
> > +# @path:        absolute path to image file in gluster volume
> > +#
> > +# @server:      gluster server description
> > +#
> > +# @debug_level: #optional libgfapi log level (default '4' which is Error)
> > +#
> 
> Per Eric's suggestion, will change this to debug-level on commit.
> 
> > +# Since: 2.7
> > +##
> > +{ 'struct': 'BlockdevOptionsGluster',
> > +  'data': { 'volume': 'str',
> > +            'path': 'str',
> > +            'server': 'GlusterServer',
> > +            '*debug_level': 'int' } }
> > +
> > +##
> >  # @BlockdevOptions
> >  #
> >  # Options for creating a block device.  Many options are available for all
> > @@ -2119,7 +2177,7 @@
> >        'file':       'BlockdevOptionsFile',
> >        'ftp':        'BlockdevOptionsFile',
> >        'ftps':       'BlockdevOptionsFile',
> > -# TODO gluster: Wait for structured options
> > +      'gluster':    'BlockdevOptionsGluster',
> >        'host_cdrom': 'BlockdevOptionsFile',
> >        'host_device':'BlockdevOptionsFile',
> >        'http':       'BlockdevOptionsFile',
> > -- 
> > 2.7.4
> >
> 
> After fix-ups:
> 
> Reviewed-by: Jeff Cody <jcody@redhat.com>
diff mbox

Patch

diff --git a/block/gluster.c b/block/gluster.c
index 8a54ad4..c4ca59e 100644
--- a/block/gluster.c
+++ b/block/gluster.c
@@ -16,6 +16,7 @@ 
 
 #define GLUSTER_OPT_FILENAME        "filename"
 #define GLUSTER_OPT_DEBUG           "debug"
+#define GLUSTER_DEFAULT_PORT        24007
 #define GLUSTER_DEBUG_DEFAULT       4
 #define GLUSTER_DEBUG_MAX           9
 
@@ -40,15 +41,6 @@  typedef struct BDRVGlusterReopenState {
     struct glfs_fd *fd;
 } BDRVGlusterReopenState;
 
-typedef struct GlusterConf {
-    char *host;
-    int port;
-    char *volume;
-    char *path;
-    char *transport;
-    int debug_level;
-} GlusterConf;
-
 
 static QemuOptsList qemu_gluster_create_opts = {
     .name = "qemu-gluster-create-opts",
@@ -92,18 +84,7 @@  static QemuOptsList runtime_opts = {
 };
 
 
-static void qemu_gluster_gconf_free(GlusterConf *gconf)
-{
-    if (gconf) {
-        g_free(gconf->host);
-        g_free(gconf->volume);
-        g_free(gconf->path);
-        g_free(gconf->transport);
-        g_free(gconf);
-    }
-}
-
-static int parse_volume_options(GlusterConf *gconf, char *path)
+static int parse_volume_options(BlockdevOptionsGluster *gconf, char *path)
 {
     char *p, *q;
 
@@ -160,8 +141,10 @@  static int parse_volume_options(GlusterConf *gconf, char *path)
  * file=gluster+tcp://host.domain.com:24007/testvol/dir/a.img
  * file=gluster+unix:///testvol/dir/a.img?socket=/tmp/glusterd.socket
  */
-static int qemu_gluster_parseuri(GlusterConf *gconf, const char *filename)
+static int qemu_gluster_parse_uri(BlockdevOptionsGluster *gconf,
+                                  const char *filename)
 {
+    GlusterServer *gsconf;
     URI *uri;
     QueryParams *qp = NULL;
     bool is_unix = false;
@@ -172,16 +155,18 @@  static int qemu_gluster_parseuri(GlusterConf *gconf, const char *filename)
         return -EINVAL;
     }
 
+    gconf->server = gsconf = g_new0(GlusterServer, 1);
+
     /* transport */
     if (!uri->scheme || !strcmp(uri->scheme, "gluster")) {
-        gconf->transport = g_strdup("tcp");
+        gsconf->type = GLUSTER_TRANSPORT_TCP;
     } else if (!strcmp(uri->scheme, "gluster+tcp")) {
-        gconf->transport = g_strdup("tcp");
+        gsconf->type = GLUSTER_TRANSPORT_TCP;
     } else if (!strcmp(uri->scheme, "gluster+unix")) {
-        gconf->transport = g_strdup("unix");
+        gsconf->type = GLUSTER_TRANSPORT_UNIX;
         is_unix = true;
     } else if (!strcmp(uri->scheme, "gluster+rdma")) {
-        gconf->transport = g_strdup("tcp");
+        gsconf->type = GLUSTER_TRANSPORT_TCP;
         error_report("Warning: rdma feature is not supported falling "
                      "back to tcp");
     } else {
@@ -209,10 +194,14 @@  static int qemu_gluster_parseuri(GlusterConf *gconf, const char *filename)
             ret = -EINVAL;
             goto out;
         }
-        gconf->host = g_strdup(qp->p[0].value);
+        gsconf->u.q_unix.path = g_strdup(qp->p[0].value);
     } else {
-        gconf->host = g_strdup(uri->server ? uri->server : "localhost");
-        gconf->port = uri->port;
+        gsconf->u.tcp.host = g_strdup(uri->server ? uri->server : "localhost");
+        if (uri->port) {
+            gsconf->u.tcp.port = g_strdup_printf("%d", uri->port);
+        } else {
+            gsconf->u.tcp.port = g_strdup_printf("%d", GLUSTER_DEFAULT_PORT);
+        }
     }
 
 out:
@@ -223,17 +212,18 @@  out:
     return ret;
 }
 
-static struct glfs *qemu_gluster_init(GlusterConf *gconf, const char *filename,
-                                      Error **errp)
+static struct glfs *qemu_gluster_init(BlockdevOptionsGluster *gconf,
+                                      const char *filename, Error **errp)
 {
     struct glfs *glfs = NULL;
     int ret;
     int old_errno;
 
-    ret = qemu_gluster_parseuri(gconf, filename);
+    ret = qemu_gluster_parse_uri(gconf, filename);
     if (ret < 0) {
-        error_setg(errp, "Usage: file=gluster[+transport]://[host[:port]]/"
-                         "volume/path[?socket=...]");
+        error_setg(errp, "Invalid URI");
+        error_append_hint(errp, "Usage: file=gluster[+transport]://"
+                                "[host[:port]]/volume/path[?socket=...]\n");
         errno = -ret;
         goto out;
     }
@@ -243,8 +233,16 @@  static struct glfs *qemu_gluster_init(GlusterConf *gconf, const char *filename,
         goto out;
     }
 
-    ret = glfs_set_volfile_server(glfs, gconf->transport, gconf->host,
-            gconf->port);
+    if (gconf->server->type == GLUSTER_TRANSPORT_UNIX) {
+        ret = glfs_set_volfile_server(glfs,
+                                      GlusterTransport_lookup[gconf->server->type],
+                                      gconf->server->u.q_unix.path, 0);
+    } else {
+        ret = glfs_set_volfile_server(glfs,
+                                      GlusterTransport_lookup[gconf->server->type],
+                                      gconf->server->u.tcp.host,
+                                      atoi(gconf->server->u.tcp.port));
+    }
     if (ret < 0) {
         goto out;
     }
@@ -256,15 +254,22 @@  static struct glfs *qemu_gluster_init(GlusterConf *gconf, const char *filename,
 
     ret = glfs_init(glfs);
     if (ret) {
-        error_setg_errno(errp, errno,
-                         "Gluster connection failed for host=%s port=%d "
-                         "volume=%s path=%s transport=%s", gconf->host,
-                         gconf->port, gconf->volume, gconf->path,
-                         gconf->transport);
+        if (gconf->server->type == GLUSTER_TRANSPORT_UNIX) {
+            error_setg(errp,
+                       "Gluster connection for volume %s, path %s failed on "
+                       "socket %s ", gconf->volume, gconf->path,
+                       gconf->server->u.q_unix.path);
+        } else {
+            error_setg(errp,
+                       "Gluster connection for volume %s, path %s failed on "
+                       "host  %s and port %s ", gconf->volume, gconf->path,
+                       gconf->server->u.tcp.host, gconf->server->u.tcp.port);
+        }
 
         /* glfs_init sometimes doesn't set errno although docs suggest that */
-        if (errno == 0)
+        if (errno == 0) {
             errno = EINVAL;
+        }
 
         goto out;
     }
@@ -352,7 +357,7 @@  static int qemu_gluster_open(BlockDriverState *bs,  QDict *options,
     BDRVGlusterState *s = bs->opaque;
     int open_flags = 0;
     int ret = 0;
-    GlusterConf *gconf = g_new0(GlusterConf, 1);
+    BlockdevOptionsGluster *gconf = NULL;
     QemuOpts *opts;
     Error *local_err = NULL;
     const char *filename;
@@ -375,7 +380,9 @@  static int qemu_gluster_open(BlockDriverState *bs,  QDict *options,
         s->debug_level = GLUSTER_DEBUG_MAX;
     }
 
+    gconf = g_new0(BlockdevOptionsGluster, 1);
     gconf->debug_level = s->debug_level;
+    gconf->has_debug_level = true;
     s->glfs = qemu_gluster_init(gconf, filename, errp);
     if (!s->glfs) {
         ret = -errno;
@@ -410,7 +417,9 @@  static int qemu_gluster_open(BlockDriverState *bs,  QDict *options,
 
 out:
     qemu_opts_del(opts);
-    qemu_gluster_gconf_free(gconf);
+    if (gconf) {
+        qapi_free_BlockdevOptionsGluster(gconf);
+    }
     if (!ret) {
         return ret;
     }
@@ -429,7 +438,7 @@  static int qemu_gluster_reopen_prepare(BDRVReopenState *state,
     int ret = 0;
     BDRVGlusterState *s;
     BDRVGlusterReopenState *reop_s;
-    GlusterConf *gconf = NULL;
+    BlockdevOptionsGluster *gconf;
     int open_flags = 0;
 
     assert(state != NULL);
@@ -442,9 +451,9 @@  static int qemu_gluster_reopen_prepare(BDRVReopenState *state,
 
     qemu_gluster_parse_flags(state->flags, &open_flags);
 
-    gconf = g_new0(GlusterConf, 1);
-
+    gconf = g_new0(BlockdevOptionsGluster, 1);
     gconf->debug_level = s->debug_level;
+    gconf->has_debug_level = true;
     reop_s->glfs = qemu_gluster_init(gconf, state->bs->filename, errp);
     if (reop_s->glfs == NULL) {
         ret = -errno;
@@ -470,7 +479,9 @@  static int qemu_gluster_reopen_prepare(BDRVReopenState *state,
 
 exit:
     /* state->opaque will be freed in either the _abort or _commit */
-    qemu_gluster_gconf_free(gconf);
+    if (gconf) {
+        qapi_free_BlockdevOptionsGluster(gconf);
+    }
     return ret;
 }
 
@@ -572,14 +583,15 @@  static inline int qemu_gluster_zerofill(struct glfs_fd *fd, int64_t offset,
 static int qemu_gluster_create(const char *filename,
                                QemuOpts *opts, Error **errp)
 {
+    BlockdevOptionsGluster *gconf;
     struct glfs *glfs;
     struct glfs_fd *fd;
     int ret = 0;
     int prealloc = 0;
     int64_t total_size = 0;
     char *tmp = NULL;
-    GlusterConf *gconf = g_new0(GlusterConf, 1);
 
+    gconf = g_new0(BlockdevOptionsGluster, 1);
     gconf->debug_level = qemu_opt_get_number_del(opts, GLUSTER_OPT_DEBUG,
                                                  GLUSTER_DEBUG_DEFAULT);
     if (gconf->debug_level < 0) {
@@ -587,6 +599,7 @@  static int qemu_gluster_create(const char *filename,
     } else if (gconf->debug_level > GLUSTER_DEBUG_MAX) {
         gconf->debug_level = GLUSTER_DEBUG_MAX;
     }
+    gconf->has_debug_level = true;
 
     glfs = qemu_gluster_init(gconf, filename, errp);
     if (!glfs) {
@@ -628,7 +641,9 @@  static int qemu_gluster_create(const char *filename,
     }
 out:
     g_free(tmp);
-    qemu_gluster_gconf_free(gconf);
+    if (gconf) {
+        qapi_free_BlockdevOptionsGluster(gconf);
+    }
     if (glfs) {
         glfs_fini(glfs);
     }
diff --git a/qapi/block-core.json b/qapi/block-core.json
index a7fdb28..1fa0674 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -1658,13 +1658,14 @@ 
 # @host_device, @host_cdrom: Since 2.1
 #
 # Since: 2.0
+# @gluster: Since 2.7
 ##
 { 'enum': 'BlockdevDriver',
   'data': [ 'archipelago', 'blkdebug', 'blkverify', 'bochs', 'cloop',
-            'dmg', 'file', 'ftp', 'ftps', 'host_cdrom', 'host_device',
-            'http', 'https', 'luks', 'null-aio', 'null-co', 'parallels',
-            'qcow', 'qcow2', 'qed', 'quorum', 'raw', 'tftp', 'vdi', 'vhdx',
-            'vmdk', 'vpc', 'vvfat' ] }
+            'dmg', 'file', 'ftp', 'ftps', 'gluster', 'host_cdrom',
+            'host_device', 'http', 'https', 'luks', 'null-aio', 'null-co',
+            'parallels', 'qcow', 'qcow2', 'qed', 'quorum', 'raw', 'tftp',
+            'vdi', 'vhdx', 'vmdk', 'vpc', 'vvfat' ] }
 
 ##
 # @BlockdevOptionsFile
@@ -2057,6 +2058,63 @@ 
             '*read-pattern': 'QuorumReadPattern' } }
 
 ##
+# @GlusterTransport
+#
+# An enumeration of Gluster transport type
+#
+# @tcp:   TCP   - Transmission Control Protocol
+#
+# @unix:  UNIX  - Unix domain socket
+#
+# Since: 2.7
+##
+{ 'enum': 'GlusterTransport',
+  'data': [ 'unix', 'tcp' ] }
+
+
+##
+# @GlusterServer
+#
+# Captures the address of a socket
+#
+# Details for connecting to a gluster server
+#
+# @type:       Transport type used for gluster connection
+#
+# @unix:       socket file
+#
+# @tcp:        host address and port number
+#
+# Since: 2.7
+##
+{ 'union': 'GlusterServer',
+  'base': { 'type': 'GlusterTransport' },
+  'discriminator': 'type',
+  'data': { 'unix': 'UnixSocketAddress',
+            'tcp': 'InetSocketAddress' } }
+
+##
+# @BlockdevOptionsGluster
+#
+# Driver specific block device options for Gluster
+#
+# @volume:      name of gluster volume where VM image resides
+#
+# @path:        absolute path to image file in gluster volume
+#
+# @server:      gluster server description
+#
+# @debug_level: #optional libgfapi log level (default '4' which is Error)
+#
+# Since: 2.7
+##
+{ 'struct': 'BlockdevOptionsGluster',
+  'data': { 'volume': 'str',
+            'path': 'str',
+            'server': 'GlusterServer',
+            '*debug_level': 'int' } }
+
+##
 # @BlockdevOptions
 #
 # Options for creating a block device.  Many options are available for all
@@ -2119,7 +2177,7 @@ 
       'file':       'BlockdevOptionsFile',
       'ftp':        'BlockdevOptionsFile',
       'ftps':       'BlockdevOptionsFile',
-# TODO gluster: Wait for structured options
+      'gluster':    'BlockdevOptionsGluster',
       'host_cdrom': 'BlockdevOptionsFile',
       'host_device':'BlockdevOptionsFile',
       'http':       'BlockdevOptionsFile',