Rebase to nbdkit 1.47.5

Synchronize spec file with Fedora
resolves: RHEL-153362
This commit is contained in:
Richard W.M. Jones 2026-03-19 10:34:44 +00:00
parent d32b4b2509
commit 6e28625330
24 changed files with 12 additions and 3261 deletions

View File

@ -1,78 +0,0 @@
From 71158f3d0091027caf8a08b0cbe825e7875e4700 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Sun, 8 Feb 2026 21:53:17 +0000
Subject: [PATCH] vram: Cast cl_ulong to uint64_t before printing
On i686, the code did not compile:
vram.c: In function 'vram_dump_plugin':
vram.c:301:37: error: format '%lu' expects argument of type 'long unsigned int', but argument 2 has type 'cl_ulong' {aka 'long long unsigned int'} [-Werror=format=]
301 | printf ("vram_device_mem_size=%lu\n", all_devices.ptr[i].global_mem_size);
| ~~^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| | |
| long unsigned int cl_ulong {aka long long unsigned int}
| %llu
vram.c:302:50: error: format '%lu' expects argument of type 'long unsigned int', but argument 2 has type 'cl_ulong' {aka 'long long unsigned int'} [-Werror=format=]
302 | printf ("vram_device_max_memory_allocation=%lu\n",
| ~~^
| |
| long unsigned int
| %llu
303 | all_devices.ptr[i].max_mem_alloc_size);
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| |
| cl_ulong {aka long long unsigned int}
vram.c: In function 'vram_config_complete':
vram.c:364:52: error: format '%lu' expects argument of type 'long unsigned int', but argument 3 has type 'cl_ulong' {aka 'long long unsigned int'} [-Werror=format=]
364 | nbdkit_error ("OpenCL device '%s' has size %lu which is smaller than "
| ~~^
| |
| long unsigned int
| %llu
......
367 | device.name, device.global_mem_size);
| ~~~~~~~~~~~~~~~~~~~~~~
| |
| cl_ulong {aka long long unsigned int}
cc1: all warnings being treated as errors
(cherry picked from commit 47c5cceeb262273c6c25c3b7f979ea90f1371e0b)
---
plugins/vram/vram.c | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/plugins/vram/vram.c b/plugins/vram/vram.c
index fe8bf60e..0ed1e841 100644
--- a/plugins/vram/vram.c
+++ b/plugins/vram/vram.c
@@ -298,9 +298,10 @@ vram_dump_plugin (void)
printf ("vram_device_vendor=%s\n", all_devices.ptr[i].vendor);
printf ("vram_device_available=%s\n",
all_devices.ptr[i].available ? "yes" : "no");
- printf ("vram_device_mem_size=%lu\n", all_devices.ptr[i].global_mem_size);
- printf ("vram_device_max_memory_allocation=%lu\n",
- all_devices.ptr[i].max_mem_alloc_size);
+ printf ("vram_device_mem_size=%" PRIu64 "\n",
+ (uint64_t) all_devices.ptr[i].global_mem_size);
+ printf ("vram_device_max_memory_allocation=%" PRIu64 "\n",
+ (uint64_t) all_devices.ptr[i].max_mem_alloc_size);
printf ("vram_device_queue_on_device_max_size=%u\n",
all_devices.ptr[i].queue_on_device_max_size);
printf ("vram_device_queue_on_device_preferred_size=%u\n",
@@ -361,10 +362,11 @@ vram_config_complete (void)
/* Pick the size. */
if (size >= 0) { /* size appeared on the command line */
if (size > device.global_mem_size) {
- nbdkit_error ("OpenCL device '%s' has size %lu which is smaller than "
+ nbdkit_error ("OpenCL device '%s' has size %" PRIu64" "
+ "which is smaller than "
"the size given on the command line. To allocate the "
"maximum size, omit the size parameter.",
- device.name, device.global_mem_size);
+ device.name, (uint64_t) device.global_mem_size);
return -1;
}
}
--
2.47.3

View File

@ -1,538 +0,0 @@
From b546cd6870fcf16422d7fb240cb717fe4a298ce4 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Tue, 30 Dec 2025 15:24:13 +0000
Subject: [PATCH] server: Add nbdkit_debug_hexdiff function
Useful function for showing the differences between two buffers,
similar to the earlier nbdkit_debug_hexdump function.
This also adds a test.
(cherry picked from commit 753d8d468240e613f3d905282446011c31548e34)
---
docs/Makefile.am | 1 +
docs/nbdkit-plugin.pod | 1 +
docs/nbdkit_debug.pod | 1 +
docs/nbdkit_debug_hexdiff.3 | 1 +
docs/nbdkit_debug_hexdump.pod | 25 ++++++-
include/nbdkit-common.h | 4 +
server/debug.c | 75 +++++++++++++++++--
server/nbdkit.syms | 1 +
tests/Makefile.am | 21 ++++++
tests/test-debug-hexdiff-plugin.c | 92 +++++++++++++++++++++++
tests/test-debug-hexdiff.sh | 118 ++++++++++++++++++++++++++++++
11 files changed, 331 insertions(+), 9 deletions(-)
create mode 100644 docs/nbdkit_debug_hexdiff.3
create mode 100755 tests/test-debug-hexdiff-plugin.c
create mode 100755 tests/test-debug-hexdiff.sh
diff --git a/docs/Makefile.am b/docs/Makefile.am
index 240d9e1d..4ee6994c 100644
--- a/docs/Makefile.am
+++ b/docs/Makefile.am
@@ -94,6 +94,7 @@ EXTRA_DIST = \
# tarball.
non_generated_mans = \
nbdkit_absolute_path.3 \
+ nbdkit_debug_hexdiff.3 \
nbdkit_disconnect.3 \
nbdkit_parse_int8_t.3 \
nbdkit_parse_int16_t.3 \
diff --git a/docs/nbdkit-plugin.pod b/docs/nbdkit-plugin.pod
index 61deb63b..308364d4 100644
--- a/docs/nbdkit-plugin.pod
+++ b/docs/nbdkit-plugin.pod
@@ -1624,6 +1624,7 @@ Utility functions provided by nbdkit for plugins and filters to use:
L<nbdkit_absolute_path(3)>,
L<nbdkit_debug(3)>,
+L<nbdkit_debug_hexdiff(3)>,
L<nbdkit_debug_hexdump(3)>,
L<nbdkit_disconnect(3)>,
L<nbdkit_error(3)>,
diff --git a/docs/nbdkit_debug.pod b/docs/nbdkit_debug.pod
index 43bb5a41..d58d9bda 100644
--- a/docs/nbdkit_debug.pod
+++ b/docs/nbdkit_debug.pod
@@ -57,6 +57,7 @@ C<nbdkit_debug> was present in nbdkit 0.1.0.
=head1 SEE ALSO
L<nbdkit(1)>,
+L<nbdkit_debug_hexdiff(3)>,
L<nbdkit_debug_hexdump(3)>,
L<nbdkit_error(3)>,
L<nbdkit-plugin(3)>,
diff --git a/docs/nbdkit_debug_hexdiff.3 b/docs/nbdkit_debug_hexdiff.3
new file mode 100644
index 00000000..c1fe3540
--- /dev/null
+++ b/docs/nbdkit_debug_hexdiff.3
@@ -0,0 +1 @@
+.so man3/nbdkit_debug_hexdump.3
diff --git a/docs/nbdkit_debug_hexdump.pod b/docs/nbdkit_debug_hexdump.pod
index 035873a6..274380bf 100644
--- a/docs/nbdkit_debug_hexdump.pod
+++ b/docs/nbdkit_debug_hexdump.pod
@@ -1,6 +1,7 @@
=head1 NAME
-nbdkit_debug_hexdump - display buffer in hexdump format
+nbdkit_debug_hexdump,
+nbdkit_debug_hexdiff - display buffer in hexdump format
=head1 SYNOPSIS
@@ -9,11 +10,15 @@ nbdkit_debug_hexdump - display buffer in hexdump format
void nbdkit_debug_hexdump (const void *buf, size_t len,
const char *prefix, uint64_t start);
+ void nbdkit_debug_hexdiff (const void *buf1, const void *buf2,
+ size_t len,
+ const char *prefix, uint64_t start);
+
=head1 DESCRIPTION
-This function displays a buffer of binary data in canonical hexdump
-format, sending the output to the same place as L<nbdkit_debug(3)>.
-For example:
+B<nbdkit_debug_hexdump> displays a buffer of binary data in canonical
+hexdump format, sending the output to the same place as
+L<nbdkit_debug(3)>. For example:
char buf[33] = "12345678123456781234567812345678";
nbdkit_debug_hexdump (buf, 32, "data: ", 0);
@@ -29,6 +34,17 @@ line of output. (This may be C<NULL> or C<""> for no prefix).
An optional C<start> may be given which changes the first offset
displayed in the output.
+B<nbdkit_debug_hexdiff> displays the differences between two binary
+buffers (of the same length).
+
+For rows which are the same in both buffers, the output is the same as
+above. For rows which are different it shows the first buffer in the
+first row (prefixed with C<->) and the differences in the second
+buffer in the second row (prefixed with C<+>):
+
+ -00000000: 31 32 33 34 35 36 37 38 31 32 33 34 35 36 37 38 |1234567812345678|
+ +00000000: 39 38 37 36 34 33 32 | 9876 432|
+
=head1 LANGUAGE BINDINGS
(There are no language bindings of this function in the current version.)
@@ -43,6 +59,7 @@ L<nbdkit(1)>,
L<nbdkit_debug(3)>,
L<nbdkit-plugin(3)>,
L<nbdkit-filter(3)>,
+L<nbdkit-evil-filter(1)>,
L<nbddump(1)>,
L<hexdump(1)>.
diff --git a/include/nbdkit-common.h b/include/nbdkit-common.h
index 8bc16ee3..d23fedb0 100644
--- a/include/nbdkit-common.h
+++ b/include/nbdkit-common.h
@@ -131,6 +131,10 @@ NBDKIT_EXTERN_DECL (void, nbdkit_vdebug,
NBDKIT_EXTERN_DECL (char *, nbdkit_absolute_path,
(const char *path)
NBDKIT_ATTRIBUTE_NONNULL ((1)));
+NBDKIT_EXTERN_DECL (void, nbdkit_debug_hexdiff,
+ (const void *buf1, const void *buf2, size_t len,
+ const char *prefix, uint64_t start)
+ NBDKIT_ATTRIBUTE_NONNULL ((1, 2)));
NBDKIT_EXTERN_DECL (void, nbdkit_debug_hexdump,
(const void *buf, size_t len,
const char *prefix, uint64_t start)
diff --git a/server/debug.c b/server/debug.c
index 90ffc600..68c768fe 100644
--- a/server/debug.c
+++ b/server/debug.c
@@ -201,12 +201,13 @@ hexdump_set_byte (struct hexdump_line *line, size_t i, uint8_t b)
/* Send the final string to nbdkit_debug. */
static inline void
-hexdump_emit_debug (struct hexdump_line *line, const char *prefix)
+hexdump_emit_debug (struct hexdump_line *line,
+ const char *prefix, const char *plusminus)
{
/* Start by splitting up the hex digits into two groups of 8. */
line->hex[8*3-1] = '\0';
- nbdkit_debug ("%s%s: %s %s |%s|",
- prefix ? : "",
+ nbdkit_debug ("%s%s%s: %s %s |%s|",
+ prefix ? : "", plusminus ? : "",
line->str_offset, line->hex, &line->hex[8*3], line->chars);
}
@@ -235,7 +236,7 @@ nbdkit_debug_hexdump (const void *vbuf, size_t len,
line.offset++;
len--;
}
- hexdump_emit_debug (&line, prefix);
+ hexdump_emit_debug (&line, prefix, NULL);
}
/* Aligned body and unaligned tail. */
@@ -248,6 +249,70 @@ nbdkit_debug_hexdump (const void *vbuf, size_t len,
line.offset++;
len--;
}
- hexdump_emit_debug (&line, prefix);
+ hexdump_emit_debug (&line, prefix, NULL);
+ }
+}
+
+NBDKIT_DLL_PUBLIC void
+nbdkit_debug_hexdiff (const void *vbuf1, const void *vbuf2, size_t len,
+ const char *prefix, uint64_t start)
+{
+ if (!verbose)
+ return;
+
+ struct hexdump_line line1 = { .offset = start };
+ struct hexdump_line line2 = { .offset = start };
+ const uint8_t *buf1 = vbuf1, *buf2 = vbuf2;
+ uint64_t skip;
+ bool differences;
+ size_t i;
+
+ /* Unaligned head. */
+ if (! IS_ALIGNED (line1.offset, 16)) {
+ hexdump_reset_line (&line1);
+ hexdump_reset_line (&line2);
+ skip = line1.offset % 16;
+ differences = false;
+
+ for (i = skip; i < 16 && len > 0; ++i) {
+ hexdump_set_byte (&line1, i, *buf1);
+ if (*buf1 != *buf2) {
+ differences = true;
+ hexdump_set_byte (&line2, i, *buf2);
+ }
+ buf1++;
+ buf2++;
+ line1.offset++;
+ line2.offset++;
+ len--;
+ }
+ hexdump_emit_debug (&line1, prefix, differences ? "-" : " ");
+ if (differences)
+ hexdump_emit_debug (&line2, prefix, "+");
+ }
+
+ /* Aligned body and unaligned tail. */
+ while (len > 0) {
+ assert (IS_ALIGNED (line1.offset, 16));
+ assert (IS_ALIGNED (line2.offset, 16));
+ hexdump_reset_line (&line1);
+ hexdump_reset_line (&line2);
+ differences = false;
+
+ for (i = 0; i < 16 && len > 0; ++i) {
+ hexdump_set_byte (&line1, i, *buf1);
+ if (*buf1 != *buf2) {
+ differences = true;
+ hexdump_set_byte (&line2, i, *buf2);
+ }
+ buf1++;
+ buf2++;
+ line1.offset++;
+ line2.offset++;
+ len--;
+ }
+ hexdump_emit_debug (&line1, prefix, differences ? "-" : " ");
+ if (differences)
+ hexdump_emit_debug (&line2, prefix, "+");
}
}
diff --git a/server/nbdkit.syms b/server/nbdkit.syms
index 239e6db1..c22356fb 100644
--- a/server/nbdkit.syms
+++ b/server/nbdkit.syms
@@ -44,6 +44,7 @@
nbdkit_context_get_backend;
nbdkit_context_set_next;
nbdkit_debug;
+ nbdkit_debug_hexdiff;
nbdkit_debug_hexdump;
nbdkit_disconnect;
nbdkit_error;
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 759a5237..a887ac75 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -328,6 +328,7 @@ TESTS += \
test-log-to-file-append.sh \
test-at-file.sh \
test-debug-hexdump.sh \
+ test-debug-hexdiff.sh \
$(NULL)
if !IS_WINDOWS
TESTS += \
@@ -359,6 +360,8 @@ EXTRA_DIST += \
test-export-handshake.sh \
test-export-handshake-tls.sh \
test-debug-flags.sh \
+ test-debug-hexdiff.sh \
+ test-debug-hexdiff-plugin.c \
test-debug-hexdump.sh \
test-debug-hexdump-plugin.c \
test-disconnect-tls.sh \
@@ -538,8 +541,10 @@ test_shutdown_plugin_la_LIBADD = $(IMPORT_LIBRARY_ON_WINDOWS)
# So we have to do this and add a dependency.
noinst_LTLIBRARIES += \
test-debug-hexdump-plugin.la \
+ test-debug-hexdiff-plugin.la \
$(NULL)
test-debug-hexdump.sh: test-debug-hexdump-plugin.la
+test-debug-hexdiff.sh: test-debug-hexdiff-plugin.la
test_debug_hexdump_plugin_la_SOURCES = \
test-debug-hexdump-plugin.c \
@@ -557,6 +562,22 @@ test_debug_hexdump_plugin_la_LDFLAGS = \
$(NULL)
test_debug_hexdump_plugin_la_LIBADD = $(IMPORT_LIBRARY_ON_WINDOWS)
+test_debug_hexdiff_plugin_la_SOURCES = \
+ test-debug-hexdiff-plugin.c \
+ $(top_srcdir)/include/nbdkit-plugin.h \
+ $(NULL)
+test_debug_hexdiff_plugin_la_CPPFLAGS = \
+ -I$(top_srcdir)/include \
+ -I$(top_builddir)/include \
+ $(NULL)
+test_debug_hexdiff_plugin_la_CFLAGS = $(WARNINGS_CFLAGS)
+# For use of the -rpath option, see:
+# https://lists.gnu.org/archive/html/libtool/2007-07/msg00067.html
+test_debug_hexdiff_plugin_la_LDFLAGS = \
+ -module -avoid-version -shared $(NO_UNDEFINED_ON_WINDOWS) -rpath /nowhere \
+ $(NULL)
+test_debug_hexdiff_plugin_la_LIBADD = $(IMPORT_LIBRARY_ON_WINDOWS)
+
endif HAVE_PLUGINS
# Test the header files can be included on their own.
diff --git a/tests/test-debug-hexdiff-plugin.c b/tests/test-debug-hexdiff-plugin.c
new file mode 100755
index 00000000..89fe0de3
--- /dev/null
+++ b/tests/test-debug-hexdiff-plugin.c
@@ -0,0 +1,92 @@
+/* nbdkit
+ * Copyright Red Hat
+ *
+ * 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.
+ */
+
+/* Plugin for testing nbdkit_debug_hexdiff. See nbdkit-debug-hexdiff.sh */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+
+#define NBDKIT_API_VERSION 2
+#include <nbdkit-plugin.h>
+
+static const uint64_t size = 1024 * 1024;
+static uint8_t data[1024 * 1024];
+
+static void *
+hexdiff_open (int readonly)
+{
+ return NBDKIT_HANDLE_NOT_NEEDED;
+}
+
+static int64_t
+hexdiff_get_size (void *handle)
+{
+ return size;
+}
+
+#define THREAD_MODEL NBDKIT_THREAD_MODEL_PARALLEL
+
+static int
+hexdiff_pread (void *handle, void *buf, uint32_t count, uint64_t offset,
+ uint32_t flags)
+{
+ memcpy (buf, &data[offset], count);
+ return 0;
+}
+
+static int
+hexdiff_pwrite (void *handle, const void *buf, uint32_t count, uint64_t offset,
+ uint32_t flags)
+{
+ /* Show the differences between the existing data and what we are
+ * about to write.
+ */
+ nbdkit_debug_hexdiff (&data[offset], buf, count, "DIFF: ", offset);
+ /* Update the RAM disk. */
+ memcpy (&data[offset], buf, count);
+ return 0;
+}
+
+static struct nbdkit_plugin plugin = {
+ .name = "hexdiff",
+ .version = PACKAGE_VERSION,
+ .open = hexdiff_open,
+ .get_size = hexdiff_get_size,
+ .pread = hexdiff_pread,
+ .pwrite = hexdiff_pwrite,
+};
+
+NBDKIT_REGISTER_PLUGIN (plugin)
diff --git a/tests/test-debug-hexdiff.sh b/tests/test-debug-hexdiff.sh
new file mode 100755
index 00000000..99d0b1ff
--- /dev/null
+++ b/tests/test-debug-hexdiff.sh
@@ -0,0 +1,118 @@
+#!/usr/bin/env bash
+# nbdkit
+# Copyright Red Hat
+#
+# 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.
+
+# Test nbdkit_debug_hexdiff function.
+#
+# We assume that the tests of nbdkit_debug_hexdump do most of the
+# heavy lifting as the two functions are very similar. This only
+# tests the different behaviour of hexdiff.
+
+source ./functions.sh
+set -e
+set -x
+set -u
+
+requires_run
+requires_nbdsh_uri
+requires diff --version
+requires $SED --version
+
+plugin=.libs/test-debug-hexdiff-plugin.$SOEXT
+requires test -f $plugin
+
+out=debug-hexdiff.out
+hexout=debug-hexdiff.hexout
+files="$out $hexout"
+rm -f $files
+cleanup_fn rm -f $files
+
+define script <<'EOF'
+import os
+
+# Write zeros over zeroes
+b = bytearray(32)
+h.pwrite(b, 0)
+
+# Write 4 lines over zeroes
+b = b"1234567890abcdef" * 4
+h.pwrite(b, 0)
+
+# Partially overwrite second line
+b = b"56780000"
+h.pwrite(b, 20)
+
+# Partially overwrite third and fourth lines
+b = b"56780000cdef1234555590"
+h.pwrite(b, 36)
+
+EOF
+export script
+
+define expected <<'EOF'
+# Write zeros over zeroes
+ 00000000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+ 00000010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+
+# Write 4 lines over zeroes
+-00000000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
++00000000: 31 32 33 34 35 36 37 38 39 30 61 62 63 64 65 66 |1234567890abcdef|
+-00000010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
++00000010: 31 32 33 34 35 36 37 38 39 30 61 62 63 64 65 66 |1234567890abcdef|
+-00000020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
++00000020: 31 32 33 34 35 36 37 38 39 30 61 62 63 64 65 66 |1234567890abcdef|
+-00000030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
++00000030: 31 32 33 34 35 36 37 38 39 30 61 62 63 64 65 66 |1234567890abcdef|
+
+# Partially overwrite second line
+-00000010: 35 36 37 38 39 30 61 62 | 567890ab |
++00000010: 30 30 30 | 0 00 |
+
+# Partially overwrite third and fourth lines
+-00000020: 35 36 37 38 39 30 61 62 63 64 65 66 | 567890abcdef|
++00000020: 30 30 30 | 0 00 |
+-00000030: 31 32 33 34 35 36 37 38 39 30 |1234567890 |
++00000030: 35 35 35 | 555 |
+EOF
+
+# Run nbdkit with the plugin and debug enabled. Capture the full
+# output including stderr so we can find the hexdump output.
+fail=
+nbdkit -f -v $plugin --run 'nbdsh -u "$uri" -c "$script"' >$out 2>&1 || fail=1
+cat $out
+if test "$fail"; then exit 1; fi
+
+# Get the hexdiff lines from the output.
+grep "DIFF: " < $out | $SED 's/.*DIFF: //' > $hexout
+cat $hexout
+
+# Compare it to the expected output (in $expected variable).
+diff -u $hexout <(echo -n "$expected" | grep -v '^#' | grep -v '^$')
--
2.47.3

View File

@ -1,254 +0,0 @@
From 567f7449c9e9486b85530b9a56a4e9ba735a5faf Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Tue, 30 Dec 2025 17:09:07 +0000
Subject: [PATCH] checkwrite: Display differences if -D checkwrite.showdiffs=1
is used
Add a debug flag which shows the differences between what was written
and what we expected.
(cherry picked from commit 6a1c92f6a30941f8a891e704eeb95296e6d5669a)
---
filters/checkwrite/checkwrite.c | 27 +++++--
.../checkwrite/nbdkit-checkwrite-filter.pod | 14 +++-
tests/Makefile.am | 2 +
tests/test-checkwrite-evil.sh | 80 +++++++++++++++++++
tests/test-checkwrite-fail.sh | 1 +
tests/test-checkwrite.sh | 3 +-
6 files changed, 120 insertions(+), 7 deletions(-)
create mode 100755 tests/test-checkwrite-evil.sh
diff --git a/filters/checkwrite/checkwrite.c b/filters/checkwrite/checkwrite.c
index d5f20e54..44fb22aa 100644
--- a/filters/checkwrite/checkwrite.c
+++ b/filters/checkwrite/checkwrite.c
@@ -108,9 +108,26 @@ checkwrite_can_multi_conn (nbdkit_next *next,
return 1;
}
+NBDKIT_DLL_PUBLIC int checkwrite_debug_showdiffs = 0;
+
static inline int
-data_does_not_match (int *err)
+data_does_not_match (int *err,
+ const void *expected, const void *actual, size_t count,
+ uint64_t offset)
{
+ if (checkwrite_debug_showdiffs) {
+ /* Caller passes expected == NULL to mean we expected zeroes.
+ * However hexdiff requires an actual buffer, so ...
+ */
+ CLEANUP_FREE char *zerobuf = NULL;
+
+ if (expected == NULL)
+ zerobuf = calloc (count, 1);
+
+ if (expected || zerobuf)
+ nbdkit_debug_hexdiff (expected ? : zerobuf, actual, count, NULL, offset);
+ }
+
*err = EIO;
nbdkit_error ("data written does not match expected");
return -1;
@@ -137,8 +154,8 @@ checkwrite_pwrite (nbdkit_next *next,
return -1;
/* If data written doesn't match data expected, inject EIO. */
- if (memcmp (buf, expected, count) != 0)
- return data_does_not_match (err);
+ if (memcmp (expected, buf, count) != 0)
+ return data_does_not_match (err, expected, buf, count, offset);
return 0;
}
@@ -207,7 +224,7 @@ checkwrite_trim_zero (nbdkit_next *next,
if (next->pread (next, buf, buflen, offset, 0, err) == -1)
return -1;
if (! is_zero (buf, buflen))
- return data_does_not_match (err);
+ return data_does_not_match (err, NULL, buf, buflen, offset);
count -= buflen;
offset += buflen;
@@ -243,7 +260,7 @@ checkwrite_trim_zero (nbdkit_next *next,
if (next->pread (next, buf, n, offset, 0, err) == -1)
return -1;
if (! is_zero (buf, n))
- return data_does_not_match (err);
+ return data_does_not_match (err, NULL, buf, n, offset);
count -= n;
offset += n;
}
diff --git a/filters/checkwrite/nbdkit-checkwrite-filter.pod b/filters/checkwrite/nbdkit-checkwrite-filter.pod
index 6855d798..0689fb26 100644
--- a/filters/checkwrite/nbdkit-checkwrite-filter.pod
+++ b/filters/checkwrite/nbdkit-checkwrite-filter.pod
@@ -4,7 +4,7 @@ nbdkit-checkwrite-filter - check writes match contents of plugin
=head1 SYNOPSIS
- nbdkit --filter=checkwrite PLUGIN
+ nbdkit --filter=checkwrite PLUGIN [-D checkwrite.showdiffs=1]
=head1 DESCRIPTION
@@ -59,6 +59,17 @@ with arbitrary plugins.
There are no parameters specific to this filter. Parameters are
passed through to the underlying plugin.
+=head1 DEBUG FLAG
+
+When both foreground mode and debugging are enabled (I<-fv>) you can
+get checkwrite to show the differences between what was written and
+what should have been written by adding:
+
+ nbdkit -fv --filter=checkwrite -D checkwrite.showdiffs=1 [...]
+
+For further information on the format used see
+L<nbdkit_debug_hexdiff(3)>.
+
=head1 FILES
=over 4
@@ -82,6 +93,7 @@ L<nbdkit-random-plugin(1)>,
L<nbdkit-sparse-random-plugin(1)>,
L<nbdkit-filter(3)>,
L<nbdkit-plugin(3)>,
+L<nbdkit_debug_hexdiff(3)>,
L<nbdcopy(1)>,
L<qemu-img(1)>.
diff --git a/tests/Makefile.am b/tests/Makefile.am
index a887ac75..beeb0fc3 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -1806,12 +1806,14 @@ EXTRA_DIST += \
TESTS += \
test-checkwrite.sh \
test-checkwrite-bounds.sh \
+ test-checkwrite-evil.sh \
test-checkwrite-fail.sh \
test-checkwrite-fastzero.sh \
$(NULL)
EXTRA_DIST += \
test-checkwrite.sh \
test-checkwrite-bounds.sh \
+ test-checkwrite-evil.sh \
test-checkwrite-fail.sh \
test-checkwrite-fastzero.sh \
$(NULL)
diff --git a/tests/test-checkwrite-evil.sh b/tests/test-checkwrite-evil.sh
new file mode 100755
index 00000000..2d9e25b4
--- /dev/null
+++ b/tests/test-checkwrite-evil.sh
@@ -0,0 +1,80 @@
+#!/usr/bin/env bash
+# nbdkit
+# Copyright Red Hat
+#
+# 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.
+
+# Test checkwrite + evil filters together.
+
+source ./functions.sh
+set -e
+set -x
+set -u
+
+# Across a 1G disk, with the default failure probability of the evil
+# filter, we expect about 43 stuck high bits. The test actually fails
+# at the first stuck high bit so we don't end up grinding across the
+# whole virtual size.
+size=1G
+
+requires_plugin null
+requires_filter checkwrite
+requires_filter evil
+requires_filter noextents
+
+# nbdcopy >= 1.5.9 required for this test.
+requires_nbdcopy
+requires_libnbd_version 1.5.9
+
+sock1=$(mktemp -u /tmp/nbdkit-test-sock.XXXXXX)
+sock2=$(mktemp -u /tmp/nbdkit-test-sock.XXXXXX)
+pid1=checkwrite-evil.pid1
+pid2=checkwrite-evil.pid2
+files="$sock1 $sock2 $pid1 $pid2"
+rm -f $files
+cleanup_fn rm -f $files
+
+# Source nbdkit.
+start_nbdkit -P $pid1 -U $sock1 \
+ null $size \
+ --filter=evil \
+ --filter=noextents
+
+# Target nbdkit.
+start_nbdkit -P $pid2 -U $sock2 \
+ -v -D checkwrite.showdiffs=1 \
+ null $size \
+ --filter=checkwrite
+
+fail=
+nbdcopy "nbd+unix:///?socket=$sock1" "nbd+unix:///?socket=$sock2" || fail=1
+if ! test "$fail"; then
+ echo "$0: expected nbdcopy to fail but it did not"
+ exit 1
+fi
diff --git a/tests/test-checkwrite-fail.sh b/tests/test-checkwrite-fail.sh
index d46c2865..c577b12d 100755
--- a/tests/test-checkwrite-fail.sh
+++ b/tests/test-checkwrite-fail.sh
@@ -49,6 +49,7 @@ import sys
h.connect_command(["nbdkit", "-s", "-v",
"--filter=checkwrite",
+ "-D", "checkwrite.showdiffs=1",
"memory", "1M"])
try:
h.pwrite(b"1", 0)
diff --git a/tests/test-checkwrite.sh b/tests/test-checkwrite.sh
index aecb729c..490ab45b 100755
--- a/tests/test-checkwrite.sh
+++ b/tests/test-checkwrite.sh
@@ -46,7 +46,8 @@ requires_libnbd_version 1.5.9
do_test ()
{
- nbdkit -v --filter=checkwrite "$@" --run 'nbdcopy "$uri" "$uri"'
+ nbdkit -v --filter=checkwrite -D checkwrite.showdiffs=1 "$@" \
+ --run 'nbdcopy "$uri" "$uri"'
}
# Tests zero-sized disk.
--
2.47.3

View File

@ -1,33 +0,0 @@
From ad67a7bbd2b596291c696e9718d68800f9a02734 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Tue, 30 Dec 2025 21:59:24 +0000
Subject: [PATCH] docs/nbdkit_debug_hexdump.pod: Document when hexdiff was
added to nbdkit
Not until the next stable branch, so 1.48.
Fixes: commit 753d8d468240e613f3d905282446011c31548e34
Cherry picked from commit 7e9ec310d4149449229a8ddbb50395a3bdbd7227.
For RHEL 10.2, add a note that it was backported.
---
docs/nbdkit_debug_hexdump.pod | 3 +++
1 file changed, 3 insertions(+)
diff --git a/docs/nbdkit_debug_hexdump.pod b/docs/nbdkit_debug_hexdump.pod
index 274380bf..4c4cae19 100644
--- a/docs/nbdkit_debug_hexdump.pod
+++ b/docs/nbdkit_debug_hexdump.pod
@@ -53,6 +53,9 @@ buffer in the second row (prefixed with C<+>):
C<nbdkit_debug_hexdump> was added in nbdkit 1.46.
+C<nbdkit_debug_hexdiff> was added in nbdkit 1.48
+(and backported to RHEL 10.2).
+
=head1 SEE ALSO
L<nbdkit(1)>,
--
2.47.3

View File

@ -1,27 +0,0 @@
From 3a75b229eec051b473886f7a324751c89d87a35f Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Tue, 30 Dec 2025 22:01:04 +0000
Subject: [PATCH] docs/nbdkit_debug_hexdump.pod: Add a link back to
nbdkit-checkwrite-filter
Updates: commit 6a1c92f6a30941f8a891e704eeb95296e6d5669a
(cherry picked from commit 674f72a6553b97f86f8f8a276f86354c977d339f)
---
docs/nbdkit_debug_hexdump.pod | 1 +
1 file changed, 1 insertion(+)
diff --git a/docs/nbdkit_debug_hexdump.pod b/docs/nbdkit_debug_hexdump.pod
index 4c4cae19..1a428699 100644
--- a/docs/nbdkit_debug_hexdump.pod
+++ b/docs/nbdkit_debug_hexdump.pod
@@ -62,6 +62,7 @@ L<nbdkit(1)>,
L<nbdkit_debug(3)>,
L<nbdkit-plugin(3)>,
L<nbdkit-filter(3)>,
+L<nbdkit-checkwrite-filter(1)>,
L<nbdkit-evil-filter(1)>,
L<nbddump(1)>,
L<hexdump(1)>.
--
2.47.3

View File

@ -1,407 +0,0 @@
From baad76a69681c0442d12010a53eb54677ff47953 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Thu, 15 Jan 2026 12:07:40 +0000
Subject: [PATCH] Add new nbdkit_name() function
In nbdkit 1.46 we added a --name parameter to name nbdkit instances.
This was only used in debug and error messages. For a forthcoming
feature it would be nice if the plugin could get the instance name.
The new nbdkit_name() function is very simple. It returns the string
set through the nbdkit --name parameter, or NULL if it was not set.
NULL does not indicate an error. I thought it was better to return
NULL as a distinct "not set" value rather than using a default like
"nbdkit" or PACKAGE_NAME, so the plugin can decide what to do.
RHEL:
Cherry picked from commit 5c24949959ccf8cf9f1093adf81336009df23f2d
and added a note about being backported in RHEL 10.2.
---
.gitignore | 1 +
docs/Makefile.am | 7 ++++
docs/nbdkit-plugin.pod | 1 +
docs/nbdkit.pod | 2 +-
docs/nbdkit_name.pod | 45 ++++++++++++++++++++
include/nbdkit-common.h | 1 +
server/nbdkit.syms | 1 +
server/public.c | 6 +++
tests/Makefile.am | 25 +++++++++++
tests/test-name-plugin.c | 88 +++++++++++++++++++++++++++++++++++++++
tests/test-name-plugin.sh | 60 ++++++++++++++++++++++++++
11 files changed, 236 insertions(+), 1 deletion(-)
create mode 100644 docs/nbdkit_name.pod
create mode 100644 tests/test-name-plugin.c
create mode 100755 tests/test-name-plugin.sh
diff --git a/.gitignore b/.gitignore
index 3562a665..55d971e6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -33,6 +33,7 @@ docs/nbdkit_error.3
docs/nbdkit_export_name.3
docs/nbdkit-filter.3
docs/nbdkit_is_tls.3
+docs/nbdkit_name.3
docs/nbdkit_nanosleep.3
docs/nbdkit_parse_bool.3
docs/nbdkit_parse_delay.3
diff --git a/docs/Makefile.am b/docs/Makefile.am
index 4ee6994c..a43b13ed 100644
--- a/docs/Makefile.am
+++ b/docs/Makefile.am
@@ -44,6 +44,7 @@ EXTRA_DIST = \
nbdkit-filter.pod \
nbdkit_is_tls.pod \
nbdkit-loop.pod \
+ nbdkit_name.pod \
nbdkit_nanosleep.pod \
nbdkit_parse_bool.pod \
nbdkit_parse_delay.pod \
@@ -134,6 +135,7 @@ generated_mans = \
nbdkit-filter.3 \
nbdkit_is_tls.3 \
nbdkit-loop.1 \
+ nbdkit_name.3 \
nbdkit_nanosleep.3 \
nbdkit_parse_bool.3 \
nbdkit_parse_delay.3 \
@@ -241,6 +243,11 @@ nbdkit-loop.1: nbdkit-loop.pod $(top_builddir)/podwrapper.pl
--html $(top_builddir)/html/$@.html \
$<
+nbdkit_name.3: nbdkit_name.pod $(top_builddir)/podwrapper.pl
+ $(PODWRAPPER) --section=3 --man $@ \
+ --html $(top_builddir)/html/$@.html \
+ $<
+
nbdkit_nanosleep.3: nbdkit_nanosleep.pod $(top_builddir)/podwrapper.pl
$(PODWRAPPER) --section=3 --man $@ \
--html $(top_builddir)/html/$@.html \
diff --git a/docs/nbdkit-plugin.pod b/docs/nbdkit-plugin.pod
index 308364d4..41f65908 100644
--- a/docs/nbdkit-plugin.pod
+++ b/docs/nbdkit-plugin.pod
@@ -1630,6 +1630,7 @@ L<nbdkit_disconnect(3)>,
L<nbdkit_error(3)>,
L<nbdkit_export_name(3)>,
L<nbdkit_is_tls(3)>,
+L<nbdkit_name(3)>,
L<nbdkit_nanosleep(3)>,
L<nbdkit_parse_bool(3)>,
L<nbdkit_parse_delay(3)>,
diff --git a/docs/nbdkit.pod b/docs/nbdkit.pod
index e8ff9438..3104d751 100644
--- a/docs/nbdkit.pod
+++ b/docs/nbdkit.pod
@@ -356,7 +356,7 @@ Name this nbdkit instance. This allows you to associate names with
nbdkit processes, if you have several. The name appears in error and
debug messages, but is otherwise unused by nbdkit. The name can be
any string, but usually a short string containing only letters,
-numbers and common punctuation is best.
+numbers and common punctuation is best. See also L<nbdkit_name(3)>.
=item B<-n>
diff --git a/docs/nbdkit_name.pod b/docs/nbdkit_name.pod
new file mode 100644
index 00000000..210c7d2f
--- /dev/null
+++ b/docs/nbdkit_name.pod
@@ -0,0 +1,45 @@
+=head1 NAME
+
+nbdkit_name - get the name of the nbdkit instance
+
+=head1 SYNOPSIS
+
+ #include <nbdkit-plugin.h>
+
+ const char *nbdkit_name (void);
+
+=head1 DESCRIPTION
+
+C<nbdkit_name> returns the name of the nbdkit instance. This is the
+string which was set through the nbdkit I<--name> parameter. If the
+name was not set, this returns C<NULL>.
+
+=head1 RETURN VALUE
+
+The function returns a constant string, valid for the lifetime of the
+process, or C<NULL>. Note that returning C<NULL> is not an error.
+
+=begin comment
+
+=head1 LANGUAGE BINDINGS
+
+=end comment
+
+=head1 HISTORY
+
+C<nbdkit_name> was added in nbdkit 1.48
+(and backported to RHEL 10.2).
+
+=head1 SEE ALSO
+
+L<nbdkit(1)>,
+L<nbdkit-plugin(3)>,
+L<nbdkit-filter(3)>.
+
+=head1 AUTHORS
+
+Richard W.M. Jones
+
+=head1 COPYRIGHT
+
+Copyright Red Hat
diff --git a/include/nbdkit-common.h b/include/nbdkit-common.h
index d23fedb0..4b42c9d7 100644
--- a/include/nbdkit-common.h
+++ b/include/nbdkit-common.h
@@ -204,6 +204,7 @@ NBDKIT_EXTERN_DECL (char *, nbdkit_peer_tls_issuer_dn,
(void) NBDKIT_ATTRIBUTE_MALLOC (free));
NBDKIT_EXTERN_DECL (void, nbdkit_shutdown, (void));
NBDKIT_EXTERN_DECL (void, nbdkit_disconnect, (int force));
+NBDKIT_EXTERN_DECL (const char *, nbdkit_name, (void));
NBDKIT_EXTERN_DECL (const char *, nbdkit_strdup_intern,
(const char *str)
diff --git a/server/nbdkit.syms b/server/nbdkit.syms
index c22356fb..bf6bb378 100644
--- a/server/nbdkit.syms
+++ b/server/nbdkit.syms
@@ -60,6 +60,7 @@
nbdkit_get_export;
nbdkit_get_extent;
nbdkit_is_tls;
+ nbdkit_name;
nbdkit_nanosleep;
nbdkit_next_context_close;
nbdkit_next_context_open;
diff --git a/server/public.c b/server/public.c
index e1a45ed0..d08930dd 100644
--- a/server/public.c
+++ b/server/public.c
@@ -1220,3 +1220,9 @@ nbdkit_disconnect (int force)
conn->close (SHUT_WR);
}
}
+
+NBDKIT_DLL_PUBLIC const char *
+nbdkit_name (void)
+{
+ return process_name;
+}
diff --git a/tests/Makefile.am b/tests/Makefile.am
index beeb0fc3..f0665926 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -272,6 +272,7 @@ TESTS += \
test-version-filter.sh \
test-name.sh \
test-no-name.sh \
+ test-name-plugin.sh \
test-dump-plugin-example1.sh \
test-dump-plugin.sh \
test-dump-plugin-example2.sh \
@@ -385,6 +386,7 @@ EXTRA_DIST += \
test-log-to-file-append.sh \
test-long-name.sh \
test-name.sh \
+ test-name-plugin.sh \
test-nbd-client-tls.sh \
test-nbd-client.sh \
test-nbdkit-backend-debug.sh \
@@ -578,6 +580,29 @@ test_debug_hexdiff_plugin_la_LDFLAGS = \
$(NULL)
test_debug_hexdiff_plugin_la_LIBADD = $(IMPORT_LIBRARY_ON_WINDOWS)
+# check_LTLIBRARIES won't build a shared library (see automake manual).
+# So we have to do this and add a dependency.
+noinst_LTLIBRARIES += \
+ test-name-plugin.la \
+ $(NULL)
+test-name-plugin.sh: test-name-plugin.la
+
+test_name_plugin_la_SOURCES = \
+ test-name-plugin.c \
+ $(top_srcdir)/include/nbdkit-plugin.h \
+ $(NULL)
+test_name_plugin_la_CPPFLAGS = \
+ -I$(top_srcdir)/include \
+ -I$(top_builddir)/include \
+ $(NULL)
+test_name_plugin_la_CFLAGS = $(WARNINGS_CFLAGS)
+# For use of the -rpath option, see:
+# https://lists.gnu.org/archive/html/libtool/2007-07/msg00067.html
+test_name_plugin_la_LDFLAGS = \
+ -module -avoid-version -shared $(NO_UNDEFINED_ON_WINDOWS) -rpath /nowhere \
+ $(NULL)
+test_name_plugin_la_LIBADD = $(IMPORT_LIBRARY_ON_WINDOWS)
+
endif HAVE_PLUGINS
# Test the header files can be included on their own.
diff --git a/tests/test-name-plugin.c b/tests/test-name-plugin.c
new file mode 100644
index 00000000..a4f8073b
--- /dev/null
+++ b/tests/test-name-plugin.c
@@ -0,0 +1,88 @@
+/* nbdkit
+ * Copyright Red Hat
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of Red Hat nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* This plugin reflects the nbdkit --name parameter back through the
+ * content of the plugin. If not set, the content is "NONE" (4 bytes).
+ *
+ * The corresponding test is 'test-name-plugin.sh'.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define NBDKIT_API_VERSION 2
+#include <nbdkit-plugin.h>
+
+static const char *name;
+
+static void
+name_load (void)
+{
+ /* The API can return NULL, it's not an error. */
+ name = nbdkit_name () ? : "NONE";
+}
+
+static void *
+flush_open (int readonly)
+{
+ return NBDKIT_HANDLE_NOT_NEEDED;
+}
+
+static int64_t
+flush_get_size (void *handle)
+{
+ return strlen (name);
+}
+
+#define THREAD_MODEL NBDKIT_THREAD_MODEL_PARALLEL
+
+static int
+flush_pread (void *handle, void *buf, uint32_t count, uint64_t offset,
+ uint32_t flags)
+{
+ memcpy (buf, &name[offset], count);
+ return 0;
+}
+
+static struct nbdkit_plugin plugin = {
+ .name = "name",
+ .version = PACKAGE_VERSION,
+ .load = name_load,
+ .open = flush_open,
+ .get_size = flush_get_size,
+ .pread = flush_pread,
+};
+
+NBDKIT_REGISTER_PLUGIN (plugin)
diff --git a/tests/test-name-plugin.sh b/tests/test-name-plugin.sh
new file mode 100755
index 00000000..842d0da7
--- /dev/null
+++ b/tests/test-name-plugin.sh
@@ -0,0 +1,60 @@
+#!/usr/bin/env bash
+# nbdkit
+# Copyright Red Hat
+#
+# 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.
+
+# Test the nbdkit_name () API.
+
+source ./functions.sh
+set -e
+set -x
+set -u
+
+requires_run
+requires_nbdcopy
+
+plugin=.libs/test-name-plugin.$SOEXT
+requires test -f $plugin
+
+out=name-plugin.out
+cleanup_fn rm -f "$out"
+rm -f "$out"
+
+# nbdkit with --name parameter.
+export out
+nbdkit --name TEST "$plugin" --run 'nbdcopy "$uri" "$out"'
+test "$(cat "$out")" = "TEST"
+
+nbdkit --name "" "$plugin" --run 'nbdcopy "$uri" "$out"'
+test "$(cat "$out")" = ""
+
+# nbdkit without --name parameter.
+nbdkit "$plugin" --run 'nbdcopy "$uri" "$out"'
+test "$(cat "$out")" = "NONE"
--
2.47.3

View File

@ -1,31 +0,0 @@
From dad58135284cb5e884bccdc8868b1ba2e245a3d3 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Thu, 15 Jan 2026 15:02:53 +0000
Subject: [PATCH] server/test-public.c: Add process_name dummy variable
This is required for the test to link correctly:
libtool: link: gcc -Wall -Wshadow -Wvla -Werror -g -O2 -o test-public test_public-test-public.o test_public-public.o test_public-exports.o test_public-extents.o ../common/utils/.libs/libutils.a -lpthread -lz ../common/replacements/.libs/libcompat.a -lm -pthread
/usr/bin/ld: test_public-public.o: in function `nbdkit_name':
/builds/nbdkit/nbdkit/server/public.c:1228:(.text+0x1e53): undefined reference to `process_name'
(cherry picked from commit 038e79802d5872a7a5e9079bdfee9fe1caa5459b)
---
server/test-public.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/server/test-public.c b/server/test-public.c
index 65b17d59..3ef530ff 100644
--- a/server/test-public.c
+++ b/server/test-public.c
@@ -71,6 +71,7 @@ bool listen_stdin;
bool configured;
bool verbose;
int tls;
+const char *process_name;
volatile int quit;
#ifndef WIN32
--
2.47.3

View File

@ -1,577 +0,0 @@
From 630f3eecbecab4c5d46c84fe48c112b503effb5a Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Thu, 29 Jan 2026 10:24:58 +0000
Subject: [PATCH] Add new nbdkit_timestamp() function
This function can be used to flexibly add timestamps to debug and
error messages (or any kind of logging).
(cherry picked from commit 773d958c8f2a5043053d385b8bfe287c43ee63d4)
---
.gitignore | 1 +
docs/Makefile.am | 7 +++
docs/nbdkit_debug.pod | 4 ++
docs/nbdkit_error.pod | 6 +++
docs/nbdkit_timestamp.pod | 75 ++++++++++++++++++++++++++++++++
include/nbdkit-common.h | 1 +
server/internal.h | 1 +
server/nbdkit.syms | 1 +
server/public.c | 55 +++++++++++++++++++++++-
server/test-public.c | 6 +++
server/threadlocal.c | 20 +++++++++
tests/Makefile.am | 25 +++++++++++
tests/test-timestamp-plugin.c | 81 +++++++++++++++++++++++++++++++++++
tests/test-timestamp.sh | 61 ++++++++++++++++++++++++++
14 files changed, 343 insertions(+), 1 deletion(-)
create mode 100644 docs/nbdkit_timestamp.pod
create mode 100644 tests/test-timestamp-plugin.c
create mode 100755 tests/test-timestamp.sh
diff --git a/.gitignore b/.gitignore
index 55d971e6..2b86a056 100644
--- a/.gitignore
+++ b/.gitignore
@@ -48,6 +48,7 @@ docs/nbdkit_realpath.3
docs/nbdkit_shutdown.3
docs/nbdkit_stdio_safe.3
docs/nbdkit_strdup_intern.3
+docs/nbdkit_timestamp.3
docs/nbdkit-tracing.3
filters/*/*.1
plugins/*/*.1
diff --git a/docs/Makefile.am b/docs/Makefile.am
index a43b13ed..742f5460 100644
--- a/docs/Makefile.am
+++ b/docs/Makefile.am
@@ -85,6 +85,7 @@ EXTRA_DIST = \
nbdkit_shutdown.pod \
nbdkit_stdio_safe.pod \
nbdkit_strdup_intern.pod \
+ nbdkit_timestamp.pod \
nbdkit-tls.pod \
nbdkit-tracing.pod \
synopsis.txt \
@@ -176,6 +177,7 @@ generated_mans = \
nbdkit_shutdown.3 \
nbdkit_stdio_safe.3 \
nbdkit_strdup_intern.3 \
+ nbdkit_timestamp.3 \
nbdkit-tls.1 \
nbdkit-tracing.3 \
$(NULL)
@@ -348,6 +350,11 @@ nbdkit_strdup_intern.3: nbdkit_strdup_intern.pod $(top_builddir)/podwrapper.pl
--html $(top_builddir)/html/$@.html \
$<
+nbdkit_timestamp.3: nbdkit_timestamp.pod $(top_builddir)/podwrapper.pl
+ $(PODWRAPPER) --section=3 --man $@ \
+ --html $(top_builddir)/html/$@.html \
+ $<
+
nbdkit-tls.1: nbdkit-tls.pod $(top_builddir)/podwrapper.pl
$(PODWRAPPER) --section=1 --man $@ \
--html $(top_builddir)/html/$@.html \
diff --git a/docs/nbdkit_debug.pod b/docs/nbdkit_debug.pod
index d58d9bda..ee1ba719 100644
--- a/docs/nbdkit_debug.pod
+++ b/docs/nbdkit_debug.pod
@@ -25,6 +25,9 @@ and also support the glibc extension of a single C<%m> in a format
string expanding to C<strerror(errno)>, even on platforms that don't
support that natively.
+C<nbdkit_debug> does not timestamp messages. To add timestamps, see
+L<nbdkit_timestamp(3)>.
+
=head1 LANGUAGE BINDINGS
In L<nbdkit-golang-plugin(3)>:
@@ -60,6 +63,7 @@ L<nbdkit(1)>,
L<nbdkit_debug_hexdiff(3)>,
L<nbdkit_debug_hexdump(3)>,
L<nbdkit_error(3)>,
+L<nbdkit_timestamp(3)>,
L<nbdkit-plugin(3)>,
L<nbdkit-filter(3)>.
diff --git a/docs/nbdkit_error.pod b/docs/nbdkit_error.pod
index 2b41a4f0..d9283baa 100644
--- a/docs/nbdkit_error.pod
+++ b/docs/nbdkit_error.pod
@@ -61,6 +61,11 @@ The default is to send error messages to stderr, unless nbdkit forks
into the background in which case they are sent to syslog. For more
information read the description in L<nbdkit(1)>.
+=head2 Timestamps
+
+C<nbdkit_error> does not timestamp messages. To add timestamps, see
+L<nbdkit_timestamp(3)>.
+
=head1 LANGUAGE BINDINGS
Most language bindings do not expose these functions explicitly.
@@ -78,6 +83,7 @@ C<nbdkit_set_error> was added in nbdkit 1.2.
L<nbdkit(1)>,
L<nbdkit_debug(3)>,
+L<nbdkit_timestamp(3)>,
L<nbdkit-plugin(3)>,
L<nbdkit-filter(3)>.
diff --git a/docs/nbdkit_timestamp.pod b/docs/nbdkit_timestamp.pod
new file mode 100644
index 00000000..2662b204
--- /dev/null
+++ b/docs/nbdkit_timestamp.pod
@@ -0,0 +1,75 @@
+=head1 NAME
+
+nbdkit_timestamp - generate a timestamp for log messages
+
+=head1 SYNOPSIS
+
+ #include <nbdkit-plugin.h>
+
+ const char *nbdkit_timestamp (void);
+
+=head1 DESCRIPTION
+
+C<nbdkit_timestamp> generates a timestamp as a printable string which
+may be added to debug or error messages (see L<nbdkit_debug(3)>,
+L<nbdkit_error(3)>).
+
+It can be used like this:
+
+ nbdkit_debug ("%s: this is a debug message", nbdkit_timestamp ());
+
+which would produce a debug message like this:
+
+ debug: 2026-01-01 12:00:00.000333: this is a debug message
+
+The timestamps show the wallclock time in approximately ISO 8601
+format, but less ugly. They are always shown in UTC, in 24 hour
+notation, to the nearest microsecond. (On Windows, timestamps use the
+same format but are rounded to the nearest millisecond.)
+
+You can also separate the nbdkit_timestamp() call from the place where
+it is used, allowing you to accurately timestamp, for example, the
+point when a system call was invoked:
+
+ const char *ts = nbdkit_timestamp ();
+ int r = pwrite (fd, ...);
+ if (r == -1) {
+ /* The error message shows the time that pwrite started. */
+ nbdkit_error ("%s: pwrite: %m", ts);
+ return -1;
+ }
+
+=head1 RETURN VALUE
+
+The function returns a constant string allocated in thread-local
+storage. The string is valid until the next call to
+C<nbdkit_timestamp> in the same thread.
+
+It never returns C<NULL>. In the (very unlikely) case that there was
+an error generating the timestamp, the string C<"!"> is returned.
+
+=begin comment
+
+=head1 LANGUAGE BINDINGS
+
+=end comment
+
+=head1 HISTORY
+
+C<nbdkit_name> was added in nbdkit 1.48.
+
+=head1 SEE ALSO
+
+L<nbdkit(1)>,
+L<nbdkit_debug(3)>,
+L<nbdkit_error(3)>,
+L<nbdkit-plugin(3)>,
+L<nbdkit-filter(3)>.
+
+=head1 AUTHORS
+
+Richard W.M. Jones
+
+=head1 COPYRIGHT
+
+Copyright Red Hat
diff --git a/include/nbdkit-common.h b/include/nbdkit-common.h
index 4b42c9d7..230365db 100644
--- a/include/nbdkit-common.h
+++ b/include/nbdkit-common.h
@@ -205,6 +205,7 @@ NBDKIT_EXTERN_DECL (char *, nbdkit_peer_tls_issuer_dn,
NBDKIT_EXTERN_DECL (void, nbdkit_shutdown, (void));
NBDKIT_EXTERN_DECL (void, nbdkit_disconnect, (int force));
NBDKIT_EXTERN_DECL (const char *, nbdkit_name, (void));
+NBDKIT_EXTERN_DECL (const char *, nbdkit_timestamp, (void));
NBDKIT_EXTERN_DECL (const char *, nbdkit_strdup_intern,
(const char *str)
diff --git a/server/internal.h b/server/internal.h
index f10de3ef..511ec536 100644
--- a/server/internal.h
+++ b/server/internal.h
@@ -633,6 +633,7 @@ extern int threadlocal_get_errno (void);
extern void threadlocal_set_last_error (char *msg);
extern void threadlocal_clear_last_error (void);
extern const char *threadlocal_get_last_error (void);
+extern int threadlocal_set_timestamp (char *timestamp);
extern void *threadlocal_buffer (size_t size);
extern void threadlocal_set_conn (struct connection *conn);
extern struct connection *threadlocal_get_conn (void);
diff --git a/server/nbdkit.syms b/server/nbdkit.syms
index bf6bb378..fb732e9e 100644
--- a/server/nbdkit.syms
+++ b/server/nbdkit.syms
@@ -93,6 +93,7 @@
nbdkit_stdio_safe;
nbdkit_strdup_intern;
nbdkit_strndup_intern;
+ nbdkit_timestamp;
nbdkit_use_default_export;
nbdkit_vdebug;
nbdkit_verror;
diff --git a/server/public.c b/server/public.c
index d08930dd..8d0b69d3 100644
--- a/server/public.c
+++ b/server/public.c
@@ -47,9 +47,11 @@
#include <limits.h>
#include <errno.h>
#include <signal.h>
-#include <sys/types.h>
#include <math.h>
+#include <sys/types.h>
+#include <sys/time.h>
+
#ifdef HAVE_TERMIOS_H
#include <termios.h>
#endif
@@ -1226,3 +1228,54 @@ nbdkit_name (void)
{
return process_name;
}
+
+NBDKIT_DLL_PUBLIC const char *
+nbdkit_timestamp (void)
+{
+ char *timestamp = NULL;
+ const size_t len = 64;
+
+ timestamp = malloc (len);
+ if (timestamp == NULL)
+ goto err;
+
+#ifndef WIN32
+ struct timeval tv;
+ struct tm tm;
+ size_t n;
+
+ if (gettimeofday (&tv, NULL) == -1)
+ goto err;
+ gmtime_r (&tv.tv_sec, &tm);
+
+ n = strftime (timestamp, len, "%F %T", &tm);
+ if (n == 0)
+ goto err;
+ snprintf (timestamp + n, len - n, ".%06" PRIu64, (uint64_t) tv.tv_usec);
+#else /* WIN32 */
+ /* Windows doesn't have thread-safe gmtime, or the strftime %F and
+ * %T formatters. Let's try to do this in a Windows native way.
+ * Windows SYSTEMTIME only returns milliseconds.
+ */
+ SYSTEMTIME st;
+ GetSystemTime (&st);
+ snprintf (timestamp, len, "%04d-%02d-%02d %02d:%02d:%02d.%03d000",
+ st.wYear, st.wMonth, st.wDay,
+ st.wHour, st.wMinute, st.wSecond,
+ st.wMilliseconds);
+#endif /* WIN32 */
+
+ /* Store the timestamp in thread-local storage. This passes
+ * ownership to threadlocal which will free it either on the next
+ * call or if the thread exits. This can fail (although it would be
+ * extremely unusual), and in that case we have to return something.
+ */
+ if (threadlocal_set_timestamp (timestamp) == -1)
+ goto err;
+
+ return timestamp;
+
+ err:
+ free (timestamp);
+ return "!";
+}
diff --git a/server/test-public.c b/server/test-public.c
index 3ef530ff..0edd3f49 100644
--- a/server/test-public.c
+++ b/server/test-public.c
@@ -92,6 +92,12 @@ threadlocal_get_context (void)
abort ();
}
+int
+threadlocal_set_timestamp (char *timestamp)
+{
+ abort ();
+}
+
conn_status
connection_get_status (void)
{
diff --git a/server/threadlocal.c b/server/threadlocal.c
index 74a3c4e5..108b9793 100644
--- a/server/threadlocal.c
+++ b/server/threadlocal.c
@@ -57,6 +57,7 @@ struct threadlocal {
size_t instance_num; /* Can be 0. */
int err;
char *last_error; /* Can be NULL. */
+ char *timestamp; /* Can be NULL. */
void *buffer; /* Can be NULL. */
size_t buffer_size;
struct connection *conn; /* Can be NULL. */
@@ -72,6 +73,7 @@ free_threadlocal (void *threadlocalv)
free (threadlocal->name);
free (threadlocal->last_error);
+ free (threadlocal->timestamp);
free (threadlocal->buffer);
free (threadlocal);
}
@@ -216,6 +218,24 @@ threadlocal_get_last_error (void)
return threadlocal ? threadlocal->last_error : NULL;
}
+/* Set the timestamp. Ownership is passed to TLS. This is used by
+ * nbdkit_timestamp(). Calling this frees any existing timestamp in
+ * the thread.
+ */
+int
+threadlocal_set_timestamp (char *timestamp)
+{
+ struct threadlocal *threadlocal = pthread_getspecific (threadlocal_key);
+
+ if (threadlocal) {
+ free (threadlocal->timestamp);
+ threadlocal->timestamp = timestamp;
+ return 0;
+ }
+ else
+ return -1;
+}
+
/* Return the single pread/pwrite buffer for this thread. The buffer
* size is increased to size bytes if required.
*
diff --git a/tests/Makefile.am b/tests/Makefile.am
index f0665926..8b7cb851 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -273,6 +273,7 @@ TESTS += \
test-name.sh \
test-no-name.sh \
test-name-plugin.sh \
+ test-timestamp.sh \
test-dump-plugin-example1.sh \
test-dump-plugin.sh \
test-dump-plugin-example2.sh \
@@ -413,6 +414,7 @@ EXTRA_DIST += \
test-timeout.sh \
test-timeout.py \
test-timeout-cancel.sh \
+ test-timestamp.sh \
test-tls-priority.sh \
test-tls-psk.sh \
test-tls.sh \
@@ -603,6 +605,29 @@ test_name_plugin_la_LDFLAGS = \
$(NULL)
test_name_plugin_la_LIBADD = $(IMPORT_LIBRARY_ON_WINDOWS)
+# check_LTLIBRARIES won't build a shared library (see automake manual).
+# So we have to do this and add a dependency.
+noinst_LTLIBRARIES += \
+ test-timestamp-plugin.la \
+ $(NULL)
+test-timestamp.sh: test-timestamp-plugin.la
+
+test_timestamp_plugin_la_SOURCES = \
+ test-timestamp-plugin.c \
+ $(top_srcdir)/include/nbdkit-plugin.h \
+ $(NULL)
+test_timestamp_plugin_la_CPPFLAGS = \
+ -I$(top_srcdir)/include \
+ -I$(top_builddir)/include \
+ $(NULL)
+test_timestamp_plugin_la_CFLAGS = $(WARNINGS_CFLAGS)
+# For use of the -rpath option, see:
+# https://lists.gnu.org/archive/html/libtool/2007-07/msg00067.html
+test_timestamp_plugin_la_LDFLAGS = \
+ -module -avoid-version -shared $(NO_UNDEFINED_ON_WINDOWS) -rpath /nowhere \
+ $(NULL)
+test_timestamp_plugin_la_LIBADD = $(IMPORT_LIBRARY_ON_WINDOWS)
+
endif HAVE_PLUGINS
# Test the header files can be included on their own.
diff --git a/tests/test-timestamp-plugin.c b/tests/test-timestamp-plugin.c
new file mode 100644
index 00000000..f7efe270
--- /dev/null
+++ b/tests/test-timestamp-plugin.c
@@ -0,0 +1,81 @@
+/* nbdkit
+ * Copyright Red Hat
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of Red Hat nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* This plugin tests nbdkit_timestamp().
+ *
+ * The corresponding test is 'test-timestamp.sh'.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define NBDKIT_API_VERSION 2
+#include <nbdkit-plugin.h>
+
+static void *
+timestamp_open (int readonly)
+{
+ nbdkit_debug ("%s: timestamped open", nbdkit_timestamp ());
+ return NBDKIT_HANDLE_NOT_NEEDED;
+}
+
+static int64_t
+timestamp_get_size (void *handle)
+{
+ return 1024*1024*1024;
+}
+
+#define THREAD_MODEL NBDKIT_THREAD_MODEL_PARALLEL
+
+static int
+timestamp_pread (void *handle, void *buf, uint32_t count, uint64_t offset,
+ uint32_t flags)
+{
+ const char *ts = nbdkit_timestamp ();
+ memset (buf, 0, count);
+ nbdkit_debug ("%s: timestamped memset", ts);
+
+ return 0;
+}
+
+static struct nbdkit_plugin plugin = {
+ .name = "timestamp",
+ .version = PACKAGE_VERSION,
+ .open = timestamp_open,
+ .get_size = timestamp_get_size,
+ .pread = timestamp_pread,
+};
+
+NBDKIT_REGISTER_PLUGIN (plugin)
diff --git a/tests/test-timestamp.sh b/tests/test-timestamp.sh
new file mode 100755
index 00000000..5479fd37
--- /dev/null
+++ b/tests/test-timestamp.sh
@@ -0,0 +1,61 @@
+#!/usr/bin/env bash
+# nbdkit
+# Copyright Red Hat
+#
+# 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.
+
+# Test the nbdkit_timestamp() API.
+
+source ./functions.sh
+set -e
+set -x
+set -u
+
+requires_run
+requires_nbdcopy
+
+plugin=.libs/test-timestamp-plugin.$SOEXT
+requires test -f $plugin
+
+out=timestamp.out
+cleanup_fn rm -f "$out"
+rm -f "$out"
+
+# Print the current date for comparison when checking the log.
+date
+
+# The plugin is large (but empty). Run nbdcopy which will invoke
+# the .pread method in the plugin in parallel.
+nbdkit -fv "$plugin" --run 'nbdcopy "$uri" null:' 2> $out
+cat $out
+
+# We are mainly interested that (a) the plugin nor nbdkit crash and
+# (b) that valgrind checks pass. So here we only need to check that
+# some timestamps were generated in the log.
+grep 'debug: [[:digit:]]\{4\}-[[:digit:]]\{2\}-[[:digit:]]\{2\} [[:digit:]]\{2\}:[[:digit:]]\{2\}:[[:digit:]]\{2\}\.[[:digit:]]\{6\}: timestamped' $out
--
2.47.3

View File

@ -1,45 +0,0 @@
From f1c763c8e15e23be656836e4b8ed740434776c3e Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Thu, 29 Jan 2026 11:14:49 +0000
Subject: [PATCH] log: Use nbdkit_timestamp()
After adding the new public nbdkit_timestamp function we can replace
the open-coded timestamp generation in the log filter. Note the
format is identical (since the nbdkit_timestamp code was copied from
here).
(cherry picked from commit 2942d8381dcbe573093e819360b5b1d5d38b80b7)
---
filters/log/output.c | 16 +---------------
1 file changed, 1 insertion(+), 15 deletions(-)
diff --git a/filters/log/output.c b/filters/log/output.c
index 4a116046..72a0ba3c 100644
--- a/filters/log/output.c
+++ b/filters/log/output.c
@@ -60,21 +60,7 @@ static void
to_file (struct handle *h, log_id_t id, const char *act, enum type type,
const char *fmt, va_list args)
{
- struct timeval tv;
- struct tm tm;
- char timestamp[27] = "Time unknown";
-
- /* Logging is best effort, so ignore failure to get timestamp */
- if (!gettimeofday (&tv, NULL)) {
- size_t s;
-
- gmtime_r (&tv.tv_sec, &tm);
- s = strftime (timestamp, sizeof timestamp - sizeof ".000000" + 1,
- "%F %T", &tm);
- assert (s);
- snprintf (timestamp + s, sizeof timestamp - s, ".%06ld",
- 0L + tv.tv_usec);
- }
+ const char *timestamp = nbdkit_timestamp ();
#ifdef HAVE_FLOCKFILE
flockfile (logfile);
--
2.47.3

View File

@ -1,29 +0,0 @@
From 69e58c8e3f98c845cc13884d3ce4b6e768d2afb7 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Thu, 29 Jan 2026 15:18:12 +0000
Subject: [PATCH] docs/nbdkit-plugin.pod: Add a link to nbdkit_timestamp(3)
The plugin page should link to every API page, and I forgot to add a
new link to nbdkit_timestamp(3).
Fixes: commit 773d958c8f2a5043053d385b8bfe287c43ee63d4
(cherry picked from commit a1a659645fa39cdba0996cb57673033be1a17385)
---
docs/nbdkit-plugin.pod | 1 +
1 file changed, 1 insertion(+)
diff --git a/docs/nbdkit-plugin.pod b/docs/nbdkit-plugin.pod
index 41f65908..3a5dc4a7 100644
--- a/docs/nbdkit-plugin.pod
+++ b/docs/nbdkit-plugin.pod
@@ -1661,6 +1661,7 @@ L<nbdkit_shutdown(3)>,
L<nbdkit_stdio_safe(3)>,
L<nbdkit_strdup_intern(3)>,
L<nbdkit_strndup_intern(3)>,
+L<nbdkit_timestamp(3)>,
L<nbdkit_vdebug(3)>,
L<nbdkit_verror(3)>,
L<nbdkit_vprintf_intern(3)>.
--
2.47.3

View File

@ -1,28 +0,0 @@
From 90547ea1ee742cf79a46dc0166f5d642df58b480 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Thu, 29 Jan 2026 19:27:07 +0000
Subject: [PATCH] docs/nbdkit_timestamp.pod: Fix copy and paste error in man
page
Fixes: commit 773d958c8f2a5043053d385b8bfe287c43ee63d4
(cherry picked from commit 0aea0a18f4665a885b77e1c1461c2aba05a0c604)
---
docs/nbdkit_timestamp.pod | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/nbdkit_timestamp.pod b/docs/nbdkit_timestamp.pod
index 2662b204..2b6859cf 100644
--- a/docs/nbdkit_timestamp.pod
+++ b/docs/nbdkit_timestamp.pod
@@ -56,7 +56,7 @@ an error generating the timestamp, the string C<"!"> is returned.
=head1 HISTORY
-C<nbdkit_name> was added in nbdkit 1.48.
+C<nbdkit_timestamp> was added in nbdkit 1.48.
=head1 SEE ALSO
--
2.47.3

View File

@ -1,33 +0,0 @@
From 996bb5a3acbf4478d4d568ddfdf32aa45fffb633 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Sat, 31 Jan 2026 08:41:56 +0000
Subject: [PATCH] todo: Add item about nbdkit_timestamp on the main thread
Updates: commit 773d958c8f2a5043053d385b8bfe287c43ee63d4
(cherry picked from commit e3d6ffc314b9774af31235c3d7ae760f62978861)
---
TODO.md | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/TODO.md b/TODO.md
index 8488dd95..46e2a0c6 100644
--- a/TODO.md
+++ b/TODO.md
@@ -87,6 +87,14 @@
`-4` or `-6` option). Once this mess is fixed, the tests should be
updated to use this.
+* `nbdkit_timestamp()` does not work when called on the main thread.
+ This is because the main thread does not allocate thread-local
+ storage (see [threadlocal.c](server/threadlocal.c)). We could
+ either special-case this in `nbdkit_timestamp` or we could implement
+ thread-local storage for the main thread (but the latter may change
+ some assumptions in the code). There may be other APIs that are
+ affected in this way too.
+
## Suggestions for plugins
Note: qemu supports other formats such as iscsi and ceph/rbd, and
--
2.47.3

View File

@ -1,121 +0,0 @@
From 02626a83a89068944e8840fef9e6deada9ae67b1 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Sat, 31 Jan 2026 13:41:36 +0000
Subject: [PATCH] server/sockets.c: Print the actual bound addresses and ports
in debug output
Previously when listening on a TCP/IP port, we printed (in debug
output) this:
nbdkit: debug: bound to IP address <any>:10809 (2 socket(s))
Change this to print the actual socket addresses for each socket:
nbdkit: debug: bound to IPv4 address 0.0.0.0:10809
nbdkit: debug: bound to IPv6 address [::]:10809
We just print the raw IP addresses to avoid doing name lookups. This
is still way harder than it should be.
(cherry picked from commit 6ef03ffdd451b730ac90d889e758e9151b14db82)
---
configure.ac | 7 ++++++
server/sockets.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++--
2 files changed, 62 insertions(+), 2 deletions(-)
diff --git a/configure.ac b/configure.ac
index a7a021e0..1cc87a44 100644
--- a/configure.ac
+++ b/configure.ac
@@ -509,6 +509,13 @@ AC_CHECK_MEMBERS([struct sockpeercred.uid], [], [],
#endif
]])
+dnl Check for types.
+AC_CHECK_TYPES([in_port_t], [], [], [[
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+]])
+
dnl Replacement functions that we provide for some platforms.
AC_CONFIG_LIBOBJ_DIR([common/replacements])
AC_REPLACE_FUNCS([\
diff --git a/server/sockets.c b/server/sockets.c
index 348da029..cef27d57 100644
--- a/server/sockets.c
+++ b/server/sockets.c
@@ -46,6 +46,10 @@
#include <sys/socket.h>
#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+
#ifdef HAVE_SYS_UN_H
#include <sys/un.h>
#endif
@@ -271,8 +275,57 @@ bind_tcpip_socket (sockets *socks)
exit (EXIT_FAILURE);
}
- debug ("bound to IP address %s:%s (%zu socket(s))",
- ipaddr ? ipaddr : "<any>", ipport, socks->len);
+ /* Print the IP address of each socket in debug output. */
+ if (verbose) {
+ char addr_str[128];
+ size_t i;
+ struct sockaddr_storage ss;
+ socklen_t sslen = sizeof ss;
+ const struct sockaddr_in *sin;
+ const struct sockaddr_in6 *sin6;
+ const void *addr;
+ const char *familyname;
+#ifdef HAVE_IN_PORT_T
+ in_port_t portno;
+#else
+ int portno;
+#endif
+ bool square_brackets = false;
+
+ for (i = 0; i < socks->len; ++i) {
+ if (getsockname (socks->ptr[i], (struct sockaddr *) &ss, &sslen) == -1) {
+ debug ("getsockname: %m");
+ continue;
+ }
+ switch (ss.ss_family) {
+ case AF_INET:
+ familyname = "IPv4";
+ sin = (const struct sockaddr_in *) &ss;
+ addr = &sin->sin_addr;
+ portno = sin->sin_port;
+ break;
+ case AF_INET6:
+ familyname = "IPv6";
+ square_brackets = true;
+ sin6 = (const struct sockaddr_in6 *) &ss;
+ addr = &sin6->sin6_addr;
+ portno = sin6->sin6_port;
+ break;
+ default:
+ /* Probably can never happen? */
+ debug ("unknown address family: %d", ss.ss_family);
+ continue;
+ }
+ if (inet_ntop (ss.ss_family, addr, addr_str, sizeof addr_str) == NULL) {
+ debug ("inet_ntop: %m");
+ continue;
+ }
+ debug ("bound to %s address %s%s%s:%d",
+ familyname,
+ square_brackets ? "[" : "", addr_str, square_brackets ? "]" : "",
+ (int) ntohs (portno));
+ }
+ }
}
void
--
2.47.3

