import Oracle_OSS nbdkit-1.46.2-3.el10_2

This commit is contained in:
AlmaLinux RelEng Bot 2026-07-15 01:48:30 -04:00
parent e7309e9d45
commit 45525ad36e
48 changed files with 3361 additions and 2049 deletions

2
.gitignore vendored
View File

@ -1,2 +1,2 @@
libguestfs.keyring
nbdkit-1.44.1.tar.gz
nbdkit-1.46.2.tar.gz

View File

@ -1,272 +0,0 @@
From de37da4184c55c6811dd02707fdd3b1773a7ce66 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Fri, 4 Jul 2025 08:13:48 +0100
Subject: [PATCH] common: Add ONCE macro to run code only once
This macro can be used to run code once, especially for debug messages
and similar. eg:
/* Print this once in the log. */
ONCE (nbdkit_debug ("falling back to less efficient method"));
(cherry picked from commit ad8630deab4639e636212f11a5a47d2c34ef2949)
---
.gitignore | 1 +
common/include/Makefile.am | 6 ++
common/include/once.h | 67 ++++++++++++++++++++
common/include/test-once.c | 126 +++++++++++++++++++++++++++++++++++++
4 files changed, 200 insertions(+)
create mode 100644 common/include/once.h
create mode 100644 common/include/test-once.c
diff --git a/.gitignore b/.gitignore
index 3629ef39..827fd53c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -68,6 +68,7 @@ plugins/*/*.3
/common/include/test-iszero
/common/include/test-minmax
/common/include/test-nextnonzero
+/common/include/test-once
/common/include/test-random
/common/include/test-tvdiff
/common/protocol/generate-protostrings.sh
diff --git a/common/include/Makefile.am b/common/include/Makefile.am
index ca488e68..3a3757e2 100644
--- a/common/include/Makefile.am
+++ b/common/include/Makefile.am
@@ -49,6 +49,7 @@ EXTRA_DIST = \
iszero.h \
minmax.h \
nextnonzero.h \
+ once.h \
random.h \
rounding.h \
static-assert.h \
@@ -71,6 +72,7 @@ TESTS = \
test-iszero \
test-minmax \
test-nextnonzero \
+ test-once \
test-random \
test-tvdiff \
$(NULL)
@@ -120,6 +122,10 @@ test_nextnonzero_SOURCES = test-nextnonzero.c nextnonzero.h
test_nextnonzero_CPPFLAGS = -I$(srcdir)
test_nextnonzero_CFLAGS = $(WARNINGS_CFLAGS)
+test_once_SOURCES = test-once.c once.h
+test_once_CPPFLAGS = -I$(srcdir)
+test_once_CFLAGS = $(WARNINGS_CFLAGS)
+
test_random_SOURCES = test-random.c random.h
test_random_CPPFLAGS = -I$(srcdir)
test_random_CFLAGS = $(WARNINGS_CFLAGS)
diff --git a/common/include/once.h b/common/include/once.h
new file mode 100644
index 00000000..bb93e767
--- /dev/null
+++ b/common/include/once.h
@@ -0,0 +1,67 @@
+/* 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.
+ */
+
+#ifndef NBDKIT_ONCE_H
+#define NBDKIT_ONCE_H
+
+#ifdef HAVE_STDATOMIC_H
+#include <stdatomic.h>
+#else
+/* This is best effort on platforms that don't support atomic.
+ * 32 bit ints are generally fine in reality.
+ */
+#define _Atomic /**/
+#endif
+
+#include "unique-name.h"
+
+/* Run the statement once (per nbdkit run). */
+#define ONCE(stmt) ONCE_1(NBDKIT_UNIQUE_NAME(_once), (stmt))
+
+/* The actual implementation:
+ *
+ * The comparison with 0 avoids var wrapping around. Mostly var will
+ * only be 0 or 1, or in rare cases other small integers.
+ *
+ * The atomic increment & comparison with 1 is what only allows a
+ * single thread to run the statement.
+ *
+ * To avoid optimisations: Use 'volatile' so reads and writes are not
+ * removed, and use 'unsigned' to avoid any with signed overflow.
+ */
+#define ONCE_1(var, stmt) \
+ do { \
+ static volatile _Atomic unsigned var = 0; \
+ if (var == 0 && ++var == 1) { stmt; } \
+ } while (0)
+
+#endif /* NBDKIT_ONCE_H */
diff --git a/common/include/test-once.c b/common/include/test-once.c
new file mode 100644
index 00000000..d7dd5c42
--- /dev/null
+++ b/common/include/test-once.c
@@ -0,0 +1,126 @@
+/* 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.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifndef HAVE_STDATOMIC_H
+
+/* Skip the test if no <stdatomic.h> */
+
+int
+main (void)
+{
+ printf ("SKIP: no <stdatomic.h> on this platform\n");
+ exit (77);
+}
+
+#else /* HAVE_STDATOMIC_H */
+
+#include <stdatomic.h>
+#include <errno.h>
+#include <unistd.h>
+
+#undef NDEBUG /* Keep test strong even for nbdkit built without assertions */
+#include <assert.h>
+
+#include <pthread.h>
+
+#include "once.h"
+
+#define NR_THREADS 8
+
+static volatile _Atomic unsigned count1 = 0, count2 = 0,
+ count3 = 0, count4 = 0;
+static pthread_barrier_t barrier;
+
+static void * __attribute__((noreturn))
+start_thread (void *idxp)
+{
+ //int idx = * (int*) idxp;
+
+ pthread_barrier_wait (&barrier);
+
+ for (;;) {
+ ONCE (count1++);
+ ONCE (count2++);
+ ONCE (count3++);
+ ONCE (count4++);
+ }
+}
+
+int
+main (void)
+{
+ int i, err;
+ pthread_t th[NR_THREADS];
+ int idx[NR_THREADS];
+
+ err = pthread_barrier_init (&barrier, NULL, NR_THREADS);
+ if (err != 0) {
+ errno = err;
+ perror ("pthread_barrier_init");
+ exit (EXIT_FAILURE);
+ }
+
+ for (i = 0; i < NR_THREADS; ++i) {
+ idx[i] = i;
+ err = pthread_create (&th[i], NULL, start_thread, &idx[i]);
+ if (err != 0) {
+ errno = err;
+ perror ("pthread_create");
+ exit (EXIT_FAILURE);
+ }
+ }
+
+ do {
+ sleep (1);
+ } while (count1 + count2 + count3 + count4 < 4);
+
+ for (i = 0; i < NR_THREADS; ++i) {
+ pthread_cancel (th[i]);
+ }
+
+ pthread_barrier_destroy (&barrier);
+
+ if (count1 != 1 || count2 != 1 || count3 != 1 || count4 != 1) {
+ fprintf (stderr, "FAIL: counts incremented to %u %u %u %u "
+ "(expected 1 1 1 1)\n", count1, count2, count3, count4);
+ exit (EXIT_FAILURE);
+ }
+
+ exit (EXIT_SUCCESS);
+}
+
+#endif /* HAVE_STDATOMIC_H */
--
2.47.3

View File

