[Libguestfs] [nbdkit PATCH 3/4] server: Implement list_exports.

Eric Blake eblake at redhat.com
Fri Jul 31 22:22:31 UTC 2020


From: "Richard W.M. Jones" <rjones at redhat.com>

See also:
https://www.redhat.com/archives/libguestfs/2020-July/msg00090.html
Message-Id: <20200722124201.1823468-2-rjones at redhat.com>

For now, this implementation is only for plugins; adding filter
support will come later (and probably requires further edits, for the
ability for any filter to open up an independent connection to the
plugin without being handed next_ops on entry).
---
 docs/nbdkit-plugin.pod   | 57 +++++++++++++++++++++++++++++++++++++---
 docs/nbdkit-protocol.pod |  7 +++--
 include/nbdkit-plugin.h  |  3 +++
 server/plugins.c         | 10 +++++--
 4 files changed, 69 insertions(+), 8 deletions(-)

diff --git a/docs/nbdkit-plugin.pod b/docs/nbdkit-plugin.pod
index f8e9962a..7ce89e9e 100644
--- a/docs/nbdkit-plugin.pod
+++ b/docs/nbdkit-plugin.pod
@@ -152,6 +152,9 @@ the plugin:
  │ preconnect │                  │
  └──────┬─────┘                  │
  ┌──────┴─────┐                  │
+ │list_exports│                  │
+ └──────┬─────┘                  │
+ ┌──────┴─────┐                  │
  │ open       │                  │
  └──────┬─────┘                  │
  ┌──────┴─────┐  NBD option      │
@@ -160,10 +163,10 @@ the plugin:
  ┌──────┴─────┐           ┌──────┴─────┐ client #2
  │ get_size   │           │ preconnect │
  └──────┬─────┘           └──────┬─────┘
- ┌──────┴─────┐ data      ┌──────┴─────┐
- │ pread      │ serving   │ open       │
- └──────┬─────┘↺          └──────┬─────┘
- ┌──────┴─────┐                 ...
+ ┌──────┴─────┐ data
+ │ pread      │ serving
+ └──────┬─────┘↺                ...
+ ┌──────┴─────┐
  │ pwrite     │
  └──────┬─────┘↺          ┌──────┴─────┐
  ┌──────┴─────┐           │ close      │
@@ -236,6 +239,12 @@ L<getpid(2)>.
 Called when a TCP connection has been made to the server.  This
 happens early, before NBD or TLS negotiation.

+=item C<.list_exports>
+
+Early in option negotiation the client may try to list the exports
+served by the plugin, and plugins can optionally implement this
+callback to answer the client.  See L</EXPORT NAME> below.
+
 =item C<.open>

 A new client has connected and finished the NBD handshake.  TLS
@@ -652,6 +661,46 @@ Returning C<0> will allow the connection to continue.  If there is an
 error or you want to deny the connection, call C<nbdkit_error> with an
 error message and return C<-1>.

+=head2 C<.list_exports>
+
+ int list_exports (int readonly, int default_only,
+                   struct nbdkit_exports *exports);
+
+This optional callback is called if the client tries to list the
+exports served by the plugin (using C<NBD_OPT_LIST>).  If the plugin
+does not supply this callback then a single export called C<""> is
+returned.  The NBD protocol defines C<""> as the default export, so
+this is suitable for plugins which ignore the export name and always
+serve the same content.  See also L</EXPORT NAME> below.
+
+The C<exports> parameter is an opaque object for collecting the list
+of exports.  Call C<nbdkit_add_export> to add a single export to the
+list.  If the plugin has a concept of a default export (usually but
+not always called C<"">) then it should return that first in the list.
+
+ int nbdkit_add_export (struct nbdkit_export *exports,
+                        const char *name, const char *description);
+
+The C<name> must be a non-NULL, UTF-8 string between 0 and 4096 bytes
+in length.  Export names must be unique.  C<description> is an
+optional description of the export which some clients can display but
+which is otherwise unused (if you don't want a description, you can
+pass this parameter as C<NULL>).  The string(s) are copied into the
+exports list so you may free them immediately after calling this
+function.
+
+If the C<default_only> flag then the client is querying for the name
+of the default export, and the plugin may add only a single export to
+the returned list (the default export name, usually C<"">).  The
+plugin can ignore this flag and return all exports if it wants.
+
+The C<readonly> flag informs the plugin that the server was started
+with the I<-r> flag on the command line.
+
+Returning C<0> will send the list of exports back to the client.  If
+there is an error, C<.list_exports> should call C<nbdkit_error> with
+an error message and return C<-1>.
+
 =head2 C<.open>

  void *open (int readonly);
diff --git a/docs/nbdkit-protocol.pod b/docs/nbdkit-protocol.pod
index 8fe8c67e..b1e182c1 100644
--- a/docs/nbdkit-protocol.pod
+++ b/docs/nbdkit-protocol.pod
@@ -99,12 +99,15 @@ Supported in nbdkit E<ge> 1.1.12, and the default in nbdkit E<ge> 1.3.
 =item export names

 Partially supported in nbdkit E<ge> 1.1.12.  Support for plugins to
-read the client export name added in nbdkit E<ge> 1.15.2.
+read the client export name added in nbdkit E<ge> 1.15.2.  Support for
+C<NBD_OPT_LIST> was added in nbdkit E<ge> 1.21.20.

 Versions of nbdkit before 1.16 could advertise a single export name to
 clients, via a now deprecated side effect of the I<-e> option.  In nbdkit
 1.15.2, plugins could read the client requested export name using
-C<nbdkit_export_name()> and serve different content.
+C<nbdkit_export_name()> and serve different content.  In nbdkit
+1.21.20, plugins could implement C<.list_exports> to answer
+C<NBD_OPT_LIST> queries.

 =item C<NBD_FLAG_NO_ZEROES>

diff --git a/include/nbdkit-plugin.h b/include/nbdkit-plugin.h
index c6c1256c..86b8565d 100644
--- a/include/nbdkit-plugin.h
+++ b/include/nbdkit-plugin.h
@@ -139,6 +139,9 @@ struct nbdkit_plugin {

   int (*get_ready) (void);
   int (*after_fork) (void);
+
+  int (*list_exports) (int readonly, int default_only,
+                       struct nbdkit_exports *exports);
 };

 extern void nbdkit_set_error (int err);
diff --git a/server/plugins.c b/server/plugins.c
index 8020046b..d4364cd2 100644
--- a/server/plugins.c
+++ b/server/plugins.c
@@ -161,6 +161,7 @@ plugin_dump_fields (struct backend *b)
   HAS (get_ready);
   HAS (after_fork);
   HAS (preconnect);
+  HAS (list_exports);
   HAS (open);
   HAS (close);
   HAS (get_size);
@@ -281,8 +282,13 @@ static int
 plugin_list_exports (struct backend *b, int readonly, int default_only,
                      struct nbdkit_exports *exports)
 {
-  /* XXX No plugin support yet, so for now just advertise "" */
-  return nbdkit_add_export (exports, "", NULL);
+  GET_CONN;
+  struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
+
+  if (!p->plugin.list_exports)
+    return nbdkit_add_export (exports, "", NULL);
+
+  return p->plugin.list_exports (readonly, default_only, exports);
 }

 static void *
-- 
2.28.0




More information about the Libguestfs mailing list