From: Markus Armbruster <armbru@redhat.com>
To: qemu-devel@nongnu.org
Cc: jdurgin@redhat.com, jcody@redhat.com, kwolf@redhat.com,
mreitz@redhat.com, eblake@redhat.com
Subject: [Qemu-devel] [PATCH RFC v2 8/9] rbd: Rewrite the code to extract list-valued options
Date: Fri, 24 Mar 2017 18:44:41 +0100 [thread overview]
Message-ID: <1490377482-13337-9-git-send-email-armbru@redhat.com> (raw)
In-Reply-To: <1490377482-13337-1-git-send-email-armbru@redhat.com>
We have two list-values options:
* "server" is a list of InetSocketAddress. We use members "host" and
"port", and silently ignore the rest.
* "auth-supported" is a list of RbdAuthMethod. We use its only member
"auth".
Since qemu_rbd_open() takes options as a flattened QDict, options has
keys of the form server.%d.host, server.%d.port and
auth-supported.%d.auth, where %d counts up from zero.
qemu_rbd_array_opts() extracts these values as follows. First, it
calls qdict_array_entries() to find the list's length. For each list
element, it first formats the list's key prefix (e.g. "server.0."),
then creates a new QDict holding the options with that key prefix,
then converts that to a QemuOpts, so it can finally get the member
values from there.
If there's one surefire way to make code using QDict more awkward,
it's creating more of them and mixing in QemuOpts for good measure.
The conversion to QemuOpts abuses runtime_opts, as described in the
commit before previous.
Rewrite to simply get the values straight from the options QDict.
Fixes -drive not to crash when server.*.* are present, but
server.*.host is absent.
Permits cleaning up runtime_opts, which fixes -drive to reject several
bogus parameters instead of silently ignoring them: host, port, auth;
server.*.P where P isn't host; port auth-supported.*.P where P isn't
auth.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
---
block/rbd.c | 150 +++++++++++++++++++++---------------------------------------
1 file changed, 52 insertions(+), 98 deletions(-)
diff --git a/block/rbd.c b/block/rbd.c
index 6397626..e962641 100644
--- a/block/rbd.c
+++ b/block/rbd.c
@@ -13,6 +13,7 @@
#include "qemu/osdep.h"
+#include <rbd/librbd.h>
#include "qapi/error.h"
#include "qemu/error-report.h"
#include "block/block_int.h"
@@ -20,8 +21,6 @@
#include "qemu/cutils.h"
#include "qapi/qmp/qstring.h"
-#include <rbd/librbd.h>
-
/*
* When specifying the image filename use:
*
@@ -341,25 +340,6 @@ static QemuOptsList runtime_opts = {
.type = QEMU_OPT_STRING,
.help = "Legacy rados key/value option parameters",
},
- /*
- * The remainder aren't option keys, but option sub-sub-keys,
- * so that qemu_rbd_array_opts() can abuse runtime_opts for
- * its own purposes
- * TODO clean this up
- */
- {
- .name = "host",
- .type = QEMU_OPT_STRING,
- },
- {
- .name = "port",
- .type = QEMU_OPT_STRING,
- },
- {
- .name = "auth",
- .type = QEMU_OPT_STRING,
- .help = "Supported authentication method, either cephx or none",
- },
{ /* end of list */ }
},
};
@@ -510,91 +490,68 @@ static void qemu_rbd_complete_aio(RADOSCB *rcb)
qemu_aio_unref(acb);
}
-#define RBD_MON_HOST 0
-#define RBD_AUTH_SUPPORTED 1
-
-static char *qemu_rbd_array_opts(QDict *options, const char *prefix, int type,
- Error **errp)
+static char *qemu_rbd_auth(QDict *options, Error **errp)
{
- int num_entries;
- QemuOpts *opts = NULL;
- QDict *sub_options;
- const char *host;
- const char *port;
- char *str;
- char *rados_str = NULL;
- Error *local_err = NULL;
+ const char **vals = g_new(const char *, qdict_size(options) + 1);
+ char keybuf[32];
+ QObject *val;
+ char *rados_str;
int i;
- assert(type == RBD_MON_HOST || type == RBD_AUTH_SUPPORTED);
+ for (i = 0;; i++) {
+ sprintf(keybuf, "auth-supported.%d.auth", i);
+ val = qdict_get(options, keybuf);
+ if (!val) {
+ break;
+ }
- num_entries = qdict_array_entries(options, prefix);
-
- if (num_entries < 0) {
- error_setg(errp, "Parse error on RBD QDict array");
- return NULL;
+ vals[i] = qstring_get_str(qobject_to_qstring(val));
+ qdict_del(options, keybuf);
}
+ vals[i] = NULL;
- for (i = 0; i < num_entries; i++) {
- char *strbuf = NULL;
- const char *value;
- char *rados_str_tmp;
+ rados_str = i ? g_strjoinv(";", (char **)vals) : NULL;
+ g_free(vals);
+ return rados_str;
+}
- str = g_strdup_printf("%s%d.", prefix, i);
- qdict_extract_subqdict(options, &sub_options, str);
- g_free(str);
+static char *qemu_mon_host(QDict *options, Error **errp)
+{
+ const char **vals = g_new(const char *, qdict_size(options) + 1);
+ char keybuf[32];
+ const char *host, *port;
+ char *rados_str;
+ int i;
- opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort);
- qemu_opts_absorb_qdict(opts, sub_options, &local_err);
- QDECREF(sub_options);
- if (local_err) {
- error_propagate(errp, local_err);
- g_free(rados_str);
+ for (i = 0;; i++) {
+ sprintf(keybuf, "server.%d.host", i);
+ host = qdict_get_try_str(options, keybuf);
+ qdict_del(options, keybuf);
+ sprintf(keybuf, "server.%d.port", i);
+ port = qdict_get_try_str(options, keybuf);
+ qdict_del(options, keybuf);
+ if (!host && !port) {
+ break;
+ }
+ if (!host) {
+ error_setg(errp, "Parameter server.%d.host is missing", i);
rados_str = NULL;
- goto exit;
+ goto out;
}
- if (type == RBD_MON_HOST) {
- host = qemu_opt_get(opts, "host");
- port = qemu_opt_get(opts, "port");
-
- value = host;
- if (port) {
- /* check for ipv6 */
- if (strchr(host, ':')) {
- strbuf = g_strdup_printf("[%s]:%s", host, port);
- } else {
- strbuf = g_strdup_printf("%s:%s", host, port);
- }
- value = strbuf;
- } else if (strchr(host, ':')) {
- strbuf = g_strdup_printf("[%s]", host);
- value = strbuf;
- }
- } else {
- value = qemu_opt_get(opts, "auth");
- }
-
-
- /* each iteration in the for loop will build upon the string, and if
- * rados_str is NULL then it is our first pass */
- if (rados_str) {
- /* separate options with ';', as that is what rados_conf_set()
- * requires */
- rados_str_tmp = rados_str;
- rados_str = g_strdup_printf("%s;%s", rados_str_tmp, value);
- g_free(rados_str_tmp);
+ if (strchr(host, ':')) {
+ vals[i] = port ? g_strdup_printf("[%s]:%s", host, port)
+ : g_strdup_printf("[%s]", host);
} else {
- rados_str = g_strdup(value);
+ vals[i] = port ? g_strdup_printf("%s:%s", host, port)
+ : g_strdup(host);
}
-
- g_free(strbuf);
- qemu_opts_del(opts);
- opts = NULL;
}
+ vals[i] = NULL;
-exit:
- qemu_opts_del(opts);
+ rados_str = i ? g_strjoinv(";", (char **)vals) : NULL;
+out:
+ g_strfreev((char **)vals);
return rados_str;
}
@@ -614,20 +571,18 @@ static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags,
qemu_opts_absorb_qdict(opts, options, &local_err);
if (local_err) {
error_propagate(errp, local_err);
- qemu_opts_del(opts);
- return -EINVAL;
+ r = -EINVAL;
+ goto failed_opts;
}
- auth_supported = qemu_rbd_array_opts(options, "auth-supported.",
- RBD_AUTH_SUPPORTED, &local_err);
+ auth_supported = qemu_rbd_auth(options, &local_err);
if (local_err) {
error_propagate(errp, local_err);
r = -EINVAL;
goto failed_opts;
}
- mon_host = qemu_rbd_array_opts(options, "server.",
- RBD_MON_HOST, &local_err);
+ mon_host = qemu_mon_host(options, &local_err);
if (local_err) {
error_propagate(errp, local_err);
r = -EINVAL;
@@ -635,7 +590,6 @@ static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags,
}
secretid = qemu_opt_get(opts, "password-secret");
-
pool = qemu_opt_get(opts, "pool");
conf = qemu_opt_get(opts, "conf");
snap = qemu_opt_get(opts, "snapshot");
--
2.7.4
next prev parent reply other threads:[~2017-03-24 17:44 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-03-24 17:44 [Qemu-devel] [PATCH RFC v2 0/9] rbd: Clean up API and code Markus Armbruster
2017-03-24 17:44 ` [Qemu-devel] [PATCH RFC v2 1/9] rbd: Reject -blockdev server.*.{numeric, to, ipv4, ipv6} Markus Armbruster
2017-03-24 18:05 ` Eric Blake
2017-03-24 17:44 ` [Qemu-devel] [PATCH RFC v2 2/9] rbd: Fix to cleanly reject -drive without pool or image Markus Armbruster
2017-03-24 18:23 ` Eric Blake
2017-03-24 17:44 ` [Qemu-devel] [PATCH RFC v2 3/9] rbd: Don't limit length of parameter values Markus Armbruster
2017-03-24 18:34 ` Eric Blake
2017-03-24 17:44 ` [Qemu-devel] [PATCH RFC v2 4/9] rbd: Clean up after the previous commit Markus Armbruster
2017-03-24 18:44 ` Eric Blake
2017-03-24 17:44 ` [Qemu-devel] [PATCH RFC v2 5/9] rbd: Don't accept -drive driver=rbd, keyvalue-pairs= Markus Armbruster
2017-03-24 18:53 ` Eric Blake
2017-03-24 17:44 ` [Qemu-devel] [PATCH RFC v2 6/9] rbd: Clean up runtime_opts, fix -drive to reject filename Markus Armbruster
2017-03-24 18:55 ` Eric Blake
2017-03-24 17:44 ` [Qemu-devel] [PATCH RFC v2 7/9] rbd: Clean up qemu_rbd_create()'s detour through QemuOpts Markus Armbruster
2017-03-24 17:44 ` Markus Armbruster [this message]
2017-03-24 19:03 ` [Qemu-devel] [PATCH RFC v2 8/9] rbd: Rewrite the code to extract list-valued options Eric Blake
2017-03-24 17:44 ` [Qemu-devel] [PATCH RFC v2 9/9] rbd: Reject invalid authentication methods Markus Armbruster
2017-03-24 19:05 ` Eric Blake
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1490377482-13337-9-git-send-email-armbru@redhat.com \
--to=armbru@redhat.com \
--cc=eblake@redhat.com \
--cc=jcody@redhat.com \
--cc=jdurgin@redhat.com \
--cc=kwolf@redhat.com \
--cc=mreitz@redhat.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).