[Libguestfs] [nbdkit] Access export name from plugins

Eric Blake eblake at redhat.com
Tue Sep 10 12:58:49 UTC 2019


On 9/10/19 5:01 AM, Richard W.M. Jones wrote:
> Of course at the moment nbdkit parses the NBD export name option but
> doesn't really do anything with it (except logging it).
> 
> I wonder if we should make this available to plugins, in case they
> wish to serve different content to different clients based on the
> export name.  Note I'm not suggesting that we use this feature in any
> existing plugins.
> 
> If we wanted to do this there seem like two possible ways to do it:

at least two ways.

> 
> (1) Add a call, like nbdkit_export_name, which plugins could call from
> any connected method to get the current export name, eg:
> 
> static void *
> myplugin_open (int readonly)
> {
>   const char *export = nbdkit_export_name ();
> 
>   ... Do something based on the export name ...
> }

I would also consider adding an optional callback:

struct nbdkit_export {
  char *name;
  size_t size;
  // maybe other fields for supporting NBD_OPT_INFO...
};

const nbdkit_export *(*list_exports) (void);

A plugin that does not implement the callback advertises whatever export
name was passed on the command line with -e (or defaults to advertising
just ""), and accepts any name, or we could even state that NBD_OPT_LIST
fails unless the callback is present.

A plugin that DOES implement the callback causes -e to fail (the plugin
is now in charge of the export names, instead of -e), and makes
NBD_OPT_LIST and NBD_OPT_INFO advertise the list returned by
.list_exports.  The plugin is responsible for returning an array of zero
or more structures terminated by an entry where .name is NULL (although
returning zero entries means the plugin is not currently accepting
clients, as no export name from the client will match).  The
.list_exports() callback would be called _prior_ to .open on a
per-connection basis (thus, there is no 'void *handle' parameter,
because the connection has not yet been established; but because it is
called once per connecting client, the resulting list could be
dynamically modified such as providing a list of filenames present in a
directory).

We'd have to figure out lifetimes - would the plugin return a malloc()d
list that nbdkit frees, or would we need a pair of functions, where the
.list_exports function returns a const list, and then nbdkit calls
.free_exports (if defined) to let the plugin clean up any allocations.
(The latter is slightly nicer, in case the plugin is using some other
memory management scheme, such as a language binding, rather than
requiring the copying of data into a form where nbdkit calling free() is
safe).

> 
> The implementation of this is straightforward.  It simply reads the
> exportname global from the server and returns it.  It also doesn't
> change the existing API at all.
> 
> (2) A better way might be to bump the API version to 3 and that would
> allow us to change the open() callback:
> 
> static void *
> myplugin_open (int readonly, const char *exportname)
> {
>   ... Do something based on the export name ...
> }
> 
> This is cleaner but is obviously a larger change.  Also if we were
> going to bump the API version I'd want to at the same time do all the
> other things we are planning for API 3, and that potentially makes it
> a much bigger deal:
> 
> https://github.com/libguestfs/nbdkit/blob/b485ade71464fc351828e2fcce54464709bf234d/TODO#L166

Yeah, bumping to API 3 is a much bigger deal; we can get most of the
benefits of just letting the plugin know WHICH export name was requested
without making that bump.

> 
> It has the advantage of making it easier to access the export name
> from sh plugins, since those don't have access to nbdkit_* API calls
> (or at least we haven't thought about how we would do that).

Note that with sh plugins, we could still make things work with v2, as
follows:

sh_open() calls nbdkit_export_name() unconditionally, prior to forming
the command line for calling into the script.  Then we alter the command
line we pass to the script:

/path/to/script open <readonly> <exportname>

where the sh plugin always gets to know what export name the client
chose, thanks to the new exportname parameter.  Compatibility-wise,
older scripts fall in one of two categories: either they ignore
unexpected parameters (no change required), or they choke because
exportname was unexpected (but it's a one-line change to the script to
deal with it).  New scripts run against an older nbdkit that did not
provide the exportname parameter will see "$3" as empty (if the script
runs under 'set -u', then spell things "${3-}").

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

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: OpenPGP digital signature
URL: <http://listman.redhat.com/archives/libguestfs/attachments/20190910/93d173b0/attachment.sig>


More information about the Libguestfs mailing list