View File

@ -1,214 +0,0 @@
From 410ee57d3708133527769e8b7eeddd5840226cb5 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Sat, 31 Jan 2026 14:16:30 +0000
Subject: [PATCH] server: Partially fix --port=0
Using nbdkit --port=0 causes nbdkit to open a TCP/IP socket with the
kernel choosing a random port number (usually two port numbers, one
for IPv4 and IPv6). This already worked, mostly, but it didn't update
the port variable and so $port was not set correctly in --run scripts,
making this option useless for our testing.
Also it didn't, and still does not, set the $uri or the output of
--print-uri correctly. The URI still has ":0" as the port number.
This is more difficult to fix, see my update to the TODO.md file.
(cherry picked from commit 8251486ec7d899628de246bc3232ddb20dceaa53)
---
TODO.md | 15 +++++-------
docs/nbdkit.pod | 12 ++++++++++
server/sockets.c | 47 ++++++++++++++++++++++++++++++++++++++
tests/Makefile.am | 2 ++
tests/test-ip-port.sh | 53 +++++++++++++++++++++++++++++++++++++++++++
5 files changed, 120 insertions(+), 9 deletions(-)
create mode 100755 tests/test-ip-port.sh
diff --git a/TODO.md b/TODO.md
index 46e2a0c6..af272405 100644
--- a/TODO.md
+++ b/TODO.md
@@ -77,15 +77,12 @@
particular `SOL_TCP` + `TCP_KEEPCNT`, `SOL_TCP` + `TCP_KEEPIDLE`,
and `SOL_TCP` + `TCP_KEEPINTVL`.
-* Fix `--port=0` / allow nbdkit to choose a TCP port: Several tests
- rely on picking a random TCP port, which is racy. The kernel can
- pick a port for us, and nbdkit `--print-uri` function can be used to
- display the random port to the user. Because of a bug, nbdkit lets
- you choose `--port=0`, causing the kernel to pick a port, but
- `--print-uri` doesn't display the port, and a different port is
- picked for IPv4 and IPv6 (so it only makes sense to use this with
- `-4` or `-6` option). Once this mess is fixed, the tests should be
- updated to use this.
+* Using `--port=0` (to get the kernel to pick a random port) works,
+ but the URI in `--print-uri` and `$uri` is wrong. Fixing this is
+ difficult because we generate and print the URI early, long before
+ we bind to ports. There is a case for binding to ports before
+ closing stdio, but that is quite a large change and needs some
+ careful thought.
* `nbdkit_timestamp()` does not work when called on the main thread.
This is because the main thread does not allocate thread-local
diff --git a/docs/nbdkit.pod b/docs/nbdkit.pod
index 3104d751..ac8a39b3 100644
--- a/docs/nbdkit.pod
+++ b/docs/nbdkit.pod
@@ -422,6 +422,18 @@ delete the file when it exits.
Change the TCP/IP port number on which nbdkit serves requests.
The default is C<10809>. See also I<-i>.
+=item B<-p 0>
+
+=item B<--port=0>
+
+Setting port to C<0> causes nbdkit to bind to a random free port
+number. On a dual-stack host it will usually bind to a I<different>
+localhost port number for IPv4 and IPv6.
+
+Currently I<--print-uri> will still print the port as C<":0"> (this is
+a bug), but the true port is available using the C<$port> variable in
+I<--run> scripts.
+
=item B<--print-uri>
Print the URI. See L</NBD URIs and endpoints> above.
diff --git a/server/sockets.c b/server/sockets.c
index cef27d57..dad7fb3c 100644
--- a/server/sockets.c
+++ b/server/sockets.c
@@ -326,6 +326,53 @@ bind_tcpip_socket (sockets *socks)
(int) ntohs (portno));
}
}
+
+ /* If port == "0" then we let the kernel choose the port number.
+ * (In the normal dual-stack case, it will actually choose two port
+ * numbers, one for IPv4 and one for IPv6). In this case we can
+ * overwrite the port variable with the chosen port number,
+ * preferring IPv6.
+ *
+ * In theory this loop could be combined with the one above but it
+ * makes the code very intricate.
+ */
+ if (strcmp (port, "0") == 0) {
+ static char port_str[16] = { 0 };
+ size_t i;
+ struct sockaddr_storage ss;
+ socklen_t sslen = sizeof ss;
+ const struct sockaddr_in *sin;
+ const struct sockaddr_in6 *sin6;
+
+ for (i = 0; i < socks->len; ++i) {
+ if (getsockname (socks->ptr[i], (struct sockaddr *) &ss, &sslen) == -1) {
+ debug ("getsockname: %m");
+ continue;
+ }
+ switch (ss.ss_family) {
+ case AF_INET:
+ sin = (const struct sockaddr_in *) &ss;
+ /* For IPv4, don't overwrite if the port_str is already set,
+ * so IPv6 takes priority.
+ */
+ if (port_str[0] == 0)
+ snprintf (port_str, sizeof port_str, "%d",
+ (int) ntohs (sin->sin_port));
+ break;
+ case AF_INET6:
+ sin6 = (const struct sockaddr_in6 *) &ss;
+ /* Prefer IPv6, so always override the port_str here. */
+ snprintf (port_str, sizeof port_str, "%d",
+ (int) ntohs (sin6->sin6_port));
+ break;
+ default:
+ abort ();
+ }
+ }
+
+ if (port_str[0] != 0)
+ port = port_str;
+ }
}
void
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 8b7cb851..e2bc640d 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -302,6 +302,7 @@ TESTS += \
test-tls-priority.sh \
test-tls-psk.sh \
test-not-linked-to-libssl.sh \
+ test-ip-port.sh \
test-ipv4-lo.sh \
test-ipv6-lo.sh \
test-foreground.sh \
@@ -379,6 +380,7 @@ EXTRA_DIST += \
test-foreground.sh \
test-help-example1.sh \
test-help-plugin.sh \
+ test-ip-port.sh \
test-ipv4-lo.sh \
test-ipv6-lo.sh \
test-keepalive.sh \
diff --git a/tests/test-ip-port.sh b/tests/test-ip-port.sh
new file mode 100755
index 00000000..cc1aa32e
--- /dev/null
+++ b/tests/test-ip-port.sh
@@ -0,0 +1,53 @@
+#!/usr/bin/env bash
+# nbdkit
+# Copyright Red Hat
+#
+# 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.
+
+# Test that --run '$port' has the correct (non-zero) port number when
+# we use --port=0.
+
+source ./functions.sh
+set -e
+set -x
+set -u
+
+requires_run
+requires_nbdinfo
+
+define script <<'EOF'
+echo port = $port
+test "$port" -gt "0"
+
+# nbdkit does not yet construct $uri correctly when using --port=0
+# but it does set $port so this will work:
+nbdinfo nbd://localhost:$port
+EOF
+
+nbdkit -v --port=0 null --run "$script"
--
2.47.3

