[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [libnbd PATCH v3 18/22] generator: Actually request extended headers
From: |
Richard W.M. Jones |
Subject: |
Re: [libnbd PATCH v3 18/22] generator: Actually request extended headers |
Date: |
Thu, 8 Jun 2023 10:41:43 +0100 |
User-agent: |
Mutt/1.5.21 (2010-09-15) |
On Thu, May 25, 2023 at 08:01:04AM -0500, Eric Blake wrote:
> This is the culmination of the previous patches' preparation work for
> using extended headers when possible. The new states in the state
> machine are copied extensively from our handling of
> OPT_STRUCTURED_REPLY. The next patch will then expose a new API
> nbd_opt_extended_headers() for manual control.
>
> At the same time I posted this patch, I had patches for qemu-nbd to
> support extended headers as server (nbdkit is a bit tougher). The
> next patches will add some interop tests that pass when using a new
> enough qemu-nbd, showing that we have cross-project interoperability
> and therefore an extension worth standardizing.
>
> Signed-off-by: Eric Blake <eblake@redhat.com>
> ---
> generator/API.ml | 87 ++++++++---------
> generator/Makefile.am | 1 +
> generator/state_machine.ml | 41 ++++++++
> .../states-newstyle-opt-extended-headers.c | 94 +++++++++++++++++++
> generator/states-newstyle-opt-starttls.c | 6 +-
> 5 files changed, 184 insertions(+), 45 deletions(-)
> create mode 100644 generator/states-newstyle-opt-extended-headers.c
>
> diff --git a/generator/API.ml b/generator/API.ml
> index 7616990a..078f140f 100644
> --- a/generator/API.ml
> +++ b/generator/API.ml
> @@ -953,23 +953,24 @@ "set_request_meta_context", {
> (all C<nbd_connect_*> calls when L<nbd_set_opt_mode(3)> is false,
> or L<nbd_opt_go(3)> and L<nbd_opt_info(3)> when option mode is
> enabled) will also try to issue NBD_OPT_SET_META_CONTEXT when
> -the server supports structured replies and any contexts were
> -registered by L<nbd_add_meta_context(3)>. The default setting
> -is true; however the extra step of negotiating meta contexts is
> -not always desirable: performing both info and go on the same
> -export works without needing to re-negotiate contexts on the
> -second call; integration testing of other servers may benefit
> -from manual invocation of L<nbd_opt_set_meta_context(3)> at
> -other times in the negotiation sequence; and even when using just
> -L<nbd_opt_info(3)>, it can be faster to collect the server's
> +the server supports structured replies or extended headers and
> +any contexts were registered by L<nbd_add_meta_context(3)>. The
> +default setting is true; however the extra step of negotiating
> +meta contexts is not always desirable: performing both info and
> +go on the same export works without needing to re-negotiate
> +contexts on the second call; integration testing of other servers
> +may benefit from manual invocation of L<nbd_opt_set_meta_context(3)>
> +at other times in the negotiation sequence; and even when using
> +just L<nbd_opt_info(3)>, it can be faster to collect the server's
> results by relying on the callback function passed to
> L<nbd_opt_list_meta_context(3)> than a series of post-process
> calls to L<nbd_can_meta_context(3)>.
>
> Note that this control has no effect if the server does not
> -negotiate structured replies, or if the client did not request
> -any contexts via L<nbd_add_meta_context(3)>. Setting this
> -control to false may cause L<nbd_block_status(3)> to fail.";
> +negotiate structured replies or extended headers, or if the
> +client did not request any contexts via L<nbd_add_meta_context(3)>.
> +Setting this control to false may cause L<nbd_block_status(3)>
> +to fail.";
> see_also = [Link "set_opt_mode"; Link "opt_go"; Link "opt_info";
> Link "opt_list_meta_context"; Link "opt_set_meta_context";
> Link "get_structured_replies_negotiated";
> @@ -1404,11 +1405,11 @@ "opt_info", {
> If successful, functions like L<nbd_is_read_only(3)> and
> L<nbd_get_size(3)> will report details about that export. If
> L<nbd_set_request_meta_context(3)> is set (the default) and
> -structured replies were negotiated, it is also valid to use
> -L<nbd_can_meta_context(3)> after this call. However, it may be
> -more efficient to clear that setting and manually utilize
> -L<nbd_opt_list_meta_context(3)> with its callback approach, for
> -learning which contexts an export supports. In general, if
> +structured replies or extended headers were negotiated, it is also
> +valid to use L<nbd_can_meta_context(3)> after this call. However,
> +it may be more efficient to clear that setting and manually
> +utilize L<nbd_opt_list_meta_context(3)> with its callback approach,
> +for learning which contexts an export supports. In general, if
> L<nbd_opt_go(3)> is called next, that call will likely succeed
> with the details remaining the same, although this is not
> guaranteed by all servers.
> @@ -1538,12 +1539,12 @@ "opt_set_meta_context", {
> recent L<nbd_set_export_name(3)> or L<nbd_connect_uri(3)>.
> This can only be used if L<nbd_set_opt_mode(3)> enabled option
> mode. Normally, this function is redundant, as L<nbd_opt_go(3)>
> -automatically does the same task if structured replies have
> -already been negotiated. But manual control over meta context
> -requests can be useful for fine-grained testing of how a server
> -handles unusual negotiation sequences. Often, use of this
> -function is coupled with L<nbd_set_request_meta_context(3)> to
> -bypass the automatic context request normally performed by
> +automatically does the same task if structured replies or extended
> +headers have already been negotiated. But manual control over
> +meta context requests can be useful for fine-grained testing of
> +how a server handles unusual negotiation sequences. Often, use
> +of this function is coupled with L<nbd_set_request_meta_context(3)>
> +to bypass the automatic context request normally performed by
> L<nbd_opt_go(3)>.
>
> The NBD protocol allows a client to decide how many queries to ask
> @@ -1597,12 +1598,13 @@ "opt_set_meta_context_queries", {
> or L<nbd_connect_uri(3)>. This can only be used if
> L<nbd_set_opt_mode(3)> enabled option mode. Normally, this
> function is redundant, as L<nbd_opt_go(3)> automatically does
> -the same task if structured replies have already been
> -negotiated. But manual control over meta context requests can
> -be useful for fine-grained testing of how a server handles
> -unusual negotiation sequences. Often, use of this function is
> -coupled with L<nbd_set_request_meta_context(3)> to bypass the
> -automatic context request normally performed by L<nbd_opt_go(3)>.
> +the same task if structured replies or extended headers have
> +already been negotiated. But manual control over meta context
> +requests can be useful for fine-grained testing of how a server
> +handles unusual negotiation sequences. Often, use of this
> +function is coupled with L<nbd_set_request_meta_context(3)> to
> +bypass the automatic context request normally performed by
> +L<nbd_opt_go(3)>.
>
> The NBD protocol allows a client to decide how many queries to ask
> the server. This function takes an explicit list of queries; to
> @@ -3281,13 +3283,13 @@ "aio_opt_set_meta_context", {
> recent L<nbd_set_export_name(3)> or L<nbd_connect_uri(3)>.
> This can only be used if L<nbd_set_opt_mode(3)> enabled option
> mode. Normally, this function is redundant, as L<nbd_opt_go(3)>
> -automatically does the same task if structured replies have
> -already been negotiated. But manual control over meta context
> -requests can be useful for fine-grained testing of how a server
> -handles unusual negotiation sequences. Often, use of this
> -function is coupled with L<nbd_set_request_meta_context(3)> to
> -bypass the automatic context request normally performed by
> -L<nbd_opt_go(3)>.
> +automatically does the same task if structured replies or
> +extended headers have already been negotiated. But manual
> +control over meta context requests can be useful for fine-grained
> +testing of how a server handles unusual negotiation sequences.
> +Often, use of this function is coupled with
> +L<nbd_set_request_meta_context(3)> to bypass the automatic
> +context request normally performed by L<nbd_opt_go(3)>.
>
> To determine when the request completes, wait for
> L<nbd_aio_is_connecting(3)> to return false. Or supply the optional
> @@ -3314,12 +3316,13 @@ "aio_opt_set_meta_context_queries", {
> or L<nbd_connect_uri(3)>. This can only be used
> if L<nbd_set_opt_mode(3)> enabled option mode. Normally, this
> function is redundant, as L<nbd_opt_go(3)> automatically does
> -the same task if structured replies have already been
> -negotiated. But manual control over meta context requests can
> -be useful for fine-grained testing of how a server handles
> -unusual negotiation sequences. Often, use of this function is
> -coupled with L<nbd_set_request_meta_context(3)> to bypass the
> -automatic context request normally performed by L<nbd_opt_go(3)>.
> +the same task if structured replies or extended headers have
> +already been negotiated. But manual control over meta context
> +requests can be useful for fine-grained testing of how a server
> +handles unusual negotiation sequences. Often, use of this
> +function is coupled with L<nbd_set_request_meta_context(3)> to
> +bypass the automatic context request normally performed by
> +L<nbd_opt_go(3)>.
>
> To determine when the request completes, wait for
> L<nbd_aio_is_connecting(3)> to return false. Or supply the optional
> diff --git a/generator/Makefile.am b/generator/Makefile.am
> index 91dbde5c..fc79b1b9 100644
> --- a/generator/Makefile.am
> +++ b/generator/Makefile.am
> @@ -30,6 +30,7 @@ states_code = \
> states-issue-command.c \
> states-magic.c \
> states-newstyle-opt-export-name.c \
> + states-newstyle-opt-extended-headers.c \
> states-newstyle-opt-list.c \
> states-newstyle-opt-go.c \
> states-newstyle-opt-meta-context.c \
> diff --git a/generator/state_machine.ml b/generator/state_machine.ml
> index 1f0d00b0..d09ac792 100644
> --- a/generator/state_machine.ml
> +++ b/generator/state_machine.ml
> @@ -297,6 +297,7 @@ and
> * NEGOTIATING after OPT_STRUCTURED_REPLY or any failed OPT_GO.
> *)
> Group ("OPT_STARTTLS", newstyle_opt_starttls_state_machine);
> + Group ("OPT_EXTENDED_HEADERS",
> newstyle_opt_extended_headers_state_machine);
> Group ("OPT_STRUCTURED_REPLY",
> newstyle_opt_structured_reply_state_machine);
> Group ("OPT_META_CONTEXT", newstyle_opt_meta_context_state_machine);
> Group ("OPT_GO", newstyle_opt_go_state_machine);
> @@ -441,6 +442,46 @@ and
> };
> ]
>
> +(* Fixed newstyle NBD_OPT_EXTENDED_HEADERS option.
> + * Implementation: generator/states-newstyle-opt-extended-headers.c
> + *)
> +and newstyle_opt_extended_headers_state_machine = [
> + State {
> + default_state with
> + name = "START";
> + comment = "Try to negotiate newstyle NBD_OPT_EXTENDED_HEADERS";
> + external_events = [];
> + };
> +
> + State {
> + default_state with
> + name = "SEND";
> + comment = "Send newstyle NBD_OPT_EXTENDED_HEADERS negotiation request";
> + external_events = [ NotifyWrite, "" ];
> + };
> +
> + State {
> + default_state with
> + name = "RECV_REPLY";
> + comment = "Receive newstyle NBD_OPT_EXTENDED_HEADERS option reply";
> + external_events = [ NotifyRead, "" ];
> + };
> +
> + State {
> + default_state with
> + name = "RECV_REPLY_PAYLOAD";
> + comment = "Receive any newstyle NBD_OPT_EXTENDED_HEADERS reply payload";
> + external_events = [ NotifyRead, "" ];
> + };
> +
> + State {
> + default_state with
> + name = "CHECK_REPLY";
> + comment = "Check newstyle NBD_OPT_EXTENDED_HEADERS option reply";
> + external_events = [];
> + };
> +]
> +
> (* Fixed newstyle NBD_OPT_STRUCTURED_REPLY option.
> * Implementation: generator/states-newstyle-opt-structured-reply.c
> *)
> diff --git a/generator/states-newstyle-opt-extended-headers.c
> b/generator/states-newstyle-opt-extended-headers.c
> new file mode 100644
> index 00000000..1ec25e97
> --- /dev/null
> +++ b/generator/states-newstyle-opt-extended-headers.c
> @@ -0,0 +1,94 @@
> +/* nbd client library in userspace: state machine
> + * Copyright Red Hat
> + *
> + * This library is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU Lesser General Public
> + * License as published by the Free Software Foundation; either
> + * version 2 of the License, or (at your option) any later version.
> + *
> + * This library is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + * Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public
> + * License along with this library; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
> USA
> + */
> +
> +/* State machine for negotiating NBD_OPT_EXTENDED_HEADERS. */
> +
> +STATE_MACHINE {
> + NEWSTYLE.OPT_EXTENDED_HEADERS.START:
> + assert (h->gflags & LIBNBD_HANDSHAKE_FLAG_FIXED_NEWSTYLE);
> + assert (h->opt_current != NBD_OPT_EXTENDED_HEADERS);
> + assert (CALLBACK_IS_NULL (h->opt_cb.completion));
> + if (!h->request_eh || !h->request_sr) {
> + SET_NEXT_STATE (%^OPT_STRUCTURED_REPLY.START);
> + return 0;
> + }
> +
> + h->sbuf.option.version = htobe64 (NBD_NEW_VERSION);
> + h->sbuf.option.option = htobe32 (NBD_OPT_EXTENDED_HEADERS);
> + h->sbuf.option.optlen = htobe32 (0);
> + h->chunks_sent++;
> + h->wbuf = &h->sbuf;
> + h->wlen = sizeof h->sbuf.option;
> + SET_NEXT_STATE (%SEND);
> + return 0;
> +
> + NEWSTYLE.OPT_EXTENDED_HEADERS.SEND:
> + switch (send_from_wbuf (h)) {
> + case -1: SET_NEXT_STATE (%.DEAD); return 0;
> + case 0:
> + h->rbuf = &h->sbuf;
> + h->rlen = sizeof h->sbuf.or.option_reply;
> + SET_NEXT_STATE (%RECV_REPLY);
> + }
> + return 0;
> +
> + NEWSTYLE.OPT_EXTENDED_HEADERS.RECV_REPLY:
> + switch (recv_into_rbuf (h)) {
> + case -1: SET_NEXT_STATE (%.DEAD); return 0;
> + case 0:
> + if (prepare_for_reply_payload (h, NBD_OPT_EXTENDED_HEADERS) == -1) {
> + SET_NEXT_STATE (%.DEAD);
> + return 0;
> + }
> + SET_NEXT_STATE (%RECV_REPLY_PAYLOAD);
> + }
> + return 0;
> +
> + NEWSTYLE.OPT_EXTENDED_HEADERS.RECV_REPLY_PAYLOAD:
> + switch (recv_into_rbuf (h)) {
> + case -1: SET_NEXT_STATE (%.DEAD); return 0;
> + case 0: SET_NEXT_STATE (%CHECK_REPLY);
> + }
> + return 0;
> +
> + NEWSTYLE.OPT_EXTENDED_HEADERS.CHECK_REPLY:
> + uint32_t reply;
> +
> + reply = be32toh (h->sbuf.or.option_reply.reply);
> + switch (reply) {
> + case NBD_REP_ACK:
> + debug (h, "negotiated extended headers on this connection");
> + h->extended_headers = true;
> + /* Extended headers trump structured replies, so skip ahead. */
> + h->structured_replies = true;
> + break;
> + default:
> + if (handle_reply_error (h) == -1) {
> + SET_NEXT_STATE (%.DEAD);
> + return 0;
> + }
> +
> + debug (h, "extended headers are not supported by this server");
> + break;
> + }
> +
> + /* Next option. */
> + SET_NEXT_STATE (%^OPT_STRUCTURED_REPLY.START);
> + return 0;
> +
> +} /* END STATE MACHINE */
> diff --git a/generator/states-newstyle-opt-starttls.c
> b/generator/states-newstyle-opt-starttls.c
> index e497548c..1e2997a3 100644
> --- a/generator/states-newstyle-opt-starttls.c
> +++ b/generator/states-newstyle-opt-starttls.c
> @@ -26,7 +26,7 @@ NEWSTYLE.OPT_STARTTLS.START:
> else {
> /* If TLS was not requested we skip this option and go to the next one.
> */
> if (h->tls == LIBNBD_TLS_DISABLE) {
> - SET_NEXT_STATE (%^OPT_STRUCTURED_REPLY.START);
> + SET_NEXT_STATE (%^OPT_EXTENDED_HEADERS.START);
> return 0;
> }
> assert (CALLBACK_IS_NULL (h->opt_cb.completion));
> @@ -128,7 +128,7 @@ NEWSTYLE.OPT_STARTTLS.CHECK_REPLY:
> SET_NEXT_STATE (%.NEGOTIATING);
> else {
> debug (h, "continuing with unencrypted connection");
> - SET_NEXT_STATE (%^OPT_STRUCTURED_REPLY.START);
> + SET_NEXT_STATE (%^OPT_EXTENDED_HEADERS.START);
> }
> return 0;
> }
> @@ -185,7 +185,7 @@ NEWSTYLE.OPT_STARTTLS.TLS_HANDSHAKE_DONE:
> if (h->opt_current == NBD_OPT_STARTTLS)
> SET_NEXT_STATE (%.NEGOTIATING);
> else
> - SET_NEXT_STATE (%^OPT_STRUCTURED_REPLY.START);
> + SET_NEXT_STATE (%^OPT_EXTENDED_HEADERS.START);
> return 0;
>
> } /* END STATE MACHINE */
Seems pretty straightforward. We add a new state machine between
NEWSTYLE.OPT_STARTTLS and NEWSTYLE.OPT_STRUCTURED_REPLY which sends
the new extended headers option (if enabled).
Reviewed-by: Richard W.M. Jones <rjones@redhat.com>
--
Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones
Read my programming and virtualization blog: http://rwmj.wordpress.com
virt-top is 'top' for virtual machines. Tiny program with many
powerful monitoring features, net stats, disk stats, logging, etc.
http://people.redhat.com/~rjones/virt-top
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- Re: [libnbd PATCH v3 18/22] generator: Actually request extended headers,
Richard W.M. Jones <=