@ -0,0 +1,78 @@
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,38 +0,0 @@
From 56dba3f1fe87f119e05b74787197ec776ef2692d Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Fri, 4 Jul 2025 08:20:43 +0100
Subject: [PATCH] file: zero: Print the debug message on the fallback path once
Use the new ONCE() macro to print the debug message when we fall back
to emulating zero only once. (Actually the core server code contains
a similar message so we probably don't need this at all.)
(cherry picked from commit fbb5d8211bf4c30144d01be80720e1a63ecd6e81)
---
plugins/file/file.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/plugins/file/file.c b/plugins/file/file.c
index 9c43ff24..b881da37 100644
--- a/plugins/file/file.c
+++ b/plugins/file/file.c
@@ -71,6 +71,7 @@
#include "isaligned.h"
#include "ispowerof2.h"
#include "minmax.h"
+#include "once.h"
#include "utils.h"
static enum {
@@ -1165,7 +1166,7 @@ file_zero (void *handle, uint32_t count, uint64_t offset, uint32_t flags)
/* Trigger a fall back to writing */
if (file_debug_zero)
- nbdkit_debug ("zero falling back to writing");
+ ONCE (nbdkit_debug ("%s: zero falling back to writing", h->name));
errno = EOPNOTSUPP;
return -1;
--
2.47.3

View File

@ -0,0 +1,538 @@
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

@ -0,0 +1,254 @@
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,65 +0,0 @@
From c9132973f88015586aa847ffcaa96e86bb23776f Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Fri, 4 Jul 2025 08:14:55 +0100
Subject: [PATCH] file: trim: Don't try BLKDISCARD if earlier
FALLOC_FL_PUNCH_HOLE worked
In file_zero, we test if the operations we are trying succeed and if
so jump to a single 'out:' label where we deal with the success path
out of that function.
We did not do the same thing in file_trim. Thus in the case where
FALLOC_FL_PUNCH_HOLE succeeds, we might fall through to trying
BLKDISCARD as well. As it happens we probably don't do this (at
least, in Linux) because we only try BLKDISCARD for block devices, and
FALLOC_FL_PUNCH_HOLE does not work on those. But it's a good thing to
clean up this code anyway, especially if we were to add more cases in
future.
This also adds a debug message if none of the trim methods worked,
which is also analogous to what happens in the same part of file_zero.
(cherry picked from commit 909e483c121c69e6b2759ef9d5401eb3d5acc998)
---
plugins/file/file.c | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/plugins/file/file.c b/plugins/file/file.c
index b881da37..66d03d4f 100644
--- a/plugins/file/file.c
+++ b/plugins/file/file.c
@@ -1191,6 +1191,7 @@ file_trim (void *handle, uint32_t count, uint64_t offset, uint32_t flags)
r = do_fallocate (h->fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
offset, count);
+ if (r == 0) goto out;
if (r == -1) {
if (!is_enotsup (errno)) {
nbdkit_error ("fallocate: %s: offset=%" PRIu64 ", count=%" PRIu32 ":"
@@ -1214,6 +1215,7 @@ file_trim (void *handle, uint32_t count, uint64_t offset, uint32_t flags)
uint64_t range[2] = {offset, count};
r = ioctl (h->fd, BLKDISCARD, &range);
+ if (r == 0) goto out;
if (r == -1) {
if (!is_enotsup (errno)) {
nbdkit_error ("ioctl: %s: offset=%" PRIu64 ", count=%" PRIu32 ":"
@@ -1227,6 +1229,15 @@ file_trim (void *handle, uint32_t count, uint64_t offset, uint32_t flags)
}
#endif
+ /* Trim is advisory. If we got here, we were unable to trim. */
+ ONCE (nbdkit_debug ("%s: could not trim, no trim methods worked",
+ h->name));
+ return 0;
+
+#ifdef __clang__
+ __attribute__ ((unused))
+#endif
+ out:
if ((flags & NBDKIT_FLAG_FUA) && file_flush (handle, 0) == -1)
return -1;
--
2.47.3

View File

@ -1,63 +0,0 @@
From 48869f1c0b6e4c318b680f6f672a9f90dfe31bff Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Tue, 8 Jul 2025 21:39:04 +0100
Subject: [PATCH] common/include/test-once.c: Skip test on macOS which lacks
pthread_barrier_t
See:
https://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap02.html
(cherry picked from commit 8271f9244f1521c716460820d8162e7641018674)
---
common/include/test-once.c | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/common/include/test-once.c b/common/include/test-once.c
index d7dd5c42..512b1a20 100644
--- a/common/include/test-once.c
+++ b/common/include/test-once.c
@@ -34,29 +34,29 @@
#include <stdio.h>
#include <stdlib.h>
+#include <unistd.h>
+#include <pthread.h>
-#ifndef HAVE_STDATOMIC_H
+#if !defined(HAVE_STDATOMIC_H) || !defined(_POSIX_BARRIERS)
-/* Skip the test if no <stdatomic.h> */
+/* Skip the test if no <stdatomic.h> or pthread_barrier_t */
int
main (void)
{
- printf ("SKIP: no <stdatomic.h> on this platform\n");
+ fprintf (stderr,
+ "SKIP: no <stdatomic.h> or pthread_barrier_t on this platform\n");
exit (77);
}
-#else /* HAVE_STDATOMIC_H */
+#else
#include <stdatomic.h>
#include <errno.h>
-#include <unistd.h>
#undef NDEBUG /* Keep test strong even for nbdkit built without assertions */
#include <assert.h>
-#include <pthread.h>
-
#include "once.h"
#define NR_THREADS 8
@@ -123,4 +123,4 @@ main (void)
exit (EXIT_SUCCESS);
}
-#endif /* HAVE_STDATOMIC_H */
+#endif
--
2.47.3

View File

@ -0,0 +1,33 @@
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,57 +0,0 @@
From f694d06d432d10699e26b2234f7a285fc018e94c Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Wed, 9 Jul 2025 12:20:34 +0100
Subject: [PATCH] common/include/test-once.c: Further fixes for
pthread_barrier_t
macOS defines _POSIX_BARRIERS but turns out to lack any implementation
of pthread_barrier_t. WTF.
FreeBSD requires linking with pthread else we get:
ld: error: undefined symbol: pthread_barrier_init
Fixes: commit ad8630deab4639e636212f11a5a47d2c34ef2949
Fixes: commit 8271f9244f1521c716460820d8162e7641018674
(cherry picked from commit 0d0e2b3d49cf8c9aa8cd37bb36b7002eb4624a2c)
---
common/include/Makefile.am | 3 ++-
common/include/test-once.c | 7 +++++--
2 files changed, 7 insertions(+), 3 deletions(-)
diff --git a/common/include/Makefile.am b/common/include/Makefile.am
index 3a3757e2..00a01091 100644
--- a/common/include/Makefile.am
+++ b/common/include/Makefile.am
@@ -124,7 +124,8 @@ test_nextnonzero_CFLAGS = $(WARNINGS_CFLAGS)
test_once_SOURCES = test-once.c once.h
test_once_CPPFLAGS = -I$(srcdir)
-test_once_CFLAGS = $(WARNINGS_CFLAGS)
+test_once_CFLAGS = $(WARNINGS_CFLAGS) $(PTHREAD_CFLAGS)
+test_once_LDFLAGS = $(PTHREAD_LIBS)
test_random_SOURCES = test-random.c random.h
test_random_CPPFLAGS = -I$(srcdir)
diff --git a/common/include/test-once.c b/common/include/test-once.c
index 512b1a20..304d512a 100644
--- a/common/include/test-once.c
+++ b/common/include/test-once.c
@@ -37,9 +37,12 @@
#include <unistd.h>
#include <pthread.h>
-#if !defined(HAVE_STDATOMIC_H) || !defined(_POSIX_BARRIERS)
+#if !defined(HAVE_STDATOMIC_H) || !defined(_POSIX_BARRIERS) || \
+ defined(__APPLE__)
-/* Skip the test if no <stdatomic.h> or pthread_barrier_t */
+/* Skip the test if no <stdatomic.h> or pthread_barrier_t or on macOS
+ * which defines _POSIX_BARRIERS but doesn't actually have them.
+ */
int
main (void)
--
2.47.3

View File

@ -0,0 +1,27 @@
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

@ -0,0 +1,407 @@
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,692 +0,0 @@
From dc8c6aae6aa1c62083421e2b2ce2988e970f2579 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Tue, 1 Jul 2025 13:26:08 +0100
Subject: [PATCH] Remove deprecated cacheextents filter
This is removed along the development branch (1.45) and in the next
stable version of nbdkit (1.46).
(cherry picked from commit 886050f6de9179b0e267e15b20376313090b2d3c)
---
configure.ac | 2 -
docs/nbdkit-protocol.pod | 9 +-
docs/nbdkit-release-notes-1.14.pod | 2 +-
docs/nbdkit-release-notes-1.44.pod | 2 +-
filters/cache/nbdkit-cache-filter.pod | 8 +-
filters/cacheextents/Makefile.am | 74 ------
filters/cacheextents/cacheextents.c | 212 ------------------
.../nbdkit-cacheextents-filter.pod | 76 -------
filters/cow/nbdkit-cow-filter.pod | 1 -
.../extentlist/nbdkit-extentlist-filter.pod | 1 -
tests/Makefile.am | 4 -
tests/test-cacheextents.sh | 114 ----------
12 files changed, 9 insertions(+), 496 deletions(-)
delete mode 100644 filters/cacheextents/Makefile.am
delete mode 100644 filters/cacheextents/cacheextents.c
delete mode 100644 filters/cacheextents/nbdkit-cacheextents-filter.pod
delete mode 100755 tests/test-cacheextents.sh
diff --git a/configure.ac b/configure.ac
index 0dca333f..9b057e6f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -143,7 +143,6 @@ filters="\
blocksize-policy \
bzip2 \
cache \
- cacheextents \
checkwrite \
cow \
ddrescue \
@@ -1787,7 +1786,6 @@ AC_CONFIG_FILES([Makefile
filters/blocksize-policy/Makefile
filters/bzip2/Makefile
filters/cache/Makefile
- filters/cacheextents/Makefile
filters/checkwrite/Makefile
filters/cow/Makefile
filters/ddrescue/Makefile
diff --git a/docs/nbdkit-protocol.pod b/docs/nbdkit-protocol.pod
index ef1934fd..93f5c5fa 100644
--- a/docs/nbdkit-protocol.pod
+++ b/docs/nbdkit-protocol.pod
@@ -275,14 +275,13 @@ filters do not work properly in this case.
blocksize-policy Yes
bzip2 No
cache No
- cacheextents No
checkwrite Yes
cow Yes, since 1.44
delay Yes
error Yes
evil Yes
-
exitlast Yes
+
exitwhen Yes
exportname Yes
ext2 No
@@ -292,8 +291,8 @@ filters do not work properly in this case.
ip Yes
limit Yes
log Yes
-
luks No
+
lzip No
multi-conn Yes
nocache Yes
@@ -303,8 +302,8 @@ filters do not work properly in this case.
nozero Yes
offset Yes, but unlikely to be useful
openonce Yes
-
partition No
+
pause Yes
protect Yes, but unlikely to be useful
qcow2dec No
@@ -314,8 +313,8 @@ filters do not work properly in this case.
retry Yes
retry-request Yes
rotational Yes
-
scan Yes
+
spinning Yes
stats Yes
swab Yes
diff --git a/docs/nbdkit-release-notes-1.14.pod b/docs/nbdkit-release-notes-1.14.pod
index 627e7e88..3c8c5d53 100644
--- a/docs/nbdkit-release-notes-1.14.pod
+++ b/docs/nbdkit-release-notes-1.14.pod
@@ -50,7 +50,7 @@ plugins own choice of thread model. Used to determine how the thread
model affects performance, or to serialize plugins if required (Eric
Blake).
-New L<nbdkit-cacheextents-filter(1)> to cache extents requests,
+New nbdkit-cacheextents-filter to cache extents requests,
especially useful with VDDK which has a slow implementation of extents
(Martin Kletzander).
diff --git a/docs/nbdkit-release-notes-1.44.pod b/docs/nbdkit-release-notes-1.44.pod
index 62d69aa5..e5872763 100644
--- a/docs/nbdkit-release-notes-1.44.pod
+++ b/docs/nbdkit-release-notes-1.44.pod
@@ -59,7 +59,7 @@ eg. C<@4M> to move the offset to 4194304 (Eric Blake).
New L<nbdkit-openonce-filter(1)> which can be used to open the
underlying plugin once, sharing the plugin across connections.
-L<nbdkit-cacheextents-filter(1)> I<has been deprecated>, and is
+I<nbdkit-cacheextents-filter has been deprecated>, and is
expected to be removed in S<nbdkit 1.46>.
L<nbdkit-cow-filter(1)> now understands that the NBD protocol export
diff --git a/filters/cache/nbdkit-cache-filter.pod b/filters/cache/nbdkit-cache-filter.pod
index ffa86919..7a64ca66 100644
--- a/filters/cache/nbdkit-cache-filter.pod
+++ b/filters/cache/nbdkit-cache-filter.pod
@@ -29,10 +29,9 @@ does not have effective caching, or (with C<cache=unsafe>) to defeat
flush requests from the client (which is unsafe and can cause data
loss, as the name suggests).
-This filter only caches image contents. To cache image metadata, use
-L<nbdkit-cacheextents-filter(1)> between this filter and the plugin.
-To accelerate sequential reads, use L<nbdkit-readahead-filter(1)> or
-L<nbdkit-scan-filter(1)> on top of this filter.
+This filter only caches image contents. To accelerate sequential
+reads, use L<nbdkit-readahead-filter(1)> or L<nbdkit-scan-filter(1)>
+on top of this filter.
=head1 PARAMETERS
@@ -181,7 +180,6 @@ C<nbdkit-cache-filter> first appeared in nbdkit 1.2.
L<nbdkit(1)>,
L<nbdkit-file-plugin(1)>,
-L<nbdkit-cacheextents-filter(1)>,
L<nbdkit-cow-filter(1)>,
L<nbdkit-readahead-filter(1)>,
L<nbdkit-filter(3)>,
diff --git a/filters/cacheextents/Makefile.am b/filters/cacheextents/Makefile.am
deleted file mode 100644
index 26ac6642..00000000
--- a/filters/cacheextents/Makefile.am
+++ /dev/null
@@ -1,74 +0,0 @@
-# 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.
-
-include $(top_srcdir)/common-rules.mk
-
-EXTRA_DIST = nbdkit-cacheextents-filter.pod
-
-filter_LTLIBRARIES = nbdkit-cacheextents-filter.la
-
-nbdkit_cacheextents_filter_la_SOURCES = \
- cacheextents.c \
- $(top_srcdir)/include/nbdkit-filter.h \
- $(NULL)
-
-nbdkit_cacheextents_filter_la_CPPFLAGS = \
- -I$(top_srcdir)/include \
- -I$(top_builddir)/include \
- -I$(top_srcdir)/common/include \
- -I$(top_srcdir)/common/utils \
- $(NULL)
-nbdkit_cacheextents_filter_la_CFLAGS = $(WARNINGS_CFLAGS)
-nbdkit_cacheextents_filter_la_LDFLAGS = \
- -module -avoid-version -shared $(NO_UNDEFINED_ON_WINDOWS) \
- $(NULL)
-if USE_LINKER_SCRIPT
-nbdkit_cacheextents_filter_la_LDFLAGS += \
- -Wl,--version-script=$(top_srcdir)/filters/filters.syms
-endif
-nbdkit_cacheextents_filter_la_LIBADD = \
- $(top_builddir)/common/utils/libutils.la \
- $(top_builddir)/common/replacements/libcompat.la \
- $(IMPORT_LIBRARY_ON_WINDOWS) \
- $(NULL)
-
-if HAVE_POD
-
-man_MANS = nbdkit-cacheextents-filter.1
-CLEANFILES += $(man_MANS)
-
-nbdkit-cacheextents-filter.1: nbdkit-cacheextents-filter.pod \
- $(top_builddir)/podwrapper.pl
- $(PODWRAPPER) --section=1 --man $@ \
- --html $(top_builddir)/html/$@.html \
- $<
-
-endif HAVE_POD
diff --git a/filters/cacheextents/cacheextents.c b/filters/cacheextents/cacheextents.c
deleted file mode 100644
index 71f73c41..00000000
--- a/filters/cacheextents/cacheextents.c
+++ /dev/null
@@ -1,212 +0,0 @@
-/* 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.
- */
-
-#include <config.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <string.h>
-#include <errno.h>
-#include <inttypes.h>
-
-#include <pthread.h>
-
-#include <nbdkit-filter.h>
-
-#include "cleanup.h"
-
-/* -D cacheextents.cache=1: Debug cache operations. */
-NBDKIT_DLL_PUBLIC int cacheextents_debug_cache = 0;
-
-/* This lock protects the global state. */
-static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
-
-/* Cached extents from the last extents () call and its start and end
- * for the sake of simplicity.
- */
-struct nbdkit_extents *cache_extents;
-static uint64_t cache_start;
-static uint64_t cache_end;
-
-static void
-cacheextents_unload (void)
-{
- nbdkit_extents_free (cache_extents);
-}
-
-static int
-cacheextents_add (struct nbdkit_extents *extents, int *err)
-{
- size_t i = 0;
-
- for (i = 0; i < nbdkit_extents_count (cache_extents); i++) {
- struct nbdkit_extent ex = nbdkit_get_extent (cache_extents, i);
- if (nbdkit_add_extent (extents, ex.offset, ex.length, ex.type) == -1) {
- *err = errno;
- return -1;
- }
- }
-
- return 0;
-}
-
-static int
-fill (struct nbdkit_extents *extents, int *err)
-{
- size_t i = 0;
- size_t count = nbdkit_extents_count (extents);
- struct nbdkit_extent first = nbdkit_get_extent (extents, 0);
- struct nbdkit_extent last = nbdkit_get_extent (extents, count - 1);
-
- nbdkit_extents_free (cache_extents);
- cache_start = first.offset;
- cache_end = last.offset + last.length;
- cache_extents = nbdkit_extents_new (cache_start, cache_end);
-
- if (!cache_extents)
- return -1;
-
- for (i = 0; i < count; i++) {
- struct nbdkit_extent ex = nbdkit_get_extent (extents, i);
-
- if (cacheextents_debug_cache)
- nbdkit_debug ("cacheextents: updating cache with:"
- " offset=%" PRIu64
- " length=%" PRIu64
- " type=%x",
- ex.offset, ex.length, ex.type);
-
- if (nbdkit_add_extent (cache_extents, ex.offset, ex.length,
- ex.type) == -1) {
- *err = errno;
- nbdkit_extents_free (cache_extents);
- cache_extents = NULL;
- return -1;
- }
- }
-
- return 0;
-}
-
-static int
-cacheextents_extents (nbdkit_next *next,
- void *handle, uint32_t count, uint64_t offset,
- uint32_t flags,
- struct nbdkit_extents *extents,
- int *err)
-{
- ACQUIRE_LOCK_FOR_CURRENT_SCOPE (&lock);
-
- if (cacheextents_debug_cache)
- nbdkit_debug ("cacheextents:"
- " cache_start=%" PRIu64
- " cache_end=%" PRIu64
- " cache_extents=%p",
- cache_start, cache_end, cache_extents);
-
- if (cache_extents &&
- offset >= cache_start && offset < cache_end) {
- if (cacheextents_debug_cache)
- nbdkit_debug ("cacheextents: returning from cache");
- return cacheextents_add (extents, err);
- }
-
- if (cacheextents_debug_cache)
- nbdkit_debug ("cacheextents: cache miss");
-
- /* Clear REQ_ONE to ask the plugin for as much information as it is
- * willing to return (the plugin may still truncate if it is too
- * costly to provide everything).
- */
- flags &= ~(NBDKIT_FLAG_REQ_ONE);
- if (next->extents (next, count, offset, flags, extents, err) == -1)
- return -1;
-
- return fill (extents, err);
-}
-
-/* Any changes to the data needs to clean the cache.
- *
- * Similar to the readahead filter this could be more intelligent, but
- * there would be very little benefit.
- */
-
-static void
-kill_cacheextents (void)
-{
- ACQUIRE_LOCK_FOR_CURRENT_SCOPE (&lock);
- nbdkit_extents_free (cache_extents);
- cache_extents = NULL;
-}
-
-static int
-cacheextents_pwrite (nbdkit_next *next,
- void *handle,
- const void *buf, uint32_t count, uint64_t offset,
- uint32_t flags, int *err)
-{
- kill_cacheextents ();
- return next->pwrite (next, buf, count, offset, flags, err);
-}
-
-static int
-cacheextents_trim (nbdkit_next *next,
- void *handle,
- uint32_t count, uint64_t offset, uint32_t flags,
- int *err)
-{
- kill_cacheextents ();
- return next->trim (next, count, offset, flags, err);
-}
-
-static int
-cacheextents_zero (nbdkit_next *next,
- void *handle,
- uint32_t count, uint64_t offset, uint32_t flags,
- int *err)
-{
- kill_cacheextents ();
- return next->zero (next, count, offset, flags, err);
-}
-
-static struct nbdkit_filter filter = {
- .name = "cacheextents",
- .longname = "nbdkit cacheextents filter",
- .unload = cacheextents_unload,
- .pwrite = cacheextents_pwrite,
- .trim = cacheextents_trim,
- .zero = cacheextents_zero,
- .extents = cacheextents_extents,
-};
-
-NBDKIT_REGISTER_FILTER (filter)
diff --git a/filters/cacheextents/nbdkit-cacheextents-filter.pod b/filters/cacheextents/nbdkit-cacheextents-filter.pod
deleted file mode 100644
index 0693ca80..00000000
--- a/filters/cacheextents/nbdkit-cacheextents-filter.pod
+++ /dev/null
@@ -1,76 +0,0 @@
-=head1 NAME
-
-nbdkit-cacheextents-filter - cache extents
-
-=head1 SYNOPSIS
-
- nbdkit --filter=cacheextents plugin
-
-=head1 DEPRECATED
-
-B<The cacheextents filter is deprecated in S<nbdkit E<ge> 1.43.10> and
-will be removed in S<nbdkit 1.46>>. There is no direct replacement,
-but as the filter only worked for a narrow and unusual range of access
-patterns it is likely that it has no effect and you can just stop
-using it.
-
-=head1 DESCRIPTION
-
-C<nbdkit-cacheextents-filter> is a filter that caches the result of last
-extents() call.
-
-A common use for this filter is to improve performance when using a
-client performing a linear pass over the entire image while asking for
-only one extent at a time (such as S<C<qemu-img convert>>), but where
-the plugin can provide multiple extents for the same high latency as a
-single extent (such as L<nbdkit-vddk-plugin(1)>). For example:
-
- nbdkit --filter=cacheextents --run 'qemu-img map "$uri"' vddk ...
-
-For files with big extents (when it is unlikely for one extents() call
-to return multiple different extents) this does not slow down the
-access.
-
-This filter only caches image metadata; to also cache image contents,
-place this filter between L<nbdkit-cache-filter(1)> and the plugin.
-
-=head1 PARAMETERS
-
-There are no parameters specific to nbdkit-cacheextents-filter. Any
-parameters are passed through to and processed by the underlying
-plugin in the normal way.
-
-=head1 FILES
-
-=over 4
-
-=item F<$filterdir/nbdkit-cacheextents-filter.so>
-
-The filter.
-
-Use C<nbdkit --dump-config> to find the location of C<$filterdir>.
-
-=back
-
-=head1 VERSION
-
-C<nbdkit-cacheextents-filter> first appeared in nbdkit 1.14.
-
-=head1 SEE ALSO
-
-L<nbdkit(1)>,
-L<nbdkit-cache-filter(1)>,
-L<nbdkit-extentlist-filter(1)>,
-L<nbdkit-readahead-filter(1)>,
-L<nbdkit-scan-filter(1)>,
-L<nbdkit-vddk-plugin(1)>,
-L<nbdkit-filter(3)>,
-L<qemu-img(1)>.
-
-=head1 AUTHORS
-
-Martin Kletzander
-
-=head1 COPYRIGHT
-
-Copyright Red Hat
diff --git a/filters/cow/nbdkit-cow-filter.pod b/filters/cow/nbdkit-cow-filter.pod
index fd551d93..9462a28d 100644
--- a/filters/cow/nbdkit-cow-filter.pod
+++ b/filters/cow/nbdkit-cow-filter.pod
@@ -169,7 +169,6 @@ C<nbdkit-cow-filter> first appeared in nbdkit 1.2.
L<nbdkit(1)>,
L<nbdkit-file-plugin(1)>,
L<nbdkit-cache-filter(1)>,
-L<nbdkit-cacheextents-filter(1)>,
L<nbdkit-xz-filter(1)>,
L<nbdkit-filter(3)>,
L<nbdcopy(1)>,
diff --git a/filters/extentlist/nbdkit-extentlist-filter.pod b/filters/extentlist/nbdkit-extentlist-filter.pod
index d5ac81eb..44c81635 100644
--- a/filters/extentlist/nbdkit-extentlist-filter.pod
+++ b/filters/extentlist/nbdkit-extentlist-filter.pod
@@ -85,7 +85,6 @@ C<nbdkit-extentlist-filter> first appeared in nbdkit 1.18.
=head1 SEE ALSO
L<nbdkit(1)>,
-L<nbdkit-cacheextents-filter(1)>,
L<nbdkit-noextents-filter(1)>,
L<nbdkit-filter(3)>,
L<nbdkit-plugin(3)>.
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 6d94c327..c16b5912 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -1694,10 +1694,6 @@ EXTRA_DIST += \
test-cache-unaligned.sh \
$(NULL)
-# cacheextents filter test.
-TESTS += test-cacheextents.sh
-EXTRA_DIST += test-cacheextents.sh
-
# checkwrite filter test.
TESTS += \
test-checkwrite.sh \
diff --git a/tests/test-cacheextents.sh b/tests/test-cacheextents.sh
deleted file mode 100755
index 34d66217..00000000
--- a/tests/test-cacheextents.sh
+++ /dev/null
@@ -1,114 +0,0 @@
-#!/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.
-
-source ./functions.sh
-set -x
-set -u
-set -e
-
-requires_plugin sh
-requires_filter cacheextents
-requires grep --version
-requires qemu-io --version
-requires dd iflag=count_bytes </dev/null
-
-sock=$(mktemp -u /tmp/nbdkit-test-sock.XXXXXX)
-sockurl="nbd+unix:///?socket=$sock"
-pidfile="test-cacheextents.pid"
-accessfile="test-cacheextents-access.log"
-accessfile_full="$PWD/test-cacheextents-access.log"
-files="$pidfile $sock"
-rm -f $files $accessfile
-cleanup_fn rm -f $files
-
-define plugin <<'EOF'
-echo "Call: $@" >>$accessfile_full
-size=4M
-block_size=$((1024*1024))
-case "$1" in
- thread_model) echo parallel ;;
- get_size) echo $size ;;
- can_extents) ;;
- extents)
- echo "extents request: $@" >>$accessfile_full
- offset=$(($4 / $block_size))
- count=$(($3 / $block_size))
- length=$(($offset + $count))
- for i in $(seq $offset $length); do
- echo ${i}M $block_size $((i%4)) >>$accessfile_full
- echo ${i}M $block_size $((i%4))
- done
- ;;
- pread) dd if=/dev/zero count=$3 iflag=count_bytes ;;
- can_write) ;;
- pwrite) dd of=/dev/null ;;
- can_trim) ;;
- trim) ;;
- can_zero) ;;
- zero) ;;
- *) exit 2 ;;
-esac
-EOF
-
-export accessfile_full
-start_nbdkit \
- -P $pidfile \
- -U $sock \
- --filter=cacheextents \
- sh - <<<"$plugin"
-
-test_me() {
- num_accesses=$1
- shift
-
- qemu-io -f raw "$@" "$sockurl"
- test "$(grep -c "^extents request: " $accessfile)" -eq "$num_accesses"
- ret=$?
- rm -f "$accessfile"
- return $ret
-}
-
-# First one causes caching, the rest should be returned from cache.
-test_me 1 -c 'map' -c 'map' -c 'map'
-# First one is still cached from last time, discard should kill the cache, then
-# one request should go through.
-test_me 1 -c 'map' -c 'discard 0 1' -c 'map'
-# Same as above, only this time the cache is killed before all the operations as
-# well. This is used from now on to clear the cache as it seems nicer and
-# faster than running new nbdkit for each test.
-test_me 2 -c 'discard 0 1' -c 'map' -c 'discard 0 1' -c 'map'
-# Write should kill the cache as well.
-test_me 2 -c 'discard 0 1' -c 'map' -c 'write 0 1' -c 'map'
-# Alloc should use cached data from map
-test_me 1 -c 'discard 0 1' -c 'map' -c 'alloc 0'
-# Read should not kill the cache
-test_me 1 -c 'discard 0 1' -c 'map' -c 'read 0 1' -c 'map' -c 'alloc 0'
--
2.47.3

