[Libguestfs] [nbdkit PATCH 2/9] plugins: Add .cache callback

Eric Blake eblake at redhat.com
Fri May 10 03:03:35 UTC 2019


Make it possible for plugins to provide an alternative behavior for
NBD_CMD_CACHE rather than just discarding the buffer of .pread.

Signed-off-by: Eric Blake <eblake at redhat.com>
---
 docs/nbdkit-plugin.pod  | 52 +++++++++++++++++++++++++++++++++++++++++
 include/nbdkit-plugin.h |  2 ++
 server/plugins.c        | 17 +++++++++-----
 3 files changed, 65 insertions(+), 6 deletions(-)

diff --git a/docs/nbdkit-plugin.pod b/docs/nbdkit-plugin.pod
index 318be4c..0657151 100644
--- a/docs/nbdkit-plugin.pod
+++ b/docs/nbdkit-plugin.pod
@@ -620,6 +620,31 @@ with an error message and return C<-1>.

 This callback is not required.  If omitted, then we return false.

+=head2 C<.can_cache>
+
+ int can_cache (void *handle);
+
+This is called during the option negotiation phase to find out if the
+plugin supports a cache operation. The nature of the caching is
+unspecified (including whether there are limits on how much can be
+cached at once, and whether writes to a cached region have
+write-through or write-back semantics), but the command exists to let
+clients issue a hint to the server that they will be accessing that
+region of the export.
+
+If there is an error, C<.can_cache> should call C<nbdkit_error> with
+an error message and return C<-1>.  Since the NBD protocol has
+reserved the right to add future flags to mandate specific caching
+capabilities, this function should only return C<1> on success (in the
+future, other positive results may be treated as a bitmask of
+supported flags).
+
+This callback is not required.  If omitted, then we return true iff a
+C<.cache> callback has been defined. Note that nbdkit always
+advertises caching capabilities to the client regardless of this
+callback; if this callback returns false, nbdkit handles a client
+cache request by calling C<.pread> and ignoring the resulting data.
+
 =head2 C<.pread>

  int pread (void *handle, void *buf, uint32_t count, uint64_t offset,
@@ -814,6 +839,33 @@ C<nbdkit_extent_add> returns C<0> on success or C<-1> on failure.  On
 failure C<nbdkit_error> and/or C<nbdkit_set_error> has already been
 called.  C<errno> will be set to a suitable value.

+=head2 C<.cache>
+
+ int cache (void *handle, uint32_t count, uint64_t offset, uint32_t flags);
+
+During the data serving phase, this callback is used to give the
+plugin a hint that the client intends to make further accesses to the
+given region of the export.  The nature of caching is not specified
+further by the NBD specification (for example, a server may place
+limits on how much may be cached at once, and there is no way to
+control if writes to a cached area have write-through or write-back
+semantics).  In fact, the cache command can always fail and still be
+compliant, and success might not guarantee a performance gain.  If
+this callback is omitted, nbdkit defaults to providing cache semantics
+obtained by calling C<.pread> over the same region and ignoring the
+results.
+
+This function will not be called if C<.can_cache> returned false.  The
+parameter C<flags> exists in case of future NBD protocol extensions;
+at this time, it will be 0 on input. A plugin must fail this function
+if C<flags> includes an unrecognized flag, as that may indicate a
+requirement that the plugin comply must with a specific caching
+semantic.
+
+If there is an error, C<.cache> should call C<nbdkit_error> with an
+error message, and C<nbdkit_set_error> to record an appropriate error
+(unless C<errno> is sufficient), then return C<-1>.
+
 =head1 THREADS

 Each nbdkit plugin must declare its thread safety model by defining
diff --git a/include/nbdkit-plugin.h b/include/nbdkit-plugin.h
index 54b4ce2..e9b1808 100644
--- a/include/nbdkit-plugin.h
+++ b/include/nbdkit-plugin.h
@@ -128,6 +128,8 @@ struct nbdkit_plugin {
   int (*can_extents) (void *handle);
   int (*extents) (void *handle, uint32_t count, uint64_t offset, uint32_t flags,
                   struct nbdkit_extents *extents);
+  int (*can_cache) (void *handle);
+  int (*cache) (void *handle, uint32_t count, uint64_t offset, uint32_t flags);
 };

 extern void nbdkit_set_error (int err);
diff --git a/server/plugins.c b/server/plugins.c
index cabf543..947fe79 100644
--- a/server/plugins.c
+++ b/server/plugins.c
@@ -201,6 +201,8 @@ plugin_dump_fields (struct backend *b)
   HAS (can_multi_conn);
   HAS (can_extents);
   HAS (extents);
+  HAS (can_cache);
+  HAS (cache);
 #undef HAS

   /* Custom fields. */
@@ -451,12 +453,16 @@ plugin_can_multi_conn (struct backend *b, struct connection *conn)
 static int
 plugin_can_cache (struct backend *b, struct connection *conn)
 {
+  struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
+
   assert (connection_get_handle (conn, 0));

   debug ("can_cache");

-  /* FIXME: return default based on plugin->cache */
-  return 0;
+  if (p->plugin.can_cache)
+    return p->plugin.can_cache (connection_get_handle (conn, 0));
+  else
+    return p->plugin.cache != NULL;
 }

 /* Plugins and filters can call this to set the true errno, in cases
@@ -710,16 +716,15 @@ plugin_cache (struct backend *b, struct connection *conn,
               int *err)
 {
   struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
-  int r = -1;
+  int r;

   assert (connection_get_handle (conn, 0));
   assert (!flags);
+  assert (p->plugin.cache);

   debug ("cache count=%" PRIu32 " offset=%" PRIu64, count, offset);

-  /* FIXME: assert plugin->cache and call it */
-  assert (false);
-
+  r = p->plugin.cache (connection_get_handle (conn, 0), count, offset, flags);
   if (r == -1)
     *err = get_error (p);
   return r;
-- 
2.20.1




More information about the Libguestfs mailing list