From 0a9205dc8c3b5d5703bd71bc58db503c05b0063b Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Sat, 7 Jul 2018 13:30:32 +0100 Subject: [PATCH 05/12] Add pattern plugin. This generates a simple, fixed test pattern which can be used to test nbdkit filters (especially nbdkit-offset-filter), and also NBD clients. --- common-rules.mk | 1 + configure.ac | 1 + plugins/null/nbdkit-null-plugin.pod | 1 + plugins/pattern/Makefile.am | 60 ++++++++++ plugins/pattern/nbdkit-pattern-plugin.pod | 99 ++++++++++++++++ plugins/pattern/pattern.c | 134 ++++++++++++++++++++++ plugins/random/nbdkit-random-plugin.pod | 1 + plugins/zero/nbdkit-zero-plugin.pod | 1 + tests/Makefile.am | 4 + tests/test-pattern.sh | 121 +++++++++++++++++++ 10 files changed, 423 insertions(+) create mode 100644 plugins/pattern/Makefile.am create mode 100644 plugins/pattern/nbdkit-pattern-plugin.pod create mode 100644 plugins/pattern/pattern.c create mode 100755 tests/test-pattern.sh diff --git a/common-rules.mk b/common-rules.mk index 5877907..01beff5 100644 --- a/common-rules.mk +++ b/common-rules.mk @@ -46,6 +46,7 @@ plugins = \ nbd \ null \ ocaml \ + pattern \ perl \ python \ random \ diff --git a/configure.ac b/configure.ac index 6e8d3e2..6304ac8 100644 --- a/configure.ac +++ b/configure.ac @@ -610,6 +610,7 @@ AC_CONFIG_FILES([Makefile plugins/nbd/Makefile plugins/null/Makefile plugins/ocaml/Makefile + plugins/pattern/Makefile plugins/perl/Makefile plugins/python/Makefile plugins/random/Makefile diff --git a/plugins/null/nbdkit-null-plugin.pod b/plugins/null/nbdkit-null-plugin.pod index 7bd7278..55affb8 100644 --- a/plugins/null/nbdkit-null-plugin.pod +++ b/plugins/null/nbdkit-null-plugin.pod @@ -33,6 +33,7 @@ This parameter is required. L, L, +L, L. L. diff --git a/plugins/pattern/Makefile.am b/plugins/pattern/Makefile.am new file mode 100644 index 0000000..da092db --- /dev/null +++ b/plugins/pattern/Makefile.am @@ -0,0 +1,60 @@ +# nbdkit +# Copyright (C) 2017-2018 Red Hat Inc. +# All rights reserved. +# +# 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-pattern-plugin.pod + +plugin_LTLIBRARIES = nbdkit-pattern-plugin.la + +nbdkit_pattern_plugin_la_SOURCES = \ + pattern.c \ + $(top_srcdir)/include/nbdkit-plugin.h + +nbdkit_pattern_plugin_la_CPPFLAGS = \ + -I$(top_srcdir)/include +nbdkit_pattern_plugin_la_CFLAGS = \ + $(WARNINGS_CFLAGS) +nbdkit_pattern_plugin_la_LDFLAGS = \ + -module -avoid-version -shared + +if HAVE_POD2MAN + +man_MANS = nbdkit-pattern-plugin.1 +CLEANFILES += $(man_MANS) + +nbdkit-pattern-plugin.1: nbdkit-pattern-plugin.pod + $(POD2MAN) $(POD2MAN_ARGS) --section=1 --name=`basename $@ .1` $< $@.t && \ + if grep 'POD ERROR' $@.t; then rm $@.t; exit 1; fi && \ + mv $@.t $@ + +endif diff --git a/plugins/pattern/nbdkit-pattern-plugin.pod b/plugins/pattern/nbdkit-pattern-plugin.pod new file mode 100644 index 0000000..7a6b498 --- /dev/null +++ b/plugins/pattern/nbdkit-pattern-plugin.pod @@ -0,0 +1,99 @@ +=encoding utf8 + +=head1 NAME + +nbdkit-pattern-plugin - plugin to serve a fixed pattern of data for testing + +=head1 SYNOPSIS + + nbdkit pattern size=SIZE + +=head1 DESCRIPTION + +C is a plugin for L which serves a +fixed pattern of data, read only. This is used for testing nbdkit +filters and NBD clients. + +The fixed pattern is the offset, as a 64 bit big endian integer, every +8 bytes. In hexadecimal this looks like: + + offset data + 0000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 08 + 0010: 00 00 00 00 00 00 00 10 00 00 00 00 00 00 00 18 + 0020: 00 00 00 00 00 00 00 20 00 00 00 00 00 00 00 28 + └──────────┬──────────┘ + 64 bit big endian int which encodes the offset of + the first byte of this int in the file + +The size of the virtual disk must be specified using the C +parameter. If the size is not a multiple of 8 then the last 8 byte +offset in the pattern is truncated. + +=head1 PARAMETERS + +=over 4 + +=item B + +Specify the virtual size of the disk image. + +This parameter is required. + +=back + +=head1 SEE ALSO + +L, +L, +L, +L, +L, +L. + +=head1 AUTHORS + +Richard W.M. Jones + +=head1 COPYRIGHT + +Copyright (C) 2018 Red Hat Inc. + +=head1 LICENSE + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +=over 4 + +=item * + +Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + +=item * + +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. + +=item * + +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. + +=back + +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. diff --git a/plugins/pattern/pattern.c b/plugins/pattern/pattern.c new file mode 100644 index 0000000..e1dc798 --- /dev/null +++ b/plugins/pattern/pattern.c @@ -0,0 +1,134 @@ +/* nbdkit + * Copyright (C) 2017-2018 Red Hat Inc. + * All rights reserved. + * + * 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 + +#include +#include +#include +#include +#include +#include +#include + +#define NBDKIT_API_VERSION 2 +#include + +/* The size of disk in bytes (initialized by size= parameter). */ +static size_t size = 0; + +static int +pattern_config (const char *key, const char *value) +{ + int64_t r; + + if (strcmp (key, "size") == 0) { + r = nbdkit_parse_size (value); + if (r == -1) + return -1; + if (r > SIZE_MAX) { + nbdkit_error ("size > SIZE_MAX"); + return -1; + } + size = (ssize_t) r; + } + else { + nbdkit_error ("unknown parameter '%s'", key); + return -1; + } + + return 0; +} + +#define pattern_config_help \ + "size= (required) Size of the backing disk" + +#define THREAD_MODEL NBDKIT_THREAD_MODEL_PARALLEL + +/* No meaning, just used as the address for the handle. */ +static int ph; + +/* Create the per-connection handle. */ +static void * +pattern_open (int readonly) +{ + return &ph; +} + +/* Get the disk size. */ +static int64_t +pattern_get_size (void *handle) +{ + return (int64_t) size; +} + +#define MIN(a, b) ((a) < (b) ? (a) : (b)) + +/* Read data. */ +static int +pattern_pread (void *handle, void *buf, uint32_t count, uint64_t offset, + uint32_t flags) +{ + char *b = buf; + uint64_t d; + uint64_t o; + size_t n; + + while (count > 0) { + d = htobe64 (offset & ~7); + o = offset & 7; + n = MIN (count, 8-o); + memcpy (b, (char *)&d + o, n); + b += 8-o; + offset += 8-o; + count -= n; + } + + return 0; +} + +static struct nbdkit_plugin plugin = { + .name = "pattern", + .version = PACKAGE_VERSION, + .config = pattern_config, + .config_help = pattern_config_help, + .open = pattern_open, + .get_size = pattern_get_size, + .pread = pattern_pread, + /* In this plugin, errno is preserved properly along error return + * paths from failed system calls. + */ + .errno_is_preserved = 1, +}; + +NBDKIT_REGISTER_PLUGIN(plugin) diff --git a/plugins/random/nbdkit-random-plugin.pod b/plugins/random/nbdkit-random-plugin.pod index e746699..6539d61 100644 --- a/plugins/random/nbdkit-random-plugin.pod +++ b/plugins/random/nbdkit-random-plugin.pod @@ -44,6 +44,7 @@ If not specified then a random seed is chosen. L, L, L, +L, L. =head1 AUTHORS diff --git a/plugins/zero/nbdkit-zero-plugin.pod b/plugins/zero/nbdkit-zero-plugin.pod index 67763da..015c70a 100644 --- a/plugins/zero/nbdkit-zero-plugin.pod +++ b/plugins/zero/nbdkit-zero-plugin.pod @@ -21,6 +21,7 @@ protocol and NBD clients. L, L, L, +L, L. =head1 AUTHORS diff --git a/tests/Makefile.am b/tests/Makefile.am index 5f21e75..354c12c 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -63,6 +63,7 @@ EXTRA_DIST = \ test-ocaml.c \ test-parallel-file.sh \ test-parallel-nbd.sh \ + test-pattern.sh \ test-python-exception.sh \ test.pl \ test.py \ @@ -315,6 +316,9 @@ test_memory_SOURCES = test-memory.c test.h test_memory_CFLAGS = $(WARNINGS_CFLAGS) $(LIBGUESTFS_CFLAGS) test_memory_LDADD = libtest.la $(LIBGUESTFS_LIBS) +# pattern plugin test. +TESTS += test-pattern.sh + # nbd plugin test. LIBGUESTFS_TESTS += test-nbd diff --git a/tests/test-pattern.sh b/tests/test-pattern.sh new file mode 100755 index 0000000..2db4e0c --- /dev/null +++ b/tests/test-pattern.sh @@ -0,0 +1,121 @@ +#!/bin/bash - +# nbdkit +# Copyright (C) 2018 Red Hat Inc. +# All rights reserved. +# +# 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 pattern plugin. +# +# Note we don't have any client which can issue misaligned NBD +# requests. qemu-io will issue 512-byte aligned requests no matter +# what read parameters we give it. Hence these tests are rather +# limited. (XXX) + +set -e + +files="pattern.out pattern.pid pattern.sock" +rm -f $files + +# Test that qemu-io works +if ! qemu-io --help >/dev/null; then + echo "$0: missing or broken qemu-io" + exit 77 +fi + +# Run nbdkit with pattern plugin. +nbdkit -P pattern.pid -U pattern.sock pattern size=1G + +# We may have to wait a short time for the pid file to appear. +for i in `seq 1 10`; do + if test -f pattern.pid; then + break + fi + sleep 1 +done +if ! test -f pattern.pid; then + echo "$0: PID file was not created" + exit 1 +fi + +pid="$(cat pattern.pid)" + +# Kill the nbdkit process on exit. +cleanup () +{ + status=$? + + kill $pid + rm -f $files + + exit $status +} +trap cleanup INT QUIT TERM EXIT ERR + +qemu-io -r -f raw 'nbd+unix://?socket=pattern.sock' \ + -c 'r -v 0 512' | grep -E '^[[:xdigit:]]+:' > pattern.out +if [ "$(cat pattern.out)" != "00000000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 08 ................ +00000010: 00 00 00 00 00 00 00 10 00 00 00 00 00 00 00 18 ................ +00000020: 00 00 00 00 00 00 00 20 00 00 00 00 00 00 00 28 ................ +00000030: 00 00 00 00 00 00 00 30 00 00 00 00 00 00 00 38 .......0.......8 +00000040: 00 00 00 00 00 00 00 40 00 00 00 00 00 00 00 48 ...............H +00000050: 00 00 00 00 00 00 00 50 00 00 00 00 00 00 00 58 .......P.......X +00000060: 00 00 00 00 00 00 00 60 00 00 00 00 00 00 00 68 ...............h +00000070: 00 00 00 00 00 00 00 70 00 00 00 00 00 00 00 78 .......p.......x +00000080: 00 00 00 00 00 00 00 80 00 00 00 00 00 00 00 88 ................ +00000090: 00 00 00 00 00 00 00 90 00 00 00 00 00 00 00 98 ................ +000000a0: 00 00 00 00 00 00 00 a0 00 00 00 00 00 00 00 a8 ................ +000000b0: 00 00 00 00 00 00 00 b0 00 00 00 00 00 00 00 b8 ................ +000000c0: 00 00 00 00 00 00 00 c0 00 00 00 00 00 00 00 c8 ................ +000000d0: 00 00 00 00 00 00 00 d0 00 00 00 00 00 00 00 d8 ................ +000000e0: 00 00 00 00 00 00 00 e0 00 00 00 00 00 00 00 e8 ................ +000000f0: 00 00 00 00 00 00 00 f0 00 00 00 00 00 00 00 f8 ................ +00000100: 00 00 00 00 00 00 01 00 00 00 00 00 00 00 01 08 ................ +00000110: 00 00 00 00 00 00 01 10 00 00 00 00 00 00 01 18 ................ +00000120: 00 00 00 00 00 00 01 20 00 00 00 00 00 00 01 28 ................ +00000130: 00 00 00 00 00 00 01 30 00 00 00 00 00 00 01 38 .......0.......8 +00000140: 00 00 00 00 00 00 01 40 00 00 00 00 00 00 01 48 ...............H +00000150: 00 00 00 00 00 00 01 50 00 00 00 00 00 00 01 58 .......P.......X +00000160: 00 00 00 00 00 00 01 60 00 00 00 00 00 00 01 68 ...............h +00000170: 00 00 00 00 00 00 01 70 00 00 00 00 00 00 01 78 .......p.......x +00000180: 00 00 00 00 00 00 01 80 00 00 00 00 00 00 01 88 ................ +00000190: 00 00 00 00 00 00 01 90 00 00 00 00 00 00 01 98 ................ +000001a0: 00 00 00 00 00 00 01 a0 00 00 00 00 00 00 01 a8 ................ +000001b0: 00 00 00 00 00 00 01 b0 00 00 00 00 00 00 01 b8 ................ +000001c0: 00 00 00 00 00 00 01 c0 00 00 00 00 00 00 01 c8 ................ +000001d0: 00 00 00 00 00 00 01 d0 00 00 00 00 00 00 01 d8 ................ +000001e0: 00 00 00 00 00 00 01 e0 00 00 00 00 00 00 01 e8 ................ +000001f0: 00 00 00 00 00 00 01 f0 00 00 00 00 00 00 01 f8 ................" ] +then + echo "$0: unexpected pattern:" + cat pattern.out + exit 1 +fi + +# The cleanup() function is called implicitly on exit. -- 2.17.1