[Libguestfs] [PATCH nbdkit] vddk: Restructure plugin to allow greater parallelism.

Richard W.M. Jones rjones at redhat.com
Thu Oct 10 10:09:23 UTC 2019


This finally solves a long-standing problem that the plugin did not
follow the peculiar rules that VDDK imposes on multithreaded
programming (see "Multithreading Considerations" in the VDDK manual).

We add a background thread to the plugin which is responsible for
issuing the following VDDK calls:

  VixDiskLib_InitEx
  VixDiskLib_Exit
  VixDiskLib_ConnectEx
  VixDiskLib_Open
  VixDiskLib_Close
  VixDiskLib_Disconnect

(Other calls are still made directly by the plugin.)  This involves
some complicated synchronization but is otherwise uninteresting.

This allows us to relax the thread model from SERIALIZE_ALL_REQUESTS
to SERIALIZE_REQUESTS.  Note that VDDK does not allow parallel
requests to be made on one handle, so we cannot relax the model any
further.
---
 plugins/vddk/Makefile.am |   2 +
 plugins/vddk/octhread.c  | 374 +++++++++++++++++++++++++++++++++++++++
 plugins/vddk/vddk.c      | 164 ++++-------------
 plugins/vddk/vddk.h      |  89 ++++++++++
 4 files changed, 504 insertions(+), 125 deletions(-)

diff --git a/plugins/vddk/Makefile.am b/plugins/vddk/Makefile.am
index b806a7d..aff1288 100644
--- a/plugins/vddk/Makefile.am
+++ b/plugins/vddk/Makefile.am
@@ -42,6 +42,8 @@ plugin_LTLIBRARIES = nbdkit-vddk-plugin.la
 
 nbdkit_vddk_plugin_la_SOURCES = \
 	vddk.c \
+	octhread.c \
+	vddk.h \
 	vddk-structs.h \
 	vddk-stubs.h \
 	$(top_srcdir)/include/nbdkit-plugin.h \
