import nbdkit-1.28.5-1.el9

This commit is contained in:
CentOS Sources 2022-05-17 04:45:25 -04:00 committed by Stepan Oksanichenko
commit bf716c3fe9
40 changed files with 9813 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
SOURCES/libguestfs.keyring
SOURCES/nbdkit-1.28.5.tar.gz

2
.nbdkit.metadata Normal file
View File

@ -0,0 +1,2 @@
cc1b37b9cfafa515aab3eefd345ecc59aac2ce7b SOURCES/libguestfs.keyring
60f2c2021658a94d778eb9cde0123d1c092ff15d SOURCES/nbdkit-1.28.5.tar.gz

View File

@ -0,0 +1,117 @@
From 4f2f557b349ad621e502e304c87280835cf13146 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Thu, 21 Oct 2021 14:49:52 +0100
Subject: [PATCH] vddk: Refactor how -D vddk.stats=1 is collected
In order to allow us to collect more per-API stats, introduce a global
struct per API for storing these stats.
(cherry picked from commit 3d8657f3d9a2c1b59284333566428b4c7ce32a74)
---
plugins/vddk/vddk.c | 36 ++++++++++++++++++------------------
1 file changed, 18 insertions(+), 18 deletions(-)
diff --git a/plugins/vddk/vddk.c b/plugins/vddk/vddk.c
index 80f5870e..3d751544 100644
--- a/plugins/vddk/vddk.c
+++ b/plugins/vddk/vddk.c
@@ -1,5 +1,5 @@
/* nbdkit
- * Copyright (C) 2013-2020 Red Hat Inc.
+ * Copyright (C) 2013-2021 Red Hat Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -103,14 +103,23 @@ static bool is_remote;
/* For each VDDK API define a variable to store the time taken (used
* to implement -D vddk.stats=1).
*/
+struct vddk_stat {
+ const char *name; /* function name */
+ int64_t usecs; /* total number of usecs consumed */
+};
static pthread_mutex_t stats_lock = PTHREAD_MUTEX_INITIALIZER;
static void display_stats (void);
-#define STUB(fn,ret,args) static int64_t stats_##fn;
-#define OPTIONAL_STUB(fn,ret,args) static int64_t stats_##fn;
+#define STUB(fn,ret,args) \
+ static struct vddk_stat stats_##fn = { .name = #fn }
+#define OPTIONAL_STUB(fn,ret,args) \
+ static struct vddk_stat stats_##fn = { .name = #fn }
#include "vddk-stubs.h"
#undef STUB
#undef OPTIONAL_STUB
+/* Macros to bracket each VDDK API call, for printing debugging
+ * information and collecting statistics.
+ */
#define VDDK_CALL_START(fn, fs, ...) \
do { \
struct timeval start_t, end_t; \
@@ -131,10 +140,11 @@ static void display_stats (void);
if (vddk_debug_stats) { \
gettimeofday (&end_t, NULL); \
ACQUIRE_LOCK_FOR_CURRENT_SCOPE (&stats_lock); \
- stats_##fn += tvdiff_usec (&start_t, &end_t); \
+ stats_##fn.usecs += tvdiff_usec (&start_t, &end_t); \
} \
} while (0)
+/* Print VDDK errors. */
#define VDDK_ERROR(err, fs, ...) \
do { \
char *vddk_err_msg; \
@@ -167,10 +177,6 @@ vddk_unload (void)
free (password);
}
-struct vddk_stat {
- const char *fn;
- int64_t usecs;
-};
DEFINE_VECTOR_TYPE(statlist, struct vddk_stat)
static int
@@ -179,7 +185,7 @@ stat_compare (const void *vp1, const void *vp2)
const struct vddk_stat *st1 = vp1;
const struct vddk_stat *st2 = vp2;
- /* Note: sorts in reverse order. */
+ /* Note: sorts in reverse order of time spent in each API call. */
if (st1->usecs < st2->usecs) return 1;
else if (st1->usecs > st2->usecs) return -1;
else return 0;
@@ -189,19 +195,13 @@ static void
display_stats (void)
{
statlist stats = empty_vector;
- struct vddk_stat st;
size_t i;
-#define ADD_ONE_STAT(fn_, usecs_) \
- st.fn = fn_; \
- st.usecs = usecs_; \
- statlist_append (&stats, st)
-#define STUB(fn,ret,args) ADD_ONE_STAT (#fn, stats_##fn);
-#define OPTIONAL_STUB(fn,ret,args) ADD_ONE_STAT (#fn, stats_##fn);
+#define STUB(fn,ret,args) statlist_append (&stats, stats_##fn)
+#define OPTIONAL_STUB(fn,ret,args) statlist_append (&stats, stats_##fn)
#include "vddk-stubs.h"
#undef STUB
#undef OPTIONAL_STUB
-#undef ADD_ONE_STAT
qsort (stats.ptr, stats.size, sizeof stats.ptr[0], stat_compare);
@@ -209,7 +209,7 @@ display_stats (void)
nbdkit_debug ("%-40s %9s", "", "µs");
for (i = 0; i < stats.size; ++i) {
if (stats.ptr[i].usecs)
- nbdkit_debug ("%-40s %9" PRIi64, stats.ptr[i].fn, stats.ptr[i].usecs);
+ nbdkit_debug ("%-40s %9" PRIi64, stats.ptr[i].name, stats.ptr[i].usecs);
}
statlist_reset (&stats);
}
--
2.31.1

View File