View File

@ -1,500 +0,0 @@
From 9c28df70cbde94e58e448c8953965510e5d952c2 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Tue, 8 Jul 2025 17:49:00 +0100
Subject: [PATCH] New filter: nbdkit-count-filter: count bytes read, written
etc.
This produces a summary of the number of bytes read, written, etc
through the filter.
This is mainly of use to virt-v2v where it's commonly asked how much
data was transferred over the wire or written to disk, and we don't
currently have an easy way to answer that. By simply adding this
filter, the numbers will be known from the virt-v2v conversion log.
(cherry picked from commit 3512c3ce9308b4d940119ac6cc87f1baa9afb655)
---
configure.ac | 2 +
docs/nbdkit-protocol.pod | 9 +-
filters/count/Makefile.am | 70 ++++++++++++++
filters/count/count.c | 132 ++++++++++++++++++++++++++
filters/count/nbdkit-count-filter.pod | 55 +++++++++++
filters/log/nbdkit-log-filter.pod | 1 +
filters/stats/nbdkit-stats-filter.pod | 3 +
plugins/file/nbdkit-file-plugin.pod | 1 +
tests/Makefile.am | 4 +
tests/test-count.sh | 55 +++++++++++
10 files changed, 328 insertions(+), 4 deletions(-)
create mode 100644 filters/count/Makefile.am
create mode 100644 filters/count/count.c
create mode 100644 filters/count/nbdkit-count-filter.pod
create mode 100755 tests/test-count.sh
diff --git a/configure.ac b/configure.ac
index 9b057e6f..26e59462 100644
--- a/configure.ac
+++ b/configure.ac
@@ -144,6 +144,7 @@ filters="\
bzip2 \
cache \
checkwrite \
+ count \
cow \
ddrescue \
delay \
@@ -1787,6 +1788,7 @@ AC_CONFIG_FILES([Makefile
filters/bzip2/Makefile
filters/cache/Makefile
filters/checkwrite/Makefile
+ filters/count/Makefile
filters/cow/Makefile
filters/ddrescue/Makefile
filters/delay/Makefile
diff --git a/docs/nbdkit-protocol.pod b/docs/nbdkit-protocol.pod
index 93f5c5fa..edf0efb0 100644
--- a/docs/nbdkit-protocol.pod
+++ b/docs/nbdkit-protocol.pod
@@ -276,12 +276,13 @@ filters do not work properly in this case.
bzip2 No
cache No
checkwrite Yes
+ count Yes
cow Yes, since 1.44
delay Yes
error Yes
evil Yes
+
exitlast Yes
-
exitwhen Yes
exportname Yes
ext2 No
@@ -291,8 +292,8 @@ filters do not work properly in this case.
ip Yes
limit Yes
log Yes
+
luks No
-
lzip No
multi-conn Yes
nocache Yes
@@ -302,8 +303,8 @@ filters do not work properly in this case.
nozero Yes
offset Yes, but unlikely to be useful
openonce Yes
+
partition No
-
pause Yes
protect Yes, but unlikely to be useful
qcow2dec No
@@ -313,8 +314,8 @@ filters do not work properly in this case.
retry Yes
retry-request Yes
rotational Yes
+
scan Yes
-
spinning Yes
stats Yes
swab Yes
diff --git a/filters/count/Makefile.am b/filters/count/Makefile.am
new file mode 100644
index 00000000..20456e17
--- /dev/null
+++ b/filters/count/Makefile.am
@@ -0,0 +1,70 @@
+# 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.
+
+include $(top_srcdir)/common-rules.mk
+
+EXTRA_DIST = nbdkit-count-filter.pod
+
+filter_LTLIBRARIES = nbdkit-count-filter.la
+
+nbdkit_count_filter_la_SOURCES = \
+ count.c \
+ $(top_srcdir)/include/nbdkit-filter.h \
+ $(NULL)
+
+nbdkit_count_filter_la_CPPFLAGS = \
+ -I$(top_srcdir)/include \
+ -I$(top_builddir)/include \
+ $(NULL)
+nbdkit_count_filter_la_CFLAGS = $(WARNINGS_CFLAGS)
+nbdkit_count_filter_la_LDFLAGS = \
+ -module -avoid-version -shared $(NO_UNDEFINED_ON_WINDOWS) \
+ $(NULL)
+if USE_LINKER_SCRIPT
+nbdkit_count_filter_la_LDFLAGS += \
+ -Wl,--version-script=$(top_srcdir)/filters/filters.syms
+endif
+nbdkit_count_filter_la_LIBADD = \
+ $(IMPORT_LIBRARY_ON_WINDOWS) \
+ $(NULL)
+
+if HAVE_POD
+
+man_MANS = nbdkit-count-filter.1
+CLEANFILES += $(man_MANS)
+
+nbdkit-count-filter.1: nbdkit-count-filter.pod \
+ $(top_builddir)/podwrapper.pl
+ $(PODWRAPPER) --section=1 --man $@ \
+ --html $(top_builddir)/html/$@.html \
+ $<
+
+endif HAVE_POD
diff --git a/filters/count/count.c b/filters/count/count.c
new file mode 100644
index 00000000..8af7f5a0
--- /dev/null
+++ b/filters/count/count.c
@@ -0,0 +1,132 @@
+/* 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.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <inttypes.h>
+
+#include <nbdkit-filter.h>
+
+#ifdef HAVE_STDATOMIC_H
+#include <stdatomic.h>
+#else
+/* Only used for counting statistics. */
+#define _Atomic /**/
+#endif
+
+static _Atomic uint64_t bytes_read, bytes_written, bytes_zeroed, bytes_trimmed;
+
+static void
+count_unload (void)
+{
+ nbdkit_debug ("count bytes: "
+ "read %" PRIu64 ", "
+ "written %" PRIu64 ", "
+ "zeroed %" PRIu64 ", "
+ "trimmed %" PRIu64,
+ bytes_read, bytes_written, bytes_zeroed, bytes_trimmed);
+}
+
+/* Read data. */
+static int
+count_pread (nbdkit_next *next,
+ void *handle,
+ void *buf,
+ uint32_t count, uint64_t offset, uint32_t flags,
+ int *err)
+{
+ int r;
+
+ r = next->pread (next, buf, count, offset, flags, err);
+ if (r >= 0)
+ bytes_read += count;
+ return r;
+}
+
+/* Write data. */
+static int
+count_pwrite (nbdkit_next *next,
+ void *handle,
+ const void *buf,
+ uint32_t count, uint64_t offset, uint32_t flags,
+ int *err)
+{
+ int r;
+
+ r = next->pwrite (next, buf, count, offset, flags, err);
+ if (r >= 0)
+ bytes_written += count;
+ return r;
+}
+
+/* Trim data. */
+static int
+count_trim (nbdkit_next *next,
+ void *handle, uint32_t count, uint64_t offset, uint32_t flags,
+ int *err)
+{
+ int r;
+
+ r = next->trim (next, count, offset, flags, err);
+ if (r >= 0)
+ bytes_trimmed += count;
+ return r;
+}
+
+/* Zero data. */
+static int
+count_zero (nbdkit_next *next,
+ void *handle, uint32_t count, uint64_t offset, uint32_t flags,
+ int *err)
+{
+ int r;
+
+ r = next->zero (next, count, offset, flags, err);
+ if (r >= 0)
+ bytes_zeroed += count;
+ return r;
+}
+
+static struct nbdkit_filter filter = {
+ .name = "count",
+ .longname = "nbdkit count filter",
+ .unload = count_unload,
+ .pread = count_pread,
+ .pwrite = count_pwrite,
+ .trim = count_trim,
+ .zero = count_zero,
+};
+
+NBDKIT_REGISTER_FILTER (filter)
diff --git a/filters/count/nbdkit-count-filter.pod b/filters/count/nbdkit-count-filter.pod
new file mode 100644
index 00000000..f0437000
--- /dev/null
+++ b/filters/count/nbdkit-count-filter.pod
@@ -0,0 +1,55 @@
+=head1 NAME
+
+nbdkit-count-filter - count bytes read, written, zeroed and trimmed
+
+=head1 SYNOPSIS
+
+ nbdkit --filter=count plugin
+
+=head1 DESCRIPTION
+
+C<nbdkit-count-filter> is a filter for L<nbdkit(1)> that simply counts
+the number of bytes that are read, written, zeroed and trimmed, and
+reports this number in debugging output when the filter is unloaded
+(usually when nbdkit exits).
+
+This is a very simple and lightweight filter. For much more
+comprehensive stats about and logging of operations, use
+L<nbdkit-stats-filter(1)> or L<nbdkit-log-filter(1)> instead.
+
+=head1 PARAMETERS
+
+There are no parameters specific to this filter. All parameters are
+passed through to the underlying plugin.
+
+=head1 FILES
+
+=over 4
+
+=item F<$filterdir/nbdkit-count-filter.so>
+
+The filter.
+
+Use C<nbdkit --dump-config> to find the location of C<$filterdir>.
+
+=back
+
+=head1 VERSION
+
+C<nbdkit-count-filter> first appeared in nbdkit 1.46.
+
+=head1 SEE ALSO
+
+L<nbdkit(1)>,
+L<nbdkit-file-plugin(1)>,
+L<nbdkit-log-filter(1)>,
+L<nbdkit-stats-filter(1)>,
+L<nbdkit-filter(3)>.
+
+=head1 AUTHORS
+
+Richard W.M. Jones
+
+=head1 COPYRIGHT
+
+Copyright Red Hat
diff --git a/filters/log/nbdkit-log-filter.pod b/filters/log/nbdkit-log-filter.pod
index b91b60c4..256701a1 100644
--- a/filters/log/nbdkit-log-filter.pod
+++ b/filters/log/nbdkit-log-filter.pod
@@ -208,6 +208,7 @@ L<nbdkit(1)>,
L<nbdkit-file-plugin(1)>,
L<nbdkit-cow-filter(1)>,
L<nbdkit-filter(3)>,
+L<nbdkit-count-filter(1)>,
L<nbdkit-stats-filter(1)>.
=head1 AUTHORS
diff --git a/filters/stats/nbdkit-stats-filter.pod b/filters/stats/nbdkit-stats-filter.pod
index c0d2b45c..10074b4a 100644
--- a/filters/stats/nbdkit-stats-filter.pod
+++ b/filters/stats/nbdkit-stats-filter.pod
@@ -13,6 +13,8 @@ C<nbdkit-stats-filter> is a filter that displays statistics about NBD
operations, such as the number of bytes read and written. Statistics
are written to a file once when nbdkit exits.
+A lighter weight version of this is L<nbdkit-count-filter(1)>.
+
=head1 EXAMPLE OUTPUT
# nbdkit --filter=exitlast --filter=stats memory 25G statsfile=example.txt
@@ -113,6 +115,7 @@ C<nbdkit-stats-filter> first appeared in nbdkit 1.14.
L<nbdkit(1)>,
L<nbdkit-filter(3)>,
+L<nbdkit-count-filter(1)>,
L<nbdkit-log-filter(1)>.
=head1 AUTHORS
diff --git a/plugins/file/nbdkit-file-plugin.pod b/plugins/file/nbdkit-file-plugin.pod
index 63d07617..626827b2 100644
--- a/plugins/file/nbdkit-file-plugin.pod
+++ b/plugins/file/nbdkit-file-plugin.pod
@@ -316,6 +316,7 @@ L<nbdkit-split-plugin(1)>,
L<nbdkit-partitioning-plugin(1)>,
L<nbdkit-tmpdisk-plugin(1)>,
L<nbdkit-nfs-plugin(1)>,
+L<nbdkit-count-filter(1)>,
L<nbdkit-exportname-filter(1)>,
L<nbdkit-fua-filter(1)>,
L<nbdkit-luks-filter(1)>,
diff --git a/tests/Makefile.am b/tests/Makefile.am
index c16b5912..d7053ba2 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -1706,6 +1706,10 @@ EXTRA_DIST += \
test-checkwrite-fail.sh \
$(NULL)
+# count filter test.
+TESTS += test-count.sh
+EXTRA_DIST += test-count.sh
+
# cow filter test.
if HAVE_MKE2FS_WITH_D
TESTS += \
diff --git a/tests/test-count.sh b/tests/test-count.sh
new file mode 100755
index 00000000..e2e10704
--- /dev/null
+++ b/tests/test-count.sh
@@ -0,0 +1,55 @@
+#!/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-count-filter.
+
+source ./functions.sh
+set -e
+set -x
+set -u
+
+requires_run
+requires_filter count
+requires_plugin sparse-random
+requires_nbdcopy
+
+log=test-count.out
+rm -f $log
+cleanup_fn rm -f $log
+
+# We use sparse-random plugin because it both provides some data for
+# nbdcopy to copy, and allows writes.
+nbdkit -v --filter=count sparse-random 1G \
+ --run 'nbdcopy "$uri" "$uri"' 2>$log
+
+# Check that something got logged when the filter was unloaded.
+grep "count bytes:" $log
--
2.47.3