diff --git a/plugins/vddk/octhread.c b/plugins/vddk/octhread.c
new file mode 100644
index 0000000..8f1985d
--- /dev/null
+++ b/plugins/vddk/octhread.c
@@ -0,0 +1,374 @@
+/* nbdkit
+ * Copyright (C) 2013-2019 Red Hat Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of Red Hat nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* This is the Open/Close Thread (octhread).
+ *
+ * Because of VDDK's complicated multi-threading requirements (see
+ * "Multithreading Considerations" in the VDDK manual) we have to
+ * issue various VDDK calls from a single thread.  In this file we
+ * create the extra thread which always runs while the VDDK plugin is
+ * loaded.
+ *
+ * The main VDDK plugin calls out to this thread synchronously
+ * whenever it needs to make one of the following calls:
+ *
+ *   VixDiskLib_InitEx
+ *   VixDiskLib_Exit
+ *   VixDiskLib_ConnectEx
+ *   VixDiskLib_Open
+ *   VixDiskLib_Close
+ *   VixDiskLib_Disconnect
+ *
+ * (Any other calls are made directly by the plugin.)
+ *
+ * To make one of the above calls, the plugin thread fills in struct
+ * request with the request type and signals on the request_cond.  The
+ * plugin thread then waits on the return_cond until that is signalled
+ * which indicates that the request was carried out (or there was an
+ * error).  The return value can be read out of the request struct.
+ * All this logic is wrapped in the octhread_do_* functions below.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+#include <errno.h>
+
+#include <pthread.h>
+
+#define NBDKIT_API_VERSION 2
+#include <nbdkit-plugin.h>
+
+#include "cleanup.h"
+
+#include "vddk.h"
+
+static pthread_t thread;
+
+/* Because the entire purpose of this is to serialize certain
+ * operations, the request struct can only be used by one calling
+ * thread.  The calling thread must hold request_lock during the
+ * entire request.
+ */
+static pthread_mutex_t request_lock = PTHREAD_MUTEX_INITIALIZER;
+static struct {
+  /* Which function to call. */
+  enum { BAD = 0,
+         INITEX = 1, EXIT, CONNECTEX, OPEN, CLOSE, DISCONNECT,
+         STOP } request_type;
+
+  /* Parameters. */
+  VixDiskLibConnectParams *params;
+  VixDiskLibConnection *connection_ret;
+  VixDiskLibConnection connection;
+  VixDiskLibHandle *handle_ret;
+  VixDiskLibHandle handle;
+  int readonly;
+
+  /* Return code. */
+  VixError ret;
+} request;
+
+/* Request and return conditions. */
+static pthread_cond_t request_cond = PTHREAD_COND_INITIALIZER;
+static pthread_mutex_t request_cond_lock = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t return_cond = PTHREAD_COND_INITIALIZER;
+static pthread_mutex_t return_cond_lock = PTHREAD_MUTEX_INITIALIZER;
+
+static inline void
+wake_up_octhread (void)
+{
+  ACQUIRE_LOCK_FOR_CURRENT_SCOPE (&request_cond_lock);
+  pthread_cond_signal (&request_cond);
+}
+
+static inline void
+wait_for_octhread (void)
+{
+  ACQUIRE_LOCK_FOR_CURRENT_SCOPE (&return_cond_lock);
+  pthread_cond_wait (&return_cond, &return_cond_lock);
+}
+
+static VixError
+do_request (void)
+{
+  wake_up_octhread ();
+  wait_for_octhread ();
+
+  request.request_type = BAD;
+  return request.ret;
+}
+
+static void *octhread_run (void *);
+
+/*----------------------------------------------------------------------*/
+/* Plugins call these functions from the normal nbdkit thread context. */
+
+/* Start the octhread.  Called by vddk_load. */
+void
+start_octhread (void)
+{
+  int err;
+
+  err = pthread_create (&thread, NULL, octhread_run, NULL);
+  if (err != 0) {
+    errno = err;
+    nbdkit_error ("octhread: pthread_create: %m");
+    exit (EXIT_FAILURE);
+  }
+}
+
+/* Terminate the octhread.  Called from vddk_unload. */
+void
+stop_octhread (void)
+{
+  ACQUIRE_LOCK_FOR_CURRENT_SCOPE (&request_lock);
+
+  request.request_type = STOP;
+  do_request ();
+  pthread_join (thread, NULL);
+}
+
+/* Request VixDiskLib_InitEx and wait for it to finish. */
+VixError
+octhread_do_VixDiskLib_InitEx (void)
+{
+  ACQUIRE_LOCK_FOR_CURRENT_SCOPE (&request_lock);
+
+  request.request_type = INITEX;
+  return do_request ();
+}
+
+/* Request VixDiskLib_Exit and wait for it to finish. */
+VixError
+octhread_do_VixDiskLib_Exit (void)
+{
+  ACQUIRE_LOCK_FOR_CURRENT_SCOPE (&request_lock);
+
+  request.request_type = EXIT;
+  return do_request ();
+}
+
+/* Request VixDiskLib_ConnectEx and wait for it to finish. */
+VixError
+octhread_do_VixDiskLib_ConnectEx (const VixDiskLibConnectParams *params,
+                                  int readonly,
+                                  VixDiskLibConnection *connection)
+{
+  ACQUIRE_LOCK_FOR_CURRENT_SCOPE (&request_lock);
+
+  request.request_type = CONNECTEX;
+  request.params = (VixDiskLibConnectParams *) params;
+  request.readonly = readonly;
+  request.connection_ret = connection;
+  return do_request ();
+}
+
+/* Request VixDiskLib_Open and wait for it to finish. */
+VixError
+octhread_do_VixDiskLib_Open (const VixDiskLibConnection connection,
+                                  int readonly,
+                             VixDiskLibHandle *handle)
+{
+  ACQUIRE_LOCK_FOR_CURRENT_SCOPE (&request_lock);
+
+  request.request_type = OPEN;
+  request.connection = connection;
+  request.readonly = readonly;
+  request.handle_ret = handle;
+  return do_request ();
+}
+
+/* Request VixDiskLib_Close and wait for it to finish. */
+VixError
+octhread_do_VixDiskLib_Close (VixDiskLibHandle handle)
+{
+  ACQUIRE_LOCK_FOR_CURRENT_SCOPE (&request_lock);
+
+  request.request_type = CLOSE;
+  request.handle = handle;
+  return do_request ();
+}
+
+/* Request VixDiskLib_Disconnect and wait for it to finish. */
+VixError
+octhread_do_VixDiskLib_Disconnect (VixDiskLibConnection connection)
+{
+  ACQUIRE_LOCK_FOR_CURRENT_SCOPE (&request_lock);
+
+  request.request_type = DISCONNECT;
+  request.connection = connection;
+  return do_request ();
+}
+
+/*----------------------------------------------------------------------*/
+/* The octhread itself. */
+
+static void
+trim (char *str)
+{
+  size_t len = strlen (str);
+
+  if (len > 0 && str[len-1] == '\n')
+    str[len-1] = '\0';
+}
+
+/* Turn log messages from the library into nbdkit_debug. */
+static void
+debug_function (const char *fs, va_list args)
+{
+  CLEANUP_FREE char *str = NULL;
+
+  if (vasprintf (&str, fs, args) == -1) {
+    nbdkit_debug ("lost debug message: %s", fs);
+    return;
+  }
+
+  trim (str);
+
+  nbdkit_debug ("%s", str);
+}
+
+/* Turn error messages from the library into nbdkit_error. */
+static void
+error_function (const char *fs, va_list args)
+{
+  CLEANUP_FREE char *str = NULL;
+
+  if (vasprintf (&str, fs, args) == -1) {
+    nbdkit_error ("lost error message: %s", fs);
+    return;
+  }
+
+  trim (str);
+
+  nbdkit_error ("%s", str);
+}
+
+static void *
+octhread_run (void *arg)
+{
+  int err;
+  uint32_t flags;
+  bool stop = false;
+
+  nbdkit_debug ("octhread started");
+
+  while (!stop) {
+    /* Wait for an incoming request. */
+    {
+      ACQUIRE_LOCK_FOR_CURRENT_SCOPE (&request_cond_lock);
+      pthread_cond_wait (&request_cond, &request_cond_lock);
+    }
+
+    switch (request.request_type) {
+    case INITEX:
+      DEBUG_CALL ("VixDiskLib_InitEx",
+                  "%d, %d, &debug_fn, &error_fn, &error_fn, %s, %s",
+                  VDDK_MAJOR, VDDK_MINOR,
+                  libdir ? : VDDK_LIBDIR, config ? : "NULL");
+      err = VixDiskLib_InitEx (VDDK_MAJOR, VDDK_MINOR,
+                               &debug_function, /* log function */
+                               &error_function, /* warn function */
+                               &error_function, /* panic function */
+                               libdir ? : VDDK_LIBDIR, config);
+      break;
+
+    case EXIT:
+      DEBUG_CALL ("VixDiskLib_Exit", "");
+      VixDiskLib_Exit ();
+      err = VIX_OK;
+      break;
+
+    case CONNECTEX:
+      DEBUG_CALL ("VixDiskLib_ConnectEx",
+                  "params, %d, %s, %s, &connection",
+                  request.readonly,
+                  snapshot_moref ? : "NULL",
+                  transport_modes ? : "NULL");
+      err = VixDiskLib_ConnectEx (request.params,
+                                  request.readonly,
+                                  snapshot_moref,
+                                  transport_modes,
+                                  request.connection_ret);
+      break;
+
+    case OPEN:
+      flags = 0;
+      if (request.readonly)
+        flags |= VIXDISKLIB_FLAG_OPEN_READ_ONLY;
+      if (single_link)
+        flags |= VIXDISKLIB_FLAG_OPEN_SINGLE_LINK;
+      if (unbuffered)
+        flags |= VIXDISKLIB_FLAG_OPEN_UNBUFFERED;
+      DEBUG_CALL ("VixDiskLib_Open",
+                  "connection, %s, %d, &handle", filename, flags);
+      err = VixDiskLib_Open (request.connection, filename, flags,
+                             request.handle_ret);
+      break;
+
+    case CLOSE:
+      DEBUG_CALL ("VixDiskLib_Close", "handle");
+      err = VixDiskLib_Close (request.handle);
+      break;
+
+    case DISCONNECT:
+      DEBUG_CALL ("VixDiskLib_Disconnect", "connection");
+      err = VixDiskLib_Disconnect (request.connection);
+      break;
+
+    case STOP:
+      stop = true;
+      err = VIX_OK;
+      break;
+
+    case BAD:
+    default:
+      abort ();
+    }
+
+    /* Set up return field and signal to plugin thread that we have
+     * finished.
+     */
+    request.ret = err;
+
+    {
+      ACQUIRE_LOCK_FOR_CURRENT_SCOPE (&return_cond_lock);
+      pthread_cond_signal (&return_cond);
+    }
+  } /* for (;;) */
+
+  return NULL;
+}
diff --git a/plugins/vddk/vddk.c b/plugins/vddk/vddk.c
index 53984ad..02e473e 100644
--- a/plugins/vddk/vddk.c
+++ b/plugins/vddk/vddk.c
@@ -42,7 +42,6 @@
 #include <dlfcn.h>
 
 #define NBDKIT_API_VERSION 2
