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