View File

@ -0,0 +1,31 @@
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

@ -0,0 +1,577 @@
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,41 +0,0 @@
From 745b959b44a67cd3def7c60b873701ad79137bda Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Tue, 8 Jul 2025 21:20:52 +0100
Subject: [PATCH] count: Clarify documentation
Updates: commit 3512c3ce9308b4d940119ac6cc87f1baa9afb655
(cherry picked from commit 7c84314ec7411fc1090bf1ca417c453d08fcf364)
---
filters/count/nbdkit-count-filter.pod | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/filters/count/nbdkit-count-filter.pod b/filters/count/nbdkit-count-filter.pod
index f0437000..c20b4737 100644
--- a/filters/count/nbdkit-count-filter.pod
+++ b/filters/count/nbdkit-count-filter.pod
@@ -4,17 +4,19 @@ nbdkit-count-filter - count bytes read, written, zeroed and trimmed
=head1 SYNOPSIS
- nbdkit --filter=count plugin
+ nbdkit -fv --filter=count plugin
=head1 DESCRIPTION
C<nbdkit-count-filter> is a filter for L<nbdkit(1)> that simply counts
the number of bytes that are read, written, zeroed and trimmed, and
reports this number in debugging output when the filter is unloaded
-(usually when nbdkit exits).
+(usually when nbdkit exits). The filter output can only be seen when
+debugging is enabled (I<-v>) which usually implies using the
+foreground (I<-f>) option as well.
This is a very simple and lightweight filter. For much more
-comprehensive stats about and logging of operations, use
+comprehensive stats and logging of operations, use
L<nbdkit-stats-filter(1)> or L<nbdkit-log-filter(1)> instead.
=head1 PARAMETERS
--
2.47.3

