It's confusing to use the same terminology for a single backend as for
the linked list of backends. In particular it's often not clear if
we're calling the next backend or the whole chain of backends.
---
server/internal.h | 14 ++++++++++--
server/connections.c | 20 ++++++++---------
server/locks.c | 2 +-
server/main.c | 32 ++++++++++++++--------------
server/plugins.c | 2 +-
server/protocol-handshake-newstyle.c | 8 +++----
server/protocol-handshake.c | 28 ++++++++++++------------
server/protocol.c | 18 ++++++++--------
8 files changed, 67 insertions(+), 57 deletions(-)
diff --git a/server/internal.h b/server/internal.h
index 45ac60ad..c3622671 100644
--- a/server/internal.h
+++ b/server/internal.h
@@ -118,8 +118,18 @@ extern char *unixsocket;
extern const char *user, *group;
extern bool verbose;
-extern struct backend *backend;
-#define for_each_backend(b) for (b = backend; b != NULL; b = b->next)
+/* Linked list of backends. Each backend struct is followed by either
+ * a filter or plugin struct. "top" points to the first one. They
+ * are linked through the backend->next field.
+ *
+ * ┌──────────┐ ┌──────────┐ ┌──────────┐
+ * top ───▶│ backend │───▶│ backend │───▶│ backend │
+ * │ b->i = 2 │ │ b->i = 1 │ │ b->i = 0 │
+ * │ filter │ │ filter │ │ plugin │
+ * └──────────┘ └──────────┘ └──────────┘
+ */
+extern struct backend *top;
+#define for_each_backend(b) for (b = top; b != NULL; b = b->next)
/* quit.c */
extern volatile int quit;
diff --git a/server/connections.c b/server/connections.c
index a2049325..7e9584b3 100644
--- a/server/connections.c
+++ b/server/connections.c
@@ -146,23 +146,23 @@ handle_single_connection (int sockin, int sockout)
lock_connection ();
- if (backend->thread_model (backend) < NBDKIT_THREAD_MODEL_PARALLEL ||
+ if (top->thread_model (top) < NBDKIT_THREAD_MODEL_PARALLEL ||
nworkers == 1)
nworkers = 0;
conn = new_connection (sockin, sockout, nworkers);
if (!conn)
goto done;
- /* NB: because of an asynchronous exit backend can be set to NULL at
+ /* NB: because of an asynchronous exit top can be set to NULL at
* just about any time.
*/
- if (backend)
- plugin_name = backend->plugin_name (backend);
+ if (top)
+ plugin_name = top->plugin_name (top);
else
plugin_name = "(unknown)";
threadlocal_set_name (plugin_name);
- if (backend && backend->preconnect (backend, read_only) == -1)
+ if (top && top->preconnect (top, read_only) == -1)
goto done;
/* NBD handshake.
@@ -225,7 +225,7 @@ handle_single_connection (int sockin, int sockout)
/* Finalize (for filters), called just before close. */
lock_request ();
- r = backend_finalize (backend);
+ r = backend_finalize (top);
unlock_request ();
if (r == -1)
goto done;
@@ -251,12 +251,12 @@ new_connection (int sockin, int sockout, int nworkers)
conn->status_pipe[0] = conn->status_pipe[1] = -1;
- conn->handles = calloc (backend->i + 1, sizeof *conn->handles);
+ conn->handles = calloc (top->i + 1, sizeof *conn->handles);
if (conn->handles == NULL) {
perror ("malloc");
goto error;
}
- conn->nr_handles = backend->i + 1;
+ conn->nr_handles = top->i + 1;
for_each_backend (b)
reset_b_conn_handle (&conn->handles[b->i]);
@@ -277,7 +277,7 @@ new_connection (int sockin, int sockout, int nworkers)
* we aren't accepting until the plugin is not running, making
* non-atomicity okay.
*/
- assert (backend->thread_model (backend) <=
+ assert (top->thread_model (top) <=
NBDKIT_THREAD_MODEL_SERIALIZE_ALL_REQUESTS);
lock_request (NULL);
if (pipe (conn->status_pipe)) {
@@ -354,7 +354,7 @@ free_connection (struct connection *conn)
*/
if (!quit) {
lock_request ();
- backend_close (backend);
+ backend_close (top);
unlock_request ();
}
diff --git a/server/locks.c b/server/locks.c
index f005710d..6211648d 100644
--- a/server/locks.c
+++ b/server/locks.c
@@ -69,7 +69,7 @@ name_of_thread_model (int model)
void
lock_init_thread_model (void)
{
- thread_model = backend->thread_model (backend);
+ thread_model = top->thread_model (top);
debug ("using thread model: %s", name_of_thread_model (thread_model));
}
diff --git a/server/main.c b/server/main.c
index 550a8714..dbeca624 100644
--- a/server/main.c
+++ b/server/main.c
@@ -102,8 +102,8 @@ bool verbose; /* -v */
bool vsock; /* --vsock */
unsigned int socket_activation /* $LISTEN_FDS and $LISTEN_PID set */;
-/* The currently loaded plugin. */
-struct backend *backend;
+/* The linked list of zero or more filters, and one plugin. */
+struct backend *top;
static char *random_fifo_dir = NULL;
static char *random_fifo = NULL;
@@ -555,10 +555,10 @@ main (int argc, char *argv[])
/* Open the plugin (first) and then wrap the plugin with the
* filters. The filters are wrapped in reverse order that they
- * appear on the command line so that in the end ‘backend’ points to
+ * appear on the command line so that in the end ‘top’ points to
* the first filter on the command line.
*/
- backend = open_plugin_so (0, filename, short_name);
+ top = open_plugin_so (0, filename, short_name);
i = 1;
while (filter_filenames) {
struct filter_filename *t = filter_filenames;
@@ -566,7 +566,7 @@ main (int argc, char *argv[])
filename = t->filename;
short_name = is_short_name (filename);
- backend = open_filter_so (backend, i++, filename, short_name);
+ top = open_filter_so (top, i++, filename, short_name);
filter_filenames = t->next;
free (t);
@@ -586,7 +586,7 @@ main (int argc, char *argv[])
printf ("\n");
b->usage (b);
}
- backend->free (backend);
+ top->free (top);
exit (EXIT_SUCCESS);
}
@@ -601,7 +601,7 @@ main (int argc, char *argv[])
printf (" %s", v);
printf ("\n");
}
- backend->free (backend);
+ top->free (top);
exit (EXIT_SUCCESS);
}
@@ -615,16 +615,16 @@ main (int argc, char *argv[])
* first parameter is bare it is prefixed with the key "script", and
* any other bare parameters are errors.
*/
- magic_config_key = backend->magic_config_key (backend);
+ magic_config_key = top->magic_config_key (top);
for (i = 0; optind < argc; ++i, ++optind) {
p = strchr (argv[optind], '=');
if (p && is_config_key (argv[optind], p - argv[optind])) { /* key=value */
*p = '\0';
- backend->config (backend, argv[optind], p+1);
+ top->config (top, argv[optind], p+1);
}
else if (magic_config_key == NULL) {
if (i == 0) /* magic script parameter */
- backend->config (backend, "script", argv[optind]);
+ top->config (top, "script", argv[optind]);
else {
fprintf (stderr,
"%s: expecting key=value on the command line but got: %s\n",
@@ -633,7 +633,7 @@ main (int argc, char *argv[])
}
}
else { /* magic config key */
- backend->config (backend, magic_config_key, argv[optind]);
+ top->config (top, magic_config_key, argv[optind]);
}
}
@@ -643,12 +643,12 @@ main (int argc, char *argv[])
* parameters.
*/
if (dump_plugin) {
- backend->dump_fields (backend);
- backend->free (backend);
+ top->dump_fields (top);
+ top->free (top);
exit (EXIT_SUCCESS);
}
- backend->config_complete (backend);
+ top->config_complete (top);
/* Select the correct thread model based on config. */
lock_init_thread_model ();
@@ -660,8 +660,8 @@ main (int argc, char *argv[])
start_serving ();
- backend->free (backend);
- backend = NULL;
+ top->free (top);
+ top = NULL;
free (unixsocket);
free (pidfile);
diff --git a/server/plugins.c b/server/plugins.c
index 9595269c..16b4099b 100644
--- a/server/plugins.c
+++ b/server/plugins.c
@@ -144,7 +144,7 @@ plugin_dump_fields (struct backend *b)
printf ("max_thread_model=%s\n",
name_of_thread_model (p->plugin._thread_model));
printf ("thread_model=%s\n",
- name_of_thread_model (backend->thread_model (backend)));
+ name_of_thread_model (top->thread_model (top)));
printf ("errno_is_preserved=%d\n", !!p->plugin.errno_is_preserved);
if (p->plugin.magic_config_key)
printf ("magic_config_key=%s\n", p->plugin.magic_config_key);
diff --git a/server/protocol-handshake-newstyle.c b/server/protocol-handshake-newstyle.c
index 41b2a6e4..946060ac 100644
--- a/server/protocol-handshake-newstyle.c
+++ b/server/protocol-handshake-newstyle.c
@@ -478,9 +478,9 @@ negotiate_handshake_newstyle_options (void)
* disconnecting.
*/
if (finish_newstyle_options (&exportsize) == -1) {
- if (backend_finalize (backend) == -1)
+ if (backend_finalize (top) == -1)
return -1;
- backend_close (backend);
+ backend_close (top);
if (send_newstyle_option_reply (option, NBD_REP_ERR_UNKNOWN) == -1)
return -1;
continue;
@@ -518,9 +518,9 @@ negotiate_handshake_newstyle_options (void)
return -1;
if (option == NBD_OPT_INFO) {
- if (backend_finalize (backend) == -1)
+ if (backend_finalize (top) == -1)
return -1;
- backend_close (backend);
+ backend_close (top);
}
break;
diff --git a/server/protocol-handshake.c b/server/protocol-handshake.c
index a32fcde0..70ea4933 100644
--- a/server/protocol-handshake.c
+++ b/server/protocol-handshake.c
@@ -79,14 +79,14 @@ protocol_common_open (uint64_t *exportsize, uint16_t *flags)
uint16_t eflags = NBD_FLAG_HAS_FLAGS;
int fl;
- if (backend_open (backend, read_only) == -1)
+ if (backend_open (top, read_only) == -1)
return -1;
/* Prepare (for filters), called just after open. */
- if (backend_prepare (backend) == -1)
+ if (backend_prepare (top) == -1)
return -1;
- size = backend_get_size (backend);
+ size = backend_get_size (top);
if (size == -1)
return -1;
if (size < 0) {
@@ -98,57 +98,57 @@ protocol_common_open (uint64_t *exportsize, uint16_t *flags)
/* Check all flags even if they won't be advertised, to prime the
* cache and make later request validation easier.
*/
- fl = backend_can_write (backend);
+ fl = backend_can_write (top);
if (fl == -1)
return -1;
if (!fl)
eflags |= NBD_FLAG_READ_ONLY;
- fl = backend_can_zero (backend);
+ fl = backend_can_zero (top);
if (fl == -1)
return -1;
if (fl)
eflags |= NBD_FLAG_SEND_WRITE_ZEROES;
- fl = backend_can_fast_zero (backend);
+ fl = backend_can_fast_zero (top);
if (fl == -1)
return -1;
if (fl)
eflags |= NBD_FLAG_SEND_FAST_ZERO;
- fl = backend_can_trim (backend);
+ fl = backend_can_trim (top);
if (fl == -1)
return -1;
if (fl)
eflags |= NBD_FLAG_SEND_TRIM;
- fl = backend_can_fua (backend);
+ fl = backend_can_fua (top);
if (fl == -1)
return -1;
if (fl)
eflags |= NBD_FLAG_SEND_FUA;
- fl = backend_can_flush (backend);
+ fl = backend_can_flush (top);
if (fl == -1)
return -1;
if (fl)
eflags |= NBD_FLAG_SEND_FLUSH;
- fl = backend_is_rotational (backend);
+ fl = backend_is_rotational (top);
if (fl == -1)
return -1;
if (fl)
eflags |= NBD_FLAG_ROTATIONAL;
/* multi-conn is useless if parallel connections are not allowed. */
- fl = backend_can_multi_conn (backend);
+ fl = backend_can_multi_conn (top);
if (fl == -1)
return -1;
- if (fl && (backend->thread_model (backend) >
+ if (fl && (top->thread_model (top) >
NBDKIT_THREAD_MODEL_SERIALIZE_CONNECTIONS))
eflags |= NBD_FLAG_CAN_MULTI_CONN;
- fl = backend_can_cache (backend);
+ fl = backend_can_cache (top);
if (fl == -1)
return -1;
if (fl)
@@ -159,7 +159,7 @@ protocol_common_open (uint64_t *exportsize, uint16_t *flags)
* not have to worry about errors, and makes test-layers easier to
* write.
*/
- fl = backend_can_extents (backend);
+ fl = backend_can_extents (top);
if (fl == -1)
return -1;
diff --git a/server/protocol.c b/server/protocol.c
index d41ad569..b56d16bd 100644
--- a/server/protocol.c
+++ b/server/protocol.c
@@ -72,7 +72,7 @@ validate_request (uint16_t cmd, uint16_t flags, uint64_t offset,
uint32_t count,
case NBD_CMD_TRIM:
case NBD_CMD_WRITE_ZEROES:
case NBD_CMD_BLOCK_STATUS:
- if (!backend_valid_range (backend, offset, count)) {
+ if (!backend_valid_range (top, offset, count)) {
/* XXX Allow writes to extend the disk? */
nbdkit_error ("invalid request: %s: offset and count are out of range: "
"offset=%" PRIu64 " count=%" PRIu32,
@@ -238,31 +238,31 @@ handle_request (uint16_t cmd, uint16_t flags, uint64_t offset,
uint32_t count,
switch (cmd) {
case NBD_CMD_READ:
- if (backend_pread (backend, buf, count, offset, 0, &err) == -1)
+ if (backend_pread (top, buf, count, offset, 0, &err) == -1)
return err;
break;
case NBD_CMD_WRITE:
if (flags & NBD_CMD_FLAG_FUA)
f |= NBDKIT_FLAG_FUA;
- if (backend_pwrite (backend, buf, count, offset, f, &err) == -1)
+ if (backend_pwrite (top, buf, count, offset, f, &err) == -1)
return err;
break;
case NBD_CMD_FLUSH:
- if (backend_flush (backend, 0, &err) == -1)
+ if (backend_flush (top, 0, &err) == -1)
return err;
break;
case NBD_CMD_TRIM:
if (flags & NBD_CMD_FLAG_FUA)
f |= NBDKIT_FLAG_FUA;
- if (backend_trim (backend, count, offset, f, &err) == -1)
+ if (backend_trim (top, count, offset, f, &err) == -1)
return err;
break;
case NBD_CMD_CACHE:
- if (backend_cache (backend, count, offset, 0, &err) == -1)
+ if (backend_cache (top, count, offset, 0, &err) == -1)
return err;
break;
@@ -273,14 +273,14 @@ handle_request (uint16_t cmd, uint16_t flags, uint64_t offset,
uint32_t count,
f |= NBDKIT_FLAG_FUA;
if (flags & NBD_CMD_FLAG_FAST_ZERO)
f |= NBDKIT_FLAG_FAST_ZERO;
- if (backend_zero (backend, count, offset, f, &err) == -1)
+ if (backend_zero (top, count, offset, f, &err) == -1)
return err;
break;
case NBD_CMD_BLOCK_STATUS:
if (flags & NBD_CMD_FLAG_REQ_ONE)
f |= NBDKIT_FLAG_REQ_ONE;
- if (backend_extents (backend, count, offset, f,
+ if (backend_extents (top, count, offset, f,
extents, &err) == -1)
return err;
break;
@@ -683,7 +683,7 @@ protocol_recv_request_send_reply (void)
/* Allocate the extents list for block status only. */
if (cmd == NBD_CMD_BLOCK_STATUS) {
- extents = nbdkit_extents_new (offset, backend_get_size (backend));
+ extents = nbdkit_extents_new (offset, backend_get_size (top));
if (extents == NULL) {
error = ENOMEM;
goto send_reply;
--
2.25.0