@ -0,0 +1,140 @@
From edfdfff0dae54a41bbfca30fa60f4fa6438d45b9 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Thu, 21 Oct 2021 15:10:00 +0100
Subject: [PATCH] vddk: Extend -D vddk.stats=1 to show number of calls and
bytes transferred
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The new output looks like this:
nbdkit: debug: VDDK function stats (-D vddk.stats=1):
nbdkit: debug: VixDiskLib_... µs calls bytes
nbdkit: debug: Exit 1000854 1
nbdkit: debug: InitEx 79304 1
nbdkit: debug: Flush 13577 1
nbdkit: debug: Write 12534 21 10485760
nbdkit: debug: Open 4753 3
nbdkit: debug: Read 966 20 5242880
nbdkit: debug: Close 574 3
nbdkit: debug: QueryAllocatedBlocks 116 4
nbdkit: debug: ConnectEx 103 3
nbdkit: debug: Disconnect 88 3
nbdkit: debug: GetTransportMode 68 3
nbdkit: debug: GetInfo 46 3
nbdkit: debug: FreeConnectParams 36 3
nbdkit: debug: FreeInfo 36 3
nbdkit: debug: FreeBlockList 22 4
nbdkit: debug: AllocateConnectParams 22 3
(cherry picked from commit 5c80f0d290db45a679d55baf37ff39bacb8ce7ec)
---
plugins/vddk/nbdkit-vddk-plugin.pod | 3 +--
plugins/vddk/vddk.c | 41 +++++++++++++++++++++++++----
2 files changed, 37 insertions(+), 7 deletions(-)
diff --git a/plugins/vddk/nbdkit-vddk-plugin.pod b/plugins/vddk/nbdkit-vddk-plugin.pod
index 078badcc..e53d3286 100644
--- a/plugins/vddk/nbdkit-vddk-plugin.pod
+++ b/plugins/vddk/nbdkit-vddk-plugin.pod
@@ -517,8 +517,7 @@ Suppress debugging of datapath calls (C<Read> and C<Write>).
=item B<-D vddk.stats=1>
-When the plugin exits print some statistics about the amount of time
-spent waiting on each VDDK call.
+When the plugin exits print some statistics about each VDDK call.
=back
diff --git a/plugins/vddk/vddk.c b/plugins/vddk/vddk.c
index 3d751544..5f1d223b 100644
--- a/plugins/vddk/vddk.c
+++ b/plugins/vddk/vddk.c
@@ -106,6 +106,8 @@ static bool is_remote;
struct vddk_stat {
const char *name; /* function name */
int64_t usecs; /* total number of usecs consumed */
+ uint64_t calls; /* number of times called */
+ uint64_t bytes; /* bytes transferred, datapath calls only */
};
static pthread_mutex_t stats_lock = PTHREAD_MUTEX_INITIALIZER;
static void display_stats (void);
@@ -141,6 +143,17 @@ static void display_stats (void);
gettimeofday (&end_t, NULL); \
ACQUIRE_LOCK_FOR_CURRENT_SCOPE (&stats_lock); \
stats_##fn.usecs += tvdiff_usec (&start_t, &end_t); \
+ stats_##fn.calls++; \
+ } \
+ } while (0)
+#define VDDK_CALL_END_DATAPATH(fn, bytes_) \
+ while (0); \
+ if (vddk_debug_stats) { \
+ gettimeofday (&end_t, NULL); \
+ ACQUIRE_LOCK_FOR_CURRENT_SCOPE (&stats_lock); \
+ stats_##fn.usecs += tvdiff_usec (&start_t, &end_t); \
+ stats_##fn.calls++; \
+ stats_##fn.bytes += bytes_; \
} \
} while (0)
@@ -191,6 +204,12 @@ stat_compare (const void *vp1, const void *vp2)
else return 0;
}
+static const char *
+api_name_without_prefix (const char *name)
+{
+ return strncmp (name, "VixDiskLib_", 11) == 0 ? name + 11 : name;
+}
+
static void
display_stats (void)
{
@@ -206,10 +225,22 @@ display_stats (void)
qsort (stats.ptr, stats.size, sizeof stats.ptr[0], stat_compare);
nbdkit_debug ("VDDK function stats (-D vddk.stats=1):");
- nbdkit_debug ("%-40s %9s", "", "µs");
+ nbdkit_debug ("%-24s %15s %5s %15s",
+ "VixDiskLib_...", "µs", "calls", "bytes");
for (i = 0; i < stats.size; ++i) {
- if (stats.ptr[i].usecs)
- nbdkit_debug ("%-40s %9" PRIi64, stats.ptr[i].name, stats.ptr[i].usecs);
+ if (stats.ptr[i].usecs) {
+ if (stats.ptr[i].bytes > 0)
+ nbdkit_debug (" %-22s %15" PRIi64 " %5" PRIu64 " %15" PRIu64,
+ api_name_without_prefix (stats.ptr[i].name),
+ stats.ptr[i].usecs,
+ stats.ptr[i].calls,
+ stats.ptr[i].bytes);
+ else
+ nbdkit_debug (" %-22s %15" PRIi64 " %5" PRIu64,
+ api_name_without_prefix (stats.ptr[i].name),
+ stats.ptr[i].usecs,
+ stats.ptr[i].calls);
+ }
}
statlist_reset (&stats);
}
@@ -831,7 +862,7 @@ vddk_pread (void *handle, void *buf, uint32_t count, uint64_t offset,
"%" PRIu32 " sectors, buffer",
offset, count) {
err = VixDiskLib_Read (h->handle, offset, count, buf);
- } VDDK_CALL_END (VixDiskLib_Read);
+ } VDDK_CALL_END_DATAPATH (VixDiskLib_Read, count * VIXDISKLIB_SECTOR_SIZE);
if (err != VIX_OK) {
VDDK_ERROR (err, "VixDiskLib_Read");
return -1;
@@ -871,7 +902,7 @@ vddk_pwrite (void *handle, const void *buf, uint32_t count, uint64_t offset,
"%" PRIu32 " sectors, buffer",
offset, count) {
err = VixDiskLib_Write (h->handle, offset, count, buf);
- } VDDK_CALL_END (VixDiskLib_Write);
+ } VDDK_CALL_END_DATAPATH (VixDiskLib_Write, count * VIXDISKLIB_SECTOR_SIZE);
if (err != VIX_OK) {
VDDK_ERROR (err, "VixDiskLib_Write");
return -1;
--
2.31.1

View File

@ -0,0 +1,320 @@
From cbcf2a2f158a9889bd597b31159ab357dea05cd6 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Thu, 21 Oct 2021 22:55:17 +0100
Subject: [PATCH] vddk: Simplify and consolidate VDDK_CALL_START/END macros
We don't need the VDDK_CALL_*_DATAPATH versions of these macros
because the compiler is able to optimize some static strcmps.
Furthermore we can remove extra { .. } when the macros are applied.
(cherry picked from commit 3ea0ed6582faa8f800b7a2a15d58032917a21bd5)
---
plugins/vddk/vddk.c | 124 ++++++++++++++++++++------------------------
1 file changed, 56 insertions(+), 68 deletions(-)
diff --git a/plugins/vddk/vddk.c b/plugins/vddk/vddk.c
index 5f1d223b..993f2d76 100644
--- a/plugins/vddk/vddk.c
+++ b/plugins/vddk/vddk.c
@@ -125,28 +125,16 @@ static void display_stats (void);
#define VDDK_CALL_START(fn, fs, ...) \
do { \
struct timeval start_t, end_t; \
+ /* GCC can optimize this away at compile time: */ \
+ const bool datapath = \
+ strcmp (#fn, "VixDiskLib_Read") == 0 || \
+ strcmp (#fn, "VixDiskLib_Write") == 0; \
if (vddk_debug_stats) \
gettimeofday (&start_t, NULL); \
- nbdkit_debug ("VDDK call: %s (" fs ")", #fn, ##__VA_ARGS__); \
- do
-#define VDDK_CALL_START_DATAPATH(fn, fs, ...) \
- do { \
- struct timeval start_t, end_t; \
- if (vddk_debug_stats) \
- gettimeofday (&start_t, NULL); \
- if (vddk_debug_datapath) \
+ if (!datapath || vddk_debug_datapath) \
nbdkit_debug ("VDDK call: %s (" fs ")", #fn, ##__VA_ARGS__); \
do
-#define VDDK_CALL_END(fn) \
- while (0); \
- if (vddk_debug_stats) { \
- gettimeofday (&end_t, NULL); \
- ACQUIRE_LOCK_FOR_CURRENT_SCOPE (&stats_lock); \
- stats_##fn.usecs += tvdiff_usec (&start_t, &end_t); \
- stats_##fn.calls++; \
- } \
- } while (0)
-#define VDDK_CALL_END_DATAPATH(fn, bytes_) \
+#define VDDK_CALL_END(fn, bytes_) \
while (0); \
if (vddk_debug_stats) { \
gettimeofday (&end_t, NULL); \
@@ -161,13 +149,13 @@ static void display_stats (void);
#define VDDK_ERROR(err, fs, ...) \
do { \
char *vddk_err_msg; \
- VDDK_CALL_START (VixDiskLib_GetErrorText, "%lu", err) { \
+ VDDK_CALL_START (VixDiskLib_GetErrorText, "%lu", err) \
vddk_err_msg = VixDiskLib_GetErrorText ((err), NULL); \
- } VDDK_CALL_END (VixDiskLib_GetErrorText); \
+ VDDK_CALL_END (VixDiskLib_GetErrorText, 0); \
nbdkit_error (fs ": %s", ##__VA_ARGS__, vddk_err_msg); \
- VDDK_CALL_START (VixDiskLib_FreeErrorText, "") { \
+ VDDK_CALL_START (VixDiskLib_FreeErrorText, "") \
VixDiskLib_FreeErrorText (vddk_err_msg); \
- } VDDK_CALL_END (VixDiskLib_FreeErrorText); \
+ VDDK_CALL_END (VixDiskLib_FreeErrorText, 0); \
} while (0)
/* Unload the plugin. */
@@ -175,9 +163,9 @@ static void
vddk_unload (void)
{
if (init_called) {
- VDDK_CALL_START (VixDiskLib_Exit, "") {
+ VDDK_CALL_START (VixDiskLib_Exit, "")
VixDiskLib_Exit ();
- } VDDK_CALL_END (VixDiskLib_Exit);
+ VDDK_CALL_END (VixDiskLib_Exit, 0);
}
if (dl)
dlclose (dl);
@@ -572,13 +560,13 @@ vddk_after_fork (void)
VDDK_CALL_START (VixDiskLib_InitEx,
"%d, %d, &debug_fn, &error_fn, &error_fn, %s, %s",
VDDK_MAJOR, VDDK_MINOR,
- libdir, config ? : "NULL") {
+ libdir, config ? : "NULL")
err = VixDiskLib_InitEx (VDDK_MAJOR, VDDK_MINOR,
&debug_function, /* log function */
&error_function, /* warn function */
&error_function, /* panic function */
libdir, config);
- } VDDK_CALL_END (VixDiskLib_InitEx);
+ VDDK_CALL_END (VixDiskLib_InitEx, 0);
if (err != VIX_OK) {
VDDK_ERROR (err, "VixDiskLib_InitEx");
exit (EXIT_FAILURE);
@@ -640,9 +628,9 @@ allocate_connect_params (void)
VixDiskLibConnectParams *ret;
if (VixDiskLib_AllocateConnectParams != NULL) {
- VDDK_CALL_START (VixDiskLib_AllocateConnectParams, "") {
+ VDDK_CALL_START (VixDiskLib_AllocateConnectParams, "")
ret = VixDiskLib_AllocateConnectParams ();
- } VDDK_CALL_END (VixDiskLib_AllocateConnectParams);
+ VDDK_CALL_END (VixDiskLib_AllocateConnectParams, 0);
}
else
ret = calloc (1, sizeof (VixDiskLibConnectParams));
@@ -657,9 +645,9 @@ free_connect_params (VixDiskLibConnectParams *params)
* originally called. Otherwise use free.
*/
if (VixDiskLib_AllocateConnectParams != NULL) {
- VDDK_CALL_START (VixDiskLib_FreeConnectParams, "params") {
+ VDDK_CALL_START (VixDiskLib_FreeConnectParams, "params")
VixDiskLib_FreeConnectParams (params);
- } VDDK_CALL_END (VixDiskLib_FreeConnectParams);
+ VDDK_CALL_END (VixDiskLib_FreeConnectParams, 0);
}
else
free (params);
@@ -716,13 +704,13 @@ vddk_open (int readonly)
"h->params, %d, %s, %s, &connection",
readonly,
snapshot_moref ? : "NULL",
- transport_modes ? : "NULL") {
+ transport_modes ? : "NULL")
err = VixDiskLib_ConnectEx (h->params,
readonly,
snapshot_moref,
transport_modes,
&h->connection);
- } VDDK_CALL_END (VixDiskLib_ConnectEx);
+ VDDK_CALL_END (VixDiskLib_ConnectEx, 0);
if (err != VIX_OK) {
VDDK_ERROR (err, "VixDiskLib_ConnectEx");
goto err1;
@@ -743,25 +731,25 @@ vddk_open (int readonly)
}
VDDK_CALL_START (VixDiskLib_Open,
- "connection, %s, %d, &handle", filename, flags) {
+ "connection, %s, %d, &handle", filename, flags)
err = VixDiskLib_Open (h->connection, filename, flags, &h->handle);
- } VDDK_CALL_END (VixDiskLib_Open);
+ VDDK_CALL_END (VixDiskLib_Open, 0);
if (err != VIX_OK) {
VDDK_ERROR (err, "VixDiskLib_Open: %s", filename);
goto err2;
}
- VDDK_CALL_START (VixDiskLib_GetTransportMode, "handle") {
+ VDDK_CALL_START (VixDiskLib_GetTransportMode, "handle")
transport_mode = VixDiskLib_GetTransportMode (h->handle);
- } VDDK_CALL_END (VixDiskLib_GetTransportMode);
+ VDDK_CALL_END (VixDiskLib_GetTransportMode, 0);
nbdkit_debug ("transport mode: %s", transport_mode);
return h;
err2:
- VDDK_CALL_START (VixDiskLib_Disconnect, "connection") {
+ VDDK_CALL_START (VixDiskLib_Disconnect, "connection")
VixDiskLib_Disconnect (h->connection);
- } VDDK_CALL_END (VixDiskLib_Disconnect);
+ VDDK_CALL_END (VixDiskLib_Disconnect, 0);
err1:
free_connect_params (h->params);
err0:
@@ -776,12 +764,12 @@ vddk_close (void *handle)
ACQUIRE_LOCK_FOR_CURRENT_SCOPE (&open_close_lock);
struct vddk_handle *h = handle;
- VDDK_CALL_START (VixDiskLib_Close, "handle") {
+ VDDK_CALL_START (VixDiskLib_Close, "handle")
VixDiskLib_Close (h->handle);
- } VDDK_CALL_END (VixDiskLib_Close);
- VDDK_CALL_START (VixDiskLib_Disconnect, "connection") {
+ VDDK_CALL_END (VixDiskLib_Close, 0);
+ VDDK_CALL_START (VixDiskLib_Disconnect, "connection")
VixDiskLib_Disconnect (h->connection);
- } VDDK_CALL_END (VixDiskLib_Disconnect);
+ VDDK_CALL_END (VixDiskLib_Disconnect, 0);
free_connect_params (h->params);
free (h);
@@ -796,9 +784,9 @@ vddk_get_size (void *handle)
VixError err;
uint64_t size;
- VDDK_CALL_START (VixDiskLib_GetInfo, "handle, &info") {
+ VDDK_CALL_START (VixDiskLib_GetInfo, "handle, &info")
err = VixDiskLib_GetInfo (h->handle, &info);
- } VDDK_CALL_END (VixDiskLib_GetInfo);
+ VDDK_CALL_END (VixDiskLib_GetInfo, 0);
if (err != VIX_OK) {
VDDK_ERROR (err, "VixDiskLib_GetInfo");
return -1;
@@ -827,9 +815,9 @@ vddk_get_size (void *handle)
info->uuid ? : "NULL");
}
- VDDK_CALL_START (VixDiskLib_FreeInfo, "info") {
+ VDDK_CALL_START (VixDiskLib_FreeInfo, "info")
VixDiskLib_FreeInfo (info);
- } VDDK_CALL_END (VixDiskLib_FreeInfo);
+ VDDK_CALL_END (VixDiskLib_FreeInfo, 0);
return (int64_t) size;
}
@@ -857,12 +845,12 @@ vddk_pread (void *handle, void *buf, uint32_t count, uint64_t offset,
offset /= VIXDISKLIB_SECTOR_SIZE;
count /= VIXDISKLIB_SECTOR_SIZE;
- VDDK_CALL_START_DATAPATH (VixDiskLib_Read,
- "handle, %" PRIu64 " sectors, "
- "%" PRIu32 " sectors, buffer",
- offset, count) {
+ VDDK_CALL_START (VixDiskLib_Read,
+ "handle, %" PRIu64 " sectors, "
+ "%" PRIu32 " sectors, buffer",
+ offset, count)
err = VixDiskLib_Read (h->handle, offset, count, buf);
- } VDDK_CALL_END_DATAPATH (VixDiskLib_Read, count * VIXDISKLIB_SECTOR_SIZE);
+ VDDK_CALL_END (VixDiskLib_Read, count * VIXDISKLIB_SECTOR_SIZE);
if (err != VIX_OK) {
VDDK_ERROR (err, "VixDiskLib_Read");
return -1;
@@ -897,12 +885,12 @@ vddk_pwrite (void *handle, const void *buf, uint32_t count, uint64_t offset,
offset /= VIXDISKLIB_SECTOR_SIZE;
count /= VIXDISKLIB_SECTOR_SIZE;
- VDDK_CALL_START_DATAPATH (VixDiskLib_Write,
- "handle, %" PRIu64 " sectors, "
- "%" PRIu32 " sectors, buffer",
- offset, count) {
+ VDDK_CALL_START (VixDiskLib_Write,
+ "handle, %" PRIu64 " sectors, "
+ "%" PRIu32 " sectors, buffer",
+ offset, count)
err = VixDiskLib_Write (h->handle, offset, count, buf);
- } VDDK_CALL_END_DATAPATH (VixDiskLib_Write, count * VIXDISKLIB_SECTOR_SIZE);
+ VDDK_CALL_END (VixDiskLib_Write, count * VIXDISKLIB_SECTOR_SIZE);
if (err != VIX_OK) {
VDDK_ERROR (err, "VixDiskLib_Write");
return -1;
@@ -945,9 +933,9 @@ vddk_flush (void *handle, uint32_t flags)
* file so it appears to be the correct call to use here.
*/
- VDDK_CALL_START (VixDiskLib_Flush, "handle") {
+ VDDK_CALL_START (VixDiskLib_Flush, "handle")
err = VixDiskLib_Flush (h->handle);
- } VDDK_CALL_END (VixDiskLib_Flush);
+ VDDK_CALL_END (VixDiskLib_Flush, 0);
if (err != VIX_OK) {
VDDK_ERROR (err, "VixDiskLib_Flush");
return -1;
@@ -983,17 +971,17 @@ vddk_can_extents (void *handle)
*/
VDDK_CALL_START (VixDiskLib_QueryAllocatedBlocks,
"handle, 0, %d sectors, %d sectors",
- VIXDISKLIB_MIN_CHUNK_SIZE, VIXDISKLIB_MIN_CHUNK_SIZE) {
+ VIXDISKLIB_MIN_CHUNK_SIZE, VIXDISKLIB_MIN_CHUNK_SIZE)
err = VixDiskLib_QueryAllocatedBlocks (h->handle,
0, VIXDISKLIB_MIN_CHUNK_SIZE,
VIXDISKLIB_MIN_CHUNK_SIZE,
&block_list);
- } VDDK_CALL_END (VixDiskLib_QueryAllocatedBlocks);
+ VDDK_CALL_END (VixDiskLib_QueryAllocatedBlocks, 0);
error_suppression = 0;
if (err == VIX_OK) {
- VDDK_CALL_START (VixDiskLib_FreeBlockList, "block_list") {
+ VDDK_CALL_START (VixDiskLib_FreeBlockList, "block_list")
VixDiskLib_FreeBlockList (block_list);
- } VDDK_CALL_END (VixDiskLib_FreeBlockList);
+ VDDK_CALL_END (VixDiskLib_FreeBlockList, 0);
}
if (err != VIX_OK) {
char *errmsg = VixDiskLib_GetErrorText (err, NULL);
@@ -1073,12 +1061,12 @@ vddk_extents (void *handle, uint32_t count, uint64_t offset, uint32_t flags,
VDDK_CALL_START (VixDiskLib_QueryAllocatedBlocks,
"handle, %" PRIu64 " sectors, %" PRIu64 " sectors, "
"%d sectors",
- start_sector, nr_sectors, VIXDISKLIB_MIN_CHUNK_SIZE) {
+ start_sector, nr_sectors, VIXDISKLIB_MIN_CHUNK_SIZE)
err = VixDiskLib_QueryAllocatedBlocks (h->handle,
start_sector, nr_sectors,
VIXDISKLIB_MIN_CHUNK_SIZE,
&block_list);
- } VDDK_CALL_END (VixDiskLib_QueryAllocatedBlocks);
+ VDDK_CALL_END (VixDiskLib_QueryAllocatedBlocks, 0);
if (err != VIX_OK) {
VDDK_ERROR (err, "VixDiskLib_QueryAllocatedBlocks");
return -1;
@@ -1097,15 +1085,15 @@ vddk_extents (void *handle, uint32_t count, uint64_t offset, uint32_t flags,
add_extent (extents, &position, blk_offset, true) == -1) ||
(add_extent (extents,
&position, blk_offset + blk_length, false) == -1)) {
- VDDK_CALL_START (VixDiskLib_FreeBlockList, "block_list") {
+ VDDK_CALL_START (VixDiskLib_FreeBlockList, "block_list")
VixDiskLib_FreeBlockList (block_list);
- } VDDK_CALL_END (VixDiskLib_FreeBlockList);
+ VDDK_CALL_END (VixDiskLib_FreeBlockList, 0);
return -1;
}
}
- VDDK_CALL_START (VixDiskLib_FreeBlockList, "block_list") {
+ VDDK_CALL_START (VixDiskLib_FreeBlockList, "block_list")
VixDiskLib_FreeBlockList (block_list);
- } VDDK_CALL_END (VixDiskLib_FreeBlockList);
+ VDDK_CALL_END (VixDiskLib_FreeBlockList, 0);
/* There's an implicit hole after the returned list of blocks, up
* to the end of the QueryAllocatedBlocks request.
--
2.31.1

View File

@ -0,0 +1,84 @@
From 8353ab55b8c6e7f1dc9ea27260fd7ec90b9d75af Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Fri, 22 Oct 2021 18:00:27 +0100
Subject: [PATCH] vddk: Document troubleshooting performance problems
Document how to use -D vddk.stats=1 to diagnose performance problems
with VDDK.
(cherry picked from commit e491978c193f49010cc28ad344d0fb3c1b5ede35)
---
plugins/vddk/nbdkit-vddk-plugin.pod | 57 +++++++++++++++++++++++++++++
1 file changed, 57 insertions(+)
diff --git a/plugins/vddk/nbdkit-vddk-plugin.pod b/plugins/vddk/nbdkit-vddk-plugin.pod
index e53d3286..5a426135 100644
--- a/plugins/vddk/nbdkit-vddk-plugin.pod
+++ b/plugins/vddk/nbdkit-vddk-plugin.pod
@@ -475,6 +475,63 @@ and restarting the C<hostd> service:
For more information see L<https://bugzilla.redhat.com/1614276>.
+=head2 Troubleshooting performance problems
+
+VDDK has very uneven performance with some operations being very slow.
+This plugin has options to allow you to debug performance issues. If
+your application has a debug or diagnostic setting, add the following
+nbdkit command line options:
+
+ -v -D nbdkit.backend.datapath=0 -D vddk.datapath=0 -D vddk.stats=1
+
+C<-v> enables verbose messages and the two datapath options I<disable>
+the very verbose per-read/-write messages. C<-D vddk.stats=1> enables
+a summary when nbdkit exits of the cumulative time taken in each VDDK
+function, the number of times each function was called, and (for read
+and write) the number of bytes transferred. An example of what those
+stats look like can be found here:
+L<https://gitlab.com/nbdkit/nbdkit/-/commit/5c80f0d290db45a679d55baf37ff39bacb8ce7ec>
+
+You can interpret the stats as follows:
+
+=over 4
+
+=item C<Read>
+
+The cumulative time spent waiting for VDDK to return from
+C<VixDiskLib_Read> calls, the number of times this function was
+called, and the total bytes read. You can use this to determine the
+read bandwidth to the VMware server.
+
+=item C<Write>
+
+=item C<Flush>
+
+Same as above, but for writing and flushing writes.
+
+=item C<QueryAllocatedBlocks>
+
+This call is used to query information about the sparseness of the
+remote disk. It is only available in VDDK E<ge> 6.7. The call is
+notably very slow in all versions of VMware we have tested.
+
+=item C<Open>
+
+=item C<Close>
+
+=item C<ConnectEx>
+
+=item C<Disconnect>
+
+=item C<InitEx>
+
+=item C<Exit>
+
+The cumulative time spent connecting and disconnecting from the VMware
+server, which can also be very slow.
+
+=back
+
=head1 SUPPORTED VERSIONS OF VDDK
This plugin requires VDDK E<ge> 5.5.5, which in turn means that it
--
2.31.1

View File

@ -0,0 +1,141 @@
From d994773724266dd5f0a8b4282cc604f6b75e077c Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Sat, 23 Oct 2021 16:16:39 +0100
Subject: [PATCH] vddk: Include VDDK major library version in --dump-plugin
output
Although it doesn't seem to be possible to get the precise VDDK
version, With a relatively simple change we can at least return the
VDDK major version. Currently this can be 5, 6 or 7.
(cherry picked from commit 8700649d147948897f3b97810a1dff37924bdd6e)
---
plugins/vddk/nbdkit-vddk-plugin.pod | 4 ++++
plugins/vddk/vddk.c | 29 +++++++++++++++++++----------
tests/test-vddk-real-dump-plugin.sh | 2 ++
3 files changed, 25 insertions(+), 10 deletions(-)
diff --git a/plugins/vddk/nbdkit-vddk-plugin.pod b/plugins/vddk/nbdkit-vddk-plugin.pod
index 5a426135..bc3c3c94 100644
--- a/plugins/vddk/nbdkit-vddk-plugin.pod
+++ b/plugins/vddk/nbdkit-vddk-plugin.pod
@@ -422,6 +422,10 @@ at runtime.
If this is printed then the C<nfchostport=PORT> parameter is supported
by this build.
+=item C<vddk_library_version=...>
+
+The VDDK major library version: 5, 6, 7, ...
+
=item C<vddk_dll=...>
Prints the full path to the VDDK shared library. Since this requires
diff --git a/plugins/vddk/vddk.c b/plugins/vddk/vddk.c
index 993f2d76..d74a484d 100644
--- a/plugins/vddk/vddk.c
+++ b/plugins/vddk/vddk.c
@@ -81,6 +81,7 @@ NBDKIT_DLL_PUBLIC int vddk_debug_stats;
static void *dl; /* dlopen handle */
static bool init_called; /* was InitEx called */
static __thread int error_suppression; /* threadlocal error suppression */
+static int library_version; /* VDDK major: 5, 6, 7, ... */
static enum { NONE = 0, ZLIB, FASTLZ, SKIPZ } compression; /* compression */
static char *config; /* config */
@@ -405,7 +406,10 @@ vddk_config (const char *key, const char *value)
static void
load_library (bool load_error_is_fatal)
{
- static const char *sonames[] = {
+ static struct {
+ const char *soname;
+ int library_version;
+ } libs[] = {
/* Prefer the newest library in case multiple exist. Check two
* possible directories: the usual VDDK installation puts .so
* files in an arch-specific subdirectory of $libdir (our minimum
@@ -413,12 +417,13 @@ load_library (bool load_error_is_fatal)
* but our testsuite is easier to write if we point libdir
* directly to a stub .so.
*/
- "lib64/libvixDiskLib.so.7",
- "libvixDiskLib.so.7",
- "lib64/libvixDiskLib.so.6",
- "libvixDiskLib.so.6",
- "lib64/libvixDiskLib.so.5",
- "libvixDiskLib.so.5",
+ { "lib64/libvixDiskLib.so.7", 7 },
+ { "libvixDiskLib.so.7", 7 },
+ { "lib64/libvixDiskLib.so.6", 6 },
+ { "libvixDiskLib.so.6", 6 },
+ { "lib64/libvixDiskLib.so.5", 5 },
+ { "libvixDiskLib.so.5", 5 },
+ { NULL }
};
size_t i;
CLEANUP_FREE char *orig_error = NULL;
@@ -431,19 +436,20 @@ load_library (bool load_error_is_fatal)
}
}
- for (i = 0; i < sizeof sonames / sizeof sonames[0]; ++i) {
+ for (i = 0; libs[i].soname != NULL; ++i) {
CLEANUP_FREE char *path;
/* Set the full path so that dlopen will preferentially load the
* system libraries from the same directory.
*/
- if (asprintf (&path, "%s/%s", libdir, sonames[i]) == -1) {
+ if (asprintf (&path, "%s/%s", libdir, libs[i].soname) == -1) {
nbdkit_error ("asprintf: %m");
exit (EXIT_FAILURE);
}
dl = dlopen (path, RTLD_NOW);
if (dl != NULL) {
+ library_version = libs[i].library_version;
/* Now that we found the library, ensure that LD_LIBRARY_PATH
* includes its directory for all future loads. This may modify
* path in-place and/or re-exec nbdkit, but that's okay.
@@ -464,10 +470,12 @@ load_library (bool load_error_is_fatal)
"If '%s' is located on a non-standard path you may need to\n"
"set libdir=/path/to/vmware-vix-disklib-distrib.\n\n"
"See nbdkit-vddk-plugin(1) man page section \"LIBRARY LOCATION\" for details.",
- orig_error ? : "(unknown error)", sonames[0]);
+ orig_error ? : "(unknown error)", libs[0].soname);
exit (EXIT_FAILURE);
}
+ assert (library_version >= 5);
+
/* Load symbols. */
#define STUB(fn,ret,args) \
do { \
@@ -583,6 +591,7 @@ vddk_dump_plugin (void)
printf ("vddk_default_libdir=%s\n", VDDK_LIBDIR);
printf ("vddk_has_nfchostport=1\n");
+ printf ("vddk_library_version=%d\n", library_version);
#if defined(HAVE_DLADDR)
/* It would be nice to print the version of VDDK from the shared
diff --git a/tests/test-vddk-real-dump-plugin.sh b/tests/test-vddk-real-dump-plugin.sh
index 2cb7724e..0a079c6c 100755
--- a/tests/test-vddk-real-dump-plugin.sh
+++ b/tests/test-vddk-real-dump-plugin.sh
@@ -58,10 +58,12 @@ rm -f $files
cleanup_fn rm -f $files
nbdkit -f -v vddk libdir="$vddkdir" --dump-plugin > $out
+cat $out
# Check the vddk_* entries are set.
grep ^vddk_default_libdir= $out
grep ^vddk_has_nfchostport= $out
+grep ^vddk_library_version= $out
grep ^vddk_dll= $out
dll="$(grep ^vddk_dll $out | cut -d= -f2)"
--
2.31.1

View File

@ -0,0 +1,52 @@
From 4c80b474a2c2a552e5bdfcaabfa2981540afe8d8 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Sat, 23 Oct 2021 16:24:27 +0100
Subject: [PATCH] vddk: Add logical and physical sector size to -D
vddk.diskinfo output
In VDDK >= 7 it is possible to display the logical and physical sector
size in debug output.
This commit also extends the test since this flag was not tested
before.
(cherry picked from commit 5bb8f0586e1faabcbf4f43d722a3b3cb5b352e33)
---
plugins/vddk/vddk.c | 6 ++++++
tests/test-vddk-real.sh | 3 ++-
2 files changed, 8 insertions(+), 1 deletion(-)
diff --git a/plugins/vddk/vddk.c b/plugins/vddk/vddk.c
index d74a484d..50bdde26 100644
--- a/plugins/vddk/vddk.c
+++ b/plugins/vddk/vddk.c
@@ -822,6 +822,12 @@ vddk_get_size (void *handle)
info->parentFileNameHint ? : "NULL");
nbdkit_debug ("disk info: uuid: %s",
info->uuid ? : "NULL");
+ if (library_version >= 7) {
+ nbdkit_debug ("disk info: sectory size: "
+ "logical %" PRIu32 " physical %" PRIu32,
+ info->logicalSectorSize,
+ info->physicalSectorSize);
+ }
}
VDDK_CALL_START (VixDiskLib_FreeInfo, "info")
diff --git a/tests/test-vddk-real.sh b/tests/test-vddk-real.sh
index a6aceac9..ae965245 100755
--- a/tests/test-vddk-real.sh
+++ b/tests/test-vddk-real.sh
@@ -89,7 +89,8 @@ if grep 'cannot open shared object file' $log; then
fi
# Now run nbdkit for the test.
-start_nbdkit -P $pid -U $sock -D vddk.stats=1 vddk libdir="$vddkdir" $vmdk
+start_nbdkit -P $pid -U $sock -D vddk.stats=1 -D vddk.diskinfo=1 \
+ vddk libdir="$vddkdir" $vmdk
uri="nbd+unix:///?socket=$sock"
# VDDK < 6.0 did not support flush, so disable flush test there. Also
--
2.31.1

View File

@ -0,0 +1,27 @@
From 4b0d278f3851baf37affa26d34e52963dc8c7c04 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Sat, 23 Oct 2021 19:41:07 +0100
Subject: [PATCH] vddk: Fix typo in debug message
Fixes: commit 5bb8f0586e1faabcbf4f43d722a3b3cb5b352e33
(cherry picked from commit 343dadeb7340d7b8c5730e2bbab33c829b569122)
---
plugins/vddk/vddk.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/plugins/vddk/vddk.c b/plugins/vddk/vddk.c
index 50bdde26..65399a91 100644
--- a/plugins/vddk/vddk.c
+++ b/plugins/vddk/vddk.c
@@ -823,7 +823,7 @@ vddk_get_size (void *handle)
nbdkit_debug ("disk info: uuid: %s",
info->uuid ? : "NULL");
if (library_version >= 7) {
- nbdkit_debug ("disk info: sectory size: "
+ nbdkit_debug ("disk info: sector size: "
"logical %" PRIu32 " physical %" PRIu32,
info->logicalSectorSize,
info->physicalSectorSize);
--
2.31.1

View File

@ -0,0 +1,55 @@
From 670c1ddb6591046256511a680605c5e2349746e8 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Sat, 23 Oct 2021 19:50:52 +0100
Subject: [PATCH] vddk: Only print vddk_library_version when we managed to load
the library
Because --dump-plugin calls load_library (false) it won't fail if we
didn't manage to load the library. This results in library_version
being 0, which we printed incorrectly.
Resolve this problem by not printing the vddk_library_version entry in
this case.
Fixes: commit 8700649d147948897f3b97810a1dff37924bdd6e
(cherry picked from commit a3fba12c3e9c2113009f556360ae0bd04c45f6bb)
---
plugins/vddk/nbdkit-vddk-plugin.pod | 1 +
plugins/vddk/vddk.c | 9 ++++++++-
2 files changed, 9 insertions(+), 1 deletion(-)
diff --git a/plugins/vddk/nbdkit-vddk-plugin.pod b/plugins/vddk/nbdkit-vddk-plugin.pod
index bc3c3c94..49e3d75d 100644
--- a/plugins/vddk/nbdkit-vddk-plugin.pod
+++ b/plugins/vddk/nbdkit-vddk-plugin.pod
@@ -425,6 +425,7 @@ by this build.
=item C<vddk_library_version=...>
The VDDK major library version: 5, 6, 7, ...
+If this is omitted it means the library could not be loaded.
=item C<vddk_dll=...>
diff --git a/plugins/vddk/vddk.c b/plugins/vddk/vddk.c
index 65399a91..39a7d261 100644
--- a/plugins/vddk/vddk.c
+++ b/plugins/vddk/vddk.c
@@ -591,7 +591,14 @@ vddk_dump_plugin (void)
printf ("vddk_default_libdir=%s\n", VDDK_LIBDIR);
printf ("vddk_has_nfchostport=1\n");
- printf ("vddk_library_version=%d\n", library_version);
+
+ /* Because load_library (false) we might not have loaded VDDK, in
+ * which case we didn't set library_version. Note this cannot
+ * happen in the normal (non-debug-plugin) path because there we use
+ * load_library (true).
+ */
+ if (library_version > 0)
+ printf ("vddk_library_version=%d\n", library_version);
#if defined(HAVE_DLADDR)
/* It would be nice to print the version of VDDK from the shared
--
2.31.1

View File

@ -0,0 +1,72 @@
From 21d6c2f8f29f0d7f98852b72ee33751814be49fe Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Mon, 25 Oct 2021 08:36:53 +0100
Subject: [PATCH] vddk: Print one line in --dump-plugin output for each VDDK
API
Helps when detecting if certain optional features are being used, such
as flush and extents.
(cherry picked from commit 4ee13559e46cf622410d0bdd7db29bb00908b40a)
---
plugins/vddk/nbdkit-vddk-plugin.pod | 9 +++++++++
plugins/vddk/vddk.c | 10 ++++++++++
tests/test-vddk-real-dump-plugin.sh | 1 +
3 files changed, 20 insertions(+)
diff --git a/plugins/vddk/nbdkit-vddk-plugin.pod b/plugins/vddk/nbdkit-vddk-plugin.pod
index 49e3d75d..0702aa75 100644
--- a/plugins/vddk/nbdkit-vddk-plugin.pod
+++ b/plugins/vddk/nbdkit-vddk-plugin.pod
@@ -432,6 +432,15 @@ If this is omitted it means the library could not be loaded.
Prints the full path to the VDDK shared library. Since this requires
a glibc extension it may not be available in all builds of the plugin.
+=item C<VixDiskLib_...=1>
+
+For each VDDK API that the plugin uses I<and> which is present in the
+VDDK library that was loaded, we print the name of the API
+(eg. C<VixDiskLib_Open=1>). This lets you see which optional APIs are
+available, such as C<VixDiskLib_Flush> and
+C<VixDiskLib_QueryAllocatedBlocks>. If the library could not be
+loaded then these lines are not printed.
+
=back
=head1 NOTES
diff --git a/plugins/vddk/vddk.c b/plugins/vddk/vddk.c
index 39a7d261..096b04bf 100644
--- a/plugins/vddk/vddk.c
+++ b/plugins/vddk/vddk.c
@@ -616,6 +616,16 @@ vddk_dump_plugin (void)
printf ("vddk_dll=%s\n", p);
}
#endif
+
+ /* Note we print all VDDK APIs found here, not just the optional
+ * ones. That is so if we update the baseline VDDK in future and
+ * make optional into required APIs, the output doesn't change.
+ */
+#define STUB(fn,ret,args) if (fn != NULL) printf ("%s=1\n", #fn);
+#define OPTIONAL_STUB(fn,ret,args) STUB(fn,ret,args)
+#include "vddk-stubs.h"
+#undef STUB
+#undef OPTIONAL_STUB
}
/* The rules on threads and VDDK are here:
diff --git a/tests/test-vddk-real-dump-plugin.sh b/tests/test-vddk-real-dump-plugin.sh
index 0a079c6c..e37c8b54 100755
--- a/tests/test-vddk-real-dump-plugin.sh
+++ b/tests/test-vddk-real-dump-plugin.sh
@@ -65,6 +65,7 @@ grep ^vddk_default_libdir= $out
grep ^vddk_has_nfchostport= $out
grep ^vddk_library_version= $out
grep ^vddk_dll= $out
+grep ^VixDiskLib_Open=1 $out
dll="$(grep ^vddk_dll $out | cut -d= -f2)"
test -f "$dll"
--
2.31.1

View File

@ -0,0 +1,147 @@
From f4379f04ea27e25c00e98db2e60d0fdb647442e9 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Tue, 26 Oct 2021 19:46:32 +0100
Subject: [PATCH] vddk: Move minimum version to VDDK 6.5
Drop support for VDDK 5.5.5 (released in 2015) and 6.0 (released the
same year). Move minimum supported version to 6.5 (released Nov
2016). This is so we can use asynchronous operations.
Acked-by: Laszlo Ersek <lersek@redhat.com>
(cherry picked from commit 5ed23616762a72e039531a9a7cd81353cd4f436e)
---
plugins/vddk/nbdkit-vddk-plugin.pod | 10 +++-------
plugins/vddk/vddk-stubs.h | 3 +--
plugins/vddk/vddk.c | 24 ++++++++++++++++--------
tests/dummy-vddk.c | 6 ++++++
4 files changed, 26 insertions(+), 17 deletions(-)
diff --git a/plugins/vddk/nbdkit-vddk-plugin.pod b/plugins/vddk/nbdkit-vddk-plugin.pod
index 0702aa75..1c16d096 100644
--- a/plugins/vddk/nbdkit-vddk-plugin.pod
+++ b/plugins/vddk/nbdkit-vddk-plugin.pod
@@ -424,7 +424,7 @@ by this build.
=item C<vddk_library_version=...>
-The VDDK major library version: 5, 6, 7, ...
+The VDDK major library version: 6, 7, ...
If this is omitted it means the library could not be loaded.
=item C<vddk_dll=...>
@@ -548,16 +548,12 @@ server, which can also be very slow.
=head1 SUPPORTED VERSIONS OF VDDK
-This plugin requires VDDK E<ge> 5.5.5, which in turn means that it
-is only supported on x64-64 platforms.
+This plugin requires VDDK E<ge> 6.5 (released Nov 2016). It is only
+supported on the x64-64 archtecture.
It has been tested with all versions up to 7.0.3 (but should work with
future versions).
-VDDK E<ge> 6.0 should be used if possible. This is the first version
-which added Flush support which is crucial for data integrity when
-writing.
-
VDDK 6.7 was the first version that supported the
C<VixDiskLib_QueryAllocatedBlocks> API, required to provide extent
information over NBD.
diff --git a/plugins/vddk/vddk-stubs.h b/plugins/vddk/vddk-stubs.h
index 5e70238d..a94df9cd 100644
--- a/plugins/vddk/vddk-stubs.h
+++ b/plugins/vddk/vddk-stubs.h
@@ -40,8 +40,7 @@
*/
/* Required stubs, present in all versions of VDDK that we support. I
- * have checked that all these exist in at least VDDK 5.5.5 (2015)
- * which is the earliest version of VDDK that we support.
+ * have checked that all these exist in at least VDDK 5.5.5 (2015).
*/
STUB (VixDiskLib_InitEx,
diff --git a/plugins/vddk/vddk.c b/plugins/vddk/vddk.c
index 096b04bf..babffc28 100644
--- a/plugins/vddk/vddk.c
+++ b/plugins/vddk/vddk.c
@@ -75,13 +75,13 @@ NBDKIT_DLL_PUBLIC int vddk_debug_stats;
#undef OPTIONAL_STUB
/* Parameters passed to InitEx. */
-#define VDDK_MAJOR 5
+#define VDDK_MAJOR 6
#define VDDK_MINOR 5
static void *dl; /* dlopen handle */
static bool init_called; /* was InitEx called */
static __thread int error_suppression; /* threadlocal error suppression */
-static int library_version; /* VDDK major: 5, 6, 7, ... */
+static int library_version; /* VDDK major: 6, 7, ... */
static enum { NONE = 0, ZLIB, FASTLZ, SKIPZ } compression; /* compression */
static char *config; /* config */
@@ -413,16 +413,14 @@ load_library (bool load_error_is_fatal)
/* Prefer the newest library in case multiple exist. Check two
* possible directories: the usual VDDK installation puts .so
* files in an arch-specific subdirectory of $libdir (our minimum
- * supported version is VDDK 5.5.5, which only supports x64-64);
- * but our testsuite is easier to write if we point libdir
- * directly to a stub .so.
+ * supported version is VDDK 6.5, which only supports x64-64); but
+ * our testsuite is easier to write if we point libdir directly to
+ * a stub .so.
*/
{ "lib64/libvixDiskLib.so.7", 7 },
{ "libvixDiskLib.so.7", 7 },
{ "lib64/libvixDiskLib.so.6", 6 },
{ "libvixDiskLib.so.6", 6 },
- { "lib64/libvixDiskLib.so.5", 5 },
- { "libvixDiskLib.so.5", 5 },
{ NULL }
};
size_t i;
@@ -474,7 +472,7 @@ load_library (bool load_error_is_fatal)
exit (EXIT_FAILURE);
}
- assert (library_version >= 5);
+ assert (library_version >= 6);
/* Load symbols. */
#define STUB(fn,ret,args) \
@@ -490,6 +488,16 @@ load_library (bool load_error_is_fatal)
#include "vddk-stubs.h"
#undef STUB
#undef OPTIONAL_STUB
+
+ /* Additionally, VDDK version must be >= 6.5. This was the first
+ * version which introduced VixDiskLib_Wait symbol so we can check
+ * for that.
+ */
+ if (VixDiskLib_Wait == NULL) {
+ nbdkit_error ("VDDK version must be >= 6.5. "
+ "See nbdkit-vddk-plugin(1) man page section \"SUPPORTED VERSIONS OF VDDK\".");
+ exit (EXIT_FAILURE);
+ }
}
static int
diff --git a/tests/dummy-vddk.c b/tests/dummy-vddk.c
index 9b5ae0a2..cb88380c 100644
--- a/tests/dummy-vddk.c
+++ b/tests/dummy-vddk.c
@@ -198,3 +198,9 @@ VixDiskLib_Write (VixDiskLibHandle handle,
memcpy (disk + offset, buf, nr_sectors * VIXDISKLIB_SECTOR_SIZE);
return VIX_OK;
}
+
+NBDKIT_DLL_PUBLIC VixError
+VixDiskLib_Wait (VixDiskLibHandle handle)
+{
+ return VIX_OK;
+}
--
2.31.1

View File

@ -0,0 +1,72 @@
From 90dc3311582784f8b078a30a7207c15c6298b1e2 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Wed, 27 Oct 2021 11:57:35 +0100
Subject: [PATCH] vddk: Add read, write and wait asynchronous functions
These functions added in VDDK 6.0 - 6.5 implement asynchronous read
and write.
Acked-by: Laszlo Ersek <lersek@redhat.com>
(cherry picked from commit ad53e7becafed6ca3573795a79c534281fe9c274)
---
plugins/vddk/vddk-structs.h | 3 +++
plugins/vddk/vddk-stubs.h | 19 ++++++++++++++++++-
2 files changed, 21 insertions(+), 1 deletion(-)
diff --git a/plugins/vddk/vddk-structs.h b/plugins/vddk/vddk-structs.h
index aeb5bfd0..e97f017c 100644
--- a/plugins/vddk/vddk-structs.h
+++ b/plugins/vddk/vddk-structs.h
@@ -43,6 +43,7 @@
typedef uint64_t VixError;
#define VIX_OK 0
+#define VIX_ASYNC 25000
#define VIXDISKLIB_FLAG_OPEN_UNBUFFERED 1
#define VIXDISKLIB_FLAG_OPEN_SINGLE_LINK 2
@@ -61,6 +62,8 @@ typedef void *VixDiskLibHandle;
typedef void VixDiskLibGenericLogFunc (const char *fmt, va_list args);
+typedef void (*VixDiskLibCompletionCB) (void *data, VixError result);
+
enum VixDiskLibCredType {
VIXDISKLIB_CRED_UID = 1,
VIXDISKLIB_CRED_SESSIONID = 2,
diff --git a/plugins/vddk/vddk-stubs.h b/plugins/vddk/vddk-stubs.h
index a94df9cd..66353691 100644
--- a/plugins/vddk/vddk-stubs.h
+++ b/plugins/vddk/vddk-stubs.h
@@ -103,10 +103,27 @@ STUB (VixDiskLib_Write,
uint64_t start_sector, uint64_t nr_sectors,
const unsigned char *buf));
-/* Added in VDDK 6.0, this will be NULL in earlier versions. */
+/* Added in VDDK 6.0, these will be NULL in earlier versions. */
OPTIONAL_STUB (VixDiskLib_Flush,
VixError,
(VixDiskLibHandle handle));
+OPTIONAL_STUB (VixDiskLib_ReadAsync,
+ VixError,
+ (VixDiskLibHandle handle,
+ uint64_t start_sector, uint64_t nr_sectors,
+ unsigned char *buf,
+ VixDiskLibCompletionCB callback, void *data));
+OPTIONAL_STUB (VixDiskLib_WriteAsync,
+ VixError,
+ (VixDiskLibHandle handle,
+ uint64_t start_sector, uint64_t nr_sectors,
+ const unsigned char *buf,
+ VixDiskLibCompletionCB callback, void *data));
+
+/* Added in VDDK 6.5, this will be NULL in earlier versions. */
+OPTIONAL_STUB (VixDiskLib_Wait,
+ VixError,
+ (VixDiskLibHandle handle));
/* Added in VDDK 6.7, these will be NULL for earlier versions: */
OPTIONAL_STUB (VixDiskLib_QueryAllocatedBlocks,
--
2.31.1

View File

@ -0,0 +1,259 @@
From c9e432e08e889d9e6edea52344b2452f0141f56b Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Wed, 27 Oct 2021 12:20:31 +0100
Subject: [PATCH] vddk: Start to split VDDK over several files
This change doesn't do anything except move some definitions into the
header file vddk.h, but it allows future commits to split up the very
large vddk.c file.
Acked-by: Laszlo Ersek <lersek@redhat.com>
(cherry picked from commit 117634dccf4e29394e8718a8d62e93a9edf0a39c)
---
plugins/vddk/vddk.c | 91 +++++++++++++--------------------------------
plugins/vddk/vddk.h | 89 +++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 112 insertions(+), 68 deletions(-)
diff --git a/plugins/vddk/vddk.c b/plugins/vddk/vddk.c
index babffc28..041bff1a 100644
--- a/plugins/vddk/vddk.c
+++ b/plugins/vddk/vddk.c
@@ -50,14 +50,12 @@
#include <nbdkit-plugin.h>
#include "cleanup.h"
-#include "isaligned.h"
#include "minmax.h"
#include "rounding.h"
#include "tvdiff.h"
#include "vector.h"
#include "vddk.h"
-#include "vddk-structs.h"
/* Debug flags. */
NBDKIT_DLL_PUBLIC int vddk_debug_diskinfo;
@@ -65,11 +63,11 @@ NBDKIT_DLL_PUBLIC int vddk_debug_extents;
NBDKIT_DLL_PUBLIC int vddk_debug_datapath = 1;
NBDKIT_DLL_PUBLIC int vddk_debug_stats;
-/* For each VDDK API define a static global variable. These globals
- * are initialized when the plugin is loaded (by vddk_get_ready).
+/* For each VDDK API define a global variable. These globals are
+ * initialized when the plugin is loaded (by vddk_get_ready).
*/
-#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
@@ -78,28 +76,28 @@ NBDKIT_DLL_PUBLIC int vddk_debug_stats;
#define VDDK_MAJOR 6
#define VDDK_MINOR 5
-static void *dl; /* dlopen handle */
-static bool init_called; /* was InitEx called */
-static __thread int error_suppression; /* threadlocal error suppression */
-static int library_version; /* VDDK major: 6, 7, ... */
+void *dl; /* dlopen handle */
+bool init_called; /* was InitEx called */
+__thread int error_suppression; /* threadlocal error suppression */
+int library_version; /* VDDK major: 6, 7, ... */
+bool is_remote; /* true if remote connection */
-static enum { NONE = 0, ZLIB, FASTLZ, SKIPZ } compression; /* compression */
-static char *config; /* config */
-static const char *cookie; /* cookie */
-static const char *filename; /* file */
-char *libdir; /* libdir */
-static uint16_t nfc_host_port; /* nfchostport */
-char *password; /* password */
-static uint16_t port; /* port */
-static const char *server_name; /* server */
-static bool single_link; /* single-link */
-static const char *snapshot_moref; /* snapshot */
-static const char *thumb_print; /* thumbprint */
-static const char *transport_modes; /* transports */
-static bool unbuffered; /* unbuffered */
-static const char *username; /* user */
-static const char *vmx_spec; /* vm */
-static bool is_remote;
+enum compression_type compression; /* compression */
+char *config; /* config */
+const char *cookie; /* cookie */
+const char *filename; /* file */
+char *libdir; /* libdir */
+uint16_t nfc_host_port; /* nfchostport */
+char *password; /* password */
+uint16_t port; /* port */
+const char *server_name; /* server */
+bool single_link; /* single-link */
+const char *snapshot_moref; /* snapshot */
+const char *thumb_print; /* thumbprint */
+const char *transport_modes; /* transports */
+bool unbuffered; /* unbuffered */
+const char *username; /* user */
+const char *vmx_spec; /* vm */
/* For each VDDK API define a variable to store the time taken (used
* to implement -D vddk.stats=1).
@@ -120,45 +118,6 @@ static void display_stats (void);
#undef STUB
#undef OPTIONAL_STUB
-/* Macros to bracket each VDDK API call, for printing debugging
- * information and collecting statistics.
- */
-#define VDDK_CALL_START(fn, fs, ...) \
- do { \
- struct timeval start_t, end_t; \
- /* GCC can optimize this away at compile time: */ \
- const bool datapath = \
- strcmp (#fn, "VixDiskLib_Read") == 0 || \
- strcmp (#fn, "VixDiskLib_Write") == 0; \
- if (vddk_debug_stats) \
- gettimeofday (&start_t, NULL); \
- if (!datapath || vddk_debug_datapath) \
- nbdkit_debug ("VDDK call: %s (" fs ")", #fn, ##__VA_ARGS__); \
- do
-#define VDDK_CALL_END(fn, bytes_) \
- while (0); \
- if (vddk_debug_stats) { \
- gettimeofday (&end_t, NULL); \
- ACQUIRE_LOCK_FOR_CURRENT_SCOPE (&stats_lock); \
- stats_##fn.usecs += tvdiff_usec (&start_t, &end_t); \
- stats_##fn.calls++; \
- stats_##fn.bytes += bytes_; \
- } \
- } while (0)
-
-/* Print VDDK errors. */
-#define VDDK_ERROR(err, fs, ...) \
- do { \
- char *vddk_err_msg; \
- VDDK_CALL_START (VixDiskLib_GetErrorText, "%lu", err) \
- vddk_err_msg = VixDiskLib_GetErrorText ((err), NULL); \
- VDDK_CALL_END (VixDiskLib_GetErrorText, 0); \
- nbdkit_error (fs ": %s", ##__VA_ARGS__, vddk_err_msg); \
- VDDK_CALL_START (VixDiskLib_FreeErrorText, "") \
- VixDiskLib_FreeErrorText (vddk_err_msg); \
- VDDK_CALL_END (VixDiskLib_FreeErrorText, 0); \
- } while (0)
-
/* Unload the plugin. */
static void
vddk_unload (void)
diff --git a/plugins/vddk/vddk.h b/plugins/vddk/vddk.h
index 8c63b4ee..29775eb4 100644
--- a/plugins/vddk/vddk.h
+++ b/plugins/vddk/vddk.h
@@ -1,5 +1,5 @@
/* nbdkit
- * Copyright (C) 2013-2020 Red Hat Inc.
+ * Copyright (C) 2013-2021 Red Hat Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -33,11 +33,96 @@
#ifndef NBDKIT_VDDK_H
#define NBDKIT_VDDK_H
+#include <stdbool.h>
+#include <stdint.h>
+#include <sys/time.h>
+
+#include <pthread.h>
+
+#include "isaligned.h"
+#include "tvdiff.h"
+#include "vector.h"
+
+#include "vddk-structs.h"
+
+enum compression_type { NONE = 0, ZLIB, FASTLZ, SKIPZ };
+
+extern void *dl;
+extern bool init_called;
+extern __thread int error_suppression;
+extern int library_version;
+extern bool is_remote;
+
+extern enum compression_type compression;
+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 int vddk_debug_diskinfo;
+extern int vddk_debug_extents;
+extern int vddk_debug_datapath;
+extern int vddk_debug_stats;
+
+#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
+
+/* Macros to bracket each VDDK API call, for printing debugging
+ * information and collecting statistics.
+ */
+#define VDDK_CALL_START(fn, fs, ...) \
+ do { \
+ struct timeval start_t, end_t; \
+ /* GCC can optimize this away at compile time: */ \
+ const bool datapath = \
+ strcmp (#fn, "VixDiskLib_Read") == 0 || \
+ strcmp (#fn, "VixDiskLib_Write") == 0; \
+ if (vddk_debug_stats) \
+ gettimeofday (&start_t, NULL); \
+ if (!datapath || vddk_debug_datapath) \
+ nbdkit_debug ("VDDK call: %s (" fs ")", #fn, ##__VA_ARGS__); \
+ do
+#define VDDK_CALL_END(fn, bytes_) \
+ while (0); \
+ if (vddk_debug_stats) { \
+ gettimeofday (&end_t, NULL); \
+ ACQUIRE_LOCK_FOR_CURRENT_SCOPE (&stats_lock); \
+ stats_##fn.usecs += tvdiff_usec (&start_t, &end_t); \
+ stats_##fn.calls++; \
+ stats_##fn.bytes += bytes_; \
+ } \
+ } while (0)
+
+/* Print VDDK errors. */
+#define VDDK_ERROR(err, fs, ...) \
+ do { \
+ char *vddk_err_msg; \
+ VDDK_CALL_START (VixDiskLib_GetErrorText, "%lu", err) \
+ vddk_err_msg = VixDiskLib_GetErrorText ((err), NULL); \
+ VDDK_CALL_END (VixDiskLib_GetErrorText, 0); \
+ nbdkit_error (fs ": %s", ##__VA_ARGS__, vddk_err_msg); \
+ VDDK_CALL_START (VixDiskLib_FreeErrorText, "") \
+ VixDiskLib_FreeErrorText (vddk_err_msg); \
+ VDDK_CALL_END (VixDiskLib_FreeErrorText, 0); \
+ } while (0)
+
+/* reexec.c */
extern bool noreexec;
extern char *reexeced;
-
extern void reexec_if_needed (const char *prepend);
extern int restore_ld_library_path (void);
--
2.31.1

View File

@ -0,0 +1,287 @@
From 66945d24e9192a67af421eecbb1835d42636ab93 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Wed, 27 Oct 2021 12:30:41 +0100
Subject: [PATCH] vddk: Refactor -D vddk.stats=1 into a new file
Acked-by: Laszlo Ersek <lersek@redhat.com>
(cherry picked from commit dcd5bc51ed7710c32d956345ea8da14ba15ef8f5)
---
plugins/vddk/Makefile.am | 1 +
plugins/vddk/stats.c | 118 +++++++++++++++++++++++++++++++++++++++
plugins/vddk/vddk.c | 78 +-------------------------
plugins/vddk/vddk.h | 15 +++++
4 files changed, 135 insertions(+), 77 deletions(-)
create mode 100644 plugins/vddk/stats.c
diff --git a/plugins/vddk/Makefile.am b/plugins/vddk/Makefile.am
index 232aaedd..4f470ff9 100644
--- a/plugins/vddk/Makefile.am
+++ b/plugins/vddk/Makefile.am
@@ -46,6 +46,7 @@ nbdkit_vddk_plugin_la_SOURCES = \
vddk.c \
vddk.h \
reexec.c \
+ stats.c \
vddk-structs.h \
vddk-stubs.h \
$(top_srcdir)/include/nbdkit-plugin.h \
diff --git a/plugins/vddk/stats.c b/plugins/vddk/stats.c
new file mode 100644
index 00000000..18a42714
--- /dev/null
+++ b/plugins/vddk/stats.c
@@ -0,0 +1,118 @@
+/* nbdkit
+ * Copyright (C) 2013-2021 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.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <inttypes.h>
+
+#include <pthread.h>
+
+#define NBDKIT_API_VERSION 2
+#include <nbdkit-plugin.h>
+
+#include "vector.h"
+
+#include "vddk.h"
+
+/* Debug flags. */
+NBDKIT_DLL_PUBLIC int vddk_debug_stats;
+
+pthread_mutex_t stats_lock = PTHREAD_MUTEX_INITIALIZER;
+
+/* For each VDDK API define a variable to store the time taken (used
+ * to implement -D vddk.stats=1).
+ */
+#define STUB(fn,ret,args) struct vddk_stat stats_##fn = { .name = #fn }
+#define OPTIONAL_STUB(fn,ret,args) STUB(fn,ret,args)
+#include "vddk-stubs.h"
+#undef STUB
+#undef OPTIONAL_STUB
+
+DEFINE_VECTOR_TYPE(statlist, struct vddk_stat)
+
+static int
+stat_compare (const void *vp1, const void *vp2)
+{
+ const struct vddk_stat *st1 = vp1;
+ const struct vddk_stat *st2 = vp2;
+
+ /* Note: sorts in reverse order of time spent in each API call. */
+ if (st1->usecs < st2->usecs) return 1;
+ else if (st1->usecs > st2->usecs) return -1;
+ else return 0;
+}
+
+static const char *
+api_name_without_prefix (const char *name)
+{
+ return strncmp (name, "VixDiskLib_", 11) == 0 ? name + 11 : name;
+}
+
+void
+display_stats (void)
+{
+ statlist stats = empty_vector;
+ size_t i;
+
+ if (!vddk_debug_stats) return;
+
+#define STUB(fn,ret,args) statlist_append (&stats, stats_##fn)
+#define OPTIONAL_STUB(fn,ret,args) statlist_append (&stats, stats_##fn)
+#include "vddk-stubs.h"
+#undef STUB
+#undef OPTIONAL_STUB
+
+ qsort (stats.ptr, stats.size, sizeof stats.ptr[0], stat_compare);
+
+ nbdkit_debug ("VDDK function stats (-D vddk.stats=1):");
+ nbdkit_debug ("%-24s %15s %5s %15s",
+ "VixDiskLib_...", "µs", "calls", "bytes");
+ for (i = 0; i < stats.size; ++i) {
+ if (stats.ptr[i].usecs) {
+ if (stats.ptr[i].bytes > 0)
+ nbdkit_debug (" %-22s %15" PRIi64 " %5" PRIu64 " %15" PRIu64,
+ api_name_without_prefix (stats.ptr[i].name),
+ stats.ptr[i].usecs,
+ stats.ptr[i].calls,
+ stats.ptr[i].bytes);
+ else
+ nbdkit_debug (" %-22s %15" PRIi64 " %5" PRIu64,
+ api_name_without_prefix (stats.ptr[i].name),
+ stats.ptr[i].usecs,
+ stats.ptr[i].calls);
+ }
+ }
+ statlist_reset (&stats);
+}
diff --git a/plugins/vddk/vddk.c b/plugins/vddk/vddk.c
index 041bff1a..67ac775c 100644
--- a/plugins/vddk/vddk.c
+++ b/plugins/vddk/vddk.c
@@ -61,7 +61,6 @@
NBDKIT_DLL_PUBLIC int vddk_debug_diskinfo;
NBDKIT_DLL_PUBLIC int vddk_debug_extents;
NBDKIT_DLL_PUBLIC int vddk_debug_datapath = 1;
-NBDKIT_DLL_PUBLIC int vddk_debug_stats;
/* For each VDDK API define a global variable. These globals are
* initialized when the plugin is loaded (by vddk_get_ready).
@@ -99,25 +98,6 @@ bool unbuffered; /* unbuffered */
const char *username; /* user */
const char *vmx_spec; /* vm */
-/* For each VDDK API define a variable to store the time taken (used
- * to implement -D vddk.stats=1).
- */
-struct vddk_stat {
- const char *name; /* function name */
- int64_t usecs; /* total number of usecs consumed */
- uint64_t calls; /* number of times called */
- uint64_t bytes; /* bytes transferred, datapath calls only */
-};
-static pthread_mutex_t stats_lock = PTHREAD_MUTEX_INITIALIZER;
-static void display_stats (void);
-#define STUB(fn,ret,args) \
- static struct vddk_stat stats_##fn = { .name = #fn }
-#define OPTIONAL_STUB(fn,ret,args) \
- static struct vddk_stat stats_##fn = { .name = #fn }
-#include "vddk-stubs.h"
-#undef STUB
-#undef OPTIONAL_STUB
-
/* Unload the plugin. */
static void
vddk_unload (void)
@@ -130,69 +110,13 @@ vddk_unload (void)
if (dl)
dlclose (dl);
- if (vddk_debug_stats)
- display_stats ();
+ display_stats ();
free (config);
free (libdir);
free (password);
}
-DEFINE_VECTOR_TYPE(statlist, struct vddk_stat)
-
-static int
-stat_compare (const void *vp1, const void *vp2)
-{
- const struct vddk_stat *st1 = vp1;
- const struct vddk_stat *st2 = vp2;
-
- /* Note: sorts in reverse order of time spent in each API call. */
- if (st1->usecs < st2->usecs) return 1;
- else if (st1->usecs > st2->usecs) return -1;
- else return 0;
-}
-
-static const char *
-api_name_without_prefix (const char *name)
-{
- return strncmp (name, "VixDiskLib_", 11) == 0 ? name + 11 : name;
-}
-
-static void
-display_stats (void)
-{
- statlist stats = empty_vector;
- size_t i;
-
-#define STUB(fn,ret,args) statlist_append (&stats, stats_##fn)
-#define OPTIONAL_STUB(fn,ret,args) statlist_append (&stats, stats_##fn)
-#include "vddk-stubs.h"
-#undef STUB
-#undef OPTIONAL_STUB
-
- qsort (stats.ptr, stats.size, sizeof stats.ptr[0], stat_compare);
-
- nbdkit_debug ("VDDK function stats (-D vddk.stats=1):");
- nbdkit_debug ("%-24s %15s %5s %15s",
- "VixDiskLib_...", "µs", "calls", "bytes");
- for (i = 0; i < stats.size; ++i) {
- if (stats.ptr[i].usecs) {
- if (stats.ptr[i].bytes > 0)
- nbdkit_debug (" %-22s %15" PRIi64 " %5" PRIu64 " %15" PRIu64,
- api_name_without_prefix (stats.ptr[i].name),
- stats.ptr[i].usecs,
- stats.ptr[i].calls,
- stats.ptr[i].bytes);
- else
- nbdkit_debug (" %-22s %15" PRIi64 " %5" PRIu64,
- api_name_without_prefix (stats.ptr[i].name),
- stats.ptr[i].usecs,
- stats.ptr[i].calls);
- }
- }
- statlist_reset (&stats);
-}
-
static void
trim (char *str)
{
diff --git a/plugins/vddk/vddk.h b/plugins/vddk/vddk.h
index 29775eb4..1400589d 100644
--- a/plugins/vddk/vddk.h
+++ b/plugins/vddk/vddk.h
@@ -126,4 +126,19 @@ extern char *reexeced;
extern void reexec_if_needed (const char *prepend);
extern int restore_ld_library_path (void);
+/* stats.c */
+struct vddk_stat {
+ const char *name; /* function name */
+ int64_t usecs; /* total number of usecs consumed */
+ uint64_t calls; /* number of times called */
+ uint64_t bytes; /* bytes transferred, datapath calls only */
+};
+extern pthread_mutex_t stats_lock;
+#define STUB(fn,ret,args) extern struct vddk_stat stats_##fn;
+#define OPTIONAL_STUB(fn,ret,args) STUB(fn,ret,args)
+#include "vddk-stubs.h"
+#undef STUB
+#undef OPTIONAL_STUB
+extern void display_stats (void);
+
#endif /* NBDKIT_VDDK_H */
--
2.31.1

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,57 @@
From c91ac233f6474b07ef181a08093c5d0f2f4ec4c3 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Fri, 29 Oct 2021 20:56:55 +0100
Subject: [PATCH] vddk: Assume that VixDiskLib_Flush is available
Since we now require and check that VDDK >= 6.5, we can assume that
VixDiskLib_Flush is always available.
(cherry picked from commit e3685e6f0d0b71ab24b96fe85430a3b75da58736)
---
plugins/vddk/vddk.c | 15 +++++++++++----
1 file changed, 11 insertions(+), 4 deletions(-)
diff --git a/plugins/vddk/vddk.c b/plugins/vddk/vddk.c
index 9f223db0..f967e2d9 100644
--- a/plugins/vddk/vddk.c
+++ b/plugins/vddk/vddk.c
@@ -378,6 +378,12 @@ load_library (bool load_error_is_fatal)
"See nbdkit-vddk-plugin(1) man page section \"SUPPORTED VERSIONS OF VDDK\".");
exit (EXIT_FAILURE);
}
+
+ /* Added in VDDK 6.0 so it must always be present. Since we are
+ * going to call this function unconditionally, fail early and hard
+ * if for some reason it's not present.
+ */
+ assert (VixDiskLib_Flush != NULL);
}
static int
@@ -725,18 +731,19 @@ vddk_get_size (void *handle)
return (int64_t) size;
}
+/* The Flush call was added in VDDK 6.0, since we support minimum 6.5
+ * we are always able to do FUA / flush.
+ */
static int
vddk_can_fua (void *handle)
{
- /* The Flush call was not available in VDDK < 6.0. */
- return VixDiskLib_Flush != NULL ? NBDKIT_FUA_NATIVE : NBDKIT_FUA_NONE;
+ return NBDKIT_FUA_NATIVE;
}
static int
vddk_can_flush (void *handle)
{
- /* The Flush call was not available in VDDK < 6.0. */
- return VixDiskLib_Flush != NULL;
+ return 1;
}
/* Read data from the file.
--
2.31.1

View File

@ -0,0 +1,186 @@
From 984e95fcbdb19c2495851322a4c33f34291ecfab Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Fri, 29 Oct 2021 21:02:54 +0100
Subject: [PATCH] vddk: Simplify detection of VDDK symbols and baseline 6.5
Make all symbols from VDDK 6.5 into required symbols and use a single
error message function if one of these is missing. The new error is:
nbdkit: error: required VDDK symbol "VixDiskLib_Wait" is
missing. VDDK version must be >= 6.5. See nbdkit-vddk-plugin(1) man
page section "SUPPORTED VERSIONS OF VDDK". Original dlopen error:
vmware-vix-disklib-distrib/lib64/libvixDiskLib.so.6: undefined
symbol: VixDiskLib_Wait
Remove the extra check and assert.
Be more consistent about #define OPTIONAL_STUB(fn,ret,args) STUB(fn,ret,args)
when we want the optional and required stubs to do the same thing.
(cherry picked from commit ec0d22e61881efa39a69d02ccb9e4ede8bf95e75)
---
plugins/vddk/stats.c | 2 +-
plugins/vddk/vddk-stubs.h | 45 ++++++++++++++++++---------------------
plugins/vddk/vddk.c | 36 ++++++++++++-------------------
plugins/vddk/vddk.h | 2 +-
4 files changed, 37 insertions(+), 48 deletions(-)
diff --git a/plugins/vddk/stats.c b/plugins/vddk/stats.c
index 18a42714..76e0c244 100644
--- a/plugins/vddk/stats.c
+++ b/plugins/vddk/stats.c
@@ -89,7 +89,7 @@ display_stats (void)
if (!vddk_debug_stats) return;
#define STUB(fn,ret,args) statlist_append (&stats, stats_##fn)
-#define OPTIONAL_STUB(fn,ret,args) statlist_append (&stats, stats_##fn)
+#define OPTIONAL_STUB(fn,ret,args) STUB(fn,ret,args)
#include "vddk-stubs.h"
#undef STUB
#undef OPTIONAL_STUB
diff --git a/plugins/vddk/vddk-stubs.h b/plugins/vddk/vddk-stubs.h
index 66353691..7d8644c3 100644
--- a/plugins/vddk/vddk-stubs.h
+++ b/plugins/vddk/vddk-stubs.h
@@ -39,10 +39,7 @@
* function name, return value, arguments.
*/
-/* Required stubs, present in all versions of VDDK that we support. I
- * have checked that all these exist in at least VDDK 5.5.5 (2015).
- */
-
+/* Required stubs, present in all versions of VDDK since 6.5 (Nov 2016). */
STUB (VixDiskLib_InitEx,
VixError,
(uint32_t major, uint32_t minor,
@@ -103,27 +100,27 @@ STUB (VixDiskLib_Write,
uint64_t start_sector, uint64_t nr_sectors,
const unsigned char *buf));
-/* Added in VDDK 6.0, these will be NULL in earlier versions. */
-OPTIONAL_STUB (VixDiskLib_Flush,
- VixError,
- (VixDiskLibHandle handle));
-OPTIONAL_STUB (VixDiskLib_ReadAsync,
- VixError,
- (VixDiskLibHandle handle,
- uint64_t start_sector, uint64_t nr_sectors,
- unsigned char *buf,
- VixDiskLibCompletionCB callback, void *data));
-OPTIONAL_STUB (VixDiskLib_WriteAsync,
- VixError,
- (VixDiskLibHandle handle,
- uint64_t start_sector, uint64_t nr_sectors,
- const unsigned char *buf,
- VixDiskLibCompletionCB callback, void *data));
+/* Added in VDDK 6.0. */
+STUB (VixDiskLib_Flush,
+ VixError,
+ (VixDiskLibHandle handle));
+STUB (VixDiskLib_ReadAsync,
+ VixError,
+ (VixDiskLibHandle handle,
+ uint64_t start_sector, uint64_t nr_sectors,
+ unsigned char *buf,
+ VixDiskLibCompletionCB callback, void *data));
+STUB (VixDiskLib_WriteAsync,
+ VixError,
+ (VixDiskLibHandle handle,
+ uint64_t start_sector, uint64_t nr_sectors,
+ const unsigned char *buf,
+ VixDiskLibCompletionCB callback, void *data));
-/* Added in VDDK 6.5, this will be NULL in earlier versions. */
-OPTIONAL_STUB (VixDiskLib_Wait,
- VixError,
- (VixDiskLibHandle handle));
+/* Added in VDDK 6.5. */
+STUB (VixDiskLib_Wait,
+ VixError,
+ (VixDiskLibHandle handle));
/* Added in VDDK 6.7, these will be NULL for earlier versions: */
OPTIONAL_STUB (VixDiskLib_QueryAllocatedBlocks,
diff --git a/plugins/vddk/vddk.c b/plugins/vddk/vddk.c
index f967e2d9..271b5ee0 100644
--- a/plugins/vddk/vddk.c
+++ b/plugins/vddk/vddk.c
@@ -63,7 +63,7 @@ NBDKIT_DLL_PUBLIC int vddk_debug_datapath = 1;
* initialized when the plugin is loaded (by vddk_get_ready).
*/
#define STUB(fn,ret,args) ret (*fn) args
-#define OPTIONAL_STUB(fn,ret,args) ret (*fn) args
+#define OPTIONAL_STUB(fn,ret,args) STUB(fn,ret,args)
#include "vddk-stubs.h"
#undef STUB
#undef OPTIONAL_STUB
@@ -282,6 +282,17 @@ vddk_config (const char *key, const char *value)
return 0;
}
+static void
+missing_required_symbol (const char *fn)
+{
+ nbdkit_error ("required VDDK symbol \"%s\" is missing. "
+ "VDDK version must be >= 6.5. "
+ "See nbdkit-vddk-plugin(1) man page section \"SUPPORTED VERSIONS OF VDDK\". "
+ "Original dlopen error: %s\n",
+ fn, dlerror ());
+ exit (EXIT_FAILURE);
+}
+
/* Load the VDDK library. */
static void
load_library (bool load_error_is_fatal)
@@ -358,32 +369,13 @@ load_library (bool load_error_is_fatal)
#define STUB(fn,ret,args) \
do { \
fn = dlsym (dl, #fn); \
- if (fn == NULL) { \
- nbdkit_error ("required VDDK symbol \"%s\" is missing: %s", \
- #fn, dlerror ()); \
- exit (EXIT_FAILURE); \
- } \
+ if (fn == NULL) \
+ missing_required_symbol (#fn); \
} while (0)
#define OPTIONAL_STUB(fn,ret,args) fn = dlsym (dl, #fn)
#include "vddk-stubs.h"
#undef STUB
#undef OPTIONAL_STUB
-
- /* Additionally, VDDK version must be >= 6.5. This was the first
- * version which introduced VixDiskLib_Wait symbol so we can check
- * for that.
- */
- if (VixDiskLib_Wait == NULL) {
- nbdkit_error ("VDDK version must be >= 6.5. "
- "See nbdkit-vddk-plugin(1) man page section \"SUPPORTED VERSIONS OF VDDK\".");
- exit (EXIT_FAILURE);
- }
-
- /* Added in VDDK 6.0 so it must always be present. Since we are
- * going to call this function unconditionally, fail early and hard
- * if for some reason it's not present.
- */
- assert (VixDiskLib_Flush != NULL);
}
static int
diff --git a/plugins/vddk/vddk.h b/plugins/vddk/vddk.h
index be0b3492..0e3dd79e 100644
--- a/plugins/vddk/vddk.h
+++ b/plugins/vddk/vddk.h
@@ -76,7 +76,7 @@ extern int vddk_debug_datapath;
extern int vddk_debug_stats;
#define STUB(fn,ret,args) extern ret (*fn) args
-#define OPTIONAL_STUB(fn,ret,args) extern ret (*fn) args
+#define OPTIONAL_STUB(fn,ret,args) STUB(fn,ret,args)
#include "vddk-stubs.h"
#undef STUB
#undef OPTIONAL_STUB
--
2.31.1

View File

@ -0,0 +1,40 @@
From 342efed6bb9f8f0c8d2cb4aa2b09da64ed2e7ed4 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Sat, 30 Oct 2021 08:34:28 +0100
Subject: [PATCH] vddk: Remove some whitespace from a couple of functions
(cherry picked from commit 974dce2c2ef84fc096ee319f340054234a29df91)
---
plugins/vddk/vddk.c | 9 ++-------
1 file changed, 2 insertions(+), 7 deletions(-)
diff --git a/plugins/vddk/vddk.c b/plugins/vddk/vddk.c
index 271b5ee0..184f1a9c 100644
--- a/plugins/vddk/vddk.c
+++ b/plugins/vddk/vddk.c
@@ -792,9 +792,7 @@ static int
vddk_flush (void *handle, uint32_t flags)
{
struct vddk_handle *h = handle;
- struct command flush_cmd = {
- .type = FLUSH,
- };
+ struct command flush_cmd = { .type = FLUSH };
return send_command_and_wait (h, &flush_cmd);
}
@@ -804,10 +802,7 @@ vddk_can_extents (void *handle)
{
struct vddk_handle *h = handle;
int ret;
- struct command can_extents_cmd = {
- .type = CAN_EXTENTS,
- .ptr = &ret,
- };
+ struct command can_extents_cmd = { .type = CAN_EXTENTS, .ptr = &ret };
if (send_command_and_wait (h, &can_extents_cmd) == -1)
return -1;
--
2.31.1

View File

@ -0,0 +1,338 @@
From edbded52b144ce3c8c45c7ef352f8969a1f5d1bb Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Sat, 30 Oct 2021 08:27:39 +0100
Subject: [PATCH] vddk: Move config, debug/error and utility functions around
Move the functions so they are nearer to where they are used.
Introduce a utils.c file for utility functions.
This is just code rearrangement with no other effects.
(cherry picked from commit c59be086210a06688b9195e0b91f8603a668654a)
---
plugins/vddk/Makefile.am | 1 +
plugins/vddk/utils.c | 51 ++++++++++
plugins/vddk/vddk.c | 201 +++++++++++++++++++--------------------
plugins/vddk/vddk.h | 3 +
4 files changed, 151 insertions(+), 105 deletions(-)
create mode 100644 plugins/vddk/utils.c
diff --git a/plugins/vddk/Makefile.am b/plugins/vddk/Makefile.am
index f8382fc9..02113da0 100644
--- a/plugins/vddk/Makefile.am
+++ b/plugins/vddk/Makefile.am
@@ -47,6 +47,7 @@ nbdkit_vddk_plugin_la_SOURCES = \
vddk.h \
reexec.c \
stats.c \
+ utils.c \
vddk-structs.h \
vddk-stubs.h \
worker.c \
diff --git a/plugins/vddk/utils.c b/plugins/vddk/utils.c
new file mode 100644
index 00000000..f0c19950
--- /dev/null
+++ b/plugins/vddk/utils.c
@@ -0,0 +1,51 @@
+/* nbdkit
+ * Copyright (C) 2013-2021 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.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define NBDKIT_API_VERSION 2
+#include <nbdkit-plugin.h>
+
+#include "vddk.h"
+
+void
+trim (char *str)
+{
+ size_t len = strlen (str);
+
+ if (len > 0 && str[len-1] == '\n')
+ str[len-1] = '\0';
+}
diff --git a/plugins/vddk/vddk.c b/plugins/vddk/vddk.c
index 184f1a9c..31e5e23b 100644
--- a/plugins/vddk/vddk.c
+++ b/plugins/vddk/vddk.c
@@ -114,61 +114,6 @@ vddk_unload (void)
free (password);
}
-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 the thread-local error_suppression flag is non-zero then we
- * will suppress error messages from VDDK in this thread.
- */
- if (error_suppression) return;
-
- if (vasprintf (&str, fs, args) == -1) {
- nbdkit_error ("lost error message: %s", fs);
- return;
- }
-
- trim (str);
-
- /* VDDK 7 added a useless error message about their "phone home"
- * system called CEIP which only panics users. Demote it to a debug
- * statement. https://bugzilla.redhat.com/show_bug.cgi?id=1834267
- */
- if (strstr (str, "Get CEIP status failed") != NULL) {
- nbdkit_debug ("%s", str);
- return;
- }
-
- nbdkit_error ("%s", str);
-}
-
/* Configuration. */
static int
vddk_config (const char *key, const char *value)
@@ -282,6 +227,56 @@ vddk_config (const char *key, const char *value)
return 0;
}
+static int
+vddk_config_complete (void)
+{
+ if (filename == NULL) {
+ nbdkit_error ("you must supply the file=<FILENAME> parameter "
+ "after the plugin name on the command line");
+ return -1;
+ }
+
+ /* For remote connections, check all the parameters have been
+ * passed. Note that VDDK will segfault if parameters that it
+ * expects are NULL (and there's no real way to tell what parameters
+ * it is expecting). This implements the same test that the VDDK
+ * sample program does.
+ */
+ is_remote =
+ vmx_spec ||
+ server_name ||
+ username ||
+ password ||
+ cookie ||
+ thumb_print ||
+ port ||
+ nfc_host_port;
+
+ if (is_remote) {
+#define missing(test, param) \
+ if (test) { \
+ nbdkit_error ("remote connection requested, missing parameter: %s", \
+ param); \
+ return -1; \
+ }
+ missing (!server_name, "server");
+ missing (!username, "user");
+ missing (!password, "password");
+ missing (!vmx_spec, "vm");
+#undef missing
+ }
+
+ /* Restore original LD_LIBRARY_PATH after reexec. */
+ if (restore_ld_library_path () == -1)
+ return -1;
+
+ return 0;
+}
+
+#define vddk_config_help \
+ "[file=]<FILENAME> (required) The filename (eg. VMDK file) to serve.\n" \
+ "Many optional parameters are supported, see nbdkit-vddk-plugin(1)."
+
static void
missing_required_symbol (const char *fn)
{
@@ -378,56 +373,6 @@ load_library (bool load_error_is_fatal)
#undef OPTIONAL_STUB
}
-static int
-vddk_config_complete (void)
-{
- if (filename == NULL) {
- nbdkit_error ("you must supply the file=<FILENAME> parameter "
- "after the plugin name on the command line");
- return -1;
- }
-
- /* For remote connections, check all the parameters have been
- * passed. Note that VDDK will segfault if parameters that it
- * expects are NULL (and there's no real way to tell what parameters
- * it is expecting). This implements the same test that the VDDK
- * sample program does.
- */
- is_remote =
- vmx_spec ||
- server_name ||
- username ||
- password ||
- cookie ||
- thumb_print ||
- port ||
- nfc_host_port;
-
- if (is_remote) {
-#define missing(test, param) \
- if (test) { \
- nbdkit_error ("remote connection requested, missing parameter: %s", \
- param); \
- return -1; \
- }
- missing (!server_name, "server");
- missing (!username, "user");
- missing (!password, "password");
- missing (!vmx_spec, "vm");
-#undef missing
- }
-
- /* Restore original LD_LIBRARY_PATH after reexec. */
- if (restore_ld_library_path () == -1)
- return -1;
-
- return 0;
-}
-
-#define vddk_config_help \
- "[file=]<FILENAME> (required) The filename (eg. VMDK file) to serve.\n" \
- "Many optional parameters are supported, see nbdkit-vddk-plugin(1)."
-
static int
vddk_get_ready (void)
{
@@ -435,6 +380,52 @@ vddk_get_ready (void)
return 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 the thread-local error_suppression flag is non-zero then we
+ * will suppress error messages from VDDK in this thread.
+ */
+ if (error_suppression) return;
+
+ if (vasprintf (&str, fs, args) == -1) {
+ nbdkit_error ("lost error message: %s", fs);
+ return;
+ }
+
+ trim (str);
+
+ /* VDDK 7 added a useless error message about their "phone home"
+ * system called CEIP which only panics users. Demote it to a debug
+ * statement. https://bugzilla.redhat.com/show_bug.cgi?id=1834267
+ */
+ if (strstr (str, "Get CEIP status failed") != NULL) {
+ nbdkit_debug ("%s", str);
+ return;
+ }
+
+ nbdkit_error ("%s", str);
+}
+
/* Defer VDDK initialization until after fork because it is known to
* create background threads from VixDiskLib_InitEx. Unfortunately
* error reporting from this callback is difficult, but we have
diff --git a/plugins/vddk/vddk.h b/plugins/vddk/vddk.h
index 0e3dd79e..d99b6f4b 100644
--- a/plugins/vddk/vddk.h
+++ b/plugins/vddk/vddk.h
@@ -183,6 +183,9 @@ extern pthread_mutex_t stats_lock;
#undef OPTIONAL_STUB
extern void display_stats (void);
+/* utils.c */
+extern void trim (char *str);
+
/* worker.c */
extern const char *command_type_string (enum command_type type);
extern int send_command_and_wait (struct vddk_handle *h, struct command *cmd);
--
2.31.1

View File

@ -0,0 +1,245 @@
From 239df6ee9583bc520e9a3e18f0c0d8e58602fb5c Mon Sep 17 00:00:00 2001
From: Nir Soffer <nsoffer@redhat.com>
Date: Fri, 5 Nov 2021 20:36:42 +0200
Subject: [PATCH] common/utils/test-vector.c: Add vector benchmarks
The generic vector reallocs on every append. Add benchmarks to measure
the cost with uint32 vector (used for copying extents) and the effect of
reserving space upfront.
The tests show that realloc is pretty efficient, but calling reserve
before the appends speeds the appends up significantly.
NBDKIT_BENCH=1 ./test-vector
bench_reserve: 1000000 appends in 0.004503 s
bench_append: 1000000 appends in 0.014986 s
The new benchmarks do not run by default to avoid trouble in CI on
overloaded machines or under qemu emulation.
A new target added to run all benchmaks:
make bench
Ported from libnbd:
- commit dc9ae0174ab1384081a57a8d54b10f8147ea6430
- commit f6c06a3b4d87fe976a96ea04f8da1f22b2531dbd
(cherry picked from commit a227af7921c9a51c4f1ab699a3b9f06a9a645126)
---
Makefile.am | 5 +++
README | 7 ++++
common/utils/Makefile.am | 5 ++-
common/utils/bench.h | 72 ++++++++++++++++++++++++++++++++++++++
common/utils/test-vector.c | 55 +++++++++++++++++++++++++++--
5 files changed, 141 insertions(+), 3 deletions(-)
create mode 100644 common/utils/bench.h
diff --git a/Makefile.am b/Makefile.am
index b21d69ed..49f5d91c 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -102,6 +102,11 @@ check-root:
check-vddk:
$(MAKE) -C tests check-vddk
+bench: all
+ @for d in common/utils; do \
+ $(MAKE) -C $$d bench || exit 1; \
+ done
+
#----------------------------------------------------------------------
# Maintainers only!
diff --git a/README b/README
index a04325be..b001620c 100644
--- a/README
+++ b/README
@@ -274,6 +274,13 @@ nbdkit-vddk-plugin against the library like this:
make check-vddk vddkdir=vmware-vix-disklib-distrib
+Running the benchmarks
+----------------------
+
+To run benchmarks:
+
+ make bench
+
DOWNLOAD TARBALLS
=================
diff --git a/common/utils/Makefile.am b/common/utils/Makefile.am
index c33811fc..b2f08cb4 100644
--- a/common/utils/Makefile.am
+++ b/common/utils/Makefile.am
@@ -101,6 +101,9 @@ test_quotes_SOURCES = test-quotes.c quote.c utils.h
test_quotes_CPPFLAGS = -I$(srcdir)
test_quotes_CFLAGS = $(WARNINGS_CFLAGS)
-test_vector_SOURCES = test-vector.c vector.c vector.h
+test_vector_SOURCES = test-vector.c vector.c vector.h bench.h
test_vector_CPPFLAGS = -I$(srcdir)
test_vector_CFLAGS = $(WARNINGS_CFLAGS)
+
+bench: test-vector
+ NBDKIT_BENCH=1 ./test-vector
diff --git a/common/utils/bench.h b/common/utils/bench.h
new file mode 100644
index 00000000..496a3614
--- /dev/null
+++ b/common/utils/bench.h
@@ -0,0 +1,72 @@
+/* libnbd
+ * Copyright (C) 2021 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 LIBNBD_BENCH_H
+#define LIBNBD_BENCH_H
+
+#include <sys/time.h>
+
+#define MICROSECONDS 1000000
+
+struct bench {
+ struct timeval start, stop;
+};
+
+static inline void
+bench_start(struct bench *b)
+{
+ gettimeofday (&b->start, NULL);
+}
+
+static inline void
+bench_stop(struct bench *b)
+{
+ gettimeofday (&b->stop, NULL);
+}
+
+static inline double
+bench_sec(struct bench *b)
+{
+ struct timeval dt;
+
+ dt.tv_sec = b->stop.tv_sec - b->start.tv_sec;
+ dt.tv_usec = b->stop.tv_usec - b->start.tv_usec;
+
+ if (dt.tv_usec < 0) {
+ dt.tv_sec -= 1;
+ dt.tv_usec += MICROSECONDS;
+ }
+
+ return ((double)dt.tv_sec * MICROSECONDS + dt.tv_usec) / MICROSECONDS;
+}
+
+#endif /* LIBNBD_BENCH_H */
diff --git a/common/utils/test-vector.c b/common/utils/test-vector.c
index 94b2aeb7..28af59b8 100644
--- a/common/utils/test-vector.c
+++ b/common/utils/test-vector.c
@@ -38,9 +38,13 @@
#undef NDEBUG /* Keep test strong even for nbdkit built without assertions */
#include <assert.h>
+#include "bench.h"
#include "vector.h"
+#define APPENDS 1000000
+
DEFINE_VECTOR_TYPE(int64_vector, int64_t);
+DEFINE_VECTOR_TYPE(uint32_vector, uint32_t);
DEFINE_VECTOR_TYPE(string_vector, char *);
static int
@@ -113,10 +117,57 @@ test_string_vector (void)
free (v.ptr);
}
+static void
+bench_reserve (void)
+{
+ uint32_vector v = empty_vector;
+ struct bench b;
+
+ bench_start(&b);
+
+ uint32_vector_reserve(&v, APPENDS);
+
+ for (uint32_t i = 0; i < APPENDS; i++) {
+ uint32_vector_append (&v, i);
+ }
+
+ bench_stop(&b);
+
+ assert (v.ptr[APPENDS - 1] == APPENDS - 1);
+ free (v.ptr);
+
+ printf ("bench_reserve: %d appends in %.6f s\n", APPENDS, bench_sec (&b));
+}
+
+static void
+bench_append (void)
+{
+ uint32_vector v = empty_vector;
+ struct bench b;
+
+ bench_start(&b);
+
+ for (uint32_t i = 0; i < APPENDS; i++) {
+ uint32_vector_append (&v, i);
+ }
+
+ bench_stop(&b);
+
+ assert (v.ptr[APPENDS - 1] == APPENDS - 1);
+ free (v.ptr);
+
+ printf ("bench_append: %d appends in %.6f s\n", APPENDS, bench_sec (&b));
+}
+
int
main (int argc, char *argv[])
{
- test_int64_vector ();
- test_string_vector ();
+ if (getenv("NBDKIT_BENCH")) {
+ bench_reserve ();
+ bench_append ();
+ } else {
+ test_int64_vector ();
+ test_string_vector ();
+ }
return 0;
}
--
2.31.1

View File

@ -0,0 +1,54 @@
From e544d86c797edec613673c7272f8d4f8b05d87f8 Mon Sep 17 00:00:00 2001
From: Nir Soffer <nsoffer@redhat.com>
Date: Fri, 5 Nov 2021 22:16:26 +0200
Subject: [PATCH] common/urils/vector.c: Optimize vector append
Minimize reallocs by growing the backing array by factor of 1.5.
Testing show that now append() is fast without calling reserve()
upfront, simplifying code using vector.
NBDKIT_BENCH=1 ./test-vector
bench_reserve: 1000000 appends in 0.004496 s
bench_append: 1000000 appends in 0.004180 s
This can make a difference in code appending millions of items.
Ported from libnbd commit 985dfa72ae2e41901f0af21e7205ef85428cd4bd.
(cherry picked from commit 12356fa97a840de19bb61e0abedd6e7c7e578e5a)
---
common/utils/vector.c | 14 ++++++++++++--
1 file changed, 12 insertions(+), 2 deletions(-)
diff --git a/common/utils/vector.c b/common/utils/vector.c
index 00cd2546..7df17e1b 100644
--- a/common/utils/vector.c
+++ b/common/utils/vector.c
@@ -41,11 +41,21 @@ int
generic_vector_reserve (struct generic_vector *v, size_t n, size_t itemsize)
{
void *newptr;
+ size_t reqalloc, newalloc;
- newptr = realloc (v->ptr, (n + v->alloc) * itemsize);
+ reqalloc = v->alloc + n;
+ if (reqalloc < v->alloc)
+ return -1; /* overflow */
+
+ newalloc = (v->alloc * 3 + 1) / 2;
+
+ if (newalloc < reqalloc)
+ newalloc = reqalloc;
+
+ newptr = realloc (v->ptr, newalloc * itemsize);
if (newptr == NULL)
return -1;
v->ptr = newptr;
- v->alloc += n;
+ v->alloc = newalloc;
return 0;
}
--
2.31.1

View File

@ -0,0 +1,188 @@
From 24e2694b302f6602e0fc7808a53a766cb983dfb4 Mon Sep 17 00:00:00 2001
From: Nir Soffer <nsoffer@redhat.com>
Date: Fri, 5 Nov 2021 22:59:38 +0200
Subject: [PATCH] common/utils/vector: Rename `alloc` to `cap`
The `alloc` field is the maximum number of items you can append to a
vector before it need to be resized. This may confuse users with the
size of the `ptr` array which is `alloc * itemsize`. Rename to "cap",
common term for this property in many languages (e.g C++, Rust, Go).
Tested with "make check". Tests requiring root or external libraries
(vddk) not tested.
Ported from libnbd commit e3c7f02a2a844295564c832108d36c939c4e4ecf.
(cherry picked from commit 75a44237c4463524dbf7951bb62b59c373c85865)
---
common/allocators/malloc.c | 24 ++++++++++++------------
common/utils/vector.c | 16 ++++++++--------
common/utils/vector.h | 12 ++++++------
plugins/vddk/reexec.c | 2 +-
4 files changed, 27 insertions(+), 27 deletions(-)
diff --git a/common/allocators/malloc.c b/common/allocators/malloc.c
index 59409c24..f7474465 100644
--- a/common/allocators/malloc.c
+++ b/common/allocators/malloc.c
@@ -88,16 +88,16 @@ extend (struct m_alloc *ma, uint64_t new_size)
ACQUIRE_WRLOCK_FOR_CURRENT_SCOPE (&ma->lock);
size_t old_size, n;
- if (ma->ba.alloc < new_size) {
- old_size = ma->ba.alloc;
- n = new_size - ma->ba.alloc;
+ if (ma->ba.cap < new_size) {
+ old_size = ma->ba.cap;
+ n = new_size - ma->ba.cap;
#ifdef HAVE_MUNLOCK
/* Since the memory might be moved by realloc, we must unlock the
* original array.
*/
if (ma->use_mlock)
- munlock (ma->ba.ptr, ma->ba.alloc);
+ munlock (ma->ba.ptr, ma->ba.cap);
#endif
if (bytearray_reserve (&ma->ba, n) == -1) {
@@ -110,7 +110,7 @@ extend (struct m_alloc *ma, uint64_t new_size)
#ifdef HAVE_MLOCK
if (ma->use_mlock) {
- if (mlock (ma->ba.ptr, ma->ba.alloc) == -1) {
+ if (mlock (ma->ba.ptr, ma->ba.cap) == -1) {
nbdkit_error ("allocator=malloc: mlock: %m");
return -1;
}
@@ -138,11 +138,11 @@ m_alloc_read (struct allocator *a, void *buf,
/* Avoid reading beyond the end of the allocated array. Return
* zeroes for that part.
*/
- if (offset >= ma->ba.alloc)
+ if (offset >= ma->ba.cap)
memset (buf, 0, count);
- else if (offset + count > ma->ba.alloc) {
- memcpy (buf, ma->ba.ptr + offset, ma->ba.alloc - offset);
- memset (buf + ma->ba.alloc - offset, 0, offset + count - ma->ba.alloc);
+ else if (offset + count > ma->ba.cap) {
+ memcpy (buf, ma->ba.ptr + offset, ma->ba.cap - offset);
+ memset (buf + ma->ba.cap - offset, 0, offset + count - ma->ba.cap);
}
else
memcpy (buf, ma->ba.ptr + offset, count);
@@ -191,9 +191,9 @@ m_alloc_zero (struct allocator *a, uint64_t count, uint64_t offset)
/* Try to avoid extending the array, since the unallocated part
* always reads as zero.
*/
- if (offset < ma->ba.alloc) {
- if (offset + count > ma->ba.alloc)
- memset (ma->ba.ptr + offset, 0, ma->ba.alloc - offset);
+ if (offset < ma->ba.cap) {
+ if (offset + count > ma->ba.cap)
+ memset (ma->ba.ptr + offset, 0, ma->ba.cap - offset);
else
memset (ma->ba.ptr + offset, 0, count);
}
diff --git a/common/utils/vector.c b/common/utils/vector.c
index 7df17e1b..a4b43ce7 100644
--- a/common/utils/vector.c
+++ b/common/utils/vector.c
@@ -41,21 +41,21 @@ int
generic_vector_reserve (struct generic_vector *v, size_t n, size_t itemsize)
{
void *newptr;
- size_t reqalloc, newalloc;
+ size_t reqcap, newcap;
- reqalloc = v->alloc + n;
- if (reqalloc < v->alloc)
+ reqcap = v->cap + n;
+ if (reqcap < v->cap)
return -1; /* overflow */
- newalloc = (v->alloc * 3 + 1) / 2;
+ newcap = (v->cap * 3 + 1) / 2;
- if (newalloc < reqalloc)
- newalloc = reqalloc;
+ if (newcap < reqcap)
+ newcap = reqcap;
- newptr = realloc (v->ptr, newalloc * itemsize);
+ newptr = realloc (v->ptr, newcap * itemsize);
if (newptr == NULL)
return -1;
v->ptr = newptr;
- v->alloc = newalloc;
+ v->cap = newcap;
return 0;
}
diff --git a/common/utils/vector.h b/common/utils/vector.h
index f6a0af78..782dcba6 100644
--- a/common/utils/vector.h
+++ b/common/utils/vector.h
@@ -86,7 +86,7 @@
struct name { \
type *ptr; /* Pointer to array of items. */ \
size_t size; /* Number of valid items in the array. */ \
- size_t alloc; /* Number of items allocated. */ \
+ size_t cap; /* Maximum number of items. */ \
}; \
typedef struct name name; \
\
@@ -106,7 +106,7 @@
name##_insert (name *v, type elem, size_t i) \
{ \
assert (i <= v->size); \
- if (v->size >= v->alloc) { \
+ if (v->size >= v->cap) { \
if (name##_reserve (v, 1) == -1) return -1; \
} \
memmove (&v->ptr[i+1], &v->ptr[i], (v->size-i) * sizeof (elem)); \
@@ -137,7 +137,7 @@
{ \
free (v->ptr); \
v->ptr = NULL; \
- v->size = v->alloc = 0; \
+ v->size = v->cap = 0; \
} \
\
/* Iterate over the vector, calling f() on each element. */ \
@@ -181,17 +181,17 @@
if (newptr == NULL) return -1; \
memcpy (newptr, vptr, len); \
copy->ptr = newptr; \
- copy->size = copy->alloc = v->size; \
+ copy->size = copy->cap = v->size; \
return 0; \
} \
\
-#define empty_vector { .ptr = NULL, .size = 0, .alloc = 0 }
+#define empty_vector { .ptr = NULL, .size = 0, .cap = 0 }
struct generic_vector {
void *ptr;
size_t size;
- size_t alloc;
+ size_t cap;
};
extern int generic_vector_reserve (struct generic_vector *v,
diff --git a/plugins/vddk/reexec.c b/plugins/vddk/reexec.c
index 46acdb62..9e87025e 100644
--- a/plugins/vddk/reexec.c
+++ b/plugins/vddk/reexec.c
@@ -116,7 +116,7 @@ perform_reexec (const char *env, const char *prepend)
nbdkit_error ("realloc: %m");
exit (EXIT_FAILURE);
}
- r = read (fd, buf.ptr + buf.size, buf.alloc - buf.size);
+ r = read (fd, buf.ptr + buf.size, buf.cap - buf.size);
if (r == -1) {
nbdkit_error ("read: %s: %m", cmdline_file);
exit (EXIT_FAILURE);
--
2.31.1

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,32 @@
From 2df98ef35c3b023a44983583f65379793599e57f Mon Sep 17 00:00:00 2001
From: Nir Soffer <nsoffer@redhat.com>
Date: Mon, 8 Nov 2021 19:47:57 +0200
Subject: [PATCH] podwrapper.pl.in: Use short commit date
We can use git short commit date format $cs. Maybe it was not available
when podwrapper.pl was created.
Signed-off-by: Nir Soffer <nsoffer@redhat.com>
(cherry picked from libnbd commit 0306fdcb08e8dc5957a9e344b54200711fca1220)
(cherry picked from commit 7a1e79c6b5ca4adcef47fc0929d25d54610fc417)
---
podwrapper.pl.in | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/podwrapper.pl.in b/podwrapper.pl.in
index abad578d..63c1025a 100755
--- a/podwrapper.pl.in
+++ b/podwrapper.pl.in
@@ -233,8 +233,7 @@ my $date;
my $filename = "$abs_top_srcdir/.git";
if (!$date && -d $filename) {
local $ENV{GIT_DIR} = $filename;
- $_ = `git show -O/dev/null -s --format=%ci`;
- $date = $1 if /^(\d+-\d+-\d+)\s/;
+ $date = `git show -O/dev/null -s --format=%cs`;
}
if (!$date) {
my ($day, $month, $year) = (gmtime($ENV{SOURCE_DATE_EPOCH} || time))[3,4,5];
--
2.31.1

View File

@ -0,0 +1,89 @@
From e9f77e9da946c963e4ec5d82dfd144305f79ebb5 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Tue, 9 Nov 2021 09:07:42 +0000
Subject: [PATCH] ocaml: Replace "noalloc" with [@@noalloc] annotation
This requires OCaml >= 4.03 (released April 2016). The previous
minimum version was 4.02.2.
(cherry picked from commit d15dd73845065cc9ca04aa785e2be994f76bf832)
---
README | 2 +-
plugins/ocaml/NBDKit.ml | 16 ++++++++--------
plugins/ocaml/nbdkit-ocaml-plugin.pod | 5 +----
3 files changed, 10 insertions(+), 13 deletions(-)
diff --git a/README b/README
index b001620c..160856b6 100644
--- a/README
+++ b/README
@@ -155,7 +155,7 @@ For the Python plugin:
For the OCaml plugin:
- - OCaml >= 4.02.2
+ - OCaml >= 4.03
For the Tcl plugin:
diff --git a/plugins/ocaml/NBDKit.ml b/plugins/ocaml/NBDKit.ml
index 75823ba5..4d45cc0c 100644
--- a/plugins/ocaml/NBDKit.ml
+++ b/plugins/ocaml/NBDKit.ml
@@ -152,11 +152,11 @@ let default_callbacks = {
export_description = None;
}
-external set_name : string -> unit = "ocaml_nbdkit_set_name" "noalloc"
-external set_longname : string -> unit = "ocaml_nbdkit_set_longname" "noalloc"
-external set_version : string -> unit = "ocaml_nbdkit_set_version" "noalloc"
-external set_description : string -> unit = "ocaml_nbdkit_set_description" "noalloc"
-external set_config_help : string -> unit = "ocaml_nbdkit_set_config_help" "noalloc"
+external set_name : string -> unit = "ocaml_nbdkit_set_name" [@@noalloc]
+external set_longname : string -> unit = "ocaml_nbdkit_set_longname" [@@noalloc]
+external set_version : string -> unit = "ocaml_nbdkit_set_version" [@@noalloc]
+external set_description : string -> unit = "ocaml_nbdkit_set_description" [@@noalloc]
+external set_config_help : string -> unit = "ocaml_nbdkit_set_config_help" [@@noalloc]
external set_field : string -> 'a -> unit = "ocaml_nbdkit_set_field"
@@ -220,7 +220,7 @@ let register_plugin plugin =
(* Bindings to nbdkit server functions. *)
-external _set_error : int -> unit = "ocaml_nbdkit_set_error" "noalloc"
+external _set_error : int -> unit = "ocaml_nbdkit_set_error" [@@noalloc]
let set_error unix_error =
(* There's an awkward triple translation going on here, because
@@ -250,9 +250,9 @@ external read_password : string -> string = "ocaml_nbdkit_read_password"
external realpath : string -> string = "ocaml_nbdkit_realpath"
external nanosleep : int -> int -> unit = "ocaml_nbdkit_nanosleep"
external export_name : unit -> string = "ocaml_nbdkit_export_name"
-external shutdown : unit -> unit = "ocaml_nbdkit_shutdown" "noalloc"
+external shutdown : unit -> unit = "ocaml_nbdkit_shutdown" [@@noalloc]
-external _debug : string -> unit = "ocaml_nbdkit_debug" "noalloc"
+external _debug : string -> unit = "ocaml_nbdkit_debug" [@@noalloc]
let debug fs =
ksprintf _debug fs
diff --git a/plugins/ocaml/nbdkit-ocaml-plugin.pod b/plugins/ocaml/nbdkit-ocaml-plugin.pod
index 2bd0af25..293f8143 100644
--- a/plugins/ocaml/nbdkit-ocaml-plugin.pod
+++ b/plugins/ocaml/nbdkit-ocaml-plugin.pod
@@ -11,10 +11,7 @@ nbdkit-ocaml-plugin - writing nbdkit plugins in OCaml
=head1 DESCRIPTION
This manual page describes how to write nbdkit plugins in natively
-compiled OCaml code.
-
-Note this requires OCaml E<ge> 4.02.2, which has support for shared
-libraries. See L<http://caml.inria.fr/mantis/view.php?id=6693>
+compiled OCaml code. This requires OCaml E<ge> 4.03.
=head1 WRITING AN OCAML NBDKIT PLUGIN
--
2.31.1

View File

@ -0,0 +1,39 @@
From 5da14da22c1e26aff24baf41fb2ae0f2832acae1 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Sat, 27 Nov 2021 16:44:41 +0000
Subject: [PATCH] vddk: Drop obsolete documentation related to thread model
Since commit 1eecf15fc3 ("vddk: Implement parallel thread model") we
have implemented a parallel thread model in this plugin, and thread
handling is believed to be safe and in conformity with the VDDK
documentation. Remove obsolete documentation contradicting this.
Reported-by: Ming Xie
Fixes: commit 1eecf15fc3d8ea253ccec4f5883fdbb9aa6f8c2b
(cherry picked from commit 370ecb711c23f9143c933e13468e11d688d0d651)
---
plugins/vddk/nbdkit-vddk-plugin.pod | 8 --------
1 file changed, 8 deletions(-)
diff --git a/plugins/vddk/nbdkit-vddk-plugin.pod b/plugins/vddk/nbdkit-vddk-plugin.pod
index ce82a734..acec0bd2 100644
--- a/plugins/vddk/nbdkit-vddk-plugin.pod
+++ b/plugins/vddk/nbdkit-vddk-plugin.pod
@@ -452,14 +452,6 @@ sector boundaries. This is because the VDDK Read and Write APIs only
take sector numbers. If your client needs finer granularity, you can
use L<nbdkit-blocksize-filter(1)> with the setting C<minblock=512>.
-=head2 Threads
-
-Handling threads in the VDDK API is complex and does not map well to
-any of the thread models offered by nbdkit (see
-L<nbdkit-plugin(3)/THREADS>). The plugin uses the nbdkit
-C<SERIALIZE_REQUESTS> model, but technically even this is not
-completely safe. This is a subject of future work.
-
=head2 Out of memory errors
In the verbose log you may see errors like:
--
2.31.1

View File

@ -0,0 +1,32 @@
From b986f25be4f013eb02cd327826fa225c8202571e Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Sat, 20 Nov 2021 17:50:25 +0000
Subject: [PATCH] Revert "podwrapper.pl.in: Use short commit date"
This commit breaks man page output because there is an extra newline
after the date which wasn't being removed.
This reverts commit 7a1e79c6b5ca4adcef47fc0929d25d54610fc417.
(cherry picked from commit 750ad5972bb082d188f17f8f71ef1ec0c616c676)
---
podwrapper.pl.in | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/podwrapper.pl.in b/podwrapper.pl.in
index 63c1025a..abad578d 100755
--- a/podwrapper.pl.in
+++ b/podwrapper.pl.in
@@ -233,7 +233,8 @@ my $date;
my $filename = "$abs_top_srcdir/.git";
if (!$date && -d $filename) {
local $ENV{GIT_DIR} = $filename;
- $date = `git show -O/dev/null -s --format=%cs`;
+ $_ = `git show -O/dev/null -s --format=%ci`;
+ $date = $1 if /^(\d+-\d+-\d+)\s/;
}
if (!$date) {
my ($day, $month, $year) = (gmtime($ENV{SOURCE_DATE_EPOCH} || time))[3,4,5];
--
2.31.1

View File

@ -0,0 +1,31 @@
From 0c430f02eec2671155c001c8a1d2f964b42022e5 Mon Sep 17 00:00:00 2001
From: Eric Blake <eblake@redhat.com>
Date: Tue, 30 Nov 2021 12:42:01 -0600
Subject: [PATCH] Fix "podwrapper.pl.in: Use short commit date"
This reverts commit 750ad5972bb082d188f17f8f71ef1ec0c616c676, then
fixes the broken newline as suggested in the thread at
https://listman.redhat.com/archives/libguestfs/2021-November/msg00275.html.
(cherry picked from commit 80036dbb0b8f9e0aab5994d80de6321c2a55c669)
---
podwrapper.pl.in | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/podwrapper.pl.in b/podwrapper.pl.in
index abad578d..6f256ba8 100755
--- a/podwrapper.pl.in
+++ b/podwrapper.pl.in
@@ -233,8 +233,7 @@ my $date;
my $filename = "$abs_top_srcdir/.git";
if (!$date && -d $filename) {
local $ENV{GIT_DIR} = $filename;
- $_ = `git show -O/dev/null -s --format=%ci`;
- $date = $1 if /^(\d+-\d+-\d+)\s/;
+ $date = `git show -O/dev/null -s --format=format:%cs`;
}
if (!$date) {
my ($day, $month, $year) = (gmtime($ENV{SOURCE_DATE_EPOCH} || time))[3,4,5];
--
2.31.1

View File

@ -0,0 +1,154 @@
From e00a8f2709fdf238daa195da03d8ea2aec9b05e1 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Tue, 30 Nov 2021 17:56:02 +0000
Subject: [PATCH] scripts: Add simple script for automating VDDK disk
connections
It's tedious to work out how to do this by hand every time. Include a
developer script to make connecting to a guest disk easy.
(cherry picked from commit 44ee90ee01677032a14d5b71118b7af0651db3d5)
---
.gitignore | 1 +
Makefile.am | 2 +-
configure.ac | 2 +
scripts/vddk-open.sh.in | 89 +++++++++++++++++++++++++++++++++++++++++
4 files changed, 93 insertions(+), 1 deletion(-)
create mode 100755 scripts/vddk-open.sh.in
diff --git a/.gitignore b/.gitignore
index 847b72dd..6565600f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -89,6 +89,7 @@ plugins/*/*.3
/plugins/S3/nbdkit-S3-plugin
/plugins/tmpdisk/default-command.c
/podwrapper.pl
+/scripts/vddk-open.sh
/server/libnbdkit.a
/server/local/nbdkit.pc
/server/nbdkit
diff --git a/Makefile.am b/Makefile.am
index 49f5d91c..6df5eba0 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -46,7 +46,7 @@ EXTRA_DIST = \
SECURITY \
$(NULL)
-CLEANFILES += html/*.html
+CLEANFILES += html/*.html scripts/*~
if !ENABLE_LIBFUZZER
# NB: This is not the real nbdkit binary. It's a wrapper that allows
diff --git a/configure.ac b/configure.ac
index 1b737fc1..08c307e9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1249,6 +1249,8 @@ dnl Produce output files.
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_FILES([podwrapper.pl],
[chmod +x,-w podwrapper.pl])
+AC_CONFIG_FILES([scripts/vddk-open.sh],
+ [chmod +x,-w scripts/vddk-open.sh])
AC_CONFIG_FILES([common/protocol/generate-protostrings.sh],
[chmod +x,-w common/protocol/generate-protostrings.sh])
AC_CONFIG_FILES([Makefile
diff --git a/scripts/vddk-open.sh.in b/scripts/vddk-open.sh.in
new file mode 100755
index 00000000..218bc93c
--- /dev/null
+++ b/scripts/vddk-open.sh.in
@@ -0,0 +1,89 @@
+#!/bin/bash -
+# @configure_input@
+# Copyright (C) 2013-2021 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.
+
+# Open an nbdkit-vddk-plugin connection to the first disk of a guest
+# on a VMware ESXi server. This script automates the tedious bits of
+# getting the disk name, moref, etc. However please read the
+# nbdkit-vddk-plugin documentation as well.
+#
+# Usage:
+# scripts/vddk-open.sh SERVER GUEST -r -f -v libdir=/path/to/vmware-vix-disklib-distrib [...]
+#
+# where SERVER is the hostname or IP address of the ESXi server and
+# GUEST is the name of the guest.
+#
+# These two required parameters are followed by any extra nbdkit
+# parameters you want to use, such as VDDK libdir, flags, filters etc.
+#
+# Note that the script runs ./nbdkit (ie. the wrapper in the top build
+# directory).
+
+nbdkit="@abs_top_builddir@/nbdkit"
+
+server="$1"
+guest="$2"
+shift 2
+
+# Get the libvirt XML, filename and moref.
+echo -n "root password? "
+xml="$( virsh -c "esx://root@$server/?no_verify=1" dumpxml "$guest" )"
+echo
+
+file="$( echo "$xml" | grep '<source file=' | head -1 |
+ sed -e "s/.*'\(.*\)'.*/\1/" )"
+moref="$( echo "$xml" | grep '<vmware:moref' |
+ sed -e 's,.*>\(.*\)<.*,\1,' )"
+
+#echo file="$file"
+#echo moref="$moref"
+
+# Get the thumbprint.
+thumbprint="$( openssl s_client -connect "$server:443" </dev/null 2>/dev/null |
+ openssl x509 -in /dev/stdin -fingerprint -sha1 -noout 2>/dev/null |
+ grep '^sha1 Fingerprint=' |
+ sed 's/.*Fingerprint=\([A-F0-9:]\+\)/\1/' )"
+
+#echo thumbprint="$thumbprint"
+
+# Construct the nbdkit command line.
+declare -a args
+
+args[${#args[@]}]="$nbdkit"
+args[${#args[@]}]="vddk"
+args[${#args[@]}]="file=$file"
+args[${#args[@]}]="vm=moref=$moref"
+args[${#args[@]}]="server=$server"
+args[${#args[@]}]="thumbprint=$thumbprint"
+args[${#args[@]}]="user=root"
+
+echo "${args[@]}" "$@"
+"${args[@]}" "$@"
--
2.31.1

View File

@ -0,0 +1,181 @@
From 5cb4adb94a6ff4325205fea3512c037c91579263 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Tue, 7 Dec 2021 21:08:26 +0000
Subject: [PATCH] file: Fix implementation of cache=none for writes
When testing virt-v2v we found that cache=none had very pessimal
performance in its current implementation when writing. See:
https://github.com/libguestfs/virt-v2v/commit/ac59d3b2310511b1537d408b675b19ec9a5d384e
However we know of a much better implementation - the one in nbdcopy.
This commit copies that implementation (for writes only).
A simple test is to do:
$ ./nbdkit file out.img cache=none --run 'nbdcopy fedora-33.img $uri'
and then check the cache usage of the output file, which should be
around 0% (using https://github.com/Feh/nocache):
$ cachestats out.img
pages in cache: 409/1572864 (0.0%) [filesize=6291456.0K, pagesize=4K]
For modular virt-v2v doing a local disk to local disk conversion:
- before this change, without cache=none
virt-v2v took 93.7 seconds, 19.1% pages cached in output file
- before this change, enabling cache=none
virt-v2v took 125.4 seconds, 0.0% pages cached in output file
^^^ this is the bad case which caused the investigation
- after this change, without cache=none
virt-v2v took 93.2 seconds, 19.1% pages cached in output file
- after this change, enabling cache=none
virt-v2v took 97.9 seconds, 0.1% pages cached in output file
I tried to adjust NR_WINDOWS to find an optimum. Increasing it made
no difference in performance but predictably caused a slight increase
in cached pages. Reducing it slowed performance slightly. So I
conclude that 8 is about right, but it probably depends on the
hardware.
(cherry picked from commit a956e2e75d6c88eeefecd967505667c9f176e3af)
---
plugins/file/file.c | 79 +++++++++++++++++++++++++----
plugins/file/nbdkit-file-plugin.pod | 3 ++
2 files changed, 72 insertions(+), 10 deletions(-)
diff --git a/plugins/file/file.c b/plugins/file/file.c
index 35270a24..caf24b2c 100644
--- a/plugins/file/file.c
+++ b/plugins/file/file.c
@@ -85,6 +85,69 @@ static int fadvise_mode =
/* cache mode */
static enum { cache_default, cache_none } cache_mode = cache_default;
+/* Define EVICT_WRITES if we are going to evict the page cache
+ * (cache=none) after writing. This is only known to work on Linux.
+ */
+#ifdef __linux__
+#define EVICT_WRITES 1
+#endif
+
+#ifdef EVICT_WRITES
+/* Queue writes so they will be evicted from the cache. See
+ * libnbd.git copy/file-ops.c for the rationale behind this.
+ */
+#define NR_WINDOWS 8
+
+struct write_window {
+ int fd;
+ uint64_t offset;
+ size_t len;
+};
+
+static pthread_mutex_t window_lock = PTHREAD_MUTEX_INITIALIZER;
+static struct write_window window[NR_WINDOWS];
+
+static void
+evict_writes (int fd, uint64_t offset, size_t len)
+{
+ ACQUIRE_LOCK_FOR_CURRENT_SCOPE (&window_lock);
+
+ /* Evict the oldest window from the page cache. */
+ if (window[0].len > 0) {
+ sync_file_range (window[0].fd, window[0].offset, window[0].len,
+ SYNC_FILE_RANGE_WAIT_BEFORE|SYNC_FILE_RANGE_WRITE|
+ SYNC_FILE_RANGE_WAIT_AFTER);
+ posix_fadvise (window[0].fd, window[0].offset, window[0].len,
+ POSIX_FADV_DONTNEED);
+ }
+
+ /* Move the Nth window to N-1. */
+ memmove (&window[0], &window[1], sizeof window[0] * (NR_WINDOWS-1));
+
+ /* Set up the current window and tell Linux to start writing it out
+ * to disk (asynchronously).
+ */
+ sync_file_range (fd, offset, len, SYNC_FILE_RANGE_WRITE);
+ window[NR_WINDOWS-1].fd = fd;
+ window[NR_WINDOWS-1].offset = offset;
+ window[NR_WINDOWS-1].len = len;
+}
+
+/* When we close the handle we must remove any windows which are still
+ * associated. They missed the boat, oh well :-(
+ */
+static void
+remove_fd_from_window (int fd)
+{
+ ACQUIRE_LOCK_FOR_CURRENT_SCOPE (&window_lock);
+ size_t i;
+
+ for (i = 0; i < NR_WINDOWS; ++i)
+ if (window[i].len > 0 && window[i].fd == fd)
+ window[i].len = 0;
+}
+#endif /* EVICT_WRITES */
+
/* Any callbacks using lseek must be protected by this lock. */
static pthread_mutex_t lseek_lock = PTHREAD_MUTEX_INITIALIZER;
@@ -431,6 +494,9 @@ file_close (void *handle)
{
struct handle *h = handle;
+#ifdef EVICT_WRITES
+ remove_fd_from_window (h->fd);
+#endif
close (h->fd);
free (h);
}
@@ -583,15 +649,9 @@ file_pwrite (void *handle, const void *buf, uint32_t count, uint64_t offset,
{
struct handle *h = handle;
-#if defined (HAVE_POSIX_FADVISE) && defined (POSIX_FADV_DONTNEED)
+#if EVICT_WRITES
uint32_t orig_count = count;
uint64_t orig_offset = offset;
-
- /* If cache=none we want to force pages we have just written to the
- * file to be flushed to disk so we can immediately evict them from
- * the page cache.
- */
- if (cache_mode == cache_none) flags |= NBDKIT_FLAG_FUA;
#endif
while (count > 0) {
@@ -608,10 +668,9 @@ file_pwrite (void *handle, const void *buf, uint32_t count, uint64_t offset,
if ((flags & NBDKIT_FLAG_FUA) && file_flush (handle, 0) == -1)
return -1;
-#if defined (HAVE_POSIX_FADVISE) && defined (POSIX_FADV_DONTNEED)
- /* On Linux this will evict the pages we just wrote from the page cache. */
+#if EVICT_WRITES
if (cache_mode == cache_none)
- posix_fadvise (h->fd, orig_offset, orig_count, POSIX_FADV_DONTNEED);
+ evict_writes (h->fd, orig_offset, orig_count);
#endif
return 0;
diff --git a/plugins/file/nbdkit-file-plugin.pod b/plugins/file/nbdkit-file-plugin.pod
index 0ac0ee53..f8f0e198 100644
--- a/plugins/file/nbdkit-file-plugin.pod
+++ b/plugins/file/nbdkit-file-plugin.pod
@@ -117,6 +117,9 @@ cache:
nbdkit file disk.img fadvise=sequential cache=none
+Only use fadvise=sequential if reading, and the reads are mainly
+sequential.
+
=head2 Files on tmpfs
If you want to expose a file that resides on a file system known to
--
2.31.1

View File

@ -0,0 +1,95 @@
From 92773e6852719354a136d31519948436f9adf7e9 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Sat, 18 Dec 2021 20:31:10 +0000
Subject: [PATCH] tests: Add configure --disable-libguestfs-tests flag
This can be used to disable tests which need libguestfs*. We were
already doing that in a hackish way in the Fedora build on some
architectures. This makes it more supportable.
Note that you can use
./configure --enable-libguestfs --disable-libguestfs-tests
to enable the bindings but disable the tests.
The difference between without and with the new flag on an otherwise
fully configured Fedora machine:
# TOTAL: 286
# PASS: 273
# SKIP: 13
# TOTAL: 263
# PASS: 251
# SKIP: 12
* except for those which directly test for requirements using
expressions like:
requires guestfish --version
(cherry picked from commit c09ae98ff3b4b786565de4aa173274531a753d30)
---
configure.ac | 17 ++++++++++++++++-
tests/Makefile.am | 2 ++
2 files changed, 18 insertions(+), 1 deletion(-)
diff --git a/configure.ac b/configure.ac
index 08c307e9..96d738d9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1146,7 +1146,8 @@ AS_IF([test "$with_libzstd" != "no"],[
])
AM_CONDITIONAL([HAVE_LIBZSTD],[test "x$LIBZSTD_LIBS" != "x"])
-dnl Check for libguestfs (only for the guestfs plugin and the test suite).
+dnl Check for libguestfs (only for the guestfs plugin and parts of
+dnl the test suite).
AC_ARG_WITH([libguestfs],
[AS_HELP_STRING([--without-libguestfs],
[disable guestfs plugin and tests @<:@default=check@:>@])],
@@ -1173,6 +1174,17 @@ AS_IF([test "$with_libguestfs" != "no"],[
])
AM_CONDITIONAL([HAVE_LIBGUESTFS],[test "x$LIBGUESTFS_LIBS" != "x"])
+dnl Disable tests which need libguestfs.
+AC_ARG_ENABLE([libguestfs-tests],
+ [AS_HELP_STRING([--disable-libguestfs-tests],
+ [disable tests which need libguestfs])],
+ [],
+ [enable_libguestfs_tests=check]
+)
+AM_CONDITIONAL([USE_LIBGUESTFS_FOR_TESTS],
+ [test "x$LIBGUESTFS_LIBS" != "x" && \
+ test "x$enable_libguestfs_tests" != "xno"])
+
dnl Check for ext2fs and com_err, for the ext2 filter.
AC_ARG_WITH([ext2],
[AS_HELP_STRING([--without-ext2],
@@ -1447,6 +1459,9 @@ echo "Other optional features:"
echo
feature "allocator=zstd ......................... " \
test "x$HAVE_LIBZSTD_TRUE" = "x"
+feature "tests using libguestfs ................. " \
+ test "x$HAVE_LIBGUESTFS_TRUE" = "x" -a \
+ "x$USE_LIBGUESTFS_FOR_TESTS_TRUE" = "x"
echo
echo "If any optional component is configured no when you expected yes"
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 2b7ae9f3..43b60943 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -1888,6 +1888,8 @@ TESTS += $(LIBNBD_TESTS)
endif HAVE_LIBNBD
if HAVE_LIBGUESTFS
+if USE_LIBGUESTFS_FOR_TESTS
check_PROGRAMS += $(LIBGUESTFS_TESTS)
TESTS += $(LIBGUESTFS_TESTS)
+endif USE_LIBGUESTFS_FOR_TESTS
endif HAVE_LIBGUESTFS
--
2.31.1

View File

@ -0,0 +1,538 @@
From cf58241f19ed179e48c53f4d6c71df47dd2f5931 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Tue, 18 Jan 2022 08:58:15 +0000
Subject: [PATCH] vddk: Implement VMDK creation
Add the create=(true|false) parameter. Setting this to true causes
the VMDK local file to be created. Currently this is done on first
connection, but we might change that in future. Various other
parameters can be used to control aspects of the VMDK file.
(cherry picked from commit a39d5773afc3ebab7e5768118a2bccb89a654585)
---
plugins/vddk/nbdkit-vddk-plugin.pod | 102 ++++++++++++++++++++++-
plugins/vddk/vddk-structs.h | 32 +++++++
plugins/vddk/vddk-stubs.h | 7 ++
plugins/vddk/vddk.c | 125 ++++++++++++++++++++++++++++
plugins/vddk/vddk.h | 5 ++
tests/Makefile.am | 6 +-
tests/dummy-vddk.c | 10 +++
tests/test-vddk-real-create.sh | 70 ++++++++++++++++
8 files changed, 354 insertions(+), 3 deletions(-)
create mode 100755 tests/test-vddk-real-create.sh
diff --git a/plugins/vddk/nbdkit-vddk-plugin.pod b/plugins/vddk/nbdkit-vddk-plugin.pod
index acec0bd2..b96192d0 100644
--- a/plugins/vddk/nbdkit-vddk-plugin.pod
+++ b/plugins/vddk/nbdkit-vddk-plugin.pod
@@ -6,7 +6,11 @@ nbdkit-vddk-plugin - nbdkit VMware VDDK plugin
nbdkit vddk [file=]FILENAME
[compression=none|zlib|fastlz|skipz]
- [config=FILENAME] [cookie=COOKIE] [libdir=LIBRARY]
+ [config=FILENAME] [cookie=COOKIE]
+ [create=true] [create-adapter-type=ide|scsi-buslogic|...]
+ [create-hwversion=workstation4|workstation5|...]
+ [create-size=...] [create-type=monolithic-sparse|...]
+ [libdir=LIBRARY]
[nfchostport=PORT] [single-link=true]
[password=PASSWORD | password=- | password=+FILENAME |
password=-FD]
@@ -26,7 +30,7 @@ yourself (see L</LIBRARY LOCATION> below).
=head1 EXAMPLES
-=head2 Open a local VMDK file
+=head2 Open an existing local VMDK file
nbdkit vddk /absolute/path/to/file.vmdk
@@ -38,6 +42,18 @@ I<-r> option):
nbdkit -r vddk /absolute/path/to/file.vmdk
+=head2 Create a new local VMDK file
+
+You can use VDDK to create a VMDK file and fill it with the contents
+of a disk image. Note the C<create-size> parameter is the virtual
+size of the final VMDK disk image and must be at least as large as the
+input disk:
+
+ nbdkit -U - vddk \
+ /absolute/path/to/output.vmdk \
+ create=1 create-size=100M \
+ --run 'qemu-img convert input.qcow2 $uri'
+
=head2 Open a file on a remote VMware ESXi hypervisor
Connect directly to a VMware ESXi hypervisor and export a particular
@@ -136,6 +152,88 @@ C<VIXDISKLIB_CRED_SESSIONID> which can improve performance. The
cookie can be found by connecting to a VCenter Server over HTTPS and
retrieving the C<vmware_soap_session> cookie.
+=item B<create=true>
+
+(nbdkit E<ge> 1.30)
+
+Create a new, local VMDK file. Instead of opening an existing VMDK
+file, a new VMDK file is created and opened. The filename is given by
+the C<file> parameter (see below). The file must not exist already.
+It is not possible to create a remote file using nbdkit.
+
+If this is used, the C<create-size> parameter is required to specify
+the virtual size of the disk. Other C<create-*> parameters (see
+below) can be used to control the VMDK sub-format.
+
+=item B<create-adapter-type=ide>
+
+=item B<create-adapter-type=scsi-buslogic>
+
+=item B<create-adapter-type=scsi-lsilogic>
+
+(nbdkit E<ge> 1.30)
+
+Specify the VMDK disk adapter type. The default is C<scsi-buslogic>.
+
+=item B<create-hwversion=workstation4>
+
+=item B<create-hwversion=workstation5>
+
+=item B<create-hwversion=workstation6>
+
+=item B<create-hwversion=esx30>
+
+=item B<create-hwversion=esx4x>
+
+=item B<create-hwversion=esx50>
+
+=item B<create-hwversion=esx51>
+
+=item B<create-hwversion=esx55>
+
+=item B<create-hwversion=esx60>
+
+=item B<create-hwversion=esx65>
+
+(nbdkit E<ge> 1.30)
+
+Specify the VMDK virtual hardware version. The default is
+C<workstation5>.
+
+=item B<create-size=>SIZE
+
+(nbdkit E<ge> 1.30)
+
+Specify the virtual size of the created disk. The C<SIZE> can use
+modifiers like C<100M> etc. It must be a multiple of 512 bytes
+because VMware only supports sector sizes.
+
+If you use C<create=true> then this parameter is required.
+
+=item B<create-type=monolithic-sparse>
+
+=item B<create-type=monolithic-flat>
+
+=item B<create-type=split-sparse>
+
+=item B<create-type=split-flat>
+
+=item B<create-type=vmfs-flat>
+
+=item B<create-type=stream-optimized>
+
+=item B<create-type=vmfs-thin>
+
+=item B<create-type=vmfs-sparse>
+
+(nbdkit E<ge> 1.30)
+
+Specify the VMDK sub-format. The default is C<monolithic-sparse>.
+
+Some VMDK sub-formats use multiple files, where the C<file> parameter
+specifies the "Disk Descriptor File" and the disk contents are stored
+in adjacent files.
+
=item [B<file=>]FILENAME
=item [B<file=>]B<[>datastoreB<] >vmname/vmnameB<.vmdk>
diff --git a/plugins/vddk/vddk-structs.h b/plugins/vddk/vddk-structs.h
index e97f017c..799c4aec 100644
--- a/plugins/vddk/vddk-structs.h
+++ b/plugins/vddk/vddk-structs.h
@@ -43,6 +43,7 @@
typedef uint64_t VixError;
#define VIX_OK 0
+#define VIX_E_NOT_SUPPORTED 6
#define VIX_ASYNC 25000
#define VIXDISKLIB_FLAG_OPEN_UNBUFFERED 1
@@ -54,6 +55,28 @@ typedef uint64_t VixError;
#define VIXDISKLIB_SECTOR_SIZE 512
+enum VixDiskLibDiskType {
+ VIXDISKLIB_DISK_MONOLITHIC_SPARSE = 1,
+ VIXDISKLIB_DISK_MONOLITHIC_FLAT = 2,
+ VIXDISKLIB_DISK_SPLIT_SPARSE = 3,
+ VIXDISKLIB_DISK_SPLIT_FLAT = 4,
+ VIXDISKLIB_DISK_VMFS_FLAT = 5,
+ VIXDISKLIB_DISK_STREAM_OPTIMIZED = 6,
+ VIXDISKLIB_DISK_VMFS_THIN = 7,
+ VIXDISKLIB_DISK_VMFS_SPARSE = 8
+};
+
+#define VIXDISKLIB_HWVERSION_WORKSTATION_4 3
+#define VIXDISKLIB_HWVERSION_WORKSTATION_5 4
+#define VIXDISKLIB_HWVERSION_WORKSTATION_6 6
+#define VIXDISKLIB_HWVERSION_ESX30 4
+#define VIXDISKLIB_HWVERSION_ESX4X 7
+#define VIXDISKLIB_HWVERSION_ESX50 8
+#define VIXDISKLIB_HWVERSION_ESX51 9
+#define VIXDISKLIB_HWVERSION_ESX55 10
+#define VIXDISKLIB_HWVERSION_ESX60 11
+#define VIXDISKLIB_HWVERSION_ESX65 13
+
#define VIXDISKLIB_MIN_CHUNK_SIZE 128
#define VIXDISKLIB_MAX_CHUNK_NUMBER (512*1024)
@@ -148,4 +171,13 @@ typedef struct {
VixDiskLibBlock blocks[1];
} VixDiskLibBlockList;
+typedef struct {
+ enum VixDiskLibDiskType diskType;
+ enum VixDiskLibAdapterType adapterType;
+ uint16_t hwVersion;
+ uint64_t capacity;
+ uint32_t logicalSectorSize;
+ uint32_t physicalSectorSize;
+} VixDiskLibCreateParams;
+
#endif /* NBDKIT_VDDK_STRUCTS_H */
diff --git a/plugins/vddk/vddk-stubs.h b/plugins/vddk/vddk-stubs.h
index 7d8644c3..d5affa10 100644
--- a/plugins/vddk/vddk-stubs.h
+++ b/plugins/vddk/vddk-stubs.h
@@ -99,6 +99,13 @@ STUB (VixDiskLib_Write,
(VixDiskLibHandle handle,
uint64_t start_sector, uint64_t nr_sectors,
const unsigned char *buf));
+STUB (VixDiskLib_Create,
+ VixError,
+ (const VixDiskLibConnection connection,
+ const char *path,
+ const VixDiskLibCreateParams *create_params,
+ void *progress_function_unused,
+ void *progress_data_unused));
/* Added in VDDK 6.0. */
STUB (VixDiskLib_Flush,
diff --git a/plugins/vddk/vddk.c b/plugins/vddk/vddk.c
index 31e5e23b..5ebf9a2c 100644
--- a/plugins/vddk/vddk.c
+++ b/plugins/vddk/vddk.c
@@ -81,6 +81,14 @@ bool is_remote; /* true if remote connection */
enum compression_type compression; /* compression */
char *config; /* config */
const char *cookie; /* cookie */
+bool create; /* create */
+enum VixDiskLibAdapterType create_adapter_type =
+ VIXDISKLIB_ADAPTER_SCSI_BUSLOGIC; /* create-adapter-type */
+uint16_t create_hwversion =
+ VIXDISKLIB_HWVERSION_WORKSTATION_5; /* create-hwversion */
+uint64_t create_size; /* create-size */
+enum VixDiskLibDiskType create_type =
+ VIXDISKLIB_DISK_MONOLITHIC_SPARSE; /* create-type */
const char *filename; /* file */
char *libdir; /* libdir */
uint16_t nfc_host_port; /* nfchostport */
@@ -119,6 +127,7 @@ static int
vddk_config (const char *key, const char *value)
{
int r;
+ int64_t r64;
if (strcmp (key, "compression") == 0) {
if (strcmp (value, "zlib") == 0)
@@ -144,6 +153,82 @@ vddk_config (const char *key, const char *value)
else if (strcmp (key, "cookie") == 0) {
cookie = value;
}
+ else if (strcmp (key, "create") == 0) {
+ r = nbdkit_parse_bool (value);
+ if (r == -1)
+ return -1;
+ create = r;
+ }
+ else if (strcmp (key, "create-adapter-type") == 0) {
+ if (strcmp (value, "ide") == 0)
+ create_adapter_type = VIXDISKLIB_ADAPTER_IDE;
+ else if (strcmp (value, "scsi-buslogic") == 0)
+ create_adapter_type = VIXDISKLIB_ADAPTER_SCSI_BUSLOGIC;
+ else if (strcmp (value, "scsi-lsilogic") == 0)
+ create_adapter_type = VIXDISKLIB_ADAPTER_SCSI_LSILOGIC;
+ else {
+ nbdkit_error ("unknown create-adapter-type: %s", value);
+ return -1;
+ }
+ }
+ else if (strcmp (key, "create-hwversion") == 0) {
+ if (strcmp (value, "workstation4") == 0)
+ create_hwversion = VIXDISKLIB_HWVERSION_WORKSTATION_4;
+ else if (strcmp (value, "workstation5") == 0)
+ create_hwversion = VIXDISKLIB_HWVERSION_WORKSTATION_5;
+ else if (strcmp (value, "workstation6") == 0)
+ create_hwversion = VIXDISKLIB_HWVERSION_WORKSTATION_6;
+ else if (strcmp (value, "esx30") == 0)
+ create_hwversion = VIXDISKLIB_HWVERSION_ESX30;
+ else if (strcmp (value, "esx4x") == 0)
+ create_hwversion = VIXDISKLIB_HWVERSION_ESX4X;
+ else if (strcmp (value, "esx50") == 0)
+ create_hwversion = VIXDISKLIB_HWVERSION_ESX50;
+ else if (strcmp (value, "esx51") == 0)
+ create_hwversion = VIXDISKLIB_HWVERSION_ESX51;
+ else if (strcmp (value, "esx55") == 0)
+ create_hwversion = VIXDISKLIB_HWVERSION_ESX55;
+ else if (strcmp (value, "esx60") == 0)
+ create_hwversion = VIXDISKLIB_HWVERSION_ESX60;
+ else if (strcmp (value, "esx65") == 0)
+ create_hwversion = VIXDISKLIB_HWVERSION_ESX65;
+ else {
+ nbdkit_error ("unknown create-hwversion: %s", value);
+ return -1;
+ }
+ }
+ else if (strcmp (key, "create-size") == 0) {
+ r64 = nbdkit_parse_size (value);
+ if (r64 == -1)
+ return -1;
+ if (r64 <= 0 || (r64 & 511) != 0) {
+ nbdkit_error ("create-size must be greater than zero and a multiple of 512");
+ return -1;
+ }
+ create_size = r64;
+ }
+ else if (strcmp (key, "create-type") == 0) {
+ if (strcmp (value, "monolithic-sparse") == 0)
+ create_type = VIXDISKLIB_DISK_MONOLITHIC_SPARSE;
+ else if (strcmp (value, "monolithic-flat") == 0)
+ create_type = VIXDISKLIB_DISK_MONOLITHIC_FLAT;
+ else if (strcmp (value, "split-sparse") == 0)
+ create_type = VIXDISKLIB_DISK_SPLIT_SPARSE;
+ else if (strcmp (value, "split-flat") == 0)
+ create_type = VIXDISKLIB_DISK_SPLIT_FLAT;
+ else if (strcmp (value, "vmfs-flat") == 0)
+ create_type = VIXDISKLIB_DISK_VMFS_FLAT;
+ else if (strcmp (value, "stream-optimized") == 0)
+ create_type = VIXDISKLIB_DISK_STREAM_OPTIMIZED;
+ else if (strcmp (value, "vmfs-thin") == 0)
+ create_type = VIXDISKLIB_DISK_VMFS_THIN;
+ else if (strcmp (value, "vmfs-sparse") == 0)
+ create_type = VIXDISKLIB_DISK_VMFS_SPARSE;
+ else {
+ nbdkit_error ("unknown create-type: %s", value);
+ return -1;
+ }
+ }
else if (strcmp (key, "file") == 0) {
/* NB: Don't convert this to an absolute path, because in the
* remote case this can be a path located on the VMware server.
@@ -266,6 +351,18 @@ vddk_config_complete (void)
#undef missing
}
+ if (create) {
+ if (is_remote) {
+ nbdkit_error ("create=true can only be used to create local VMDK files");
+ return -1;
+ }
+
+ if (create_size == 0) {
+ nbdkit_error ("if using create=true you must specify the size using the create-size parameter");
+ return -1;
+ }
+ }
+
/* Restore original LD_LIBRARY_PATH after reexec. */
if (restore_ld_library_path () == -1)
return -1;
@@ -618,6 +715,34 @@ vddk_open (int readonly)
goto err1;
}
+ /* Creating a disk? The first time the connection is opened we will
+ * create it here (we need h->connection). Then set create=false so
+ * we don't create it again. This is all serialized through
+ * open_close_lock so it is safe.
+ */
+ if (create) {
+ VixDiskLibCreateParams cparams = {
+ .diskType = create_type,
+ .adapterType = create_adapter_type,
+ .hwVersion = create_hwversion,
+ .capacity = create_size / VIXDISKLIB_SECTOR_SIZE,
+ .logicalSectorSize = 0,
+ .physicalSectorSize = 0
+ };
+
+ VDDK_CALL_START (VixDiskLib_Create,
+ "h->connection, %s, &cparams, NULL, NULL",
+ filename)
+ err = VixDiskLib_Create (h->connection, filename, &cparams, NULL, NULL);
+ VDDK_CALL_END (VixDiskLib_Create, 0);
+ if (err != VIX_OK) {
+ VDDK_ERROR (err, "VixDiskLib_Create: %s", filename);
+ goto err2;
+ }
+
+ create = false; /* Don't create it again. */
+ }
+
flags = 0;
if (readonly)
flags |= VIXDISKLIB_FLAG_OPEN_READ_ONLY;
diff --git a/plugins/vddk/vddk.h b/plugins/vddk/vddk.h
index d99b6f4b..3a808013 100644
--- a/plugins/vddk/vddk.h
+++ b/plugins/vddk/vddk.h
@@ -56,6 +56,11 @@ extern bool is_remote;
extern enum compression_type compression;
extern char *config;
extern const char *cookie;
+extern bool create;
+extern enum VixDiskLibAdapterType create_adapter_type;
+extern uint16_t create_hwversion;
+extern uint64_t create_size;
+extern enum VixDiskLibDiskType create_type;
extern const char *filename;
extern char *libdir;
extern uint16_t nfc_host_port;
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 43b60943..ad2d43b9 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -171,7 +171,9 @@ if HAVE_VDDK
#
# make check-vddk vddkdir=vmware-vix-disklib-distrib
check-vddk:
- $(MAKE) check TESTS="test-vddk-real.sh test-vddk-real-dump-plugin.sh"
+ $(MAKE) check TESTS="test-vddk-real.sh
+ test-vddk-real-dump-plugin.sh
+ test-vddk-real-create.sh"
endif HAVE_VDDK
#----------------------------------------------------------------------
@@ -1033,6 +1035,7 @@ TESTS += \
test-vddk-dump-plugin.sh \
test-vddk-password-fd.sh \
test-vddk-password-interactive.sh \
+ test-vddk-real-create.sh \
test-vddk-real-dump-plugin.sh \
test-vddk-real.sh \
test-vddk-reexec.sh \
@@ -1063,6 +1066,7 @@ EXTRA_DIST += \
test-vddk-dump-plugin.sh \
test-vddk-password-fd.sh \
test-vddk-password-interactive.sh \
+ test-vddk-real-create.sh \
test-vddk-real-dump-plugin.sh \
test-vddk-real.sh \
test-vddk-reexec.sh \
diff --git a/tests/dummy-vddk.c b/tests/dummy-vddk.c
index b6f12042..0c5e505f 100644
--- a/tests/dummy-vddk.c
+++ b/tests/dummy-vddk.c
@@ -236,3 +236,13 @@ VixDiskLib_Wait (VixDiskLibHandle handle)
{
return VIX_OK;
}
+
+NBDKIT_DLL_PUBLIC VixError
+VixDiskLib_Create (const VixDiskLibConnection connection,
+ const char *path,
+ const VixDiskLibCreateParams *create_params,
+ void *progress_function_unused,
+ void *progress_data_unused)
+{
+ return VIX_E_NOT_SUPPORTED;
+}
diff --git a/tests/test-vddk-real-create.sh b/tests/test-vddk-real-create.sh
new file mode 100755
index 00000000..8f39a4c9
--- /dev/null
+++ b/tests/test-vddk-real-create.sh
@@ -0,0 +1,70 @@
+#!/usr/bin/env bash
+# nbdkit
+# Copyright (C) 2018-2022 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.
+
+source ./functions.sh
+set -e
+set -x
+
+requires test "x$vddkdir" != "x"
+requires test -d "$vddkdir"
+requires test -f "$vddkdir/lib64/libvixDiskLib.so"
+requires test -f disk
+requires nbdcopy --version
+requires stat --version
+
+# Testing $LD_LIBRARY_PATH stuff breaks valgrind, so skip the rest of
+# this test if valgrinding.
+if [ "x$NBDKIT_VALGRIND" = "x1" ]; then
+ echo "$0: skipped LD_LIBRARY_PATH test when doing valgrind"
+ exit 77
+fi
+
+# VDDK > 5.1.1 only supports x86_64.
+if [ `uname -m` != "x86_64" ]; then
+ echo "$0: unsupported architecture"
+ exit 77
+fi
+
+vmdk=$PWD/test-vddk-real-create.vmdk ;# note must be an absolute path
+files="$vmdk"
+rm -f $files
+cleanup_fn rm -f $files
+
+size="$(stat -c %s disk)"
+
+nbdkit -fv -U - vddk libdir="$vddkdir" $vmdk \
+ create=true create-size=$size \
+ --run 'nbdcopy disk $uri'
+
+# Check the VMDK file was created and looks reasonable.
+test -f $vmdk
+file $vmdk | grep 'VMware'
--
2.31.1

View File

@ -0,0 +1,29 @@
From eb5d5a628968c7fd5401cf7e73a6cff6c43994aa Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Tue, 18 Jan 2022 13:14:01 +0000
Subject: [PATCH] vddk: Fix documentation of new create flag
create=1 works, but for consistency use create=true
Fixes: commit a39d5773afc3ebab7e5768118a2bccb89a654585
(cherry picked from commit 0b21897b64a6a1d97a8a7361e8f781ae743dedca)
---
plugins/vddk/nbdkit-vddk-plugin.pod | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/plugins/vddk/nbdkit-vddk-plugin.pod b/plugins/vddk/nbdkit-vddk-plugin.pod
index b96192d0..6c7ae989 100644
--- a/plugins/vddk/nbdkit-vddk-plugin.pod
+++ b/plugins/vddk/nbdkit-vddk-plugin.pod
@@ -51,7 +51,7 @@ input disk:
nbdkit -U - vddk \
/absolute/path/to/output.vmdk \
- create=1 create-size=100M \
+ create=true create-size=100M \
--run 'qemu-img convert input.qcow2 $uri'
=head2 Open a file on a remote VMware ESXi hypervisor
--
2.31.1

View File

@ -0,0 +1,55 @@
From c8cdce47bc38d2f59ecc4b75d6db7f032b63d527 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Tue, 18 Jan 2022 20:49:21 +0000
Subject: [PATCH] vddk: Allow create-hwversion to be specified as a number
This gives us a bit of future-proofing so we don't always need to add
new hardware versions immediately. Another reason for this is that
VDDK allows you to specify seemingly any number here without
complaint.
Updates: commit a39d5773afc3ebab7e5768118a2bccb89a654585
(cherry picked from commit 071e32927237c2c00d78684c8a0f2e5fbca9963e)
---
plugins/vddk/nbdkit-vddk-plugin.pod | 8 ++++++--
plugins/vddk/vddk.c | 3 ++-
2 files changed, 8 insertions(+), 3 deletions(-)
diff --git a/plugins/vddk/nbdkit-vddk-plugin.pod b/plugins/vddk/nbdkit-vddk-plugin.pod
index 6c7ae989..e6972900 100644
--- a/plugins/vddk/nbdkit-vddk-plugin.pod
+++ b/plugins/vddk/nbdkit-vddk-plugin.pod
@@ -195,10 +195,14 @@ Specify the VMDK disk adapter type. The default is C<scsi-buslogic>.
=item B<create-hwversion=esx65>
+=item B<create-hwversion=>N
+
(nbdkit E<ge> 1.30)
-Specify the VMDK virtual hardware version. The default is
-C<workstation5>.
+Specify the VMDK virtual hardware version. You can give either the
+named version or the equivalent 16 bit number.
+
+The default is C<workstation5> (N = 4).
=item B<create-size=>SIZE
diff --git a/plugins/vddk/vddk.c b/plugins/vddk/vddk.c
index 5ebf9a2c..bab8de6f 100644
--- a/plugins/vddk/vddk.c
+++ b/plugins/vddk/vddk.c
@@ -192,7 +192,8 @@ vddk_config (const char *key, const char *value)
create_hwversion = VIXDISKLIB_HWVERSION_ESX60;
else if (strcmp (value, "esx65") == 0)
create_hwversion = VIXDISKLIB_HWVERSION_ESX65;
- else {
+ else if (nbdkit_parse_uint16_t ("create-hwversion", value,
+ &create_hwversion) == -1) {
nbdkit_error ("unknown create-hwversion: %s", value);
return -1;
}
--
2.31.1

View File

@ -0,0 +1,31 @@
From 84c5bc4664607fdf1f051e9e52ac6d0e4f0be049 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Tue, 18 Jan 2022 21:02:32 +0000
Subject: [PATCH] tests: Fix VDDK tests
We need to use quoting for the subcommand split across lines.
Fixes: commit a39d5773afc3ebab7e5768118a2bccb89a654585
(cherry picked from commit 4df525566b38202ed8a7485ac8e7f06edd5ee49a)
---
tests/Makefile.am | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/tests/Makefile.am b/tests/Makefile.am
index ad2d43b9..62a6f05b 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -171,8 +171,8 @@ if HAVE_VDDK
#
# make check-vddk vddkdir=vmware-vix-disklib-distrib
check-vddk:
- $(MAKE) check TESTS="test-vddk-real.sh
- test-vddk-real-dump-plugin.sh
+ $(MAKE) check TESTS="test-vddk-real.sh \
+ test-vddk-real-dump-plugin.sh \
test-vddk-real-create.sh"
endif HAVE_VDDK
--
2.31.1

View File

@ -0,0 +1,204 @@
From 222bce6b83421db1afdad24cf4e8ab7b1aa7b273 Mon Sep 17 00:00:00 2001
From: Laszlo Ersek <lersek@redhat.com>
Date: Tue, 18 Jan 2022 14:48:33 +0100
Subject: [PATCH] server/sockets: get rid of AI_ADDRCONFIG
The AI_ADDRCONFIG hint of getaddrinfo() is supposed to restrict the name
resolution to such address families (IPv4 vs. IPv6) for which the
resolving host has publicly routable addresses assigned.
The main problem with AI_ADDRCONFIG can be shown with the following
command line:
$ nbdkit -f -p 32776 -P pidfile -i ::1 --exit-with-parent null
On a host where ::1 is the only IPv6 address assigned (namely to the
loopback interface), the command fails with
> nbdkit: getaddrinfo: ::1: 32776: Address family for hostname not
> supported
due to the "publicly routable" requirement.
Remove AI_ADDRCONFIG from the getaddrinfo() hints, and as a replacement,
introduce the "-4" and "-6" options, similarly to netcat and ssh.
(1) This makes options of the form:
-i 127.0.0.1
-i ::1
work regardless of "public" IPv6 / IPv4 connectivity;
(2) options of the form
-i localhost
-i FQDN
will bind both IPv4 and IPv6 addresses of the desired interface(s);
(3) omitting the option "-i" will bind both IPv4 and IPv6 wildcard
addresses (0.0.0.0 and ::);
(4) the configurations in (2) and (3) can be restricted to IPv4 or IPv6
addresses by adding the "-4" or "-6" option, respectively.
Importantly, this change allows the "connect-tcp6" test case of libnbd to
pass on such hosts that have no IPv6 connectivity (i.e., where the only
assigned IPv6 address is ::1, namely on the loopback interface).
Ref: https://listman.redhat.com/archives/libguestfs/2022-January/msg00110.html
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Message-Id: <20220118134833.13246-3-lersek@redhat.com>
[lersek@redhat.com: fix typo in "--exit-with-parent" (Eric)]
Acked-by: Eric Blake <eblake@redhat.com>
(cherry picked from commit 9eec2335d630ae8ef947a927c1922d725d482f4a)
---
common/utils/windows-compat.h | 7 -------
docs/nbdkit.pod | 20 +++++++++++++++++++-
docs/synopsis.txt | 3 ++-
server/internal.h | 1 +
server/main.c | 9 +++++++++
server/options.h | 4 +++-
server/sockets.c | 3 ++-
7 files changed, 36 insertions(+), 11 deletions(-)
diff --git a/common/utils/windows-compat.h b/common/utils/windows-compat.h
index 7695bf7e..658c1d8b 100644
--- a/common/utils/windows-compat.h
+++ b/common/utils/windows-compat.h
@@ -75,13 +75,6 @@ struct sockaddr_un
#define O_NOCTTY 0
#endif
-/* AI_ADDRCONFIG is not available on Windows. It enables a rather
- * obscure feature of getaddrinfo to do with IPv6.
- */
-#ifndef AI_ADDRCONFIG
-#define AI_ADDRCONFIG 0
-#endif
-
/* Windows <errno.h> lacks certain errnos, so replace them here as
* best we can.
*/
diff --git a/docs/nbdkit.pod b/docs/nbdkit.pod
index 99cfb362..042607fb 100644
--- a/docs/nbdkit.pod
+++ b/docs/nbdkit.pod
@@ -173,6 +173,24 @@ Display information about nbdkit or a specific plugin:
Display brief command line usage information and exit.
+=item B<-4>
+
+=item B<--ipv4-only>
+
+=item B<-6>
+
+=item B<--ipv6-only>
+
+When a non-numeric argument is passed to the I<-i> option (such as a
+Fully Qualified Domain Name, or a host name from C</etc/hosts>),
+restrict the name resolution to IPv4 or IPv6 addresses.
+
+When the I<-i> option is omitted, listen on only the IPv4 or IPv6
+address of all interfaces (C<0.0.0.0> or C<::>, respectively).
+
+When both I<-4> and I<-6> options are present on the command line, the
+last one takes effect.
+
=item B<-D> PLUGIN.FLAG=N
=item B<-D> FILTER.FLAG=N
@@ -265,7 +283,7 @@ See also I<-u>.
=item B<--ipaddr> IPADDR
Listen on the specified interface. The default is to listen on all
-interfaces. See also I<-p>.
+interfaces. See also I<-4>, I<-6>, and I<-p>.
=item B<--log=stderr>
diff --git a/docs/synopsis.txt b/docs/synopsis.txt
index 07b9dcff..6154bb2e 100644
--- a/docs/synopsis.txt
+++ b/docs/synopsis.txt
@@ -1,4 +1,5 @@
-nbdkit [-D|--debug PLUGIN|FILTER|nbdkit.FLAG=N]
+nbdkit [-4|--ipv4-only] [-6|--ipv6-only]
+ [-D|--debug PLUGIN|FILTER|nbdkit.FLAG=N]
[-e|--exportname EXPORTNAME] [--exit-with-parent]
[--filter FILTER ...] [-f|--foreground]
[-g|--group GROUP] [-i|--ipaddr IPADDR]
diff --git a/server/internal.h b/server/internal.h
index bc81b786..46fcdd46 100644
--- a/server/internal.h
+++ b/server/internal.h
@@ -113,6 +113,7 @@ enum log_to {
LOG_TO_NULL, /* --log=null forced on the command line */
};
+extern int tcpip_sock_af;
extern struct debug_flag *debug_flags;
extern const char *export_name;
extern bool foreground;
diff --git a/server/main.c b/server/main.c
index 225258de..8e7ac149 100644
--- a/server/main.c
+++ b/server/main.c
@@ -86,6 +86,7 @@ static void error_if_stdio_closed (void);
static void switch_stdio (void);
static void winsock_init (void);
+int tcpip_sock_af = AF_UNSPEC; /* -4, -6 */
struct debug_flag *debug_flags; /* -D */
bool exit_with_parent; /* --exit-with-parent */
const char *export_name; /* -e */
@@ -367,6 +368,14 @@ main (int argc, char *argv[])
exit (EXIT_FAILURE);
#endif
+ case '4':
+ tcpip_sock_af = AF_INET;
+ break;
+
+ case '6':
+ tcpip_sock_af = AF_INET6;
+ break;
+
case 'D':
add_debug_flag (optarg);
break;
diff --git a/server/options.h b/server/options.h
index e59ef17f..39299b9d 100644
--- a/server/options.h
+++ b/server/options.h
@@ -59,8 +59,10 @@ enum {
VSOCK_OPTION,
};
-static const char *short_options = "D:e:fg:i:nop:P:rst:u:U:vV";
+static const char *short_options = "46D:e:fg:i:nop:P:rst:u:U:vV";
static const struct option long_options[] = {
+ { "ipv4-only", no_argument, NULL, '4' },
+ { "ipv6-only", no_argument, NULL, '6' },
{ "debug", required_argument, NULL, 'D' },
{ "dump-config", no_argument, NULL, DUMP_CONFIG_OPTION },
{ "dump-plugin", no_argument, NULL, DUMP_PLUGIN_OPTION },
diff --git a/server/sockets.c b/server/sockets.c
index 15a26f69..4e4ccbc4 100644
--- a/server/sockets.c
+++ b/server/sockets.c
@@ -179,7 +179,8 @@ bind_tcpip_socket (sockets *socks)
port = "10809";
memset (&hints, 0, sizeof hints);
- hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG;
+ hints.ai_flags = AI_PASSIVE;
+ hints.ai_family = tcpip_sock_af;
hints.ai_socktype = SOCK_STREAM;
err = getaddrinfo (ipaddr, port, &hints, &ai);
--
2.31.1

55
SOURCES/copy-patches.sh Executable file
View File

@ -0,0 +1,55 @@
#!/bin/bash -
set -e
# Maintainer script to copy patches from the git repo to the current
# directory. Use it like this:
# ./copy-patches.sh
rhel_version=9.0
# Check we're in the right directory.
if [ ! -f nbdkit.spec ]; then
echo "$0: run this from the directory containing 'nbdkit.spec'"
exit 1
fi
git_checkout=$HOME/d/nbdkit-rhel-$rhel_version
if [ ! -d $git_checkout ]; then
echo "$0: $git_checkout does not exist"
echo "This script is only for use by the maintainer when preparing a"
echo "nbdkit release on RHEL."
exit 1
fi
# Get the base version of nbdkit.
version=`grep '^Version:' nbdkit.spec | awk '{print $2}'`
tag="v$version"
# Remove any existing patches.
git rm -f [0-9]*.patch ||:
rm -f [0-9]*.patch
# Get the patches.
(cd $git_checkout; rm -f [0-9]*.patch; git format-patch -N $tag)
mv $git_checkout/[0-9]*.patch .
# Remove any not to be applied.
rm -f *NOT-FOR-RPM*.patch
# Add the patches.
git add [0-9]*.patch
# Print out the patch lines.
echo
echo "--- Copy the following text into nbdkit.spec file"
echo
echo "# Patches."
for f in [0-9]*.patch; do
n=`echo $f | awk -F- '{print $1}'`
echo "Patch$n: $f"
done
echo
echo "--- End of text"

View File

@ -0,0 +1,17 @@
-----BEGIN PGP SIGNATURE-----
iQJFBAABCAAvFiEE93dPsa0HSn6Mh2fqkXOPc+G3aKAFAmHumIgRHHJpY2hAYW5u
ZXhpYS5vcmcACgkQkXOPc+G3aKAt/RAAlUnU/dJ6d1bec5ggmfTgWYwHcXqc6bGi
Tp0vxG+2LiE/D52xhGvaRWQwd2mR4vvHiDLlBitlBZNHItyuB9wM9r5SAIRw5PcR
1kCILAKGQN2dLSS+HUyib6cnlughFwIeSt4XuhwgedLlIBZ+2d38IRC3ia4ShbIX
btZMwRmpD/06Py8A+tM856zb1YgjpA3nQIC56r/ne25vLyAY4LE8T2BtjlkmBxBy
Lswg0KM3+SBsMWwbo0aCfyTOW9lpVa2WnLgu/9nsfIjA+m9kcjfpjfmhduV6lfrx
KRFGtKQnl+RWfhhfmxeCWo5/mXqrqOga7VIWltxRkjQ916TrzTWwMnWBtOvVfRSL
QS1tlJYbClRGHHkM9YHjvV0v+xHcUTt9VAd+RruVjnz2H4hZrEi8klAHWjOUe/1m
37PEoLAh9+ox+zcSODc+MWWOA98oJoXyS0PZvPOzzlSokxaLEY/TRUMrILGBJSyz
hIwdMi63gM1KzIw0ysNJ639Nvu0n/PiIgpPheXK81fNyNpzsThS1uEqonAMC9+Hr
QIMBgfRMdvbG791lVo7WRHSdGpSO+hun4scla+3VZpszqSwFX2+O/ji0+5cos4RR
dxfzV4gt/1FH72OhWGHMSmmTpd+G2ZjXFsjNTmzMYbS0kMeXdIXalVXJrfDroSoU
ITXkfk5uFtU=
=Wlxf
-----END PGP SIGNATURE-----

2312
SPECS/nbdkit.spec Normal file

File diff suppressed because it is too large Load Diff