[Libguestfs] [PATCH libnbd PROPOSAL] Add APIs for listing exports from an NBD server.
Richard W.M. Jones
rjones at redhat.com
Mon Jul 20 16:47:39 UTC 2020
On Mon, Jul 20, 2020 at 10:50:51AM -0500, Eric Blake wrote:
> Is it worth trying to have some sort of a callback mode where the
> callback function is called once per export name advertised while
> the connection attempt is underway, rather than this post-mortem
> query of the data copied into the nbd handle? But as your added
> example code showed, this wasn't too bad to code with.
My reasoning not to have a callback is that it's both a little harder
to use, but more importantly ties us to a specific set of per-export
fields. For example if we had a callback which was:
int cb (const char *export_name);
then you could only have an export name, but my reading of the
protocol spec is that in fact there's already another field we are
ignoring (some sort of description - not sure what servers actually
set it), and there's scope for more fields in future.
With the current API we can add more fields in future.
> >+++ b/generator/states-newstyle-opt-list.c
>
> >+STATE_MACHINE {
> >+ NEWSTYLE.OPT_LIST.START:
> >+ if (!h->list_exports) {
> >+ SET_NEXT_STATE (%^OPT_STRUCTURED_REPLY.START);
> >+ return 0;
> >+ }
> >+
> >+ h->sbuf.option.version = htobe64 (NBD_NEW_VERSION);
> >+ h->sbuf.option.option = htobe32 (NBD_OPT_LIST);
> >+ h->sbuf.option.optlen = 0;
> >+ h->wbuf = &h->sbuf;
> >+ h->wlen = sizeof (h->sbuf.option);
> >+ SET_NEXT_STATE (%SEND);
> >+ return 0;
>
> Is it worth enhancing the code to add another list mode where we can
> also query NBD_OPT_INFO on each export thus listed? (Compare to
> 'qemu-nbd --list'). Hmm, if we do that, list mode may need to be an
> enum instead of a bool. But that would be a followup because it
> adds more complexity; this is already a good addition on its own.
I'm actually a little unclear on the protocol spec around this. Would
we be able to issue N x NBD_OPT_INFO (after NBD_OPT_LIST, on the same
connection)? I was envisaging opening one new connection per export
and just using the usual APIs to fetch the data.
> >+ case NBD_REP_ACK:
> >+ /* Finished receiving the list. */
> >+ SET_NEXT_STATE (%^OPT_STRUCTURED_REPLY.START);
> >+ return 0;
> >+
> >+ default:
> >+ if (handle_reply_error (h) == -1) {
> >+ SET_NEXT_STATE (%.DEAD);
>
> Would this be better as %.CLOSED, or even a transition into a state
> where we send a clean NBD_OPT_ABORT for graceful shutdown rather
> than abrupt disconnect from the server?
In fact we cannot move to CLOSED. The reason is obscure, it's because
you hit this code while doing the connect:
https://github.com/libguestfs/libnbd/blob/3599c79480df2932b3dba0b6f9c689634768c423/lib/connect.c#L47
It doesn't really work to have connect APIs return an error for what
is not in fact an error. However to complicate things, with qemu-nbd
-x we do return an error from connect* each time because we cannot set
the export name correctly until we've fetched the export names. Hence
the example ignores the return value from connect (unless ENOTSUP).
This is a bit of a mess ...
> >+int
> >+nbd_unlocked_set_list_exports (struct nbd_handle *h, bool list)
> >+{
> >+ h->list_exports = true;
>
> s/true/list/ (you never really tested clearing the mode...)
Oops.
> >+char *
> >+nbd_unlocked_get_list_export_name (struct nbd_handle *h,
> >+ int i)
> >+{
> >+ char *name;
> >+
> >+ if (!h->list_exports) {
> >+ set_error (EINVAL, "list exports mode not selected on this handle");
> >+ return NULL;
> >+ }
> >+ if (i < 0 || i >= (int) h->nr_exports) {
>
> That cast makes sense, but looks odd - any server that tries to send
> more than 2G export names (by assuming that our size_t > 32 bits) is
> sending a LOT of traffic in response to a single NBD_OPT_LIST
> command. Would it be better to just track the list size as int, and
> change the state machine to fail if the server hasn't completed its
> listing in X number of responses (perhaps where X is 1 million, or
> determined by the user, or...)?
Yes we should definitely limit this to something reasonable. There's
not a good way to handle servers which can serve any export name
(nbdkit info as you pointed out).
Rich.
--
Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones
Read my programming and virtualization blog: http://rwmj.wordpress.com
libguestfs lets you edit virtual machines. Supports shell scripting,
bindings from many languages. http://libguestfs.org
More information about the Libguestfs
mailing list