View File

@ -0,0 +1,45 @@
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,109 +0,0 @@
From 65b6b241dcac900e996171897b46fecb6551cd27 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Mon, 20 Oct 2025 11:35:51 +0100
Subject: [PATCH] vddk: Don't use FNM_PATHNAME when matching export parameter
Commit 18866d92d1 ("vddk: Add export parameter") added recently allows
a single VDDK plugin instance to serve multiple files on the VMware
server. The NBD client chooses which file to serve by sending an NBD
export name.
As a mild protection against an attacker who has access to the NBD
endpoint from requesting any file from the server (and not just those
related to a single virtual machine), you are able to specify an
export wildcard. The NBD export name from the client is compared to
the wildcard before allowing the connection to read anything.
The wildcard was matched (before this commit) using:
fnmatch (export_wildcard, nbd_export_name, FNM_PATHNAME)
As a concrete example:
- Virtual machine with two disks called:
"[esx] esx-win11/esx-win11.vmdk"
"[esx] esx-win11/esx-win11-2.vmdk"
- nbdkit vddk export="\[esx\] esx-win11/*.vmdk"
NBD client requests "[esx] esx-win11/esx-win11.vmdk" => allowed
(because this export name matches the wildcard).
NBD client requests "[esx] unrelated guest/disk.vmdk" => denied
(because this export name does not match the wildcard).
Note the effect of FNM_PATHNAME, as described in the man page:
FNM_PATHNAME
If this flag is set, match a slash in string only with a slash in
pattern and not by an asterisk (*) or a question mark (?)
metacharacter, nor by a bracket expression ([]) containing a
slash.
Now consider a different guest where the disks are located at
different subdirectory depths:
- Virtual machine with two disks called:
"[esx] esx-win10/esx-win10.vmdk"
"[esx] esx-win10/disk2/esx-win10-2.vmdk"
- nbdkit vddk export=???
It is not possible to construct an export wildcard that matches both
disk names, because the special character '/' in the export name must
match exactly one '/' in the wildcard, but the two paths have
different numbers of '/' characters.
The best solution I can come up with for this is to relax the
restriction by removing the FNM_PATHNAME parameter of fnmatch. Thus
(after this commit is applied):
- Virtual machine with two disks called:
"[esx] esx-win10/esx-win10.vmdk"
"[esx] esx-win10/disk2/esx-win10-2.vmdk"
- nbdkit vddk export="\[esx\] esx-win10/*.vmdk"
As part of this change, I also tested how "//" and "/../" in paths
behaves, so that we weren't opening up a hole where someone could
request "[esx] esx-win10/../unrelated guest/disk.vmdk". It turns out
that VMware does not parse these as paths. It seems to treat these
parameters only as simple strings, and any variation in the string is
rejected.
Note also that the export wildcard is really a backstop in case
regular permissions on the NBD endpoint fail. It's not supposed to
offer complete security.
Reported-by: Ming Xie
Related: https://issues.redhat.com/browse/RHEL-121728
Related: https://github.com/libguestfs/virt-v2v/commit/ba86b22c75a65240fdb65ac2e91c472c0f68f78e
(cherry picked from commit 01b429c412504a491a4b5cc009a9c2e906f993ef)
---
plugins/vddk/vddk.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/plugins/vddk/vddk.c b/plugins/vddk/vddk.c
index e16813e4..6c667dc7 100644
--- a/plugins/vddk/vddk.c
+++ b/plugins/vddk/vddk.c
@@ -639,6 +639,7 @@ vddk_dump_plugin (void)
printf ("vddk_default_libdir=%s\n", VDDK_LIBDIR);
printf ("vddk_has_nfchostport=1\n");
+ printf ("vddk_has_fnm_pathname=0\n");
/* Because load_library (false) we might not have loaded VDDK, in
* which case we didn't set library_version. Note this cannot
@@ -744,7 +745,7 @@ vddk_open (int readonly)
goto err0;
}
- r = fnmatch (export_wildcard, nbd_export_name, FNM_PATHNAME);
+ r = fnmatch (export_wildcard, nbd_export_name, 0);
switch (r) {
case 0: /* OK */ break;
case FNM_NOMATCH:
--
2.47.3