-
 #include <nbdkit-plugin.h>
 
 #include "cleanup.h"
@@ -50,7 +49,7 @@
 #include "minmax.h"
 #include "rounding.h"
 
-#include "vddk-structs.h"
+#include "vddk.h"
 
 /* Enable extra disk info debugging with: -D vddk.diskinfo=1 */
 int vddk_debug_diskinfo;
@@ -58,90 +57,34 @@ int vddk_debug_diskinfo;
 /* Enable debugging of extents code with: -D vddk.extents=1 */
 int vddk_debug_extents;
 
-/* For each VDDK API define a static global variable.  These globals
- * are initialized when the plugin is loaded (by vddk_load).
+/* For each VDDK API define a global variable.  These globals are
+ * initialized when the plugin is loaded (by vddk_load).
  */
-#define STUB(fn,ret,args) static ret (*fn) args
-#define OPTIONAL_STUB(fn,ret,args) static ret (*fn) args
+#define STUB(fn,ret,args) ret (*fn) args
+#define OPTIONAL_STUB(fn,ret,args) ret (*fn) args
 #include "vddk-stubs.h"
 #undef STUB
 #undef OPTIONAL_STUB
 
-/* Parameters passed to InitEx. */
-#define VDDK_MAJOR 5
-#define VDDK_MINOR 1
-
 static void *dl = NULL;                    /* dlopen handle */
 static int init_called = 0;                /* was InitEx called */
 
