On 08/31/22 16:39, Eric Blake wrote:
Instead of open-coding a linked list, we can utilize our vector.h
helpers. No semantic change intended.
---
lib/internal.h | 17 +++++----
generator/states-newstyle-opt-meta-context.c | 36 ++++++++------------
generator/states-reply-structured.c | 10 +++---
lib/flags.c | 19 ++++-------
lib/rw.c | 2 +-
5 files changed, 35 insertions(+), 49 deletions(-)
diff --git a/lib/internal.h b/lib/internal.h
index 0a61b15..d601d5d 100644
--- a/lib/internal.h
+++ b/lib/internal.h
@@ -64,10 +64,15 @@
*/
#define MAX_REQUEST_SIZE (64 * 1024 * 1024)
-struct meta_context;
struct socket;
struct command;
+struct meta_context {
+ char *name; /* Name of meta context. */
+ uint32_t context_id; /* Context ID negotiated with the server. */
+};
+DEFINE_VECTOR_TYPE(meta_vector, struct meta_context);
+
struct export {
char *name;
char *description;
@@ -174,8 +179,8 @@ struct nbd_handle {
bool structured_replies; /* If we negotiated NBD_OPT_STRUCTURED_REPLY */
- /* Linked list of negotiated metadata contexts. */
- struct meta_context *meta_contexts;
+ /* Vector of negotiated metadata contexts. */
+ meta_vector meta_contexts;
/* The socket or a wrapper if using GnuTLS. */
struct socket *sock;
@@ -311,12 +316,6 @@ struct nbd_handle {
bool tls_shut_writes; /* Used by lib/crypto.c to track disconnect. */
};
-struct meta_context {
- struct meta_context *next; /* Linked list. */
- char *name; /* Name of meta context. */
- uint32_t context_id; /* Context ID negotiated with the server. */
-};
-
struct socket_ops {
ssize_t (*recv) (struct nbd_handle *h,
struct socket *sock, void *buf, size_t len);
diff --git a/generator/states-newstyle-opt-meta-context.c
b/generator/states-newstyle-opt-meta-context.c
index 30b9617..8f4dee2 100644
--- a/generator/states-newstyle-opt-meta-context.c
+++ b/generator/states-newstyle-opt-meta-context.c
@@ -1,5 +1,5 @@
/* nbd client library in userspace: state machine
- * Copyright (C) 2013-2020 Red Hat Inc.
+ * Copyright (C) 2013-2022 Red Hat Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -44,7 +44,7 @@ STATE_MACHINE {
}
}
- assert (h->meta_contexts == NULL);
+ assert (h->meta_contexts.len == 0);
/* Calculate the length of the option request data. */
len = 4 /* exportname len */ + strlen (h->export_name) + 4 /* nr queries */;
@@ -176,7 +176,7 @@ STATE_MACHINE {
uint32_t reply;
uint32_t len;
const size_t maxpayload = sizeof h->sbuf.or.payload.context;
- struct meta_context *meta_context;
+ struct meta_context meta_context;
uint32_t opt;
int err = 0;
@@ -202,33 +202,27 @@ STATE_MACHINE {
debug (h, "skipping too large meta context");
else {
assert (len > sizeof h->sbuf.or.payload.context.context.context_id);
- meta_context = malloc (sizeof *meta_context);
- if (meta_context == NULL) {
- set_error (errno, "malloc");
- SET_NEXT_STATE (%.DEAD);
- return 0;
- }
- meta_context->context_id =
+ meta_context.context_id =
be32toh (h->sbuf.or.payload.context.context.context_id);
/* String payload is not NUL-terminated. */
- meta_context->name = strndup (h->sbuf.or.payload.context.str,
- len - sizeof meta_context->context_id);
- if (meta_context->name == NULL) {
+ meta_context.name = strndup (h->sbuf.or.payload.context.str,
+ len - sizeof meta_context.context_id);
+ if (meta_context.name == NULL) {
set_error (errno, "strdup");
SET_NEXT_STATE (%.DEAD);
- free (meta_context);
return 0;
}
debug (h, "negotiated %s with context ID %" PRIu32,
- meta_context->name, meta_context->context_id);
+ meta_context.name, meta_context.context_id);
if (opt == NBD_OPT_LIST_META_CONTEXT) {
- CALL_CALLBACK (h->opt_cb.fn.context, meta_context->name);
- free (meta_context->name);
- free (meta_context);
+ CALL_CALLBACK (h->opt_cb.fn.context, meta_context.name);
+ free (meta_context.name);
}
- else {
- meta_context->next = h->meta_contexts;
- h->meta_contexts = meta_context;
+ else if (meta_vector_append (&h->meta_contexts, meta_context) == -1) {
+ set_error (errno, "realloc");
haha, I see what you did there! We're leaking our knowledge of vector's
internal use of "realloc" :)
Reviewed-by: Laszlo Ersek <lersek(a)redhat.com>
Laszlo
+ free (meta_context.name);
+ SET_NEXT_STATE (%.DEAD);
+ return 0;
}
}
SET_NEXT_STATE (%PREPARE_FOR_REPLY);
diff --git a/generator/states-reply-structured.c b/generator/states-reply-structured.c
index 19d9fb2..aaf75b8 100644
--- a/generator/states-reply-structured.c
+++ b/generator/states-reply-structured.c
@@ -454,18 +454,16 @@ STATE_MACHINE {
/* Look up the context ID. */
context_id = h->bs_entries[0];
- for (meta_context = h->meta_contexts;
- meta_context;
- meta_context = meta_context->next)
- if (context_id == meta_context->context_id)
+ for (i = 0; i < h->meta_contexts.len; ++i)
+ if (context_id == h->meta_contexts.ptr[i].context_id)
break;
- if (meta_context) {
+ if (i < h->meta_contexts.len) {
/* Call the caller's extent function. */
int error = cmd->error;
if (CALL_CALLBACK (cmd->cb.fn.extent,
- meta_context->name, cmd->offset,
+ h->meta_contexts.ptr[i].name, cmd->offset,
&h->bs_entries[1], (length-4) / 4,
&error) == -1)
if (cmd->error == 0)
diff --git a/lib/flags.c b/lib/flags.c
index 44d61c8..87c20ee 100644
--- a/lib/flags.c
+++ b/lib/flags.c
@@ -33,16 +33,13 @@
void
nbd_internal_reset_size_and_flags (struct nbd_handle *h)
{
- struct meta_context *m, *m_next;
+ size_t i;
h->exportsize = 0;
h->eflags = 0;
- for (m = h->meta_contexts; m != NULL; m = m_next) {
- m_next = m->next;
- free (m->name);
- free (m);
- }
- h->meta_contexts = NULL;
+ for (i = 0; i < h->meta_contexts.len; ++i)
+ free (h->meta_contexts.ptr[i].name);
+ meta_vector_reset (&h->meta_contexts);
h->block_minimum = 0;
h->block_preferred = 0;
h->block_maximum = 0;
@@ -195,7 +192,7 @@ nbd_unlocked_can_cache (struct nbd_handle *h)
int
nbd_unlocked_can_meta_context (struct nbd_handle *h, const char *name)
{
- struct meta_context *meta_context;
+ size_t i;
if (h->eflags == 0) {
set_error (EINVAL, "server has not returned export flags, "
@@ -203,10 +200,8 @@ nbd_unlocked_can_meta_context (struct nbd_handle *h, const char
*name)
return -1;
}
- for (meta_context = h->meta_contexts;
- meta_context;
- meta_context = meta_context->next)
- if (strcmp (meta_context->name, name) == 0)
+ for (i = 0; i < h->meta_contexts.len; ++i)
+ if (strcmp (h->meta_contexts.ptr[i].name, name) == 0)
return 1;
return 0;
}
diff --git a/lib/rw.c b/lib/rw.c
index f32481a..81f8f35 100644
--- a/lib/rw.c
+++ b/lib/rw.c
@@ -482,7 +482,7 @@ nbd_unlocked_aio_block_status (struct nbd_handle *h,
return -1;
}
- if (h->meta_contexts == NULL) {
+ if (h->meta_contexts.len == 0) {
set_error (ENOTSUP, "did not negotiate any metadata contexts, "
"either you did not call nbd_add_meta_context before "
"connecting or the server does not support it");