qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH v5 1/1] block/gluster: add support for multiple


From: Peter Krempa
Subject: Re: [Qemu-devel] [PATCH v5 1/1] block/gluster: add support for multiple gluster backup volfile servers
Date: Wed, 7 Oct 2015 11:09:58 +0200
User-agent: Mutt/1.5.23 (2014-03-12)

On Mon, Sep 28, 2015 at 18:06:12 +0530, Prasanna Kumar Kalever wrote:
> This patch adds a way to specify multiple volfile servers to the gluster
> block backend of QEMU with tcp|rdma transport types and their port numbers.
> 
> Problem:
> 
> Currenly VM Image on gluster volume is specified like this:
> 
> file=gluster[+tcp]://server1[:port]/testvol/a.img
> 
> Assuming we have have three servers in trustred pool with replica 3 volume
> in action and unfortunately server1 (mentioned in the command above) went down
> for some reason, since the volume is replica 3 we now have other 2 servers
> active from which we can boot the VM.
> 
> But currently there is no mechanism to pass the other 2 gluster server
> addresses to qemu.
> 
> Solution:
> 
> New way of specifying VM Image on gluster volume with volfile servers:
> (We still support old syntax to maintain backward compatibility)
> 
> Basic command line syntax looks like:
> 
> Pattern I:
>  -drive driver=gluster,
>         volname=testvol,image-path=/path/a.raw,
>         volfile-servers.0.server=1.2.3.4,

I still think 'volfile-servers' should be just 'server'. I don't
understand why it needs to contain anything else. See below for
suggestions ...

>        [volfile-servers.0.port=24007,]
>        [volfile-servers.0.transport=tcp,]
>         volfile-servers.1.server=5.6.7.8,
>        [volfile-servers.1.port=24008,]
>        [volfile-servers.1.transport=rdma,] ...
> 
> Pattern II:
>  'json:{"driver":"qcow2","file":{"driver":"gluster",
>        "volname":"testvol","image-path":"/path/a.qcow2",
>        "volfile-servers":[{tuple0},{tuple1}, ...{tupleN}]}}'
> 
>    driver       => 'gluster' (protocol name)
>    volname      => name of gluster volume where our VM image resides
>    image-path   => is the absolute path of image in gluster volume
> 
>   {tuple}       => {"server":"1.2.3.4"[,"port":"24007","transport":"tcp"]}
> 
>    server       => server address (hostname/ipv4/ipv6 addresses)
>    port         => port number on which glusterd is listening. (default 24007)
>    tranport     => transport type used to connect to gluster management 
> daemon,
>                     it can be tcp|rdma (default 'tcp')
> 
> Examples:
> 1.
>  -drive driver=qcow2,file.driver=gluster,
>         file.volname=testvol,file.image-path=/path/a.qcow2,
>         file.volfile-servers.0.server=1.2.3.4,
>         file.volfile-servers.0.port=24007,
>         file.volfile-servers.0.transport=tcp,
>         file.volfile-servers.1.server=5.6.7.8,
>         file.volfile-servers.1.port=24008,
>         file.volfile-servers.1.transport=rdma
> 2.
>  'json:{"driver":"qcow2","file":{"driver":"gluster","volname":"testvol",
>          "image-path":"/path/a.qcow2","volfile-servers":
>          [{"server":"1.2.3.4","port":"24007","transport":"tcp"},
>           {"server":"4.5.6.7","port":"24008","transport":"rdma"}] } }'

  -drive driver=qcow2,file.driver=gluster,
         file.volume=testvol,
         file.path=/path/a.qcow2,
         file.server.0.host=1.2.3.4,
         file.server.0.port=24007,
         file.server.0.transport=tcp,
         file.server.1.host=5.6.7.8,
         file.server.1.port=24008,
         file.server.1.transport=rdma

