Re: [Libguestfs] [PATCH nbdkit v2] PROPOSED: server: Implement list_exports.

Eric Blake
2020-07-22T13:08:44Z

On 7/22/20 7:42 AM, Richard W.M. Jones wrote:
> Updated proposal, taking into account the default export.  Instead of
> adding a second call, I made a couple of changes to list_exports:
>
> (1) If the plugin has a concept of a default export, it should add it
>      as the first element in the exports list.
>
> (2) There is a new default_only flag which tells the plugin that the
>      client is trying to request the name of the default export, so the
>      plugin may return only a single element.  However it's fine for
>      plugins to ignore this flag.

Works for me.  Also, a plugin can implement the callback and set 0
exports, which is different from omitting the callback which always
provides "" as one export.  Returning 0 exports may make it harder for
clients to actually make a meaningful connection, but that situation can
indeed make sense (such as the file plugin set to serve all files in a
directory by exportname, but the directory is empty).

>
> What about plugins that don't have any concept of a default export?
> This makes the default export be whatever happens to be first in the
> list.  Not sure if this is a bad thing or not.

I'm not seeing it as too bad of a problem.  A client that does not call
NBD_OPT_LIST will never know the difference, and the plugin can still
choose whether to accept or reject "" as a valid export name.

So far, the patch is just about public interface.  Implementation-wise,
I see no problem with providing either of two implementations, with the
user none the wiser other than observing memory usage and timing:

idea 1:
struct nbdkit_exports is merely a vector of {name,description} pairs.
During .list_exports, nbdkit_add_export merely strdup's its input onto
the growing list stored in memory, and then after .list_exports returns,
that list is used by the various clients:
  - implementing NBD_OPT_LIST traverses the list calling NBD_REP_SERVER
for each list element, then ends with NBD_REP_ACK
  - implementing NBD_OPT_INFO("") scrapes the first element out of the
list, and ignores the rest
nbdkit then has to free the list after use.

idea 2:
struct nbdkit_exports wraps a function pointer. nbdkit_add_export then
triggers a call to that underlying function.
  - implementing NBD_OPT_LIST sets a function pointer that directly
replies with NBD_REP_SERVER each time it is called (works since
handshake phase is synchronous - there is no other traffic in parallel
on that connection to worry about). When .list_exports returns, all that
is left is sending NBD_REP_ACK
  - implementing NBD_OPT_INFO("") sets an initial function pointer
that
grabs info on the first call, then alters to a second function pointer
that is a no-op for remaining calls
since there was no copying of strings, there is no further cleanup needed

--
Eric Blake, Principal Software Engineer
Red Hat, Inc.           +1-919-301-3226
Virtualization:  qemu.org | libvirt.org