Richard W.M. Jones
2019-Oct-10 10:09 UTC
[Libguestfs] [PATCH NOT WORKING nbdkit] vddk: Restructure plugin to allow greater parallelism.
We had a query yesterday about the VDDK plugin and making it actually obey the weird "Multithreading Considerations" rules in the VDDK documentation (https://vdc-download.vmware.com/vmwb-repository/dcr-public/8f96698a-0e7b-4d67-bb6c-d18a1d101540/ef536a47-27cd-481a-90ef-76b38e75353c/vsphere-vddk-671-programming-guide.pdf) This patch is my attempt to implement this. The idea is that the plugin starts a background thread and routes all calls to certain VDDK functions through this thread, ensuring that the "Multithreading Considerations" are obeyed. It doesn't work. Because we start the background thread when the plugin is loaded, when nbdkit forks the thread disappears. It's possible that we need in nbdkit a supported way for plugins to create background threads. In any case the actual benefit of this patch is dubious. Closer reading of the documentation indicates that VDDK does not allow full parallel requests on single handles. The way we normally use VDDK (eg. from virt-v2v) is that we only have a single connection open (and therefore a single handle). So whether we'd gain any benefit in real world cases seems unlikely. We cannot enable multi-conn on writable VDDK handles because the documentation gives us no indication that VDDK provides the required guarantees, although we might consider enabling multi-conn for readonly handles. Rich.
Richard W.M. Jones
2019-Oct-10 10:09 UTC
[Libguestfs] [PATCH nbdkit] vddk: Restructure plugin to allow greater parallelism.
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
Apparently Analagous Threads
- [PATCH NOT WORKING nbdkit v2 0/2] vddk: Restructure plugin to allow greater parallelism.
- [PATCH nbdkit NOT WORKING 0/2] vddk: Relax threading model.
- [PATCH nbdkit 0/5] vddk: Fix password parameter.
- [PATCH nbdkit] vddk: Add support for VIXDISKLIB_FLAG_OPEN_UNBUFFERED.
- [nbdkit PATCH 0/3] Fix data integrity in vddk plugin