[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PULL 12/21] nbd/client: Split out nbd_receive_one_meta_con
From: |
Eric Blake |
Subject: |
[Qemu-devel] [PULL 12/21] nbd/client: Split out nbd_receive_one_meta_context() |
Date: |
Mon, 21 Jan 2019 16:48:58 -0600 |
Extract portions of nbd_negotiate_simple_meta_context() to
a new function nbd_receive_one_meta_context() that copies the
pattern of nbd_receive_list() for performing the argument
validation of one reply. The error message when the server
replies with more than one context changes slightly, but
that shouldn't happen in the common case.
Signed-off-by: Eric Blake <address@hidden>
Reviewed-by: Vladimir Sementsov-Ogievskiy <address@hidden>
Message-Id: <address@hidden>
---
nbd/client.c | 147 +++++++++++++++++++++++++++++------------------
nbd/trace-events | 2 +-
2 files changed, 91 insertions(+), 58 deletions(-)
diff --git a/nbd/client.c b/nbd/client.c
index 96da68ee18a..c7bb7081553 100644
--- a/nbd/client.c
+++ b/nbd/client.c
@@ -669,7 +669,86 @@ static int nbd_send_meta_query(QIOChannel *ioc, uint32_t
opt,
return ret;
}
-/* nbd_negotiate_simple_meta_context:
+/*
+ * nbd_receive_one_meta_context:
+ * Called in a loop to receive and trace one set/list meta context reply.
+ * Pass non-NULL @name or @id to collect results back to the caller, which
+ * must eventually call g_free().
+ * return 1 if name is set and iteration must continue,
+ * 0 if iteration is complete (including if option is unsupported),
+ * -1 with errp set for any error
+ */
+static int nbd_receive_one_meta_context(QIOChannel *ioc,
+ uint32_t opt,
+ char **name,
+ uint32_t *id,
+ Error **errp)
+{
+ int ret;
+ NBDOptionReply reply;
+ char *local_name = NULL;
+ uint32_t local_id;
+
+ if (nbd_receive_option_reply(ioc, opt, &reply, errp) < 0) {
+ return -1;
+ }
+
+ ret = nbd_handle_reply_err(ioc, &reply, errp);
+ if (ret <= 0) {
+ return ret;
+ }
+
+ if (reply.type == NBD_REP_ACK) {
+ if (reply.length != 0) {
+ error_setg(errp, "Unexpected length to ACK response");
+ nbd_send_opt_abort(ioc);
+ return -1;
+ }
+ return 0;
+ } else if (reply.type != NBD_REP_META_CONTEXT) {
+ error_setg(errp, "Unexpected reply type %u (%s), expected %u (%s)",
+ reply.type, nbd_rep_lookup(reply.type),
+ NBD_REP_META_CONTEXT, nbd_rep_lookup(NBD_REP_META_CONTEXT));
+ nbd_send_opt_abort(ioc);
+ return -1;
+ }
+
+ if (reply.length <= sizeof(local_id) ||
+ reply.length > NBD_MAX_BUFFER_SIZE) {
+ error_setg(errp, "Failed to negotiate meta context, server "
+ "answered with unexpected length %" PRIu32,
+ reply.length);
+ nbd_send_opt_abort(ioc);
+ return -1;
+ }
+
+ if (nbd_read(ioc, &local_id, sizeof(local_id), errp) < 0) {
+ return -1;
+ }
+ local_id = be32_to_cpu(local_id);
+
+ reply.length -= sizeof(local_id);
+ local_name = g_malloc(reply.length + 1);
+ if (nbd_read(ioc, local_name, reply.length, errp) < 0) {
+ g_free(local_name);
+ return -1;
+ }
+ local_name[reply.length] = '\0';
+ trace_nbd_opt_meta_reply(nbd_opt_lookup(opt), local_name, local_id);
+
+ if (name) {
+ *name = local_name;
+ } else {
+ g_free(local_name);
+ }
+ if (id) {
+ *id = local_id;
+ }
+ return 1;
+}
+
+/*
+ * nbd_negotiate_simple_meta_context:
* Request the server to set the meta context for export @info->name
* using @info->x_dirty_bitmap with a fallback to "base:allocation",
* setting @info->context_id to the resulting id. Fail if the server
@@ -690,50 +769,21 @@ static int nbd_negotiate_simple_meta_context(QIOChannel
*ioc,
* function should lose the term _simple.
*/
int ret;
- NBDOptionReply reply;
const char *context = info->x_dirty_bitmap ?: "base:allocation";
bool received = false;
+ char *name = NULL;
if (nbd_send_meta_query(ioc, NBD_OPT_SET_META_CONTEXT,
info->name, context, errp) < 0) {
return -1;
}
- if (nbd_receive_option_reply(ioc, NBD_OPT_SET_META_CONTEXT, &reply,
- errp) < 0)
- {
+ ret = nbd_receive_one_meta_context(ioc, NBD_OPT_SET_META_CONTEXT,
+ &name, &info->context_id, errp);
+ if (ret < 0) {
return -1;
}
-
- ret = nbd_handle_reply_err(ioc, &reply, errp);
- if (ret <= 0) {
- return ret;
- }
-
- if (reply.type == NBD_REP_META_CONTEXT) {
- char *name;
-
- if (reply.length != sizeof(info->context_id) + strlen(context)) {
- error_setg(errp, "Failed to negotiate meta context '%s', server "
- "answered with unexpected length %" PRIu32, context,
- reply.length);
- nbd_send_opt_abort(ioc);
- return -1;
- }
-
- if (nbd_read(ioc, &info->context_id, sizeof(info->context_id),
- errp) < 0) {
- return -1;
- }
- info->context_id = be32_to_cpu(info->context_id);
-
- reply.length -= sizeof(info->context_id);
- name = g_malloc(reply.length + 1);
- if (nbd_read(ioc, name, reply.length, errp) < 0) {
- g_free(name);
- return -1;
- }
- name[reply.length] = '\0';
+ if (ret == 1) {
if (strcmp(context, name)) {
error_setg(errp, "Failed to negotiate meta context '%s', server "
"answered with different context '%s'", context,
@@ -743,36 +793,19 @@ static int nbd_negotiate_simple_meta_context(QIOChannel
*ioc,
return -1;
}
g_free(name);
-
- trace_nbd_opt_meta_reply(context, info->context_id);
received = true;
- /* receive NBD_REP_ACK */
- if (nbd_receive_option_reply(ioc, NBD_OPT_SET_META_CONTEXT, &reply,
- errp) < 0)
- {
+ ret = nbd_receive_one_meta_context(ioc, NBD_OPT_SET_META_CONTEXT,
+ NULL, NULL, errp);
+ if (ret < 0) {
return -1;
}
-
- ret = nbd_handle_reply_err(ioc, &reply, errp);
- if (ret <= 0) {
- return ret;
- }
}
-
- if (reply.type != NBD_REP_ACK) {
- error_setg(errp, "Unexpected reply type %u (%s), expected %u (%s)",
- reply.type, nbd_rep_lookup(reply.type),
- NBD_REP_ACK, nbd_rep_lookup(NBD_REP_ACK));
+ if (ret != 0) {
+ error_setg(errp, "Server answered with more than one context");
nbd_send_opt_abort(ioc);
return -1;
}
- if (reply.length) {
- error_setg(errp, "Unexpected length to ACK response");
- nbd_send_opt_abort(ioc);
- return -1;
- }
-
return received;
}
diff --git a/nbd/trace-events b/nbd/trace-events
index 59521e47a3d..b4802c1570e 100644
--- a/nbd/trace-events
+++ b/nbd/trace-events
@@ -13,7 +13,7 @@ nbd_receive_query_exports_success(const char *wantname)
"Found desired export na
nbd_receive_starttls_new_client(void) "Setting up TLS"
nbd_receive_starttls_tls_handshake(void) "Starting TLS handshake"
nbd_opt_meta_request(const char *optname, const char *context, const char
*export) "Requesting %s %s for export %s"
-nbd_opt_meta_reply(const char *context, uint32_t id) "Received mapping of
context %s to id %" PRIu32
+nbd_opt_meta_reply(const char *optname, const char *context, uint32_t id)
"Received %s mapping of %s to id %" PRIu32
nbd_receive_negotiate(void *tlscreds, const char *hostname) "Receiving
negotiation tlscreds=%p hostname=%s"
nbd_receive_negotiate_magic(uint64_t magic) "Magic is 0x%" PRIx64
nbd_receive_negotiate_server_flags(uint32_t globalflags) "Global flags are
0x%" PRIx32
--
2.20.1
- [Qemu-devel] [PULL 04/21] qemu-nbd: Sanity check partition bounds, (continued)
- [Qemu-devel] [PULL 04/21] qemu-nbd: Sanity check partition bounds, Eric Blake, 2019/01/21
- [Qemu-devel] [PULL 05/21] nbd/server: Hoist length check to qmp_nbd_server_add, Eric Blake, 2019/01/21
- [Qemu-devel] [PULL 17/21] nbd/client: Add nbd_receive_export_list(), Eric Blake, 2019/01/21
- [Qemu-devel] [PULL 08/21] nbd/client: Refactor nbd_receive_list(), Eric Blake, 2019/01/21
- [Qemu-devel] [PULL 16/21] nbd/client: Refactor nbd_opt_go() to support NBD_OPT_INFO, Eric Blake, 2019/01/21
- [Qemu-devel] [PULL 06/21] nbd/server: Favor [u]int64_t over off_t, Eric Blake, 2019/01/21
- [Qemu-devel] [PULL 14/21] nbd/client: Split handshake into two functions, Eric Blake, 2019/01/21
- [Qemu-devel] [PULL 09/21] nbd/client: Move export name into NBDExportInfo, Eric Blake, 2019/01/21
- [Qemu-devel] [PULL 11/21] nbd/client: Split out nbd_send_meta_query(), Eric Blake, 2019/01/21
- [Qemu-devel] [PULL 18/21] nbd/client: Add meta contexts to nbd_receive_export_list(), Eric Blake, 2019/01/21
- [Qemu-devel] [PULL 12/21] nbd/client: Split out nbd_receive_one_meta_context(),
Eric Blake <=
- [Qemu-devel] [PULL 10/21] nbd/client: Change signature of nbd_negotiate_simple_meta_context(), Eric Blake, 2019/01/21
- [Qemu-devel] [PULL 15/21] nbd/client: Pull out oldstyle size determination, Eric Blake, 2019/01/21
- [Qemu-devel] [PULL 20/21] nbd/client: Work around 3.0 bug for listing meta contexts, Eric Blake, 2019/01/21
- [Qemu-devel] [PULL 07/21] qemu-nbd: Avoid strtol open-coding, Eric Blake, 2019/01/21
- [Qemu-devel] [PULL 13/21] nbd/client: Refactor return of nbd_receive_negotiate(), Eric Blake, 2019/01/21
- [Qemu-devel] [PULL 21/21] iotests: Enhance 223, 233 to cover 'qemu-nbd --list', Eric Blake, 2019/01/21
- [Qemu-devel] [PULL 19/21] qemu-nbd: Add --list option, Eric Blake, 2019/01/21
- Re: [Qemu-devel] [PULL 00/21] NBD patches through 2019-01-21, Peter Maydell, 2019/01/22