View File

@ -1,104 +0,0 @@
From 05b8884ccab68a224fe4f240557082fb575bc407 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Sat, 31 Jan 2026 14:34:39 +0000
Subject: [PATCH] tests/test-ip-filter.sh: Remove use of pick_unused_port
Since nbdkit --port=0 is working somewhat now, we can remove use of
the racy pick_unused_port function.
We can now improve this test to check IPv6 only filtering.
(cherry picked from commit 1e1ba9b58a5988af746de0b3c0472e12462b8eb0)
---
TODO.md | 16 ++++++++++------
tests/test-ip-filter.sh | 40 ++++++++++++++++++++++++++++++----------
2 files changed, 40 insertions(+), 16 deletions(-)
diff --git a/TODO.md b/TODO.md
index af272405..ecb36f29 100644
--- a/TODO.md
+++ b/TODO.md
@@ -77,12 +77,16 @@
particular `SOL_TCP` + `TCP_KEEPCNT`, `SOL_TCP` + `TCP_KEEPIDLE`,
and `SOL_TCP` + `TCP_KEEPINTVL`.
-* Using `--port=0` (to get the kernel to pick a random port) works,
- but the URI in `--print-uri` and `$uri` is wrong. Fixing this is
- difficult because we generate and print the URI early, long before
- we bind to ports. There is a case for binding to ports before
- closing stdio, but that is quite a large change and needs some
- careful thought.
+* Using `--port=0` (to get the kernel to pick a random port) works:
+
+ - But the URI in `--print-uri` and `$uri` is wrong. Fixing this is
+ difficult because we generate and print the URI early, long before
+ we bind to ports. There is a case for binding to ports before
+ closing stdio, but that is quite a large change and needs some
+ careful thought.
+
+ - Consider exposing `$port4` and `$port6` to `--run` scripts. This
+ would allow `tests/test-ip-filter.sh` to work.
* `nbdkit_timestamp()` does not work when called on the main thread.
This is because the main thread does not allocate thread-local
diff --git a/tests/test-ip-filter.sh b/tests/test-ip-filter.sh
index cb7d6315..c8f7b051 100755
--- a/tests/test-ip-filter.sh
+++ b/tests/test-ip-filter.sh
@@ -38,7 +38,7 @@ set -e
set -x
set -u
-requires ip -V
+requires_run
requires_nbdinfo
requires_ipv6_loopback
@@ -46,15 +46,35 @@ requires_ipv6_loopback
# "nbd://[::1]:$port" URIs (commit 17df436cea5 added in 1.7.7).
requires_libnbd_version 1.8
-rm -f ip-filter.pid
-cleanup_fn rm -f ip-filter.pid
+fail=0
-# Find an unused port to listen on.
-pick_unused_port
+# Allow IPv4 and IPv6.
+nbdkit -v --port=0 --filter=ip null \
+ -D ip.rules=1 \
+ allow=allipv4,allipv6 deny=all \
+ --run '
+ nbdinfo "nbd://127.0.0.1:$port"
+ nbdinfo "nbd://[::1]:$port"
+'
-start_nbdkit -P ip-filter.pid -p $port --filter=ip null \
- -D ip.rules=1 \
- allow=allipv4,allipv6 deny=all
+# Allow IPv4 only, deny IPv6.
+# XXX We cannot test this because $port is set preferentially to the
+# IPv6 port, and we cannot find the IPv4 port here.
+#nbdkit -v --port=0 --filter=ip null \
+# -D ip.rules=1 \
+# allow=allipv4 deny=all --run 'nbdinfo "nbd://127.0.0.1:$port"'
+#
+#nbdkit -v --port=0 --filter=ip null \
+# -D ip.rules=1 \
+# allow=allipv4 deny=all --run 'nbdinfo "nbd://[::1]:$port"' && fail=1
-nbdinfo "nbd://127.0.0.1:$port"
-nbdinfo "nbd://[::1]:$port"
+# Allow IPv6 only, deny IPv4.
+nbdkit -v --port=0 --filter=ip null \
+ -D ip.rules=1 \
+ allow=allipv6 deny=all --run 'nbdinfo "nbd://[::1]:$port"'
+
+nbdkit -v --port=0 --filter=ip null \
+ -D ip.rules=1 \
+ allow=allipv6 deny=all --run 'nbdinfo "nbd://127.0.0.1:$port"' && fail=1
+
+exit $fail
--
2.47.3

