[Libguestfs] [nbdkit PATCH 6/9] sh: Implement .cache script callback

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


It's easy to expose new callbacks to sh plugins. I have no idea how
any plugin would actually usefully cache anything in shell (you can't
really store it in a shell variable, since a new shell process is
started for each command); but if nothing else, this allows a user to
implement .can_cache returning true to bypass nbdkit's normal fallback
to .pread.

The shell plugin, coupled with Rich's work on libnbd as a client-side
library for actually exercising calls to NBD_CMD_CACHE, will be a
useful way to prove that cache commands even make it through the
stack. (Remember, qemu 3.0 was released with a fatally flawed
NBD_CMD_CACHE server implementation, because there were no open source
clients at the time that could actually send the command to test the
server with).

Signed-off-by: Eric Blake <eblake at redhat.com>
---
 plugins/sh/nbdkit-sh-plugin.pod | 12 +++++++++-
 plugins/sh/sh.c                 | 40 +++++++++++++++++++++++++++++++++
 2 files changed, 51 insertions(+), 1 deletion(-)

diff --git a/plugins/sh/nbdkit-sh-plugin.pod b/plugins/sh/nbdkit-sh-plugin.pod
index 8af88b4..bfd58ab 100644
--- a/plugins/sh/nbdkit-sh-plugin.pod
+++ b/plugins/sh/nbdkit-sh-plugin.pod
@@ -218,9 +218,11 @@ This method is required.

 =item C<can_extents>

+=item C<can_cache>
+
 Unlike in other languages, you B<must> provide the C<can_*> methods
 otherwise they are assumed to all return false and your C<pwrite>,
-C<flush>, C<trim>, C<zero> and C<extents> methods will never be
+C<flush>, C<trim>, C<zero>, C<extents>, and C<cache> methods will never be
 called.  The reason for this is obscure: In other languages we can
 detect if (eg) a C<pwrite> method is defined and synthesize an
 appropriate response if no actual C<can_write> method is defined.
@@ -232,6 +234,7 @@ possible with this plugin.
  /path/to/script can_trim <handle>
  /path/to/script can_zero <handle>
  /path/to/script can_extents <handle>
+ /path/to/script can_cache <handle>

 The script should exit with code C<0> for true or code C<3> for false.

@@ -334,6 +337,13 @@ Unlike in other languages, if you provide an C<extents> method you
 B<must> also provide a C<can_extents> method which exits with code
 C<0> (true).

+=item C<cache>
+
+ /path/to/script cache <handle> <count> <offset>
+
+Unlike in other languages, if you provide a C<cache> method you B<must>
+also provide a C<can_cache> method which exits with code C<0> (true).
+
 =back

 =head2 Missing callbacks
diff --git a/plugins/sh/sh.c b/plugins/sh/sh.c
index a5beb57..7aded44 100644
--- a/plugins/sh/sh.c
+++ b/plugins/sh/sh.c
@@ -578,6 +578,12 @@ sh_can_multi_conn (void *handle)
   return boolean_method (handle, "can_multi_conn");
 }

+static int
+sh_can_cache (void *handle)
+{
+  return boolean_method (handle, "can_cache");
+}
+
 static int
 sh_flush (void *handle, uint32_t flags)
 {
@@ -782,6 +788,38 @@ sh_extents (void *handle, uint32_t count, uint64_t offset, uint32_t flags,
   }
 }

+static int
+sh_cache (void *handle, uint32_t count, uint64_t offset, uint32_t flags)
+{
+  char *h = handle;
+  char cbuf[32], obuf[32];
+  const char *args[] = { script, "cache", h, cbuf, obuf, NULL };
+
+  snprintf (cbuf, sizeof cbuf, "%" PRIu32, count);
+  snprintf (obuf, sizeof obuf, "%" PRIu64, offset);
+  assert (!flags);
+
+  switch (call (args)) {
+  case OK:
+    return 0;
+
+  case MISSING:
+    /* Ignore lack of cache callback. */
+    return 0;
+
+  case ERROR:
+    return -1;
+
+  case RET_FALSE:
+    nbdkit_error ("%s: %s method returned unexpected code (3/false)",
+                  script, "cache");
+    errno = EIO;
+    return -1;
+
+  default: abort ();
+  }
+}
+
 #define sh_config_help \
   "script=<FILENAME>     (required) The shell script to run.\n" \
   "[other arguments may be used by the plugin that you load]"
@@ -812,6 +850,7 @@ static struct nbdkit_plugin plugin = {
   .can_extents       = sh_can_extents,
   .can_fua           = sh_can_fua,
   .can_multi_conn    = sh_can_multi_conn,
+  .can_cache         = sh_can_cache,

   .pread             = sh_pread,
   .pwrite            = sh_pwrite,
@@ -819,6 +858,7 @@ static struct nbdkit_plugin plugin = {
   .trim              = sh_trim,
   .zero              = sh_zero,
   .extents           = sh_extents,
+  .cache             = sh_cache,

   .errno_is_preserved = 1,
 };
-- 
2.20.1




More information about the Libguestfs mailing list