I'm suggesting the above naming scheme.
So:
'path' instead of 'image-path'
'volume' instead of 'volname'
'server' instead of 'volfile-servers'
'host' instead of 'server'

 2.
  'json:{"driver":"qcow2","file":{"driver":"gluster","volume":"testvol",
          "path":"/path/a.qcow2","server":
          [{"host":"1.2.3.4","port":"24007","transport":"tcp"},
           {"host":"4.5.6.7","port":"24008","transport":"rdma"}] } }'

> 
> This patch gives a mechanism to provide all the server addresses which are in
> replica set, so in case server1 is down VM can still boot from any of the
> active servers.
> 
> This is equivalent to the volfile-servers option supported by
> mount.glusterfs (FUSE way of mounting gluster volume)

I don't think qemu needs to follow mount.glusterfs in naming.

> 
> This patch depends on a recent fix in libgfapi raised as part of this work:
> http://review.gluster.org/#/c/12114/
> 
> Credits: Sincere thanks to Kevin Wolf <address@hidden> and
> "Deepak C Shetty" <address@hidden> for inputs and all their support
> 
> Signed-off-by: Prasanna Kumar Kalever <address@hidden>
> ---

[snip]

> diff --git a/block/gluster.c b/block/gluster.c
> index 1eb3a8c..63c3dcb 100644
> --- a/block/gluster.c
> +++ b/block/gluster.c
> @@ -11,6 +11,15 @@
>  #include "block/block_int.h"
>  #include "qemu/uri.h"
>  
> +#define GLUSTER_OPT_FILENAME      "filename"
> +#define GLUSTER_OPT_VOLNAME       "volname"
> +#define GLUSTER_OPT_IMAGE_PATH    "image-path"
> +#define GLUSTER_OPT_SERVER        "server"
> +#define GLUSTER_OPT_PORT          "port"
> +#define GLUSTER_OPT_TRANSPORT     "transport"
> +#define GLUSTER_OPT_READ_PATTERN  "volfile-servers."
> +
> +
>  typedef struct GlusterAIOCB {
>      int64_t size;
>      int ret;
> @@ -43,6 +52,60 @@ static void qemu_gluster_gconf_free(GlusterConf *gconf)
>      }
>  }
>  
> +static QemuOptsList runtime_opts = {
> +    .name = "gluster",
> +    .head = QTAILQ_HEAD_INITIALIZER(runtime_opts.head),
> +    .desc = {
> +        {
> +            .name = GLUSTER_OPT_FILENAME,
> +            .type = QEMU_OPT_STRING,
> +            .help = "URL to the gluster image",
> +        },
> +        { /* end of list */ }
> +    },
> +};
> +
> +static QemuOptsList runtime_json_opts = {
> +    .name = "gluster_json",
> +    .head = QTAILQ_HEAD_INITIALIZER(runtime_json_opts.head),
> +    .desc = {
> +        {
> +            .name = GLUSTER_OPT_VOLNAME,
> +            .type = QEMU_OPT_STRING,
> +            .help = "name of gluster volume where our VM image resides",
> +        },
> +        {
> +            .name = GLUSTER_OPT_IMAGE_PATH,
> +            .type = QEMU_OPT_STRING,
> +            .help = "absolute path to image file in gluster volume",
> +        },
> +        { /* end of list */ }
> +    },
> +};
> +
> +static QemuOptsList runtime_tuple_opts = {
> +    .name = "gluster_tuple",
> +    .head = QTAILQ_HEAD_INITIALIZER(runtime_tuple_opts.head),
> +    .desc = {
> +        {
> +            .name = GLUSTER_OPT_SERVER,
> +            .type = QEMU_OPT_STRING,
> +            .help = "server address (hostname/ipv4/ipv6 addresses)",
> +        },
> +        {
> +            .name = GLUSTER_OPT_PORT,
> +            .type = QEMU_OPT_NUMBER,
> +            .help = "port number on which glusterd is listening(default 
> 24007)",
> +        },
> +        {
> +            .name = GLUSTER_OPT_TRANSPORT,
> +            .type = QEMU_OPT_STRING,
> +            .help = "transport type used to connect to glusterd(default 
> tcp)",
> +        },
> +        { /* end of list */ }
> +    },
> +};
> +
>  static int parse_volume_options(GlusterConf *gconf, char *path)
>  {
>      char *p, *q;
> @@ -105,6 +168,7 @@ static int parse_volume_options(GlusterConf *gconf, char 
> *path)
>   * file=gluster+unix:///testvol/dir/a.img?socket=/tmp/glusterd.socket
>   * file=gluster+rdma://1.2.3.4:24007/testvol/a.img
>   */
> +

Spurious whitespace change.

>  static int qemu_gluster_parseuri(GlusterConf *gconf, const char *filename)
>  {
>      URI *uri;
> @@ -166,30 +230,25 @@ out:
>      return ret;
>  }
>  
> -static struct glfs *qemu_gluster_init(GlusterConf *gconf, const char 
> *filename,
> -                                      Error **errp)
> +static struct glfs *qemu_gluster_glfs_init(GlusterConf *gconf, int 
> num_servers,
> +                                           Error **errp)
>  {
>      struct glfs *glfs = NULL;
> -    int ret;
>      int old_errno;
> -
> -    ret = qemu_gluster_parseuri(gconf, filename);
> -    if (ret < 0) {
> -        error_setg(errp, "Usage: file=gluster[+transport]://[server[:port]]/"
> -                   "volname/image[?socket=...]");

[3] (see below)

> -        errno = -ret;
> -        goto out;
> -    }
> +    int ret = 0;
> +    int i = 0;
>  
>      glfs = glfs_new(gconf->volname);
>      if (!glfs) {
>          goto out;
>      }
>  
> -    ret = glfs_set_volfile_server(glfs, gconf->transport, gconf->server,
> -            gconf->port);
> -    if (ret < 0) {
> -        goto out;
> +    for (i = 0; i < num_servers; i++) {
> +        ret = glfs_set_volfile_server(glfs, gconf[i].transport, 
> gconf[i].server,
> +                gconf[i].port);

This adds back the pre-existing strange alignment of the code it removed
before.

> +        if (ret < 0) {
> +            goto out;
> +        }
>      }
>  
>      /*
> @@ -204,15 +263,12 @@ 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 server=%s port=%d "
> -                         "volume=%s image=%s transport=%s", gconf->server,
> -                         gconf->port, gconf->volname, gconf->image,
> -                         gconf->transport);
> +                "Gluster connection failed for volname=%s image=%s",
> +                gconf->volname, gconf->image);

The above error message doesn't mention any server at all. I think it
should contain at least the first server. Also the alignment of the code
got strange.

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

Removal of the empty line decreases readability.

>          goto out;
>      }
>      return glfs;
> @@ -226,6 +282,297 @@ out:
>      return NULL;
>  }
>  
> +
> +static struct glfs *qemu_gluster_init(GlusterConf *gconf, const char 
> *filename,
> +                                      Error **errp)
> +{
> +    struct glfs *glfs = NULL;
> +    int ret;

This function should allocate 'gconf' rather than have it passed. [5]

> +
> +    ret = qemu_gluster_parseuri(gconf, filename);
> +    if (ret < 0) {
> +        error_setg(errp, "Usage: file=gluster[+transport]://[server[:port]]/"
> +                   "volname/image[?socket=...]");
> +        errno = -ret;
> +        goto out;
> +    }
> +
> +    glfs = qemu_gluster_glfs_init(gconf, 1, errp);

Everyting below can be replaced by "return qemu_gluster_glfs_init(.."

> +    if (!glfs) {
> +        goto out;
> +    }
> +    return glfs;
> +
> +out:
> +    return NULL;
> +}
> +
> +static int parse_transport_option(const char *opt)
> +{
> +    int i;
> +
> +    if (!opt) {
> +        /* Set tcp as default */
> +        return GLUSTER_TRANSPORT_TCP;
> +    }
> +
> +    for (i = 0; i < GLUSTER_TRANSPORT_MAX; i++) {
> +        if (!strcmp(opt, GlusterTransport_lookup[i])) {
> +            return i;
> +        }
> +    }
> +
> +    return -EINVAL;
> +}
> +
> +/*
> +*
> +*  Basic command line syntax looks like:
> +*
> +* Pattern I:
> +* -drive driver=gluster,
> +*        volname=testvol,file.image-path=/path/a.raw,
> +*        volfile-servers.0.server=1.2.3.4,
> +*       [volfile-servers.0.port=24007,]
> +*       [volfile-servers.0.transport=tcp,]
> +*        volfile-servers.1.server=5.6.7.8,
> +*       [volfile-servers.1.port=24008,]
> +*       [volfile-servers.1.transport=rdma,] ...
> +*
> +* Pattern II:
> +* 'json:{"driver":"qcow2","file":{"driver":"gluster",
> +*       "volname":"testvol","image-path":"/path/a.qcow2",
> +*       "volfile-servers":[{tuple0},{tuple1}, ...{tupleN}]}}'
> +*
> +*
> +*   driver       => 'gluster' (protocol name)
> +*   volname      => name of gluster volume where our VM image resides
> +*   image-path   => is the absolute path of image in gluster volume
> +*
> +*  {tuple}       => {"server":"1.2.3.4"[,"port":"24007","transport":"tcp"]}
> +*
> +*   server       => server address (hostname/ipv4/ipv6 addresses)
> +*   port         => port number on which glusterd is listening. (default 
> 24007)
> +*   tranport     => transport type used to connect to gluster management 
> daemon,
> +*                    it can be tcp|rdma (default 'tcp')
> +*
> +*
> +* Examples:
> +* Pattern I:
> +* -drive driver=qcow2,file.driver=gluster,
> +*        file.volname=testvol,file.image-path=/path/a.qcow2,
> +*        file.volfile-servers.0.server=1.2.3.4,
> +*        file.volfile-servers.0.port=24007,
> +*        file.volfile-servers.0.transport=tcp,
> +*        file.volfile-servers.1.server=5.6.7.8,
> +*        file.volfile-servers.1.port=24008,
> +*        file.volfile-servers.1.transport=rdma, ...
> +*
> +* -drive driver=qcow2,file.driver=gluster,
> +*        file.volname=testvol,file.image-path=/path/a.qcow2,
> +*        file.volfile-servers.0.server=1.2.3.4,
> +*        file.volfile-servers.1.server=5.6.7.8, ...
> +*
> +* -drive driver=qcow2,file.driver=gluster,
> +*        file.volname=testvol,file.image-path=/path/a.qcow2,
> +*        file.volfile-servers.0.server=1.2.3.4,
> +*        file.volfile-servers.0.port=24007,
> +*        file.volfile-servers.1.server=5.6.7.8,
> +*        file.volfile-servers.1.port=24008, ...
> +*
> +* -drive driver=qcow2,file.driver=gluster,
> +*        file.volname=testvol,file.image-path=/path/a.qcow2,
> +*        file.volfile-servers.0.server=1.2.3.4,
> +*        file.volfile-servers.0.transport=tcp,
> +*        file.volfile-servers.1.server=5.6.7.8,
> +*        file.volfile-servers.1.transport=rdma, ...
> +*
> +* Pattern II:
> +* 'json:{"driver":"qcow2","file":{"driver":"gluster","volname":"testvol",
> +*         "image-path":"/path/a.qcow2","volfile-servers":
> +*         [{"server":"1.2.3.4","port":"24007","transport":"tcp"},
> +*          {"server":"4.5.6.7","port":"24008","transport":"rdma"}, ...]}}'
> +*
> +* 'json:{"driver":"qcow2","file":{"driver":"gluster","volname":"testvol",
> +*         "image-path":"/path/a.qcow2","volfile-servers":
> +*                                    [{"server":"1.2.3.4"},
> +*                                     {"server":"4.5.6.7"}, ...]}}'
> +*
> +*
> +* 'json:{"driver":"qcow2","file":{"driver":"gluster","volname":"testvol",
> +*         "image-path":"/path/a.qcow2","volfile-servers":
> +*                                  [{"server":"1.2.3.4","port":"24007"},
> +*                                   {"server":"4.5.6.7","port":"24008"}, 
> ...]}}'
> +*
> +*
> +* 'json:{"driver":"qcow2","file":{"driver":"gluster","volname":"testvol",
> +*        "image-path":"/path/a.qcow2","volfile-servers":
> +*                              [{"server":"1.2.3.4","transport":"tcp"},
> +*                               {"server":"4.5.6.7","transport":"rdma"}, 
> ...]}}'
> +*
> +* Just for better readability pattern II is kept as:
> +* json:
> +* {
> +*    "driver":"qcow2",
> +*    "file":{
> +*       "driver":"gluster",
> +*       "volname":"testvol",
> +*       "image-path":"/path/a.qcow2",
> +*       "volfile-servers":[
> +*          {
> +*             "server":"1.2.3.4",
> +*             "port":"24007",
> +*             "transport":"tcp"
> +*          },
> +*          {
> +*             "server":"5.6.7.8",
> +*             "port":"24008",
> +*             "transport":"rdma"
> +*          }
> +*       ]
> +*    }
> +* }
> +*
> +*/
> +
> +static int qemu_gluster_parseopts(GlusterConf **pgconf, QDict *options)
> +{
> +    QemuOpts *opts;
> +    GlusterConf *gconf = NULL;
> +    QDict *backing_options;
> +    Error *local_err = NULL;
> +    char *str = NULL;
> +    int num_servers = 0;
> +    int ret = 0;
> +    int i = 0;
> +
> +    /* parse options in dict */
> +    opts = qemu_opts_create(&runtime_json_opts, NULL, 0, &error_abort);
> +    qemu_opts_absorb_qdict(opts, options, &local_err);
> +    if (local_err) {
> +        error_report_err(local_err);
> +        goto out;
> +    }
> +    num_servers = qdict_array_entries(options, GLUSTER_OPT_READ_PATTERN);

[1]

The function above isn't really optimal in way it's written. It
basically does the same as the loop below that is using it by formatting
the prefix and a number and tries to find the maximum. The code could
avoid using it by basically merging it with the loop below.

> +    if (num_servers < 1) {
> +        error_setg(&local_err, "\n\n ********* qemu_gluster: "

[2]

These error messages are really unusual. Most of the error messages
contain no newlines at the beginning and no stars. I think it should be
kept consistent.

Additionally, possible early errors from qemu are read back to libvirt
and displayed to the users, so this would make also some libvirt error
messages really ugly.

> +                "please provide 'volfile-servers' option "
> +                "with valid fields in array of tuples *********\n");
> +        error_report_err(local_err);
> +        goto out;
> +    }
> +
> +    gconf = g_new0(GlusterConf, num_servers);
> +
> +    gconf->volname = (char *) qemu_opt_get(opts, GLUSTER_OPT_VOLNAME);
> +    if (!gconf->volname) {
> +        error_setg(&local_err, "\n\n ********* qemu_gluster: "
> +                "please provide 'volname'option *********\n");

[2]

> +        error_report_err(local_err);
> +        goto out;
> +    }
> +    gconf->image = (char *) qemu_opt_get(opts, GLUSTER_OPT_IMAGE_PATH);
> +    if (!gconf->image) {
> +        error_setg(&local_err, "\n\n ********* qemu_gluster: "
> +                "please provide 'image-path' option *********\n");

[2]

> +        error_report_err(local_err);
> +        goto out;
> +    }
> +    opts = qemu_opts_create(&runtime_tuple_opts, NULL, 0, &error_abort);
> +    for (i = 0; i < num_servers; i++) {
> +        if (i > 0) {
> +            gconf[i].volname = gconf->volname;
> +            gconf[i].image = gconf->image;

[4]

So this looks weird. struct GlusterConf has all the fields and you
basically make an array of the structs includig of duplicated entries
that can't be different for servers.

I think what you want is 'GlusterServerConf' struct that will be as a
sub-struct of 'GlusterConf' which will contain just information relevant
to the volume file servers.

> +        }
> +        str = g_malloc(40);
> +        snprintf(str, 40, GLUSTER_OPT_READ_PATTERN"%d.", i);
> +        qdict_extract_subqdict(options, &backing_options, str);
> +        g_free(str);

This buffer could theoretically be reused.

> +        qemu_opts_absorb_qdict(opts, backing_options, &local_err);
> +        if (local_err) {
> +            error_report_err(local_err);
> +            goto out;
> +        }

One unfortunate drawback of the way I've described in [1] would be that
the gconf array would need to be resized here.


> +        gconf[i].server = (char *) qemu_opt_get(opts, GLUSTER_OPT_SERVER);
> +        if (!gconf[i].server) {
> +            error_setg(&local_err, "\n\n ********* qemu_gluster: "

[2]

> +                    "volfile-servers.{tuple.%d} requires 'server' "
> +                    "option *********\n", i);
> +            error_report_err(local_err);
> +            goto out;
> +        }
> +        ret = parse_transport_option(qemu_opt_get(opts, 
> GLUSTER_OPT_TRANSPORT));

So this converts the 'transport' field string to a number describing the
protocol ...

> +        if (ret < 0) {
> +            error_setg(&local_err, "\n\n ********* qemu_gluster: "

[2]

> +                    "please set 'transport' type in tuple.%d as tcp or rdma "
> +                    "*********\n", i);
> +            error_report_err(local_err);
> +            goto out;
> +        } else {

... and here you convert it back to a string?!

> +            if (ret == GLUSTER_TRANSPORT_TCP) {
> +                gconf[i].transport = (char *)"tcp";
> +            } else {
> +                gconf[i].transport = (char *)"rdma";
> +            }

A rather weird way. I don't see a reason to go back and forth to integer
values. You either need a string later or a integer option.

> +        }
> +        gconf[i].port = qemu_opt_get_number(opts, GLUSTER_OPT_PORT, 24007);
> +
> +        /*
> +         * reset current tuple opts to NULL/0, so that in case if the next 
> tuple
> +         * misses any of (server, tranport, port) options there is no chance 
> of
> +         * copying from current set.
> +         */
> +        qemu_opt_set_number(opts, GLUSTER_OPT_PORT, 0, &error_abort);
> +        qemu_opt_set(opts, GLUSTER_OPT_TRANSPORT, NULL, &error_abort);
> +        qemu_opt_set(opts, GLUSTER_OPT_SERVER, NULL, &error_abort);

This seems strange too. If the code that is parsing it is correct there
should be no need to remove the fields which can possibly mask other
bugs or legitimate usage.

> +    }
> +    *pgconf = gconf;
> +    return num_servers;
> +
> +out:
> +    ret = -EINVAL;
> +    errno = -ret;
> +    qemu_opts_del(opts);
> +    return ret;

This can be written as:

out:
    errno = EINVAL;
    qemu_opts_del(opts);
    return -EINVAL;

So that you don't confuse readers of the function by reusing 'ret'.

> +}
> +
> +static struct glfs  *qemu_gluster_opts_init(GlusterConf **pgconf,
> +                                            QDict *options, Error **errp)
> +{
> +    struct glfs *glfs = NULL;
> +    int num_servers = 0;

No need to initialize any of those.

> +
> +    num_servers = qemu_gluster_parseopts(pgconf, options);
> +    if (num_servers < 1) {
> +        error_setg(errp, "\n"
> +                        "\n#Usage1:\n"

The string again looks very suspicious with so many newlines in front.
The previous version didn't have a newline in front of the string nor in
the back [3].

> +                        "-drive driver=qcow2,file.driver=gluster,"
> +                        "file.volname=testvol,file.image-path=/path/a.qcow2,"
> +                        "file.volfile-servers.0.server=1.2.3.4,"
> +                        "[file.volfile-servers.0.port=24007,]"
> +                        "[file.volfile-servers.0.transport=tcp,]"
> +                        "file.volfile-servers.1.server=5.6.7.8,"
> +                        "[file.volfile-servers.1.port=24008,]"
> +                        "[file.volfile-servers.1.transport=rdma,] ...\n"
> +                        "\n#Usage2:\n'json:{\"driver\":\"qcow2\",\"file\":"
> +                        "{\"driver\":\"gluster\",\"volname\":\""
> +                        "testvol\",\"image-path\":\"/path/a.qcow2\","
> +                        "\"volfile-servers\":[{\"server\":\"1.2.3.4\","
> +                        "\"port\":\"24007\",\"transport\":\"tcp\"},"
> +                        "{\"server\":\"4.5.6.7\",\"port\":\"24007\","
> +                        "\"transport\":\"rdma\"}, ...]}}'\n");
> +        goto out;
> +    }
> +    glfs = qemu_gluster_glfs_init(*pgconf, num_servers, errp);

Everything below can be replaced by just "return qemu_gluster_glfs_init ..."

> +    if (!glfs) {
> +        goto out;
> +    }
> +    return glfs;
> +
> +out:
> +    return NULL;
> +}
> +

[snip]

> @@ -291,11 +624,12 @@ 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);
> +    GlusterConf *gconf = NULL;
>      QemuOpts *opts;
>      Error *local_err = NULL;
> -    const char *filename;
> +    const char *filename = NULL;