-static char *config = NULL;                /* config */
-static const char *cookie = NULL;          /* cookie */
-static const char *filename = NULL;        /* file */
-static char *libdir = NULL;                /* libdir */
-static uint16_t nfc_host_port = 0;         /* nfchostport */
-static char *password = NULL;              /* password */
-static uint16_t port = 0;                  /* port */
-static const char *server_name = NULL;     /* server */
-static bool single_link = false;           /* single-link */
-static const char *snapshot_moref = NULL;  /* snapshot */
-static const char *thumb_print = NULL;     /* thumbprint */
-static const char *transport_modes = NULL; /* transports */
-static bool unbuffered = false;            /* unbuffered */
-static const char *username = NULL;        /* user */
-static const char *vmx_spec = NULL;        /* vm */
-static bool is_remote = false;
-
-#define VDDK_ERROR(err, fs, ...)                                \
-  do {                                                          \
-    char *vddk_err_msg;                                         \
-    vddk_err_msg = VixDiskLib_GetErrorText ((err), NULL);       \
-    nbdkit_error (fs ": %s", ##__VA_ARGS__, vddk_err_msg);      \
-    VixDiskLib_FreeErrorText (vddk_err_msg);                    \
-  } while (0)
-
-#define DEBUG_CALL(fn, fs, ...)                                 \
-  nbdkit_debug ("VDDK call: %s (" fs ")", fn, ##__VA_ARGS__)
-
-static void
-trim (char *str)
-{
-  size_t len = strlen (str);
-
-  if (len > 0 && str[len-1] == '\n')
-    str[len-1] = '\0';
-}
-
-/* Turn log messages from the library into nbdkit_debug. */
-static void
-debug_function (const char *fs, va_list args)
-{
-  CLEANUP_FREE char *str = NULL;
-
-  if (vasprintf (&str, fs, args) == -1) {
-    nbdkit_debug ("lost debug message: %s", fs);
-    return;
-  }
-
-  trim (str);
-
-  nbdkit_debug ("%s", str);
-}
-
-/* Turn error messages from the library into nbdkit_error. */
-static void
-error_function (const char *fs, va_list args)
-{
-  CLEANUP_FREE char *str = NULL;
-
-  if (vasprintf (&str, fs, args) == -1) {
-    nbdkit_error ("lost error message: %s", fs);
-    return;
-  }
-
-  trim (str);
-
-  nbdkit_error ("%s", str);
-}
+char *config = NULL;                       /* config */
+const char *cookie = NULL;                 /* cookie */
+const char *filename = NULL;               /* file */
+char *libdir = NULL;                       /* libdir */
+uint16_t nfc_host_port = 0;                /* nfchostport */
+char *password = NULL;                     /* password */
+uint16_t port = 0;                         /* port */
+const char *server_name = NULL;            /* server */
+bool single_link = false;                  /* single-link */
+const char *snapshot_moref = NULL;         /* snapshot */
+const char *thumb_print = NULL;            /* thumbprint */
+const char *transport_modes = NULL;        /* transports */
+bool unbuffered = false;                   /* unbuffered */
+const char *username = NULL;               /* user */
+const char *vmx_spec = NULL;               /* vm */
+bool is_remote = false;                    /* is a remote connection? */
 
 /* Load and unload the plugin. */
 static void
@@ -189,15 +132,16 @@ vddk_load (void)
 #include "vddk-stubs.h"
 #undef STUB
 #undef OPTIONAL_STUB
+
+  start_octhread ();
 }
 
 static void
 vddk_unload (void)
 {
-  if (init_called) {
-    DEBUG_CALL ("VixDiskLib_Exit", "");
-    VixDiskLib_Exit ();
-  }
+  if (init_called)
+    octhread_do_VixDiskLib_Exit ();
+  stop_octhread ();
   if (dl)
     dlclose (dl);
   free (config);
@@ -331,18 +275,10 @@ vddk_config_complete (void)
   }
 
   /* Initialize VDDK library. */
-  DEBUG_CALL ("VixDiskLib_InitEx",
-              "%d, %d, &debug_fn, &error_fn, &error_fn, %s, %s",
-              VDDK_MAJOR, VDDK_MINOR,
-              libdir ? : VDDK_LIBDIR, config ? : "NULL");
-  err = VixDiskLib_InitEx (VDDK_MAJOR, VDDK_MINOR,
-                           &debug_function, /* log function */
-                           &error_function, /* warn function */
-                           &error_function, /* panic function */
-                           libdir ? : VDDK_LIBDIR, config);
+  err = octhread_do_VixDiskLib_InitEx ();
   if (err != VIX_OK) {
     VDDK_ERROR (err, "VixDiskLib_InitEx");
-    exit (EXIT_FAILURE);
+    return -1;
   }
   init_called = 1;
 
@@ -376,11 +312,11 @@ vddk_dump_plugin (void)
 #endif
 }
 