View File

@ -1,109 +0,0 @@
From 2cb53b22419fa33f7a85efda0c940116f5c60ea5 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Sat, 31 Jan 2026 15:31:59 +0000
Subject: [PATCH] tests/test-ipv4-lo.sh, tests/test-ipv6-lo.sh: Remove
pick_unused_port
Remove use of pick_unused_port, and greatly simply these tests by
using --run and nbdinfo.
(cherry picked from commit e1ee17022c63d90dd7469c66ca4980e489fa3f95)
---
tests/test-ipv4-lo.sh | 35 ++++-------------------------------
tests/test-ipv6-lo.sh | 35 ++++-------------------------------
2 files changed, 8 insertions(+), 62 deletions(-)
diff --git a/tests/test-ipv4-lo.sh b/tests/test-ipv4-lo.sh
index e0e1878a..9b6e5c42 100755
--- a/tests/test-ipv4-lo.sh
+++ b/tests/test-ipv4-lo.sh
@@ -38,36 +38,9 @@ set -e
set -x
set -u
-# Cannot use kill pidfile below to test if the process is running on
-# Windows.
-if is_windows; then
- echo "$0: this test needs to be revised to work on Windows"
- exit 77
-fi
-
-requires ip -V
-requires "$QEMU_IMG" --version
-requires "$QEMU_IMG" info --image-opts driver=file,filename=functions.sh
-
-rm -f ipv4lo.pid ipv4lo.out
-cleanup_fn rm -f ipv4lo.pid ipv4lo.out
-
-# Find an unused port to listen on.
-pick_unused_port
+requires_run
+requires_nbdinfo
# By default nbdkit will listen on all available interfaces, ie.
-# IPv4 and IPv6.
-start_nbdkit -P ipv4lo.pid -p $port example1
-pid="$(cat ipv4lo.pid)"
-
-# Check the process exists.
-kill -s 0 $pid
-
-# Check we can connect over the IPv4 loopback interface.
-ipv4_lo="$(ip -o -4 addr show scope host)"
-if test -n "$ipv4_lo"; then
- "$QEMU_IMG" info --output=json \
- --image-opts "file.driver=nbd,file.host=127.0.0.1,file.port=$port" > ipv4lo.out
- cat ipv4lo.out
- grep -sq '"virtual-size": *104857600\b' ipv4lo.out
-fi
+# IPv4 and IPv6, so use -4 to force IPv4 only.
+nbdkit -v -4 --port=0 example1 --run 'nbdinfo nbd://127.0.0.1:$port/'
diff --git a/tests/test-ipv6-lo.sh b/tests/test-ipv6-lo.sh
index d30ae205..ea17bafc 100755
--- a/tests/test-ipv6-lo.sh
+++ b/tests/test-ipv6-lo.sh
@@ -38,37 +38,10 @@ set -e
set -x
set -u
-# Cannot use kill pidfile below to test if the process is running on
-# Windows.
-if is_windows; then
- echo "$0: this test needs to be revised to work on Windows"
- exit 77
-fi
-
-requires ip -V
-requires "$QEMU_IMG" --version
-requires "$QEMU_IMG" info --image-opts driver=file,filename=functions.sh
+requires_run
+requires_nbdinfo
requires_ipv6_loopback
-rm -f ipv6lo.pid ipv6lo.out
-cleanup_fn rm -f ipv6lo.pid ipv6lo.out
-
-# Find an unused port to listen on.
-pick_unused_port
-
# By default nbdkit will listen on all available interfaces, ie.
-# IPv4 and IPv6.
-start_nbdkit -P ipv6lo.pid -p $port example1
-pid="$(cat ipv6lo.pid)"
-
-# Check the process exists.
-kill -s 0 $pid
-
-# Check we can connect over the IPv6 loopback interface.
-ipv6_lo="$(ip -o -6 addr show scope host)"
-if test -n "$ipv6_lo"; then
- "$QEMU_IMG" info --output=json \
- --image-opts "file.driver=nbd,file.host=::1,file.port=$port" > ipv6lo.out
- cat ipv6lo.out
- grep -sq '"virtual-size": *104857600\b' ipv6lo.out
-fi
+# IPv4 and IPv6, so use -6 to force IPv6 only.
+nbdkit -v -6 --port=0 example1 --run 'nbdinfo nbd://[::1]:$port/'
--
2.47.3