View File

@ -0,0 +1,29 @@
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,47 +0,0 @@
From b49ef5b2fa3482272082fa3ef34c55c567b8d8c6 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Wed, 7 Jan 2026 20:25:56 +0000
Subject: [PATCH] file: Don't advertise minimum_io_size > 64K (the max
supported by NBD)
If you create an LVM thin pool with chunk size of 128K then the kernel
will advertise /sys/block/dm-X/queue/minimum_io_size as 131072 (128K)
and the file plugin will set the minimum block size to 128K as well.
However the NBD protocol only supports a max of 64K, thus we get the
following failure:
nbdkit: file[2]: error: plugin must set minimum block size between 1 and 64K
This is not a hard limit and the kernel will split smaller requests,
so the simplest solution is to round down larger sizes to 64K.
Fixes: https://issues.redhat.com/browse/RHEL-139390
Reported-by: Nijin Ashok
Thanks: Eric Blake
See: https://github.com/NetworkBlockDevice/nbd/blob/master/doc/proto.md#size-constraints
(cherry picked from commit 42b72dc751030c1210bc2d50f6ff0c1c1a902afc)
(cherry picked from commit 5db5982dc9b801fe37c0d4086724abc330656609)
---
plugins/file/file.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/plugins/file/file.c b/plugins/file/file.c
index 66d03d4f..ce84b7ca 100644
--- a/plugins/file/file.c
+++ b/plugins/file/file.c
@@ -728,6 +728,12 @@ file_open (int readonly)
if (ioctl (h->fd, BLKIOMIN, &minimum_io_size) == -1)
nbdkit_debug ("cannot get BLKIOMIN: %s: %m", h->name);
+ /* This is the maximum that NBD supports. For Linux devices,
+ * minimum_io_size is only a hint and smaller operations work.
+ */
+ if (minimum_io_size > 65536)
+ minimum_io_size = 65536;
+
if (ioctl (h->fd, BLKIOOPT, &optimal_io_size) == -1)
nbdkit_debug ("cannot get BLKIOOPT: %s: %m", h->name);
else if (optimal_io_size == 0)
--
2.47.3

View File