-/* XXX To really do threading correctly in accordance with the VDDK
- * documentation, we must do all open/close calls from a single
- * thread.  This is a huge pain.
+/* See "Multithreading Considerations" in the VDDK manual.  VDDK does
+ * not allow parallel requests on the same handle, so we cannot use
+ * the parallel thread model.
  */
-#define THREAD_MODEL NBDKIT_THREAD_MODEL_SERIALIZE_ALL_REQUESTS
+#define THREAD_MODEL NBDKIT_THREAD_MODEL_SERIALIZE_REQUESTS
 
 /* The per-connection handle. */
 struct vddk_handle {
@@ -424,7 +360,6 @@ vddk_open (int readonly)
 {
   struct vddk_handle *h;
   VixError err;
-  uint32_t flags;
 
   h = malloc (sizeof *h);
   if (h == NULL) {
@@ -462,33 +397,15 @@ vddk_open (int readonly)
    * Advanced Transport modes, but I could not make it work with
    * either ESXi or vCenter servers.
    */
-
-  DEBUG_CALL ("VixDiskLib_ConnectEx",
-              "h->params, %d, %s, %s, &connection",
-              readonly,
-              snapshot_moref ? : "NULL",
-              transport_modes ? : "NULL");
-  err = VixDiskLib_ConnectEx (h->params,
-                              readonly,
-                              snapshot_moref,
-                              transport_modes,
-                              &h->connection);
+  err = octhread_do_VixDiskLib_ConnectEx (h->params, readonly,
+                                          &h->connection);
   if (err != VIX_OK) {
     VDDK_ERROR (err, "VixDiskLib_ConnectEx");
     goto err1;
   }
 
-  flags = 0;
-  if (readonly)
-    flags |= VIXDISKLIB_FLAG_OPEN_READ_ONLY;
-  if (single_link)
-    flags |= VIXDISKLIB_FLAG_OPEN_SINGLE_LINK;
-  if (unbuffered)
-    flags |= VIXDISKLIB_FLAG_OPEN_UNBUFFERED;
-
-  DEBUG_CALL ("VixDiskLib_Open",
-              "connection, %s, %d, &handle", filename, flags);
-  err = VixDiskLib_Open (h->connection, filename, flags, &h->handle);
+  err = octhread_do_VixDiskLib_Open (h->connection, readonly,
+                                     &h->handle);
   if (err != VIX_OK) {
     VDDK_ERROR (err, "VixDiskLib_Open: %s", filename);
     goto err2;
@@ -500,8 +417,7 @@ vddk_open (int readonly)
   return h;
 
  err2:
-  DEBUG_CALL ("VixDiskLib_Disconnect", "connection");
-  VixDiskLib_Disconnect (h->connection);
+  octhread_do_VixDiskLib_Disconnect (h->connection);
  err1:
   free_connect_params (h->params);
  err0:
@@ -515,11 +431,9 @@ vddk_close (void *handle)
 {
   struct vddk_handle *h = handle;
 
+  octhread_do_VixDiskLib_Close (h->handle);
+  octhread_do_VixDiskLib_Disconnect (h->connection);
   free_connect_params (h->params);
-  DEBUG_CALL ("VixDiskLib_Close", "handle");
-  VixDiskLib_Close (h->handle);
-  DEBUG_CALL ("VixDiskLib_Disconnect", "connection");
-  VixDiskLib_Disconnect (h->connection);
   free (h);
 }
 
diff --git a/plugins/vddk/vddk.h b/plugins/vddk/vddk.h
new file mode 100644
index 0000000..7d012eb
--- /dev/null
+++ b/plugins/vddk/vddk.h
@@ -0,0 +1,89 @@
+/* nbdkit
+ * Copyright (C) 2013-2019 Red Hat Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of Red Hat nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef NBDKIT_VDDK_H
+#define NBDKIT_VDDK_H
+
+#include "vddk-structs.h"
+
+/* For each VDDK API define an extern global variable.  These globals
+ * are initialized when the plugin is loaded (by vddk_load).
+ */
+#define STUB(fn,ret,args) extern ret (*fn) args
+#define OPTIONAL_STUB(fn,ret,args) extern ret (*fn) args
+#include "vddk-stubs.h"
+#undef STUB
+#undef OPTIONAL_STUB
+
+extern char *config;
+extern const char *cookie;
+extern const char *filename;
+extern char *libdir;
+extern uint16_t nfc_host_port;
+extern char *password;
+extern uint16_t port;
+extern const char *server_name;
+extern bool single_link;
+extern const char *snapshot_moref;
+extern const char *thumb_print;
+extern const char *transport_modes;
+extern bool unbuffered;
+extern const char *username;
+extern const char *vmx_spec;
+extern bool is_remote;
+
+#define VDDK_ERROR(err, fs, ...)                                \
+  do {                                                          \
+    char *vddk_err_msg;                                         \
+    vddk_err_msg = VixDiskLib_GetErrorText ((err), NULL);       \
+    nbdkit_error (fs ": %s", ##__VA_ARGS__, vddk_err_msg);      \
+    VixDiskLib_FreeErrorText (vddk_err_msg);                    \
+  } while (0)
+
+#define DEBUG_CALL(fn, fs, ...)                                 \
+  nbdkit_debug ("VDDK call: %s (" fs ")", fn, ##__VA_ARGS__)
+
+/* Parameters passed to InitEx. */
+#define VDDK_MAJOR 5
+#define VDDK_MINOR 1
+
+/* Functions in octhread.c */
+extern void start_octhread (void);
+extern void stop_octhread (void);
+extern VixError octhread_do_VixDiskLib_InitEx (void);
+extern VixError octhread_do_VixDiskLib_Exit (void);
+extern VixError octhread_do_VixDiskLib_ConnectEx (const VixDiskLibConnectParams *params, int readonly, VixDiskLibConnection *connection);
+extern VixError octhread_do_VixDiskLib_Open (const VixDiskLibConnection connection, int readonly, VixDiskLibHandle *handle);
+extern VixError octhread_do_VixDiskLib_Close (VixDiskLibHandle handle);
+extern VixError octhread_do_VixDiskLib_Disconnect (VixDiskLibConnection connection);
+
+#endif /* NBDKIT_VDDK_H */
-- 
2.23.0




More information about the Libguestfs mailing list