On 1/4/19 4:08 PM, Richard W.M. Jones wrote:
From the protocol document:
"NBD_FLAG_CAN_MULTI_CONN: Indicates that the server operates entirely without cache, or that the cache it uses is shared among all connections to the given device. In particular, if this flag is present, then the effects of NBD_CMD_FLUSH and NBD_CMD_FLAG_FUA MUST be visible across all connections when the server sends its reply to that command to the client. In the absence of this flag, clients SHOULD NOT multiplex their commands over more than one connection to the export."
This is implemented in nbdkit by a boolean function which plugins may implement if they believe they satisfy the requirements above. It can also be passed through or modified by filters. It defaults to false, which is the safe default. --- docs/nbdkit-filter.pod | 4 ++++ docs/nbdkit-plugin.pod | 20 ++++++++++++++++++++ docs/nbdkit-protocol.pod | 4 ++++ include/nbdkit-filter.h | 3 +++ include/nbdkit-plugin.h | 2 ++ server/internal.h | 1 + server/protocol.h | 1 + server/connections.c | 9 +++++++++ server/filters.c | 24 ++++++++++++++++++++++++ server/plugins.c | 17 +++++++++++++++++ tests/test-layers-filter.c | 10 ++++++++++ tests/test-layers-plugin.c | 8 ++++++++ tests/test-layers.c | 6 ++++++ 13 files changed, 109 insertions(+)
+++ b/server/connections.c @@ -84,6 +84,7 @@ struct connection { bool can_trim; bool can_zero; bool can_fua; + bool can_multi_conn; bool using_tls;
int sockin, sockout; @@ -463,6 +464,14 @@ compute_eflags (struct connection *conn, uint16_t *flags) conn->is_rotational = true; }
+ fl = backend->can_multi_conn (backend, conn); + if (fl == -1) + return -1; + if (fl) { + eflags |= NBD_FLAG_CAN_MULTI_CONN; + conn->can_multi_conn = true; + }
One more tweak: we should never advertise multi-conn if we are serializing connections (a client attempting a second connection will block on that connection, which defeats the point). I'm applying this followup: +++ b/server/protocol-handshake.c @@ -101,12 +101,16 @@ protocol_compute_eflags (struct connection *conn, uint16_t *flags) conn->is_rotational = true; } - fl = backend->can_multi_conn (backend, conn); - if (fl == -1) - return -1; - if (fl) { - eflags |= NBD_FLAG_CAN_MULTI_CONN; - conn->can_multi_conn = true; + /* multi-conn is useless if parallel connections are not allowed */ + if (backend->thread_model (backend) > + NBDKIT_THREAD_MODEL_SERIALIZE_CONNECTIONS) { + fl = backend->can_multi_conn (backend, conn); + if (fl == -1) + return -1; + if (fl) { + eflags |= NBD_FLAG_CAN_MULTI_CONN; + conn->can_multi_conn = true; + } } fl = backend->can_cache (backend, conn); -- 2.20.1 -- Eric Blake, Principal Software Engineer Red Hat, Inc. +1-919-301-3226 Virtualization: qemu.org | libvirt.org