This commit adds a new API which can be used from the connected to state to read back which NBD protocol (eg. oldstyle, newstyle-fixed) we are using.
It was helpful to add a new state in newstyle negotiation (%NEWSTYLE.FINISHED) so we can route all successful option negotiations through a single path before moving to the %READY state, allowing us to set h->protocol in one place. --- generator/generator | 25 +++++++++++++++++++++ generator/states-newstyle-opt-export-name.c | 2 +- generator/states-newstyle-opt-go.c | 2 +- generator/states-newstyle.c | 9 ++++++++ generator/states-oldstyle.c | 2 ++ lib/handle.c | 12 ++++++++++ lib/internal.h | 5 ++++- tests/get-size.c | 13 ++++++++++- tests/oldstyle.c | 9 ++++++++ 9 files changed, 75 insertions(+), 4 deletions(-) diff --git a/generator/generator b/generator/generator index 28248ed..21aae3b 100755 --- a/generator/generator +++ b/generator/generator @@ -357,6 +357,16 @@ and newstyle_state_machine = [ Group ("OPT_SET_META_CONTEXT", newstyle_opt_set_meta_context_state_machine); Group ("OPT_GO", newstyle_opt_go_state_machine); Group ("OPT_EXPORT_NAME", newstyle_opt_export_name_state_machine); + + (* When option parsing has successfully finished negotiation + * it will jump to this state for final steps before moving to + * the %READY state. + *) + State { + default_state with + name = "FINISHED"; + comment = "Finish off newstyle negotiation"; + }; ] (* Fixed newstyle NBD_OPT_STARTTLS option. *) @@ -1574,6 +1584,20 @@ are free to pass in other contexts." "L<nbd_block_status(3)>"; "L<nbd_aio_block_status(3)>"]; }; + "get_protocol", { + default_call with + args = []; ret = RStaticString; + permitted_states = [ Connected; Closed ]; + shortdesc = "return the NBD protocol variant"; + longdesc = "\ +Return the NBD protocol variant in use on the connection. At +the moment this returns one of the strings C<\"oldstyle\">, +C<\"newstyle\"> or C<\"newstyle-fixed\">. Other strings might +be returned in future. Most modern NBD servers use C<\"newstyle-fixed\">. +" +^ non_blocking_test_call_description + }; + "get_size", { default_call with args = []; ret = RInt64; @@ -2553,6 +2577,7 @@ let first_version = [ "set_request_structured_replies", (1, 2); "get_request_structured_replies", (1, 2); "get_tls_negotiated", (1, 2); + "get_protocol", (1, 2); (* These calls are proposed for a future version of libnbd, but * have not been added to any released version so far. diff --git a/generator/states-newstyle-opt-export-name.c b/generator/states-newstyle-opt-export-name.c index ec73136..1c6b443 100644 --- a/generator/states-newstyle-opt-export-name.c +++ b/generator/states-newstyle-opt-export-name.c @@ -68,7 +68,7 @@ SET_NEXT_STATE (%.DEAD); return 0; } - SET_NEXT_STATE (%.READY); + SET_NEXT_STATE (%^FINISHED); return 0; } /* END STATE MACHINE */ diff --git a/generator/states-newstyle-opt-go.c b/generator/states-newstyle-opt-go.c index 49875a5..d0d2123 100644 --- a/generator/states-newstyle-opt-go.c +++ b/generator/states-newstyle-opt-go.c @@ -108,7 +108,7 @@ switch (reply) { case NBD_REP_ACK: - SET_NEXT_STATE (%.READY); + SET_NEXT_STATE (%^FINISHED); return 0; case NBD_REP_INFO: if (len > maxpayload /* see RECV_NEWSTYLE_OPT_GO_REPLY */) diff --git a/generator/states-newstyle.c b/generator/states-newstyle.c index c8f817e..7742ea3 100644 --- a/generator/states-newstyle.c +++ b/generator/states-newstyle.c @@ -155,4 +155,13 @@ handle_reply_error (struct nbd_handle *h) } return 0; + NEWSTYLE.FINISHED: + if ((h->gflags & NBD_FLAG_FIXED_NEWSTYLE) == 0) + h->protocol = "newstyle"; + else + h->protocol = "newstyle-fixed"; + + SET_NEXT_STATE (%.READY); + return 0; + } /* END STATE MACHINE */ diff --git a/generator/states-oldstyle.c b/generator/states-oldstyle.c index 1aff185..cb4f0da 100644 --- a/generator/states-oldstyle.c +++ b/generator/states-oldstyle.c @@ -64,6 +64,8 @@ return 0; } + h->protocol = "oldstyle"; + SET_NEXT_STATE (%.READY); return 0; diff --git a/lib/handle.c b/lib/handle.c index bc4206c..85d10cd 100644 --- a/lib/handle.c +++ b/lib/handle.c @@ -315,3 +315,15 @@ nbd_unlocked_supports_uri (struct nbd_handle *h) return 0; #endif } + +const char * +nbd_unlocked_get_protocol (struct nbd_handle *h) +{ + /* I believe that if we reach the Connected or Closed permitted + * states, then the state machine must have set h->protocol. So if + * this assertion is hit then it indicates a bug in libnbd. + */ + assert (h->protocol); + + return h->protocol; +} diff --git a/lib/internal.h b/lib/internal.h index eb76ac1..87b413d 100644 --- a/lib/internal.h +++ b/lib/internal.h @@ -87,7 +87,10 @@ struct nbd_handle { uint64_t exportsize; uint16_t eflags; - /* Flag set by the state machine to tell whether TLS was negotiated. */ + /* Flags set by the state machine to tell what protocol and whether + * TLS was negotiated. + */ + const char *protocol; bool tls_negotiated; int64_t unique; /* Used for generating cookie numbers. */ diff --git a/tests/get-size.c b/tests/get-size.c index f10597c..e6f44f7 100644 --- a/tests/get-size.c +++ b/tests/get-size.c @@ -26,6 +26,7 @@ #include <stdlib.h> #include <stdint.h> #include <inttypes.h> +#include <string.h> #include <libnbd.h> @@ -38,8 +39,10 @@ main (int argc, char *argv[]) { struct nbd_handle *nbd; int64_t r; - char *args[] = { "nbdkit", "-s", "--exit-with-parent", "-v", + /* -n forces newstyle even if someone is still using nbdkit < 1.3 */ + char *args[] = { "nbdkit", "-s", "--exit-with-parent", "-n", "-v", "null", "size=" STR(SIZE), NULL }; + const char *s; nbd = nbd_create (); if (nbd == NULL) { @@ -51,6 +54,14 @@ main (int argc, char *argv[]) exit (EXIT_FAILURE); } + /* Even ancient versions of nbdkit only supported newstyle-fixed. */ + s = nbd_get_protocol (nbd); + if (strcmp (s, "newstyle-fixed") != 0) { + fprintf (stderr, + "incorrect protocol \"%s\", expected \"newstyle-fixed\"\n", s); + exit (EXIT_FAILURE); + } + if ((r = nbd_get_size (nbd)) == -1) { fprintf (stderr, "%s\n", nbd_get_error ()); exit (EXIT_FAILURE); diff --git a/tests/oldstyle.c b/tests/oldstyle.c index c179c45..b90b775 100644 --- a/tests/oldstyle.c +++ b/tests/oldstyle.c @@ -84,6 +84,7 @@ main (int argc, char *argv[]) char *args[] = { "nbdkit", "-s", "-o", "--exit-with-parent", "-v", "memory", "size=" STR(SIZE), NULL }; int calls = 0; + const char *s; progname = argv[0]; @@ -114,6 +115,14 @@ main (int argc, char *argv[]) exit (EXIT_FAILURE); } + /* Protocol should be "oldstyle". */ + s = nbd_get_protocol (nbd); + if (strcmp (s, "oldstyle") != 0) { + fprintf (stderr, + "incorrect protocol \"%s\", expected \"oldstyle\"\n", s); + exit (EXIT_FAILURE); + } + if ((r = nbd_get_size (nbd)) == -1) { fprintf (stderr, "%s\n", nbd_get_error ()); exit (EXIT_FAILURE); -- 2.23.0 _______________________________________________ Libguestfs mailing list Libguestfs@redhat.com https://www.redhat.com/mailman/listinfo/libguestfs