You don't need to initialize 'filename';

>  
> +    qdict_flatten(options);
>      opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort);
>      qemu_opts_absorb_qdict(opts, options, &local_err);
>      if (local_err) {
> @@ -305,8 +639,12 @@ static int qemu_gluster_open(BlockDriverState *bs,  
> QDict *options,
>      }
>  
>      filename = qemu_opt_get(opts, "filename");
> -
> -    s->glfs = qemu_gluster_init(gconf, filename, errp);
> +    if (filename) {
> +        gconf = g_new0(GlusterConf, 1);
> +        s->glfs = qemu_gluster_init(gconf, filename, errp);

qemu_gluster_init can be made to allocate gconf the same way as
qemu_gluster_opts_init, so that there's no difference in calling
semantics. See [5]

> +    } else {
> +        s->glfs = qemu_gluster_opts_init(&gconf, options, errp);
> +    }
>      if (!s->glfs) {
>          ret = -errno;
>          goto out;
> @@ -321,7 +659,11 @@ static int qemu_gluster_open(BlockDriverState *bs,  
> QDict *options,
>  
>  out:
>      qemu_opts_del(opts);
> -    qemu_gluster_gconf_free(gconf);
> +    if (filename) {
> +        qemu_gluster_gconf_free(gconf);
> +    } else {
> +        g_free(gconf);
> +    }

Fixing [4] will actually make this hunk really simpler.

>      if (!ret) {
>          return ret;
>      }
> @@ -339,7 +681,6 @@ typedef struct BDRVGlusterReopenState {
>      struct glfs_fd *fd;
>  } BDRVGlusterReopenState;
>  
> -
>  static int qemu_gluster_reopen_prepare(BDRVReopenState *state,
>                                         BlockReopenQueue *queue, Error **errp)
>  {
> @@ -401,7 +742,6 @@ static void qemu_gluster_reopen_commit(BDRVReopenState 
> *state)
>      return;
>  }
>  
> -
>  static void qemu_gluster_reopen_abort(BDRVReopenState *state)
>  {
>      BDRVGlusterReopenState *reop_s = state->opaque;

Both hunks above are spurious whitespace change.

Peter

Attachment: signature.asc
Description: Digital signature


reply via email to

[Prev in Thread] Current Thread [Next in Thread]