@ -0,0 +1,28 @@
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,91 +0,0 @@
From 1e059d8146908aa37046db4759665e51f97feaea Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Thu, 8 Jan 2026 21:38:36 +0000
Subject: [PATCH] file: Change calculations of block size hints for block
devices
Related: https://issues.redhat.com/browse/RHEL-139390
Related: commit 42b72dc751030c1210bc2d50f6ff0c1c1a902afc
Thanks: Eric Blake, Mikulas Patocka
(cherry picked from commit d0ee3c8a6dde446385c9b8e02f8d4623cb4d4184)
(cherry picked from commit 07cbf8b7a1e94079946c36ab83c1ae75ac175d4e)
---
plugins/file/file.c | 45 ++++++++++++++++++++++++++++-----------------
1 file changed, 28 insertions(+), 17 deletions(-)
diff --git a/plugins/file/file.c b/plugins/file/file.c
index ce84b7ca..c0d5524c 100644
--- a/plugins/file/file.c
+++ b/plugins/file/file.c
@@ -396,7 +396,7 @@ file_config_complete (void)
static void
file_dump_plugin (void)
{
-#if defined(BLKIOMIN) && defined(BLKIOOPT)
+#if defined(BLKSSZGET) && defined(BLKIOMIN) && defined(BLKIOOPT)
printf ("file_block_size=yes\n");
#endif
#ifdef BLKROTATIONAL
@@ -721,32 +721,43 @@ file_open (int readonly)
#endif
h->minimum = h->preferred = h->maximum = 0;
-#if defined(BLKIOMIN) && defined(BLKIOOPT)
+#if defined(BLKSSZGET) && defined(BLKIOMIN) && defined(BLKIOOPT)
if (h->is_block_device) {
- unsigned int minimum_io_size = 0, optimal_io_size = 0;
+ int logical_block_size = 0;
+ unsigned minimum_io_size = 0, optimal_io_size = 0;
+
+ if (ioctl (h->fd, BLKSSZGET, &logical_block_size) == -1)
+ nbdkit_debug ("ioctl: %s: %s: %m", "BLKSSZGET", h->name);
if (ioctl (h->fd, BLKIOMIN, &minimum_io_size) == -1)
- nbdkit_debug ("cannot get BLKIOMIN: %s: %m", h->name);
-
- /* This is the maximum that NBD supports. For Linux devices,
- * minimum_io_size is only a hint and smaller operations work.
- */
- if (minimum_io_size > 65536)
- minimum_io_size = 65536;
+ nbdkit_debug ("ioctl: %s: %s: %m", "BLKIOMIN", h->name);
if (ioctl (h->fd, BLKIOOPT, &optimal_io_size) == -1)
- nbdkit_debug ("cannot get BLKIOOPT: %s: %m", h->name);
+ nbdkit_debug ("ioctl: %s: %s: %m", "BLKIOOPT", h->name);
else if (optimal_io_size == 0)
/* All devices in the Linux kernel except for MD report optimal
- * as 0. In that case guess a good value.
+ * as 0. In that case use logical_block_size.
*/
- optimal_io_size = MAX (minimum_io_size, 4096);
+ optimal_io_size = logical_block_size;
/* Check the values are sane before using them. */
- if (minimum_io_size >= 512 && is_power_of_2 (minimum_io_size) &&
- optimal_io_size >= minimum_io_size && is_power_of_2 (optimal_io_size)) {
- h->minimum = minimum_io_size;
- h->preferred = optimal_io_size;
+ if (logical_block_size >= 512 && is_power_of_2 (logical_block_size) &&
+ minimum_io_size >= 512 && is_power_of_2 (minimum_io_size) &&
+ minimum_io_size >= logical_block_size &&
+ optimal_io_size >= 512 && is_power_of_2 (optimal_io_size) &&
+ optimal_io_size >= logical_block_size) {
+ /* The mapping from Linux kernel settings to NBD protocol block
+ * sizes is not obvious. logical_block_size is the sector size,
+ * and anything smaller than this will cause a RMW cycle. For
+ * the preferred size, we are advised to use the largest of
+ * minimum_io_size and optimal_io_size. For this plugin maximum
+ * can be the largest that NBD can handle.
+ */
+
+ /* 64K is the largest minimum that the NBD protocol supports. */
+ h->minimum = MIN (65536, logical_block_size);
+
+ h->preferred = MAX (minimum_io_size, optimal_io_size);
h->maximum = 0xffffffff;
}
}
--
2.47.3

View File

@ -0,0 +1,33 @@
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

@ -0,0 +1,121 @@
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

@ -0,0 +1,214 @@
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

@ -0,0 +1,104 @@
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

@ -0,0 +1,109 @@
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

@ -0,0 +1,51 @@
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

@ -0,0 +1,416 @@
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

@ -0,0 +1,39 @@
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

@ -0,0 +1,60 @@
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

@ -0,0 +1,40 @@
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

@ -1,4 +1,4 @@
From 34ee72b180f2a35e35df7d763881e7cfc205c665 Mon Sep 17 00:00:00 2001
From 5f292e76d5c2fcc0a1765fff452d1f2fa902025a Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Wed, 1 Apr 2026 14:34:39 +0100
Subject: [PATCH] cache, cow: Prefix ftruncate error with filter name

View File

@ -1,4 +1,4 @@
From e60280f405be972d6ca585494825642817d37629 Mon Sep 17 00:00:00 2001
From 9a178f43031d4f4b175adff7849ebfbd6b86081b Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Wed, 1 Apr 2026 15:30:15 +0100
Subject: [PATCH] cow: Don't leak blk->lock and blk->bm on error paths

View File

@ -1,4 +1,4 @@
From d0f211ae730f5cea4610b1e5455f2ca649c9ae69 Mon Sep 17 00:00:00 2001
From 9434e8839e55ac90250a235c22d201a632a1dfe7 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Wed, 1 Apr 2026 15:33:30 +0100
Subject: [PATCH] cow: Use a vector to store the overlay file descriptor

View File

@ -1,4 +1,4 @@
From 0fc4138b253d3803ea2239df2f268c005ee3b3f4 Mon Sep 17 00:00:00 2001
From 710967c5bb4c26d4df7c40ee9c29fa11cf1a7de5 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Wed, 1 Apr 2026 16:03:21 +0100
Subject: [PATCH] cow: Split out function to create temporary files

View File

@ -1,4 +1,4 @@
From 021b9fab2ba58dde338658052b45618fcbb8ebc7 Mon Sep 17 00:00:00 2001
From 159c55ed72616e6e52a031b4fe28d356c10a6b56 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Wed, 1 Apr 2026 16:43:45 +0100
Subject: [PATCH] cow: Add name of the temporary file to debug output

View File

@ -1,4 +1,4 @@
From c02b8506469203e537fdf6fe37d4447cc4d358a3 Mon Sep 17 00:00:00 2001
From d065b469450beeb8479149987d7dd3b201b58154 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Wed, 1 Apr 2026 16:37:01 +0100
Subject: [PATCH] cow: Support overlays larger than 16T on ext4
@ -173,10 +173,10 @@ index 1012fb5e..defd0d94 100644
if (cow_debug_verbose)
nbdkit_debug ("cow: blk_write block %" PRIu64 " (offset %" PRIu64 ")",
diff --git a/tests/Makefile.am b/tests/Makefile.am
index d7053ba2..bc66b61c 100644
index 2ae0c3c2..df7b801b 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -1724,7 +1724,10 @@ TESTS += \
@@ -1890,7 +1890,10 @@ TESTS += \
test-cow-unaligned.sh \
$(NULL)
endif
@ -188,7 +188,7 @@ index d7053ba2..bc66b61c 100644
EXTRA_DIST += \
test-cow.sh \
test-cow-block-size.sh \
@@ -1732,6 +1735,7 @@ EXTRA_DIST += \
@@ -1898,6 +1901,7 @@ EXTRA_DIST += \
test-cow-extents1.sh \
test-cow-extents2.sh \
test-cow-extents-large.sh \

View File

@ -1,4 +1,4 @@
From 5261fbf8b7579bd6592fbfd51b6a99ce09a8b3c1 Mon Sep 17 00:00:00 2001
From 203423f0fdd28af36705e89b3b63e62a5964d0a0 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Fri, 3 Apr 2026 13:41:36 +0100
Subject: [PATCH] cache, cow: Add prefix before more calls

View File

@ -1,4 +1,4 @@
From ed6aca2c0a58a8b96531f015cf4d629f5208348b Mon Sep 17 00:00:00 2001
From 7ee5ea99aeb697069572a479b30d7451626d1caa Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Fri, 3 Apr 2026 14:06:31 +0100
Subject: [PATCH] cow: Fix block -> fd calculation

View File

@ -1,4 +1,4 @@
From 24d4313cddced9920a262e43e7dde70bb4aeae90 Mon Sep 17 00:00:00 2001
From 305ec1211a8a594f6cb87154ae48edc0c8fb7ece Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Fri, 3 Apr 2026 13:50:37 +0100
Subject: [PATCH] cow: Fix offsets when overlay is split

View File

@ -1,4 +1,4 @@
From aba2a885ab8dc8796fdc8f100cd35ad621bb307a Mon Sep 17 00:00:00 2001
From f4968119f7b8b01d5b88c2f015bad9b4338480ad Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Fri, 3 Apr 2026 14:10:51 +0100
Subject: [PATCH] cow: Make some offset variables const

View File

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

View File

@ -1,17 +0,0 @@
-----BEGIN PGP SIGNATURE-----
iQJFBAABCgAvFiEE93dPsa0HSn6Mh2fqkXOPc+G3aKAFAmho1AYRHHJpY2hAYW5u
ZXhpYS5vcmcACgkQkXOPc+G3aKCFIg/9GJF0Ok1j2FXx7rZEanLv4lJveFi0rYQD
z3BXRX4JuaiCPLzvWiABqBN9P0h8WzhdE3ir50gG1a03+q9AfRbyVGu/LCnakVUv
58h/SE36sK4K1Gptp+cZbbjb7kwMNXl/c158YChOAW4St35zYELW79Vf9+rjj7Nz
S3ppKMCE1lkBmd3R5+AUN962yz2BPF9K1CTBLJZD89nwsPw5e5A0RvRedxEvgxYD
lMT/6DgxhPFpywqpv6NxN/Qq/vHGT0EtuAco3+Iqp5LX/sPBxPWNUGK+zZn5T8dp
ss/s8uC8YIGwlPtGNUm25lS5hbA9l3D8RTtk/fL7BJB/92z3BEx8H0F0H2PokG9Z
9FEmqaYglZM7Z4fdpJxkBjXN6UFOsu0nUR6EnIZKHnU/HtzmgXLsjrEPtxem/jqe
iYgLL2ykpRrRLdZIvG1SpyTGLtJqgEGquo+3OWj1FfzFf93a2x1KoIdatBVCYzM5
5JCE42RolpOsRJQ0t297zM93H6njz7irrvpFiVlYIUbVr3+tzAe77F/PBTnBapUe
Dxcy61t5PWWLGwAsFtxb8Q6Vx1ssnCpn+8wqslBJWcIWrKtn8GF5dTrGUvvilwkH
66VcLXGaNbyOq5jyS4gpMdZWw1GLmyujQB8hoyOc9+n6tLe3hHEYuTTT2pY/jLk2
EYCKR70jPIQ=
=XzGJ
-----END PGP SIGNATURE-----

17
nbdkit-1.46.2.tar.gz.sig Normal file
View File

@ -0,0 +1,17 @@
-----BEGIN PGP SIGNATURE-----
iQJFBAABCgAvFiEE93dPsa0HSn6Mh2fqkXOPc+G3aKAFAmmI30URHHJpY2hAYW5u
ZXhpYS5vcmcACgkQkXOPc+G3aKABzxAAsDpD3HN8YsV5PHQbnKs32ML5uoHLxX1e
turH2CTEv08I97n8xlUuOoYebiPPg3k4hX1FdQoYRJuDh3l0jzvYRXt860E/OeBg
zzPMTi1XMZZ702hFabdPnwegXsn1CqQtO0a5HjXo2wGqujMAWpf2Vx9zls5Yzswi
LEDB1akPMsJIV8ih3lgGQVEcpgXm3ttugzUk8TMxf7f6muRzrTTFhhf74sBJt+0e
1zDsAhHiRYopVdVuibAhwnocn4PI600bgysXfpwuT6IQZNA/32Vponehv8qIilQi
DjRFXe+wq2l2hlSE0VjcWsZEP5VNUf8zmnz0TVJlTS98N8Fo2M+bGwzuyTZ8BXUN
wWXn/chONi3P8mk3D2AxZKxlSfpOsnxLmwsaHzCFmDUrTQMqSrlmSIpch3fWs7ir
p/paqTxZUhYF6AwmC4ppmrKAaw69GAur0R1oYicDOxX8YjWjIbqzYIwTWt6TZIcJ
7SefBusbetVCY7ISx5+PESbLSTcqxaLMwLOv+qjXiGI1nObltrA4IGqPAhvvNqLw
tG7mtN0sEsyoW1nLBb83Kmqetg/6oMyexsgOa6MnO+GOeP5asrff0N7aHUcQFx5D
aVlr5dM2yh372WqQQ9alou+Cje4xtcGdoEYHOMUEkgRsZr8xhbH86Jy1i/apPpI6
ze7kdv9tFsw=
=fw+J
-----END PGP SIGNATURE-----

View File

@ -51,11 +51,11 @@
%global verify_tarball_signature 1
# The source directory.
%global source_directory 1.44-stable
%global source_directory 1.46-stable
Name: nbdkit
Version: 1.44.1
Release: 6%{?dist}
Version: 1.46.2
Release: 3%{?dist}
Summary: NBD server
License: BSD-3-Clause
@ -77,30 +77,40 @@ Source2: libguestfs.keyring
Source3: copy-patches.sh
# Patches come from the upstream repository:
# https://gitlab.com/nbdkit/nbdkit/-/commits/rhel-10.1/
# https://gitlab.com/nbdkit/nbdkit/-/commits/rhel-10.2/
# Patches.
Patch0001: 0001-common-Add-ONCE-macro-to-run-code-only-once.patch
Patch0002: 0002-file-zero-Print-the-debug-message-on-the-fallback-pa.patch
Patch0003: 0003-file-trim-Don-t-try-BLKDISCARD-if-earlier-FALLOC_FL_.patch
Patch0004: 0004-common-include-test-once.c-Skip-test-on-macOS-which-.patch
Patch0005: 0005-common-include-test-once.c-Further-fixes-for-pthread.patch
Patch0006: 0006-Remove-deprecated-cacheextents-filter.patch
Patch0007: 0007-New-filter-nbdkit-count-filter-count-bytes-read-writ.patch
Patch0008: 0008-count-Clarify-documentation.patch
Patch0009: 0009-vddk-Don-t-use-FNM_PATHNAME-when-matching-export-par.patch
Patch0010: 0010-file-Don-t-advertise-minimum_io_size-64K-the-max-sup.patch
Patch0011: 0011-file-Change-calculations-of-block-size-hints-for-blo.patch
Patch0012: 0012-cache-cow-Prefix-ftruncate-error-with-filter-name.patch
Patch0013: 0013-cow-Don-t-leak-blk-lock-and-blk-bm-on-error-paths.patch
Patch0014: 0014-cow-Use-a-vector-to-store-the-overlay-file-descripto.patch
Patch0015: 0015-cow-Split-out-function-to-create-temporary-files.patch
Patch0016: 0016-cow-Add-name-of-the-temporary-file-to-debug-output.patch
Patch0017: 0017-cow-Support-overlays-larger-than-16T-on-ext4.patch
Patch0018: 0018-cache-cow-Add-prefix-before-more-calls.patch
Patch0019: 0019-cow-Fix-block-fd-calculation.patch
Patch0020: 0020-cow-Fix-offsets-when-overlay-is-split.patch
Patch0021: 0021-cow-Make-some-offset-variables-const.patch
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
Patch0022: 0022-cache-cow-Prefix-ftruncate-error-with-filter-name.patch
Patch0023: 0023-cow-Don-t-leak-blk-lock-and-blk-bm-on-error-paths.patch
Patch0024: 0024-cow-Use-a-vector-to-store-the-overlay-file-descripto.patch
Patch0025: 0025-cow-Split-out-function-to-create-temporary-files.patch
Patch0026: 0026-cow-Add-name-of-the-temporary-file-to-debug-output.patch
Patch0027: 0027-cow-Support-overlays-larger-than-16T-on-ext4.patch
Patch0028: 0028-cache-cow-Add-prefix-before-more-calls.patch
Patch0029: 0029-cow-Fix-block-fd-calculation.patch
Patch0030: 0030-cow-Fix-offsets-when-overlay-is-split.patch
Patch0031: 0031-cow-Make-some-offset-variables-const.patch
# For automatic RPM Provides generation.
# See: https://rpm-software-management.github.io/rpm/manual/dependency_generators.html
@ -152,7 +162,13 @@ BuildRequires: pkgconfig(libtorrent-rasterbar)
%if 0%{?have_blkio}
BuildRequires: pkgconfig(blkio)
%endif
%if !0%{?rhel}
BuildRequires: pkgconfig(OpenCL)
%endif
BuildRequires: bash-completion
%if 0%{?fedora} || 0%{?rhel} >= 11
BuildRequires: bash-completion-devel
%endif
BuildRequires: perl-devel
BuildRequires: perl(ExtUtils::Embed)
%if 0%{?rhel} == 8
@ -171,11 +187,6 @@ BuildRequires: ocaml-ocamldoc
BuildRequires: pkgconfig(tcl)
BuildRequires: pkgconfig(lua)
%endif
# Only needed until the following bug gets fixed in boost:
# https://bugzilla.redhat.com/show_bug.cgi?id=2297642
%if 0%{?fedora} >= 41
BuildRequires: openssl-devel-engine
%endif
%if 0%{verify_tarball_signature}
BuildRequires: gnupg2
%endif
@ -195,9 +206,11 @@ BuildRequires: /usr/bin/lzip
BuildRequires: /usr/bin/nbdcopy
BuildRequires: /usr/bin/nbdinfo
BuildRequires: /usr/bin/nbdsh
%ifnarch %{ix86}
BuildRequires: /usr/bin/qemu-img
BuildRequires: /usr/bin/qemu-io
BuildRequires: /usr/bin/qemu-nbd
%endif
BuildRequires: /usr/sbin/sfdisk
%if !0%{?rhel}
BuildRequires: /usr/bin/socat
@ -602,11 +615,20 @@ VMware VDDK for accessing VMware disks and servers.
%endif
%if !0%{?rhel}
%package vram-plugin
Summary: use GPU Video RAM as a network block device
Requires: %{name}-server%{?_isa} = %{version}-%{release}
Recommends: %{_bindir}/clinfo
%description vram-plugin
This package contains GPU Video RAM support for %{name}.
%endif
%package basic-filters
Summary: Basic filters for %{name}
Requires: %{name}-server%{?_isa} = %{version}-%{release}
# Remove this in Fedora 43:
Obsoletes: nbdkit-gzip-filter < %{version}-%{release}
%description basic-filters
This package contains filters for %{name} which only depend on simple
@ -645,6 +667,8 @@ nbdkit-fua-filter Modify flush behaviour in plugins.
nbdkit-gzip-filter Decompress a .gz file
nbdkit-indexed-gzip-filter Access .gz contents efficiently.
nbdkit-ip-filter Filter clients by IP address.
nbdkit-limit-filter Limit nr clients that can connect concurrently.
@ -653,6 +677,8 @@ nbdkit-log-filter Log all transactions to a file.
nbdkit-luks-filter Read and write LUKS-encrypted disks.
nbdkit-map-filter Remap disk blocks.
nbdkit-multi-conn-filter Enable, emulate or disable multi-conn.
nbdkit-nocache-filter Disable cache requests in the underlying plugin.
@ -880,6 +906,7 @@ export PYTHON=%{__python3}
--enable-perl \
--enable-tcl \
--enable-torrent \
--enable-vram \
--with-ext2 \
--with-iso \
--with-libvirt \
@ -888,6 +915,7 @@ export PYTHON=%{__python3}
--disable-perl \
--disable-tcl \
--disable-torrent \
--disable-vram \
--without-ext2 \
--without-iso \
--without-libvirt \
@ -952,6 +980,7 @@ popd
--disable-torrent \
--disable-valgrind \
--disable-vddk \
--disable-vram \
--without-bash-completions \
--without-curl \
--without-ext2 \
@ -1361,6 +1390,15 @@ fi
%endif
%if !0%{?rhel}
%files vram-plugin
%doc README.md
%license LICENSE
%{_libdir}/%{name}/plugins/nbdkit-vram-plugin.so
%{_mandir}/man1/nbdkit-vram-plugin.1*
%endif
%files basic-filters
%doc README.md
%license LICENSE
@ -1380,10 +1418,12 @@ fi
%{_libdir}/%{name}/filters/nbdkit-extentlist-filter.so
%{_libdir}/%{name}/filters/nbdkit-fua-filter.so
%{_libdir}/%{name}/filters/nbdkit-gzip-filter.so
%{_libdir}/%{name}/filters/nbdkit-indexed-gzip-filter.so
%{_libdir}/%{name}/filters/nbdkit-ip-filter.so
%{_libdir}/%{name}/filters/nbdkit-limit-filter.so
%{_libdir}/%{name}/filters/nbdkit-log-filter.so
%{_libdir}/%{name}/filters/nbdkit-luks-filter.so
%{_libdir}/%{name}/filters/nbdkit-map-filter.so
%{_libdir}/%{name}/filters/nbdkit-multi-conn-filter.so
%{_libdir}/%{name}/filters/nbdkit-nocache-filter.so
%{_libdir}/%{name}/filters/nbdkit-noextents-filter.so
@ -1426,10 +1466,12 @@ fi
%{_mandir}/man1/nbdkit-extentlist-filter.1*
%{_mandir}/man1/nbdkit-fua-filter.1*
%{_mandir}/man1/nbdkit-gzip-filter.1*
%{_mandir}/man1/nbdkit-indexed-gzip-filter.1*
%{_mandir}/man1/nbdkit-ip-filter.1*
%{_mandir}/man1/nbdkit-limit-filter.1*
%{_mandir}/man1/nbdkit-log-filter.1*
%{_mandir}/man1/nbdkit-luks-filter.1*
%{_mandir}/man1/nbdkit-map-filter.1*
%{_mandir}/man1/nbdkit-multi-conn-filter.1*
%{_mandir}/man1/nbdkit-nocache-filter.1*
%{_mandir}/man1/nbdkit-noextents-filter.1*
@ -1498,7 +1540,7 @@ fi
%files devel
%doc BENCHMARKING OTHER_PLUGINS README.md SECURITY TODO
%doc BENCHMARKING OTHER_PLUGINS README.md SECURITY.md TODO.md
%license LICENSE
# Include the source of the example plugins in the documentation.
%doc plugins/example*/*.c
@ -1538,8 +1580,13 @@ fi
%files bash-completion
%license LICENSE
%if 0%{?fedora} || 0%{?rhel} >= 11
%dir %{bash_completions_dir}
%{bash_completions_dir}/nbdkit
%else
%dir %{_datadir}/bash-completion/completions
%{_datadir}/bash-completion/completions/nbdkit
%endif
%if 0%{?with_selinux}
@ -1571,17 +1618,23 @@ fi
%changelog
* Fri Apr 03 2026 Richard W.M. Jones <rjones@redhat.com> - 1.44.1-6
* Fri Apr 03 2026 Richard W.M. Jones <rjones@redhat.com> - 1.46.2-3
- cow: Support overlays larger than 16T on ext4 + further fixes
resolves: RHEL-164552
resolves: RHEL-164229
* Mon Jan 12 2026 Richard W.M. Jones <rjones@redhat.com> - 1.44.1-4
* 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
from nbdkit 1.47.
resolves: RHEL-111242
- Synchronize spec file with Fedora.
- vddk: Don't use FNM_PATHNAME when matching export parameter
resolves: RHEL-122755
- Fix assertion failure in blocksize-policy filter
- Fix v2v conversion failure when minimum_io_size > 64K
resolves: RHEL-140707
* Tue Jan 06 2026 Richard W.M. Jones <rjones@redhat.com> - 1.44.1-3
- vddk export parameter should allow loose wildcards without FNM_PATHNAME
resolves: RHEL-137303
resolves: RHEL-139390
- Test and document that VDDK 9.0.1.0 works
resolves: RHEL-140615
* Wed Jul 09 2025 Richard W.M. Jones <rjones@redhat.com> - 1.44.1-2
- Rebase to nbdkit 1.44.1

View File

@ -1,2 +1,2 @@
SHA512 (libguestfs.keyring) = 69663d5dd3edb47af6f18119c0748211c1cecf230c2dd8baaf349f44df1f893730ca6bb8b1f60a55ea42f8ff04fd48c3e5954501bb57952950032012a42c9f19
SHA512 (nbdkit-1.44.1.tar.gz) = 150a31ca7f64b76a4e4cc90d077e88531458f2766c0bb1f6f1ae23176d5c55a2e4dab61be58bd92b166e67fe70b67c9458a04d29978cbb1b89a6fa8ebca4617d
SHA512 (nbdkit-1.46.2.tar.gz) = ce01ac7a90cb995ec3ef46c8cec0be7b47d7266edc4383df6e867881fd4ba66b5f36ccc4de356a0df0f1d47f86adb40212e8de62332d19014b293649f25d4b37