[Libguestfs] [PATCH nbdkit] cc: Handle missing callbacks.

Richard W.M. Jones rjones at redhat.com
Thu Jun 4 11:25:33 UTC 2020


If can_write is defined by the subplugin and returns true, but pwrite
is missing, then the plugin would crash.  nbdkit itself handles these
kinds of cases in different ways, and this commit replicates that
handling.  Except for .zero where the fallback is complex.

Thanks: Eric Blake
---
 plugins/cc/cc.c | 50 +++++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 44 insertions(+), 6 deletions(-)

diff --git a/plugins/cc/cc.c b/plugins/cc/cc.c
index 4d92be66..2139cf62 100644
--- a/plugins/cc/cc.c
+++ b/plugins/cc/cc.c
@@ -37,6 +37,7 @@
 #include <stdbool.h>
 #include <string.h>
 #include <unistd.h>
+#include <errno.h>
 #include <dlfcn.h>
 
 #define NBDKIT_API_VERSION 2
@@ -463,38 +464,75 @@ static int
 cc_pwrite (void *handle, const void *buf, uint32_t count, uint64_t offset,
            uint32_t flags)
 {
-  return subplugin.pwrite (handle, buf, count, offset, flags);
+  if (subplugin.pwrite)
+    return subplugin.pwrite (handle, buf, count, offset, flags);
+  else {
+    nbdkit_error ("missing %s callback", "pwrite");
+    errno = EROFS;
+    return -1;
+  }
 }
 
 static int
 cc_flush (void *handle, uint32_t flags)
 {
-  return subplugin.flush (handle, flags);
+  if (subplugin.flush)
+    return subplugin.flush (handle, flags);
+  else {
+    nbdkit_error ("missing %s callback", "flush");
+    errno = EINVAL;
+    return -1;
+  }
 }
 
 static int
 cc_trim (void *handle, uint32_t count, uint64_t offset, uint32_t flags)
 {
-  return subplugin.trim (handle, count, offset, flags);
+  if (subplugin.trim)
+    return subplugin.trim (handle, count, offset, flags);
+  else {
+    nbdkit_error ("missing %s callback", "trim");
+    errno = EINVAL;
+    return -1;
+  }
 }
 
 static int
 cc_zero (void *handle, uint32_t count, uint64_t offset, uint32_t flags)
 {
-  return subplugin.zero (handle, count, offset, flags);
+  if (subplugin.zero)
+    return subplugin.zero (handle, count, offset, flags);
+  else {
+    /* XXX nbdkit tries to emulate this and we should too. */
+    nbdkit_error ("missing %s callback", "zero");
+    errno = EINVAL;
+    return -1;
+  }
 }
 
 static int
 cc_extents (void *handle, uint32_t count, uint64_t offset,
             uint32_t flags, struct nbdkit_extents *extents)
 {
-  return subplugin.extents (handle, count, offset, flags, extents);
+  if (subplugin.extents)
+    return subplugin.extents (handle, count, offset, flags, extents);
+  else {
+    nbdkit_error ("missing %s callback", "extents");
+    errno = EINVAL;
+    return -1;
+  }
 }
 
 static int
 cc_cache (void *handle, uint32_t count, uint64_t offset, uint32_t flags)
 {
-  return subplugin.cache (handle, count, offset, flags);
+  if (subplugin.cache)
+    return subplugin.cache (handle, count, offset, flags);
+  else
+    /* A plugin may advertise caching but not provide .cache; in that
+     * case, caching is explicitly a no-op.
+     */
+    return 0;
 }
 
 static struct nbdkit_plugin plugin = {
-- 
2.25.0




More information about the Libguestfs mailing list