Backport nbdkit_debug_hexdiff 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
255 lines
8.2 KiB
Diff
255 lines
8.2 KiB
Diff
From 99153ed5592c9a08c5d5c393a625c54a5a0ea0c0 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
|
|
|