View File

@ -1,51 +0,0 @@
From 53f021813744745f0ec0996f4e16bc71d3484336 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Sun, 1 Feb 2026 13:40:01 +0000
Subject: [PATCH] server/sockets.c: Don't crash if TCP/IP selected without
--port
Because of a thinko in commit 8251486ec7 ("server: Partially fix
--port=0") I neglected the case where we select TCP/IP but don't use
the --port parameter (thus port == NULL), eg:
$ nbdkit file disk.img
Segmentation fault (core dumped) nbdkit file disk.img
Ooops. The fix is to use ioport which is never NULL in this function.
Our tests don't test this case, since we cannot in general open port
10809 safely from the test suite.
Fixes: commit 8251486ec7d899628de246bc3232ddb20dceaa53
(cherry picked from commit 490c1a6980de65bb21f007dddb4a5a7ffa136c66)
---
server/sockets.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/server/sockets.c b/server/sockets.c
index dad7fb3c..473f8ee6 100644
--- a/server/sockets.c
+++ b/server/sockets.c
@@ -327,8 +327,8 @@ bind_tcpip_socket (sockets *socks)
}
}
- /* If port == "0" then we let the kernel choose the port number.
- * (In the normal dual-stack case, it will actually choose two port
+ /* If --port=0 then we let the kernel choose the port number. (In
+ * the normal dual-stack case, it will actually choose two port
* numbers, one for IPv4 and one for IPv6). In this case we can
* overwrite the port variable with the chosen port number,
* preferring IPv6.
@@ -336,7 +336,7 @@ bind_tcpip_socket (sockets *socks)
* In theory this loop could be combined with the one above but it
* makes the code very intricate.
*/
- if (strcmp (port, "0") == 0) {
+ if (strcmp (ipport, "0") == 0) {
static char port_str[16] = { 0 };
size_t i;
struct sockaddr_storage ss;
--
2.47.3

View File

@ -1,416 +0,0 @@
From d48364b33bea7997c38461ba2d85015a8901f2f3 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Sun, 1 Feb 2026 19:01:54 +0000
Subject: [PATCH] sparse-random: Make block size configurable
For trying to reproduce a virt-v2v corruption case, we would like to
use this plugin to simulate quite closely a VDDK source. VDDK uses a
64K block size for extents, which is different from the default (4K)
for this plugin. This change allows us to use 'blocksize=64K' to
simulate this.
(cherry picked from commit 5612598a49aaf4ac49f1b3e096dc4945ea7df640)
---
.../nbdkit-sparse-random-plugin.pod | 11 ++-
plugins/sparse-random/sparse-random.c | 99 +++++++++++--------
tests/Makefile.am | 2 +
tests/test-sparse-random-blocksize.sh | 49 +++++++++
4 files changed, 117 insertions(+), 44 deletions(-)
create mode 100755 tests/test-sparse-random-blocksize.sh
diff --git a/plugins/sparse-random/nbdkit-sparse-random-plugin.pod b/plugins/sparse-random/nbdkit-sparse-random-plugin.pod
index 0d64633f..d0472e00 100644
--- a/plugins/sparse-random/nbdkit-sparse-random-plugin.pod
+++ b/plugins/sparse-random/nbdkit-sparse-random-plugin.pod
@@ -4,8 +4,8 @@ nbdkit-sparse-random-plugin - make sparse random disks
=head1 SYNOPSIS
- nbdkit sparse-random [size=]SIZE [seed=SEED]
- [percent=N] [runlength=N]
+ nbdkit sparse-random [size=]SIZE [blocksize=N]
+ [seed=SEED] [percent=N] [runlength=N]
[random-content=true]
=head1 DESCRIPTION
@@ -52,6 +52,13 @@ See also L<nbdkit-checkwrite-filter(1)>.
=over 4
+=item B<blocksize=>N
+
+Set the block size. This is the granularity that this plugin operates
+at. Sparse extents will be aligned to the block size.
+
+It must be a power of 2 and E<ge> 1024. The default is 4096.
+
=item B<percent=>N
Specify the approximate percentage of the disk which contains random
diff --git a/plugins/sparse-random/sparse-random.c b/plugins/sparse-random/sparse-random.c
index 823f85a1..8d1c2944 100644
--- a/plugins/sparse-random/sparse-random.c
+++ b/plugins/sparse-random/sparse-random.c
@@ -36,6 +36,7 @@
#include <stdlib.h>
#include <stdint.h>
#include <inttypes.h>
+#include <limits.h>
#include <string.h>
#include <errno.h>
#include <time.h>
@@ -46,6 +47,7 @@
#include "bitmap.h"
#include "cleanup.h"
#include "isaligned.h"
+#include "ispowerof2.h"
#include "iszero.h"
#include "minmax.h"
#include "random.h"
@@ -60,7 +62,7 @@ static int random_content; /* false: Repeat same byte true: Random bytes*/
/* We need to store 1 bit per block. Using a 4K block size means we
* need 32M to map each 1T of virtual disk.
*/
-#define BLOCKSIZE 4096
+static unsigned blocksize = 4096;
static struct bitmap bm; /* Bitmap of data blocks. */
@@ -72,8 +74,6 @@ sparse_random_load (void)
* parameter.
*/
seed = time (NULL);
-
- bitmap_init (&bm, BLOCKSIZE, 1 /* bits per block */);
}
static void
@@ -97,6 +97,18 @@ sparse_random_config (const char *key, const char *value)
return -1;
size = r;
}
+ else if (strcmp (key, "blocksize") == 0 ||
+ strcmp (key, "block-size") == 0) {
+ r = nbdkit_parse_size (value);
+ if (r == -1)
+ return -1;
+ if (r < 1024 || r > 0x10000000 || !is_power_of_2 (r)) {
+ nbdkit_error ("block size must be a power of 2, "
+ "and between 1024 and 2^28");
+ return -1;
+ }
+ blocksize = r;
+ }
else if (strcmp (key, "percent") == 0) {
if (sscanf (value, "%lf", &percent) != 1 ||
percent < 0 || percent > 100) {
@@ -129,6 +141,7 @@ sparse_random_config (const char *key, const char *value)
#define sparse_random_config_help \
"size=<SIZE> (required) Size of the backing disk\n" \
+ "blocksize=<SIZE> Set block size (default: 4K)\n" \
"seed=<SEED> Random number generator seed\n" \
"percent=<PERCENT> Percentage of data\n" \
"runlength=<BYTES> Expected average run length of data\n" \
@@ -182,6 +195,8 @@ sparse_random_get_ready (void)
uint64_t data_run_length = 0;
uint64_t avg_data_run_length = 0;
+ bitmap_init (&bm, blocksize, 1 /* bits per block */);
+
if (bitmap_resize (&bm, size) == -1)
return -1;
@@ -196,7 +211,7 @@ sparse_random_get_ready (void)
}
/* Otherwise calculate the probability parameters as above. */
- P_dh = 1. / ((double) runlength / BLOCKSIZE);
+ P_dh = 1. / ((double) runlength / blocksize);
P_hd = (percent / 100.) * P_dh / (1. - (percent / 100.));
nbdkit_debug ("percent requested = %g%%, "
@@ -242,8 +257,8 @@ sparse_random_get_ready (void)
avg_data_run_length = 0;
nbdkit_debug ("percent actual = %g%%, "
"average run length = %" PRIu64,
- 100. * BLOCKSIZE * nr_data_blocks / size,
- avg_data_run_length * BLOCKSIZE);
+ 100. * blocksize * nr_data_blocks / size,
+ avg_data_run_length * blocksize);
return 0;
}
@@ -270,7 +285,7 @@ sparse_random_block_size (void *handle,
uint32_t *maximum)
{
*minimum = 1;
- *preferred = BLOCKSIZE;
+ *preferred = blocksize;
*maximum = 0xffffffff;
return 0;
}
@@ -301,20 +316,20 @@ read_block (uint64_t blknum, uint64_t offset, void *buf)
struct random_state state;
if (bitmap_get_blk (&bm, blknum, 0) == 0) /* hole */
- memset (buf, 0, BLOCKSIZE);
+ memset (buf, 0, blocksize);
else if (!random_content) { /* data when random-content=false */
xsrandom (seed + offset, &state);
s = xrandom (&state);
s &= 255;
if (s == 0) s = 1;
- memset (buf, (int)s, BLOCKSIZE);
+ memset (buf, (int)s, blocksize);
}
else { /* data when random-content=true */
/* This produces repeatable data for the same offset. Note it
* works because we are called on whole blocks only.
*/
xsrandom (seed + offset, &state);
- for (i = 0; i < BLOCKSIZE; ++i) {
+ for (i = 0; i < blocksize; ++i) {
s = xrandom (&state);
s &= 255;
b[i] = s;
@@ -330,20 +345,20 @@ sparse_random_pread (void *handle, void *buf, uint32_t count, uint64_t offset,
CLEANUP_FREE uint8_t *block = NULL;
uint64_t blknum, blkoffs;
- if (!IS_ALIGNED (count | offset, BLOCKSIZE)) {
- block = malloc (BLOCKSIZE);
+ if (!IS_ALIGNED (count | offset, blocksize)) {
+ block = malloc (blocksize);
if (block == NULL) {
nbdkit_error ("malloc: %m");
return -1;
}
}
- blknum = offset / BLOCKSIZE; /* block number */
- blkoffs = offset % BLOCKSIZE; /* offset within the block */
+ blknum = offset / blocksize; /* block number */
+ blkoffs = offset % blocksize; /* offset within the block */
/* Unaligned head */
if (blkoffs) {
- uint64_t n = MIN (BLOCKSIZE - blkoffs, count);
+ uint64_t n = MIN (blocksize - blkoffs, count);
read_block (blknum, offset, block);
memcpy (buf, &block[blkoffs], n);
@@ -355,12 +370,12 @@ sparse_random_pread (void *handle, void *buf, uint32_t count, uint64_t offset,
}
/* Aligned body */
- while (count >= BLOCKSIZE) {
+ while (count >= blocksize) {
read_block (blknum, offset, buf);
- buf += BLOCKSIZE;
- count -= BLOCKSIZE;
- offset += BLOCKSIZE;
+ buf += blocksize;
+ count -= blocksize;
+ offset += blocksize;
blknum++;
}
@@ -386,18 +401,18 @@ sparse_random_pwrite (void *handle, const void *buf,
CLEANUP_FREE uint8_t *block;
uint64_t blknum, blkoffs;
- block = malloc (BLOCKSIZE);
+ block = malloc (blocksize);
if (block == NULL) {
nbdkit_error ("malloc: %m");
return -1;
}
- blknum = offset / BLOCKSIZE; /* block number */
- blkoffs = offset % BLOCKSIZE; /* offset within the block */
+ blknum = offset / blocksize; /* block number */
+ blkoffs = offset % blocksize; /* offset within the block */
/* Unaligned head */
if (blkoffs) {
- uint64_t n = MIN (BLOCKSIZE - blkoffs, count);
+ uint64_t n = MIN (blocksize - blkoffs, count);
read_block (blknum, offset, block);
if (memcmp (buf, &block[blkoffs], n) != 0) {
@@ -414,23 +429,23 @@ sparse_random_pwrite (void *handle, const void *buf,
}
/* Aligned body */
- while (count >= BLOCKSIZE) {
+ while (count >= blocksize) {
/* As an optimization, skip calling read_block if we know this is
* a hole. Call is_zero instead which should be faster.
*/
if (bitmap_get_blk (&bm, blknum, 0) == 0) {
- if (! is_zero (buf, BLOCKSIZE))
+ if (! is_zero (buf, blocksize))
goto unexpected_data;
}
else {
read_block (blknum, offset, block);
- if (memcmp (buf, block, BLOCKSIZE) != 0)
+ if (memcmp (buf, block, blocksize) != 0)
goto unexpected_data;
}
- buf += BLOCKSIZE;
- count -= BLOCKSIZE;
- offset += BLOCKSIZE;
+ buf += blocksize;
+ count -= blocksize;
+ offset += blocksize;
blknum++;
}
@@ -465,12 +480,12 @@ sparse_random_trim_zero (void *handle, uint32_t count, uint64_t offset,
{
uint64_t blknum, blkoffs;
- blknum = offset / BLOCKSIZE; /* block number */
- blkoffs = offset % BLOCKSIZE; /* offset within the block */
+ blknum = offset / blocksize; /* block number */
+ blkoffs = offset % blocksize; /* offset within the block */
/* Unaligned head */
if (blkoffs) {
- uint64_t n = MIN (BLOCKSIZE - blkoffs, count);
+ uint64_t n = MIN (blocksize - blkoffs, count);
if (bitmap_get_blk (&bm, blknum, 0) != 0) {
unexpected_trim:
@@ -485,12 +500,12 @@ sparse_random_trim_zero (void *handle, uint32_t count, uint64_t offset,
}
/* Aligned body */
- while (count >= BLOCKSIZE) {
+ while (count >= blocksize) {
if (bitmap_get_blk (&bm, blknum, 0) != 0)
goto unexpected_trim;
- count -= BLOCKSIZE;
- offset += BLOCKSIZE;
+ count -= blocksize;
+ offset += blocksize;
blknum++;
}
@@ -510,12 +525,12 @@ sparse_random_extents (void *handle, uint32_t count, uint64_t offset,
uint64_t blknum, blkoffs;
uint32_t type;
- blknum = offset / BLOCKSIZE; /* block number */
- blkoffs = offset % BLOCKSIZE; /* offset within the block */
+ blknum = offset / blocksize; /* block number */
+ blkoffs = offset % blocksize; /* offset within the block */
/* Unaligned head */
if (blkoffs) {
- uint64_t n = MIN (BLOCKSIZE - blkoffs, count);
+ uint64_t n = MIN (blocksize - blkoffs, count);
if (bitmap_get_blk (&bm, blknum, 0) == 0)
type = NBDKIT_EXTENT_HOLE | NBDKIT_EXTENT_ZERO;
@@ -530,16 +545,16 @@ sparse_random_extents (void *handle, uint32_t count, uint64_t offset,
}
/* Aligned body */
- while (count >= BLOCKSIZE) {
+ while (count >= blocksize) {
if (bitmap_get_blk (&bm, blknum, 0) == 0)
type = NBDKIT_EXTENT_HOLE | NBDKIT_EXTENT_ZERO;
else
type = 0; /* data */
- if (nbdkit_add_extent (extents, offset, BLOCKSIZE, type) == -1)
+ if (nbdkit_add_extent (extents, offset, blocksize, type) == -1)
return -1;
- count -= BLOCKSIZE;
- offset += BLOCKSIZE;
+ count -= blocksize;
+ offset += blocksize;
blknum++;
}
diff --git a/tests/Makefile.am b/tests/Makefile.am
index e2bc640d..2ae0c3c2 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -1293,10 +1293,12 @@ EXTRA_DIST += \
# sparse-random plugin test.
TESTS += \
+ test-sparse-random-blocksize.sh \
test-sparse-random-copy.sh \
test-sparse-random-info.sh \
$(NULL)
EXTRA_DIST += \
+ test-sparse-random-blocksize.sh \
test-sparse-random-copy.sh \
test-sparse-random-info.sh \
$(NULL)
diff --git a/tests/test-sparse-random-blocksize.sh b/tests/test-sparse-random-blocksize.sh
new file mode 100755
index 00000000..c1230809
--- /dev/null
+++ b/tests/test-sparse-random-blocksize.sh
@@ -0,0 +1,49 @@
+#!/usr/bin/env bash
+# nbdkit
+# Copyright Red Hat
+#
+# 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.
+
+# Test the sparse-random plugin with non-standard blocksize.
+
+source ./functions.sh
+set -e
+set -x
+set -u
+
+requires_run
+
+# nbdcopy >= 1.5.9 required for this test.
+requires_nbdcopy
+requires_libnbd_version 1.5.9
+
+nbdkit -v \
+ sparse-random \
+ size=10G blocksize=64K \
+ --run 'nbdcopy "$uri" "$uri"'
--
2.47.3

View File

@ -1,39 +0,0 @@
From bf567e9488c0241cd58c13ef998b208a7f8a58f3 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Sun, 1 Feb 2026 21:21:59 +0000
Subject: [PATCH] sparse-random: Clamp preferred block size
The preferred block size must be between 512 and 32M. It was possible
to set a larger block size, so we must clamp it. (I clamped it at
both ends, even though currently the smallest block size is 1024).
Fixes: commit 5612598a49aaf4ac49f1b3e096dc4945ea7df640
(cherry picked from commit 7a7a103b0711a89a1912d6768db4a91bec3a5f17)
---
plugins/sparse-random/sparse-random.c | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/plugins/sparse-random/sparse-random.c b/plugins/sparse-random/sparse-random.c
index 8d1c2944..3d7da426 100644
--- a/plugins/sparse-random/sparse-random.c
+++ b/plugins/sparse-random/sparse-random.c
@@ -285,7 +285,15 @@ sparse_random_block_size (void *handle,
uint32_t *maximum)
{
*minimum = 1;
- *preferred = blocksize;
+
+ /* Preferred blocksize must be 512..32M so clamp this value. */
+ if (blocksize < 512)
+ *preferred = 512;
+ else if (blocksize > 32*1024*1024)
+ *preferred = 32*1024*1024;
+ else
+ *preferred = blocksize;
+
*maximum = 0xffffffff;
return 0;
}
--
2.47.3

View File

@ -1,60 +0,0 @@
From 26dd53f15d522ae137ec92afa2f49fd010ff2c15 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Sun, 1 Feb 2026 21:09:04 +0000
Subject: [PATCH] tests/test-sparse-random-blocksize.sh: Enhance the test
Check that all extents are aligned to the block size, and randomly
select the block size so we are testing both small and large blocks.
Updates: commit 5612598a49aaf4ac49f1b3e096dc4945ea7df640
(cherry picked from commit e11011043556b6ee4333212264bdefa5324eedc4)
---
tests/test-sparse-random-blocksize.sh | 28 +++++++++++++++++++++++++--
1 file changed, 26 insertions(+), 2 deletions(-)
diff --git a/tests/test-sparse-random-blocksize.sh b/tests/test-sparse-random-blocksize.sh
index c1230809..3ddc1f26 100755
--- a/tests/test-sparse-random-blocksize.sh
+++ b/tests/test-sparse-random-blocksize.sh
@@ -38,12 +38,36 @@ set -x
set -u
requires_run
+requires_nbdinfo
# nbdcopy >= 1.5.9 required for this test.
requires_nbdcopy
requires_libnbd_version 1.5.9
+out=sparse-random-blocksize.out
+cleanup_fn rm -f $out
+rm -f $out
+
+#blocksize=65536
+blocksize_r="$(( 10 + (RANDOM % 19) ))" ;# 10..28
+blocksize="$(( 1 << blocksize_r ))"
+
+export out
nbdkit -v \
sparse-random \
- size=10G blocksize=64K \
- --run 'nbdcopy "$uri" "$uri"'
+ size=10G blocksize=$blocksize \
+ --run '
+ nbdinfo --map "$uri" > $out &&
+ nbdcopy "$uri" "$uri"
+'
+
+# Check all the extents are aligned to $blocksize
+cat $out
+( while read offset size rest ; do
+ echo checking $offset $size ...
+ if test "$(( $offset % blocksize ))" != 0 ||
+ test "$(( $size % blocksize ))" != 0 ; then
+ echo error: extent is not aligned to $blocksize: offset $offset size $size
+ exit 1
+ fi
+done ) <$out
--
2.47.3

View File

@ -1,40 +0,0 @@
From 2e4212b86bd56ff6aaec6166cc3198050fcb172a Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Sun, 8 Feb 2026 22:10:17 +0000
Subject: [PATCH] tests/test-sparse-random-blocksize.sh: Reduce maximum block
size
On i686 this would fail if blocksize=32M was chosen, because we could
allocate (up to) 4 connections * 16 threads * 32M == 2G of RAM.
Probably we are not allocating that much, but it still often failed
with blocksize=32M.
Reduce the maximum we will choose down to 8M.
(cherry picked from commit 5edcc592dc9d4466596618da2d7507b575492a02)
---
tests/test-sparse-random-blocksize.sh | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/tests/test-sparse-random-blocksize.sh b/tests/test-sparse-random-blocksize.sh
index 3ddc1f26..29eec3f8 100755
--- a/tests/test-sparse-random-blocksize.sh
+++ b/tests/test-sparse-random-blocksize.sh
@@ -49,7 +49,13 @@ cleanup_fn rm -f $out
rm -f $out
#blocksize=65536
-blocksize_r="$(( 10 + (RANDOM % 19) ))" ;# 10..28
+
+# We could do this:
+#blocksize_r="$(( 10 + (RANDOM % 19) ))" ;# 10..28
+# but if this picks a 32M block size, then this could consume up to
+# 4 * 16 * 32 == 2048 MB of RAM. This is a problem on smaller systems
+# (and especially 32 bit), so choose a lesser maximum.
+blocksize_r="$(( 10 + (RANDOM % 17) ))" ;# 10..26
blocksize="$(( 1 << blocksize_r ))"
export out
--
2.47.3

View File

@ -6,7 +6,7 @@ set -e
# directory. Use it like this:
# ./copy-patches.sh
rhel_version=10.2
rhel_version=10.3
# Check we're in the right directory.
if [ ! -f nbdkit.spec ]; then

View File

@ -51,10 +51,10 @@
%global verify_tarball_signature 1
# The source directory.
%global source_directory 1.46-stable
%global source_directory 1.47-development
Name: nbdkit
Version: 1.46.2
Version: 1.47.5
Release: 1%{?dist}
Summary: NBD server
@ -77,30 +77,10 @@ Source2: libguestfs.keyring
Source3: copy-patches.sh
# Patches come from the upstream repository:
# https://gitlab.com/nbdkit/nbdkit/-/commits/rhel-10.2/
# https://gitlab.com/nbdkit/nbdkit/-/commits/rhel-10.3/
# Patches.
Patch0001: 0001-vram-Cast-cl_ulong-to-uint64_t-before-printing.patch
Patch0002: 0002-server-Add-nbdkit_debug_hexdiff-function.patch
Patch0003: 0003-checkwrite-Display-differences-if-D-checkwrite.showd.patch
Patch0004: 0004-docs-nbdkit_debug_hexdump.pod-Document-when-hexdiff-.patch
Patch0005: 0005-docs-nbdkit_debug_hexdump.pod-Add-a-link-back-to-nbd.patch
Patch0006: 0006-Add-new-nbdkit_name-function.patch
Patch0007: 0007-server-test-public.c-Add-process_name-dummy-variable.patch
Patch0008: 0008-Add-new-nbdkit_timestamp-function.patch
Patch0009: 0009-log-Use-nbdkit_timestamp.patch
Patch0010: 0010-docs-nbdkit-plugin.pod-Add-a-link-to-nbdkit_timestam.patch
Patch0011: 0011-docs-nbdkit_timestamp.pod-Fix-copy-and-paste-error-i.patch
Patch0012: 0012-todo-Add-item-about-nbdkit_timestamp-on-the-main-thr.patch
Patch0013: 0013-server-sockets.c-Print-the-actual-bound-addresses-an.patch
Patch0014: 0014-server-Partially-fix-port-0.patch
Patch0015: 0015-tests-test-ip-filter.sh-Remove-use-of-pick_unused_po.patch
Patch0016: 0016-tests-test-ipv4-lo.sh-tests-test-ipv6-lo.sh-Remove-p.patch
Patch0017: 0017-server-sockets.c-Don-t-crash-if-TCP-IP-selected-with.patch
Patch0018: 0018-sparse-random-Make-block-size-configurable.patch
Patch0019: 0019-sparse-random-Clamp-preferred-block-size.patch
Patch0020: 0020-tests-test-sparse-random-blocksize.sh-Enhance-the-te.patch
Patch0021: 0021-tests-test-sparse-random-blocksize.sh-Reduce-maximum.patch
#(nothing)
# For automatic RPM Provides generation.
# See: https://rpm-software-management.github.io/rpm/manual/dependency_generators.html
@ -1608,6 +1588,11 @@ fi
%changelog
* Thu Mar 19 2026 Richard W.M. Jones <rjones@redhat.com> - 1.47.5-1
- Rebase to nbdkit 1.47.5
Synchronize spec file with Fedora
resolves: RHEL-153362
* Mon Feb 09 2026 Richard W.M. Jones <rjones@redhat.com> - 1.46.2-1
- Rebase to nbdkit 1.46.2
- Backport nbdkit_debug_hexdiff, nbdkit_name, nbdkit_timestamp

View File

@ -1,2 +1,2 @@
SHA512 (nbdkit-1.46.2.tar.gz) = ce01ac7a90cb995ec3ef46c8cec0be7b47d7266edc4383df6e867881fd4ba66b5f36ccc4de356a0df0f1d47f86adb40212e8de62332d19014b293649f25d4b37
SHA512 (nbdkit-1.46.2.tar.gz.sig) = 73df3e276564c292ef5d94e6f5db0e25c77c65d1f6dab4d090528e7546340cfbea5e96bb385841ac4c2de29eebf7e52db8e74fbf3b59bbb48cef64e50dfa0790
SHA512 (nbdkit-1.47.5.tar.gz) = e5063b5acf10bac25f11af1a04d073ec068aac3f9ffcf1a1f3066e58a2508a2408d90deb821acd8916f498334d739791e4f69a8ae3d1f0a5954d9a2858a82c0f
SHA512 (nbdkit-1.47.5.tar.gz.sig) = bbf4150788788801a9f70f1dfa3e54f40e86d4d3abd8bd28c8a98ee29fdfe4ede7019e42476a7e5dede91d5b49aaf6668587d3382559f7dde8c7408d4c6c8fd1