[Libguestfs] [nbdkit PATCH 7/7] RFC: plugins: Add back-compat for new plugin with old nbdkit

Eric Blake eblake at redhat.com
Tue Jan 16 02:51:47 UTC 2018


New nbdkit already knows how to gracefully handle a plugin that
defines .pwrite_fua but not .pwrite, making it possible to write
a plugin that does not have to provide duplicate boilerplate
code.  But for maximum cross-version compatibility, we must make
sure that older nbdkit, which doesn't know about the existance
of the .pwrite_fua callback, can still perform writes when loading
such a newer plugin.  The trick is to make our registration
macro provide sane fallback definitions, marked such that gcc
won't warn if the fallbacks are not needed.

Signed-off-by: Eric Blake <eblake at redhat.com>
---
 docs/nbdkit.pod         | 11 +++++------
 include/nbdkit-plugin.h | 26 ++++++++++++++++++++++++++
 2 files changed, 31 insertions(+), 6 deletions(-)

diff --git a/docs/nbdkit.pod b/docs/nbdkit.pod
index 2b868d9..a72c9b1 100644
--- a/docs/nbdkit.pod
+++ b/docs/nbdkit.pod
@@ -785,12 +785,11 @@ information about that plugin, eg:
  [etc]

 Plugins which ship with nbdkit usually have the same version as the
-corresponding nbdkit binary.  The nbdkit binary will always be able
-to utilize plugins compiled against an older version of the header;
-however, there are cases where a newer plugin may not be fully
-supported by an older nbdkit binary (for example, a plugin that
-supplies C<.pwrite_fua> but not C<.pwrite> may not support writes
-when loaded by the older nbdkit).
+corresponding nbdkit binary.  The nbdkit binary will always be able to
+utilize plugins compiled against an older version of the header; the
+converse direction of an older nbdkit driving a newer plugin is not
+guaranteed to work, although the design tries hard to preserve
+back-compatibility.

 =head2 Detect if a plugin is installed

diff --git a/include/nbdkit-plugin.h b/include/nbdkit-plugin.h
index d3b0050..0c6e67e 100644
--- a/include/nbdkit-plugin.h
+++ b/include/nbdkit-plugin.h
@@ -117,6 +117,12 @@ extern char *nbdkit_absolute_path (const char *path);
 extern int64_t nbdkit_parse_size (const char *str);
 extern int nbdkit_read_password (const char *value, char **password);

+#ifdef __GNUC__
+#define NBDKIT_UNUSED __attribute__ (( __unused__ ))
+#else
+#define NBDKIT_UNUSED /* empty */
+#endif
+
 #ifdef __cplusplus
 #define NBDKIT_CXX_LANG_C extern "C"
 #else
@@ -124,6 +130,20 @@ extern int nbdkit_read_password (const char *value, char **password);
 #endif

 #define NBDKIT_REGISTER_PLUGIN(plugin)                                  \
+  static int NBDKIT_UNUSED                                              \
+  nbdkit_pwrite_no_fua (void *handle, const void *buf, uint32_t count,  \
+                        uint64_t offset) {                              \
+    return (plugin).pwrite_fua (handle, buf, count, offset, 0);         \
+  }                                                                     \
+  static int NBDKIT_UNUSED                                              \
+  nbdkit_zero_no_fua (void *handle, uint32_t count, uint64_t offset,    \
+                      int may_trim) {                                   \
+    return (plugin).zero_fua (handle, count, offset, may_trim, 0);      \
+  }                                                                     \
+  static int NBDKIT_UNUSED                                              \
+  nbdkit_trim_no_fua (void *handle, uint32_t count, uint64_t offset) {  \
+    return (plugin).trim_fua (handle, count, offset, 0);                \
+  }                                                                     \
   NBDKIT_CXX_LANG_C                                                     \
   struct nbdkit_plugin *                                                \
   plugin_init (void)                                                    \
@@ -131,6 +151,12 @@ extern int nbdkit_read_password (const char *value, char **password);
     (plugin)._struct_size = sizeof (plugin);                            \
     (plugin)._api_version = NBDKIT_API_VERSION;                         \
     (plugin)._thread_model = THREAD_MODEL;                              \
+    if ((plugin).pwrite_fua && !(plugin).pwrite)                        \
+      (plugin).pwrite = nbdkit_pwrite_no_fua;                           \
+    if ((plugin).zero_fua && !(plugin).zero)                            \
+      (plugin).zero = nbdkit_zero_no_fua;                               \
+    if ((plugin).trim_fua && !(plugin).trim)                            \
+      (plugin).trim = nbdkit_trim_no_fua;                               \
     return &(plugin);                                                   \
   }

-- 
2.14.3




More information about the Libguestfs mailing list