import nbdkit-1.16.2-2.module+el8.3.0+6423+e4cb6418
This commit is contained in:
		
						commit
						fa44cefe07
					
				
							
								
								
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,2 @@ | |||||||
|  | SOURCES/libguestfs.keyring | ||||||
|  | SOURCES/nbdkit-1.16.2.tar.gz | ||||||
							
								
								
									
										2
									
								
								.nbdkit.metadata
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								.nbdkit.metadata
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,2 @@ | |||||||
|  | 1bbc40f501a7fef9eef2a39b701a71aee2fea7c4 SOURCES/libguestfs.keyring | ||||||
|  | 42a5761cd3403c02c43cdf7d541ff3faaf8b4769 SOURCES/nbdkit-1.16.2.tar.gz | ||||||
| @ -0,0 +1,74 @@ | |||||||
|  | From d7836fb0a7131c725e3c02be7e48e99c671637c3 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: "Richard W.M. Jones" <rjones@redhat.com> | ||||||
|  | Date: Thu, 12 Dec 2019 08:57:15 +0000 | ||||||
|  | Subject: [PATCH] server: Allow -D nbdkit.* debug flags for the core server. | ||||||
|  | 
 | ||||||
|  | These work like plugin/filter debug flags, but apply to the internals | ||||||
|  | of the server. | ||||||
|  | 
 | ||||||
|  | (cherry picked from commit 3b45db234a691f8ff926a6fef583e11c3601f112) | ||||||
|  | ---
 | ||||||
|  |  docs/nbdkit.pod    | 7 +++++++ | ||||||
|  |  docs/synopsis.txt  | 2 +- | ||||||
|  |  server/main.c      | 3 +++ | ||||||
|  |  server/nbdkit.syms | 2 ++ | ||||||
|  |  4 files changed, 13 insertions(+), 1 deletion(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/docs/nbdkit.pod b/docs/nbdkit.pod
 | ||||||
|  | index a2e72b1..346d833 100644
 | ||||||
|  | --- a/docs/nbdkit.pod
 | ||||||
|  | +++ b/docs/nbdkit.pod
 | ||||||
|  | @@ -177,6 +177,13 @@ Display brief command line usage information and exit.
 | ||||||
|  |  Set the plugin or filter Debug Flag called C<FLAG> to the integer | ||||||
|  |  value C<N>.  See L<nbdkit-plugin(3)/Debug Flags>. | ||||||
|  |   | ||||||
|  | +=item B<-D> nbdkit.FLAG=N
 | ||||||
|  | +
 | ||||||
|  | +=item B<--debug> nbdkit.FLAG=N
 | ||||||
|  | +
 | ||||||
|  | +Set the nbdkit server Debug Flag called C<FLAG> to the integer value
 | ||||||
|  | +C<N>.
 | ||||||
|  | +
 | ||||||
|  |  =item B<--dump-config> | ||||||
|  |   | ||||||
|  |  Dump out the compile-time configuration values and exit. | ||||||
|  | diff --git a/docs/synopsis.txt b/docs/synopsis.txt
 | ||||||
|  | index 3c23937..c367542 100644
 | ||||||
|  | --- a/docs/synopsis.txt
 | ||||||
|  | +++ b/docs/synopsis.txt
 | ||||||
|  | @@ -1,4 +1,4 @@
 | ||||||
|  | -nbdkit [-D|--debug PLUGIN|FILTER.FLAG=N]
 | ||||||
|  | +nbdkit [-D|--debug PLUGIN|FILTER|nbdkit.FLAG=N]
 | ||||||
|  |         [-e|--exportname EXPORTNAME] [--exit-with-parent] | ||||||
|  |         [--filter FILTER ...] [-f|--foreground] | ||||||
|  |         [-g|--group GROUP] [-i|--ipaddr IPADDR] | ||||||
|  | diff --git a/server/main.c b/server/main.c
 | ||||||
|  | index d39941b..11ba1e6 100644
 | ||||||
|  | --- a/server/main.c
 | ||||||
|  | +++ b/server/main.c
 | ||||||
|  | @@ -563,6 +563,9 @@ main (int argc, char *argv[])
 | ||||||
|  |      free (t); | ||||||
|  |    } | ||||||
|  |   | ||||||
|  | +  /* Apply nbdkit.* flags for the server. */
 | ||||||
|  | +  apply_debug_flags (NULL, "nbdkit");
 | ||||||
|  | +
 | ||||||
|  |    /* Check all debug flags were used, and free them. */ | ||||||
|  |    free_debug_flags (); | ||||||
|  |   | ||||||
|  | diff --git a/server/nbdkit.syms b/server/nbdkit.syms
 | ||||||
|  | index 390972e..96c22c0 100644
 | ||||||
|  | --- a/server/nbdkit.syms
 | ||||||
|  | +++ b/server/nbdkit.syms
 | ||||||
|  | @@ -67,6 +67,8 @@
 | ||||||
|  |      nbdkit_vdebug; | ||||||
|  |      nbdkit_verror; | ||||||
|  |   | ||||||
|  | +    nbdkit_debug_*;
 | ||||||
|  | +
 | ||||||
|  |    # Everything else is hidden. | ||||||
|  |    local: *; | ||||||
|  |  }; | ||||||
|  | -- 
 | ||||||
|  | 2.18.2 | ||||||
|  | 
 | ||||||
| @ -0,0 +1,66 @@ | |||||||
|  | From e5d2d44fff9214725506cbc84e7b3c035ec0eae9 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: "Richard W.M. Jones" <rjones@redhat.com> | ||||||
|  | Date: Thu, 12 Dec 2019 11:06:36 +0000 | ||||||
|  | Subject: [PATCH] server: Allow -D debug flags to contain dots for namespacing. | ||||||
|  | 
 | ||||||
|  | This is just a convenience.  Either of: | ||||||
|  | 
 | ||||||
|  |  -D myplugin.foo_bar=1 | ||||||
|  |  -D myplugin.foo.bar=1 | ||||||
|  | 
 | ||||||
|  | correspond to the same plugin variable "myplugin_debug_foo_bar". | ||||||
|  | 
 | ||||||
|  | (cherry picked from commit a895fa84aaa50f52af68319523020046394c789f) | ||||||
|  | ---
 | ||||||
|  |  docs/nbdkit-plugin.pod |  8 ++++++++ | ||||||
|  |  server/debug-flags.c   | 10 +++++++++- | ||||||
|  |  2 files changed, 17 insertions(+), 1 deletion(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/docs/nbdkit-plugin.pod b/docs/nbdkit-plugin.pod
 | ||||||
|  | index b69cb82..879ddf0 100644
 | ||||||
|  | --- a/docs/nbdkit-plugin.pod
 | ||||||
|  | +++ b/docs/nbdkit-plugin.pod
 | ||||||
|  | @@ -1298,6 +1298,14 @@ You should only use this feature for debug settings.  For general
 | ||||||
|  |  settings use ordinary plugin parameters.  Debug Flags can only be C | ||||||
|  |  ints.  They are not supported by non-C language plugins. | ||||||
|  |   | ||||||
|  | +For convenience C<'.'> characters are replaced with C<'_'> characters
 | ||||||
|  | +in the variable name, so both of these parameters:
 | ||||||
|  | +
 | ||||||
|  | + -D myplugin.foo_bar=1
 | ||||||
|  | + -D myplugin.foo.bar=1
 | ||||||
|  | +
 | ||||||
|  | +correspond to the plugin variable C<myplugin_debug_foo_bar>.
 | ||||||
|  | +
 | ||||||
|  |  =head1 INSTALLING THE PLUGIN | ||||||
|  |   | ||||||
|  |  The plugin is a C<*.so> file and possibly a manual page.  You can of | ||||||
|  | diff --git a/server/debug-flags.c b/server/debug-flags.c
 | ||||||
|  | index 9344d85..5e06f5e 100644
 | ||||||
|  | --- a/server/debug-flags.c
 | ||||||
|  | +++ b/server/debug-flags.c
 | ||||||
|  | @@ -56,12 +56,20 @@ static char *
 | ||||||
|  |  symbol_of_debug_flag (const char *name, const char *flag) | ||||||
|  |  { | ||||||
|  |    char *var; | ||||||
|  | +  size_t i;
 | ||||||
|  | +  int len;
 | ||||||
|  |   | ||||||
|  | -  if (asprintf (&var, "%s_debug_%s", name, flag) == -1) {
 | ||||||
|  | +  if ((len = asprintf (&var, "%s_debug_%s", name, flag)) == -1) {
 | ||||||
|  |      perror ("asprintf"); | ||||||
|  |      exit (EXIT_FAILURE); | ||||||
|  |    } | ||||||
|  |   | ||||||
|  | +  /* If there are any '.'s remaining in the name, convert them to '_'. */
 | ||||||
|  | +  for (i = 0; i < (size_t) len; ++i) {
 | ||||||
|  | +    if (var[i] == '.')
 | ||||||
|  | +      var[i] = '_';
 | ||||||
|  | +  }
 | ||||||
|  | +
 | ||||||
|  |    return var;                   /* caller frees */ | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | -- 
 | ||||||
|  | 2.18.2 | ||||||
|  | 
 | ||||||
| @ -0,0 +1,451 @@ | |||||||
|  | From 83c72d9bf9d6a9ccf6939b4ebd0028b62673a78a Mon Sep 17 00:00:00 2001 | ||||||
|  | From: "Richard W.M. Jones" <rjones@redhat.com> | ||||||
|  | Date: Thu, 12 Dec 2019 10:57:52 +0000 | ||||||
|  | Subject: [PATCH] server: Add -D nbdkit.backend.controlpath and -D | ||||||
|  |  nbdkit.backend.datapath. | ||||||
|  | 
 | ||||||
|  | These can be used to suppress verbose debugging messages from the | ||||||
|  | backend. | ||||||
|  | 
 | ||||||
|  | BugLink: https://bugzilla.redhat.com/1782868 | ||||||
|  | 
 | ||||||
|  | Cherry picked from commit 231717e8cd5f27d76631be6651062d5a5ccf7fdc. | ||||||
|  | Remove use of nofilter from the test. | ||||||
|  | ---
 | ||||||
|  |  docs/nbdkit.pod                    | 35 ++++++++++++- | ||||||
|  |  server/backend.c                   | 83 ++++++++++++++++++------------ | ||||||
|  |  tests/Makefile.am                  |  4 ++ | ||||||
|  |  tests/test-nbdkit-backend-debug.sh | 70 +++++++++++++++++++++++++ | ||||||
|  |  4 files changed, 158 insertions(+), 34 deletions(-) | ||||||
|  |  create mode 100755 tests/test-nbdkit-backend-debug.sh | ||||||
|  | 
 | ||||||
|  | diff --git a/docs/nbdkit.pod b/docs/nbdkit.pod
 | ||||||
|  | index 346d833..38e6bfc 100644
 | ||||||
|  | --- a/docs/nbdkit.pod
 | ||||||
|  | +++ b/docs/nbdkit.pod
 | ||||||
|  | @@ -182,7 +182,7 @@ value C<N>.  See L<nbdkit-plugin(3)/Debug Flags>.
 | ||||||
|  |  =item B<--debug> nbdkit.FLAG=N | ||||||
|  |   | ||||||
|  |  Set the nbdkit server Debug Flag called C<FLAG> to the integer value | ||||||
|  | -C<N>.
 | ||||||
|  | +C<N>.  See L</SERVER DEBUG FLAGS> below.
 | ||||||
|  |   | ||||||
|  |  =item B<--dump-config> | ||||||
|  |   | ||||||
|  | @@ -527,6 +527,39 @@ languages.  The file should be executable.  For example:
 | ||||||
|  |   | ||||||
|  |  (see L<nbdkit-perl-plugin(3)> for a full example). | ||||||
|  |   | ||||||
|  | +=head1 SERVER DEBUG FLAGS
 | ||||||
|  | +
 | ||||||
|  | +As well as enabling or disabling debugging in the server using
 | ||||||
|  | +I<--verbose> you can control extra debugging in the server using the
 | ||||||
|  | +C<-D nbdkit.*> flags listed in this section.  Note these flags are an
 | ||||||
|  | +internal implementation detail of the server and may be changed or
 | ||||||
|  | +removed at any time in the future.
 | ||||||
|  | +
 | ||||||
|  | +=over 4
 | ||||||
|  | +
 | ||||||
|  | +=item B<-D nbdkit.backend.controlpath=0>
 | ||||||
|  | +
 | ||||||
|  | +=item B<-D nbdkit.backend.controlpath=1>
 | ||||||
|  | +
 | ||||||
|  | +=item B<-D nbdkit.backend.datapath=0>
 | ||||||
|  | +
 | ||||||
|  | +=item B<-D nbdkit.backend.datapath=1>
 | ||||||
|  | +
 | ||||||
|  | +These flags control the verbosity of nbdkit backend debugging messages
 | ||||||
|  | +(the ones which show every request processed by the server).  The
 | ||||||
|  | +default for both settings is C<1> (normal debugging) but you can set
 | ||||||
|  | +them to C<0> to suppress these messages.
 | ||||||
|  | +
 | ||||||
|  | +C<-D nbdkit.backend.datapath=0> is the more useful setting which lets you
 | ||||||
|  | +suppress messages about pread, pwrite, zero, trim, etc. commands.
 | ||||||
|  | +When transferring large amounts of data these messages are numerous
 | ||||||
|  | +and not usually very interesting.
 | ||||||
|  | +
 | ||||||
|  | +C<-D nbdkit.backend.controlpath=0> suppresses the non-datapath
 | ||||||
|  | +commands (config, open, close, can_write, etc.)
 | ||||||
|  | +
 | ||||||
|  | +=back
 | ||||||
|  | +
 | ||||||
|  |  =head1 SIGNALS | ||||||
|  |   | ||||||
|  |  nbdkit responds to the following signals: | ||||||
|  | diff --git a/server/backend.c b/server/backend.c
 | ||||||
|  | index b9fe2a2..208c07b 100644
 | ||||||
|  | --- a/server/backend.c
 | ||||||
|  | +++ b/server/backend.c
 | ||||||
|  | @@ -46,6 +46,22 @@
 | ||||||
|  |   | ||||||
|  |  /* Helpers for registering a new backend. */ | ||||||
|  |   | ||||||
|  | +/* Use:
 | ||||||
|  | + * -D nbdkit.backend.controlpath=0 to suppress control path debugging.
 | ||||||
|  | + * -D nbdkit.backend.datapath=0 to suppress data path debugging.
 | ||||||
|  | + */
 | ||||||
|  | +int nbdkit_debug_backend_controlpath = 1;
 | ||||||
|  | +int nbdkit_debug_backend_datapath = 1;
 | ||||||
|  | +
 | ||||||
|  | +#define controlpath_debug(fs, ...)                                     \
 | ||||||
|  | +  do {                                                                 \
 | ||||||
|  | +    if (nbdkit_debug_backend_controlpath) debug ((fs), ##__VA_ARGS__); \
 | ||||||
|  | +  } while (0)
 | ||||||
|  | +#define datapath_debug(fs, ...)                                        \
 | ||||||
|  | +  do {                                                                 \
 | ||||||
|  | +    if (nbdkit_debug_backend_datapath) debug ((fs), ##__VA_ARGS__);    \
 | ||||||
|  | +  } while (0)
 | ||||||
|  | +
 | ||||||
|  |  void | ||||||
|  |  backend_init (struct backend *b, struct backend *next, size_t index, | ||||||
|  |                const char *filename, void *dl, const char *type) | ||||||
|  | @@ -108,7 +124,7 @@ backend_load (struct backend *b, const char *name, void (*load) (void))
 | ||||||
|  |    apply_debug_flags (b->dl, name); | ||||||
|  |   | ||||||
|  |    /* Call the on-load callback if it exists. */ | ||||||
|  | -  debug ("%s: load", name);
 | ||||||
|  | +  controlpath_debug ("%s: load", name);
 | ||||||
|  |    if (load) | ||||||
|  |      load (); | ||||||
|  |  } | ||||||
|  | @@ -121,7 +137,7 @@ backend_unload (struct backend *b, void (*unload) (void))
 | ||||||
|  |     */ | ||||||
|  |    lock_unload (); | ||||||
|  |   | ||||||
|  | -  debug ("%s: unload %s", b->name, b->type);
 | ||||||
|  | +  controlpath_debug ("%s: unload %s", b->name, b->type);
 | ||||||
|  |    if (unload) | ||||||
|  |      unload (); | ||||||
|  |   | ||||||
|  | @@ -139,7 +155,7 @@ backend_open (struct backend *b, struct connection *conn, int readonly)
 | ||||||
|  |  { | ||||||
|  |    struct b_conn_handle *h = &conn->handles[b->i]; | ||||||
|  |   | ||||||
|  | -  debug ("%s: open readonly=%d", b->name, readonly);
 | ||||||
|  | +  controlpath_debug ("%s: open readonly=%d", b->name, readonly);
 | ||||||
|  |   | ||||||
|  |    assert (h->handle == NULL); | ||||||
|  |    assert ((h->state & HANDLE_OPEN) == 0); | ||||||
|  | @@ -151,7 +167,7 @@ backend_open (struct backend *b, struct connection *conn, int readonly)
 | ||||||
|  |     * inner-to-outer ordering. | ||||||
|  |     */ | ||||||
|  |    h->handle = b->open (b, conn, readonly); | ||||||
|  | -  debug ("%s: open returned handle %p", b->name, h->handle);
 | ||||||
|  | +  controlpath_debug ("%s: open returned handle %p", b->name, h->handle);
 | ||||||
|  |   | ||||||
|  |    if (h->handle == NULL) { | ||||||
|  |      if (b->i) /* Do not strand backend if this layer failed */ | ||||||
|  | @@ -179,7 +195,7 @@ backend_prepare (struct backend *b, struct connection *conn)
 | ||||||
|  |    if (b->i && backend_prepare (b->next, conn) == -1) | ||||||
|  |      return -1; | ||||||
|  |   | ||||||
|  | -  debug ("%s: prepare readonly=%d", b->name, h->can_write == 0);
 | ||||||
|  | +  controlpath_debug ("%s: prepare readonly=%d", b->name, h->can_write == 0);
 | ||||||
|  |   | ||||||
|  |    if (b->prepare (b, conn, h->handle, h->can_write == 0) == -1) | ||||||
|  |      return -1; | ||||||
|  | @@ -196,7 +212,7 @@ backend_finalize (struct backend *b, struct connection *conn)
 | ||||||
|  |     * filter furthest away from the plugin, and matching .close order. | ||||||
|  |     */ | ||||||
|  |   | ||||||
|  | -  debug ("%s: finalize", b->name);
 | ||||||
|  | +  controlpath_debug ("%s: finalize", b->name);
 | ||||||
|  |   | ||||||
|  |    /* Once finalize fails, we can do nothing further on this connection */ | ||||||
|  |    if (h->state & HANDLE_FAILED) | ||||||
|  | @@ -223,7 +239,7 @@ backend_close (struct backend *b, struct connection *conn)
 | ||||||
|  |    struct b_conn_handle *h = &conn->handles[b->i]; | ||||||
|  |   | ||||||
|  |    /* outer-to-inner order, opposite .open */ | ||||||
|  | -  debug ("%s: close", b->name);
 | ||||||
|  | +  controlpath_debug ("%s: close", b->name);
 | ||||||
|  |   | ||||||
|  |    if (h->handle) { | ||||||
|  |      assert (h->state & HANDLE_OPEN); | ||||||
|  | @@ -252,7 +268,7 @@ backend_valid_range (struct backend *b, struct connection *conn,
 | ||||||
|  |  int | ||||||
|  |  backend_reopen (struct backend *b, struct connection *conn, int readonly) | ||||||
|  |  { | ||||||
|  | -  debug ("%s: reopen readonly=%d", b->name, readonly);
 | ||||||
|  | +  controlpath_debug ("%s: reopen readonly=%d", b->name, readonly);
 | ||||||
|  |   | ||||||
|  |    if (backend_finalize (b, conn) == -1) | ||||||
|  |      return -1; | ||||||
|  | @@ -274,7 +290,7 @@ backend_get_size (struct backend *b, struct connection *conn)
 | ||||||
|  |  { | ||||||
|  |    struct b_conn_handle *h = &conn->handles[b->i]; | ||||||
|  |   | ||||||
|  | -  debug ("%s: get_size", b->name);
 | ||||||
|  | +  controlpath_debug ("%s: get_size", b->name);
 | ||||||
|  |   | ||||||
|  |    assert (h->handle && (h->state & HANDLE_CONNECTED)); | ||||||
|  |    if (h->exportsize == -1) | ||||||
|  | @@ -287,7 +303,7 @@ backend_can_write (struct backend *b, struct connection *conn)
 | ||||||
|  |  { | ||||||
|  |    struct b_conn_handle *h = &conn->handles[b->i]; | ||||||
|  |   | ||||||
|  | -  debug ("%s: can_write", b->name);
 | ||||||
|  | +  controlpath_debug ("%s: can_write", b->name);
 | ||||||
|  |   | ||||||
|  |    assert (h->handle && (h->state & HANDLE_CONNECTED)); | ||||||
|  |    if (h->can_write == -1) | ||||||
|  | @@ -300,7 +316,7 @@ backend_can_flush (struct backend *b, struct connection *conn)
 | ||||||
|  |  { | ||||||
|  |    struct b_conn_handle *h = &conn->handles[b->i]; | ||||||
|  |   | ||||||
|  | -  debug ("%s: can_flush", b->name);
 | ||||||
|  | +  controlpath_debug ("%s: can_flush", b->name);
 | ||||||
|  |   | ||||||
|  |    assert (h->handle && (h->state & HANDLE_CONNECTED)); | ||||||
|  |    if (h->can_flush == -1) | ||||||
|  | @@ -313,7 +329,7 @@ backend_is_rotational (struct backend *b, struct connection *conn)
 | ||||||
|  |  { | ||||||
|  |    struct b_conn_handle *h = &conn->handles[b->i]; | ||||||
|  |   | ||||||
|  | -  debug ("%s: is_rotational", b->name);
 | ||||||
|  | +  controlpath_debug ("%s: is_rotational", b->name);
 | ||||||
|  |   | ||||||
|  |    assert (h->handle && (h->state & HANDLE_CONNECTED)); | ||||||
|  |    if (h->is_rotational == -1) | ||||||
|  | @@ -327,7 +343,7 @@ backend_can_trim (struct backend *b, struct connection *conn)
 | ||||||
|  |    struct b_conn_handle *h = &conn->handles[b->i]; | ||||||
|  |    int r; | ||||||
|  |   | ||||||
|  | -  debug ("%s: can_trim", b->name);
 | ||||||
|  | +  controlpath_debug ("%s: can_trim", b->name);
 | ||||||
|  |   | ||||||
|  |    assert (h->handle && (h->state & HANDLE_CONNECTED)); | ||||||
|  |    if (h->can_trim == -1) { | ||||||
|  | @@ -347,7 +363,7 @@ backend_can_zero (struct backend *b, struct connection *conn)
 | ||||||
|  |    struct b_conn_handle *h = &conn->handles[b->i]; | ||||||
|  |    int r; | ||||||
|  |   | ||||||
|  | -  debug ("%s: can_zero", b->name);
 | ||||||
|  | +  controlpath_debug ("%s: can_zero", b->name);
 | ||||||
|  |   | ||||||
|  |    assert (h->handle && (h->state & HANDLE_CONNECTED)); | ||||||
|  |    if (h->can_zero == -1) { | ||||||
|  | @@ -367,7 +383,7 @@ backend_can_fast_zero (struct backend *b, struct connection *conn)
 | ||||||
|  |    struct b_conn_handle *h = &conn->handles[b->i]; | ||||||
|  |    int r; | ||||||
|  |   | ||||||
|  | -  debug ("%s: can_fast_zero", b->name);
 | ||||||
|  | +  controlpath_debug ("%s: can_fast_zero", b->name);
 | ||||||
|  |   | ||||||
|  |    assert (h->handle && (h->state & HANDLE_CONNECTED)); | ||||||
|  |    if (h->can_fast_zero == -1) { | ||||||
|  | @@ -386,7 +402,7 @@ backend_can_extents (struct backend *b, struct connection *conn)
 | ||||||
|  |  { | ||||||
|  |    struct b_conn_handle *h = &conn->handles[b->i]; | ||||||
|  |   | ||||||
|  | -  debug ("%s: can_extents", b->name);
 | ||||||
|  | +  controlpath_debug ("%s: can_extents", b->name);
 | ||||||
|  |   | ||||||
|  |    assert (h->handle && (h->state & HANDLE_CONNECTED)); | ||||||
|  |    if (h->can_extents == -1) | ||||||
|  | @@ -400,7 +416,7 @@ backend_can_fua (struct backend *b, struct connection *conn)
 | ||||||
|  |    struct b_conn_handle *h = &conn->handles[b->i]; | ||||||
|  |    int r; | ||||||
|  |   | ||||||
|  | -  debug ("%s: can_fua", b->name);
 | ||||||
|  | +  controlpath_debug ("%s: can_fua", b->name);
 | ||||||
|  |   | ||||||
|  |    assert (h->handle && (h->state & HANDLE_CONNECTED)); | ||||||
|  |    if (h->can_fua == -1) { | ||||||
|  | @@ -420,7 +436,7 @@ backend_can_multi_conn (struct backend *b, struct connection *conn)
 | ||||||
|  |    struct b_conn_handle *h = &conn->handles[b->i]; | ||||||
|  |   | ||||||
|  |    assert (h->handle && (h->state & HANDLE_CONNECTED)); | ||||||
|  | -  debug ("%s: can_multi_conn", b->name);
 | ||||||
|  | +  controlpath_debug ("%s: can_multi_conn", b->name);
 | ||||||
|  |   | ||||||
|  |    if (h->can_multi_conn == -1) | ||||||
|  |      h->can_multi_conn = b->can_multi_conn (b, conn, h->handle); | ||||||
|  | @@ -432,7 +448,7 @@ backend_can_cache (struct backend *b, struct connection *conn)
 | ||||||
|  |  { | ||||||
|  |    struct b_conn_handle *h = &conn->handles[b->i]; | ||||||
|  |   | ||||||
|  | -  debug ("%s: can_cache", b->name);
 | ||||||
|  | +  controlpath_debug ("%s: can_cache", b->name);
 | ||||||
|  |   | ||||||
|  |    assert (h->handle && (h->state & HANDLE_CONNECTED)); | ||||||
|  |    if (h->can_cache == -1) | ||||||
|  | @@ -451,8 +467,8 @@ backend_pread (struct backend *b, struct connection *conn,
 | ||||||
|  |    assert (h->handle && (h->state & HANDLE_CONNECTED)); | ||||||
|  |    assert (backend_valid_range (b, conn, offset, count)); | ||||||
|  |    assert (flags == 0); | ||||||
|  | -  debug ("%s: pread count=%" PRIu32 " offset=%" PRIu64,
 | ||||||
|  | -         b->name, count, offset);
 | ||||||
|  | +  datapath_debug ("%s: pread count=%" PRIu32 " offset=%" PRIu64,
 | ||||||
|  | +                  b->name, count, offset);
 | ||||||
|  |   | ||||||
|  |    r = b->pread (b, conn, h->handle, buf, count, offset, flags, err); | ||||||
|  |    if (r == -1) | ||||||
|  | @@ -475,8 +491,8 @@ backend_pwrite (struct backend *b, struct connection *conn,
 | ||||||
|  |    assert (!(flags & ~NBDKIT_FLAG_FUA)); | ||||||
|  |    if (fua) | ||||||
|  |      assert (h->can_fua > NBDKIT_FUA_NONE); | ||||||
|  | -  debug ("%s: pwrite count=%" PRIu32 " offset=%" PRIu64 " fua=%d",
 | ||||||
|  | -         b->name, count, offset, fua);
 | ||||||
|  | +  datapath_debug ("%s: pwrite count=%" PRIu32 " offset=%" PRIu64 " fua=%d",
 | ||||||
|  | +                  b->name, count, offset, fua);
 | ||||||
|  |   | ||||||
|  |    r = b->pwrite (b, conn, h->handle, buf, count, offset, flags, err); | ||||||
|  |    if (r == -1) | ||||||
|  | @@ -494,7 +510,7 @@ backend_flush (struct backend *b, struct connection *conn,
 | ||||||
|  |    assert (h->handle && (h->state & HANDLE_CONNECTED)); | ||||||
|  |    assert (h->can_flush == 1); | ||||||
|  |    assert (flags == 0); | ||||||
|  | -  debug ("%s: flush", b->name);
 | ||||||
|  | +  datapath_debug ("%s: flush", b->name);
 | ||||||
|  |   | ||||||
|  |    r = b->flush (b, conn, h->handle, flags, err); | ||||||
|  |    if (r == -1) | ||||||
|  | @@ -518,8 +534,8 @@ backend_trim (struct backend *b, struct connection *conn,
 | ||||||
|  |    assert (!(flags & ~NBDKIT_FLAG_FUA)); | ||||||
|  |    if (fua) | ||||||
|  |      assert (h->can_fua > NBDKIT_FUA_NONE); | ||||||
|  | -  debug ("%s: trim count=%" PRIu32 " offset=%" PRIu64 " fua=%d",
 | ||||||
|  | -         b->name, count, offset, fua);
 | ||||||
|  | +  datapath_debug ("%s: trim count=%" PRIu32 " offset=%" PRIu64 " fua=%d",
 | ||||||
|  | +                  b->name, count, offset, fua);
 | ||||||
|  |   | ||||||
|  |    r = b->trim (b, conn, h->handle, count, offset, flags, err); | ||||||
|  |    if (r == -1) | ||||||
|  | @@ -547,9 +563,10 @@ backend_zero (struct backend *b, struct connection *conn,
 | ||||||
|  |      assert (h->can_fua > NBDKIT_FUA_NONE); | ||||||
|  |    if (fast) | ||||||
|  |      assert (h->can_fast_zero == 1); | ||||||
|  | -  debug ("%s: zero count=%" PRIu32 " offset=%" PRIu64
 | ||||||
|  | -         " may_trim=%d fua=%d fast=%d",
 | ||||||
|  | -         b->name, count, offset, !!(flags & NBDKIT_FLAG_MAY_TRIM), fua, fast);
 | ||||||
|  | +  datapath_debug ("%s: zero count=%" PRIu32 " offset=%" PRIu64
 | ||||||
|  | +                  " may_trim=%d fua=%d fast=%d",
 | ||||||
|  | +                  b->name, count, offset,
 | ||||||
|  | +                  !!(flags & NBDKIT_FLAG_MAY_TRIM), fua, fast);
 | ||||||
|  |   | ||||||
|  |    r = b->zero (b, conn, h->handle, count, offset, flags, err); | ||||||
|  |    if (r == -1) { | ||||||
|  | @@ -572,8 +589,8 @@ backend_extents (struct backend *b, struct connection *conn,
 | ||||||
|  |    assert (h->can_extents >= 0); | ||||||
|  |    assert (backend_valid_range (b, conn, offset, count)); | ||||||
|  |    assert (!(flags & ~NBDKIT_FLAG_REQ_ONE)); | ||||||
|  | -  debug ("%s: extents count=%" PRIu32 " offset=%" PRIu64 " req_one=%d",
 | ||||||
|  | -         b->name, count, offset, !!(flags & NBDKIT_FLAG_REQ_ONE));
 | ||||||
|  | +  datapath_debug ("%s: extents count=%" PRIu32 " offset=%" PRIu64 " req_one=%d",
 | ||||||
|  | +                  b->name, count, offset, !!(flags & NBDKIT_FLAG_REQ_ONE));
 | ||||||
|  |   | ||||||
|  |    if (h->can_extents == 0) { | ||||||
|  |      /* By default it is safe assume that everything in the range is | ||||||
|  | @@ -602,8 +619,8 @@ backend_cache (struct backend *b, struct connection *conn,
 | ||||||
|  |    assert (h->can_cache > NBDKIT_CACHE_NONE); | ||||||
|  |    assert (backend_valid_range (b, conn, offset, count)); | ||||||
|  |    assert (flags == 0); | ||||||
|  | -  debug ("%s: cache count=%" PRIu32 " offset=%" PRIu64,
 | ||||||
|  | -         b->name, count, offset);
 | ||||||
|  | +  datapath_debug ("%s: cache count=%" PRIu32 " offset=%" PRIu64,
 | ||||||
|  | +                  b->name, count, offset);
 | ||||||
|  |   | ||||||
|  |    if (h->can_cache == NBDKIT_CACHE_EMULATE) { | ||||||
|  |      static char buf[MAX_REQUEST_SIZE]; /* data sink, never read */ | ||||||
|  | diff --git a/tests/Makefile.am b/tests/Makefile.am
 | ||||||
|  | index 0134197..d225cc6 100644
 | ||||||
|  | --- a/tests/Makefile.am
 | ||||||
|  | +++ b/tests/Makefile.am
 | ||||||
|  | @@ -135,6 +135,7 @@ EXTRA_DIST = \
 | ||||||
|  |  	test-nbd-extents.sh \ | ||||||
|  |  	test-nbd-tls.sh \ | ||||||
|  |  	test-nbd-tls-psk.sh \ | ||||||
|  | +	test-nbdkit-backend-debug.sh \
 | ||||||
|  |  	test-nozero.sh \ | ||||||
|  |  	test-null-extents.sh \ | ||||||
|  |  	test_ocaml_plugin.ml \ | ||||||
|  | @@ -746,6 +747,9 @@ endif HAVE_VDDK
 | ||||||
|  |  # zero plugin test. | ||||||
|  |  TESTS += test-zero.sh | ||||||
|  |   | ||||||
|  | +# -D nbdkit.backend.* settings.
 | ||||||
|  | +TESTS += test-nbdkit-backend-debug.sh
 | ||||||
|  | +
 | ||||||
|  |  #---------------------------------------------------------------------- | ||||||
|  |  # Tests of language plugins. | ||||||
|  |   | ||||||
|  | diff --git a/tests/test-nbdkit-backend-debug.sh b/tests/test-nbdkit-backend-debug.sh
 | ||||||
|  | new file mode 100755 | ||||||
|  | index 0000000..69a69a7
 | ||||||
|  | --- /dev/null
 | ||||||
|  | +++ b/tests/test-nbdkit-backend-debug.sh
 | ||||||
|  | @@ -0,0 +1,70 @@
 | ||||||
|  | +#!/usr/bin/env bash
 | ||||||
|  | +# nbdkit
 | ||||||
|  | +# Copyright (C) 2019 Red Hat Inc.
 | ||||||
|  | +#
 | ||||||
|  | +# Redistribution and use in source and binary forms, with or without
 | ||||||
|  | +# modification, are permitted provided that the following conditions are
 | ||||||
|  | +# met:
 | ||||||
|  | +#
 | ||||||
|  | +# * Redistributions of source code must retain the above copyright
 | ||||||
|  | +# notice, this list of conditions and the following disclaimer.
 | ||||||
|  | +#
 | ||||||
|  | +# * Redistributions in binary form must reproduce the above copyright
 | ||||||
|  | +# notice, this list of conditions and the following disclaimer in the
 | ||||||
|  | +# documentation and/or other materials provided with the distribution.
 | ||||||
|  | +#
 | ||||||
|  | +# * Neither the name of Red Hat nor the names of its contributors may be
 | ||||||
|  | +# used to endorse or promote products derived from this software without
 | ||||||
|  | +# specific prior written permission.
 | ||||||
|  | +#
 | ||||||
|  | +# THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND
 | ||||||
|  | +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 | ||||||
|  | +# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 | ||||||
|  | +# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR
 | ||||||
|  | +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | ||||||
|  | +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | ||||||
|  | +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 | ||||||
|  | +# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 | ||||||
|  | +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 | ||||||
|  | +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 | ||||||
|  | +# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 | ||||||
|  | +# SUCH DAMAGE.
 | ||||||
|  | +
 | ||||||
|  | +source ./functions.sh
 | ||||||
|  | +set -x
 | ||||||
|  | +set -e
 | ||||||
|  | +
 | ||||||
|  | +requires qemu-img --version
 | ||||||
|  | +
 | ||||||
|  | +out="test-nbdkit-backend-debug.out"
 | ||||||
|  | +debug="test-nbdkit-backend-debug.debug"
 | ||||||
|  | +files="$out $debug"
 | ||||||
|  | +rm -f $files
 | ||||||
|  | +cleanup_fn rm -f $files
 | ||||||
|  | +
 | ||||||
|  | +nbdkit -U - \
 | ||||||
|  | +       -v \
 | ||||||
|  | +       memory 10M \
 | ||||||
|  | +       --run "qemu-img convert \$nbd $out" |& tee $debug
 | ||||||
|  | +
 | ||||||
|  | +# Should contain all debugging messages.
 | ||||||
|  | +grep '^nbdkit:.*debug: memory: open' $debug
 | ||||||
|  | +grep '^nbdkit:.*debug: memory: pread' $debug
 | ||||||
|  | +
 | ||||||
|  | +nbdkit -U - \
 | ||||||
|  | +       -v -D nbdkit.backend.controlpath=0 \
 | ||||||
|  | +       memory 10M \
 | ||||||
|  | +       --run "qemu-img convert \$nbd $out" |& tee $debug
 | ||||||
|  | +
 | ||||||
|  | +# Should contain only datapath messages.
 | ||||||
|  | +grep -v '^nbdkit:.*debug: memory: open' $debug
 | ||||||
|  | +grep '^nbdkit:.*debug: memory: pread' $debug
 | ||||||
|  | +
 | ||||||
|  | +nbdkit -U - \
 | ||||||
|  | +       -v -D nbdkit.backend.datapath=0 \
 | ||||||
|  | +       memory 10M \
 | ||||||
|  | +       --run "qemu-img convert \$nbd $out" |& tee $debug
 | ||||||
|  | +
 | ||||||
|  | +# Should contain only controlpath messages.
 | ||||||
|  | +grep '^nbdkit:.*debug: memory: open' $debug
 | ||||||
|  | +grep -v '^nbdkit:.*debug: memory: pread' $debug
 | ||||||
|  | -- 
 | ||||||
|  | 2.18.2 | ||||||
|  | 
 | ||||||
							
								
								
									
										65
									
								
								SOURCES/0004-python-Add-various-constants-to-the-API.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								SOURCES/0004-python-Add-various-constants-to-the-API.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,65 @@ | |||||||
|  | From b646050b8da51c39cf21f95fa847c12784a1169c Mon Sep 17 00:00:00 2001 | ||||||
|  | From: "Richard W.M. Jones" <rjones@redhat.com> | ||||||
|  | Date: Thu, 21 Nov 2019 15:02:44 +0000 | ||||||
|  | Subject: [PATCH] python: Add various constants to the API. | ||||||
|  | 
 | ||||||
|  | These are accessible from the plugin by: | ||||||
|  | 
 | ||||||
|  |   import nbdkit | ||||||
|  | 
 | ||||||
|  |   if flags & nbdkit.FLAG_MAY_TRIM: | ||||||
|  |   &c. | ||||||
|  | 
 | ||||||
|  | Many (all?) of these are not yet useful for plugins, some will never | ||||||
|  | be useful, but they only consume a tiny bit of memory and it's nice to | ||||||
|  | have the complete set available for future use. | ||||||
|  | 
 | ||||||
|  | (cherry picked from commit 14b7fe2e0de881e3dfc8803484ade29a61e323c9) | ||||||
|  | ---
 | ||||||
|  |  plugins/python/python.c | 30 ++++++++++++++++++++++++++++++ | ||||||
|  |  1 file changed, 30 insertions(+) | ||||||
|  | 
 | ||||||
|  | diff --git a/plugins/python/python.c b/plugins/python/python.c
 | ||||||
|  | index 7052aac..47da083 100644
 | ||||||
|  | --- a/plugins/python/python.c
 | ||||||
|  | +++ b/plugins/python/python.c
 | ||||||
|  | @@ -231,6 +231,36 @@ create_nbdkit_module (void)
 | ||||||
|  |      nbdkit_error ("could not create the nbdkit API module"); | ||||||
|  |      exit (EXIT_FAILURE); | ||||||
|  |    } | ||||||
|  | +
 | ||||||
|  | +  /* Constants corresponding to various flags. */
 | ||||||
|  | +#define ADD_INT_CONSTANT(name)                                      \
 | ||||||
|  | +  if (PyModule_AddIntConstant (m, #name, NBDKIT_##name) == -1) {    \
 | ||||||
|  | +    nbdkit_error ("could not add constant %s to nbdkit API module", \
 | ||||||
|  | +                  #name);                                           \
 | ||||||
|  | +    exit (EXIT_FAILURE);                                            \
 | ||||||
|  | +  }
 | ||||||
|  | +  ADD_INT_CONSTANT (THREAD_MODEL_SERIALIZE_CONNECTIONS);
 | ||||||
|  | +  ADD_INT_CONSTANT (THREAD_MODEL_SERIALIZE_ALL_REQUESTS);
 | ||||||
|  | +  ADD_INT_CONSTANT (THREAD_MODEL_SERIALIZE_REQUESTS);
 | ||||||
|  | +  ADD_INT_CONSTANT (THREAD_MODEL_PARALLEL);
 | ||||||
|  | +
 | ||||||
|  | +  ADD_INT_CONSTANT (FLAG_MAY_TRIM);
 | ||||||
|  | +  ADD_INT_CONSTANT (FLAG_FUA);
 | ||||||
|  | +  ADD_INT_CONSTANT (FLAG_REQ_ONE);
 | ||||||
|  | +  ADD_INT_CONSTANT (FLAG_FAST_ZERO);
 | ||||||
|  | +
 | ||||||
|  | +  ADD_INT_CONSTANT (FUA_NONE);
 | ||||||
|  | +  ADD_INT_CONSTANT (FUA_EMULATE);
 | ||||||
|  | +  ADD_INT_CONSTANT (FUA_NATIVE);
 | ||||||
|  | +
 | ||||||
|  | +  ADD_INT_CONSTANT (CACHE_NONE);
 | ||||||
|  | +  ADD_INT_CONSTANT (CACHE_EMULATE);
 | ||||||
|  | +  ADD_INT_CONSTANT (CACHE_NATIVE);
 | ||||||
|  | +
 | ||||||
|  | +  ADD_INT_CONSTANT (EXTENT_HOLE);
 | ||||||
|  | +  ADD_INT_CONSTANT (EXTENT_ZERO);
 | ||||||
|  | +#undef ADD_INT_CONSTANT
 | ||||||
|  | +
 | ||||||
|  |    return m; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | -- 
 | ||||||
|  | 2.18.2 | ||||||
|  | 
 | ||||||
							
								
								
									
										558
									
								
								SOURCES/0005-python-Implement-nbdkit-API-version-2.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										558
									
								
								SOURCES/0005-python-Implement-nbdkit-API-version-2.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,558 @@ | |||||||
|  | From 49ef7e7d7c3602cc8e53d2052fce9d3a12840ea2 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: "Richard W.M. Jones" <rjones@redhat.com> | ||||||
|  | Date: Thu, 21 Nov 2019 15:44:39 +0000 | ||||||
|  | Subject: [PATCH] python: Implement nbdkit API version 2. | ||||||
|  | 
 | ||||||
|  | To avoid breaking existing plugins, Python plugins wishing to use | ||||||
|  | version 2 of the API must opt in by declaring: | ||||||
|  | 
 | ||||||
|  |   API_VERSION = 2 | ||||||
|  | 
 | ||||||
|  | (Plugins which do not do this are assumed to want API version 1). | ||||||
|  | 
 | ||||||
|  | For v2 API, we also avoid a copy by passing a buffer into pread. | ||||||
|  | 
 | ||||||
|  | It's more efficient if we pass the C buffer directly to Python code. | ||||||
|  | In some cases the Python code will be able to write directly into the | ||||||
|  | C buffer using functions like file.readinto and socket.recv_into. | ||||||
|  | This avoids an extra copy. | ||||||
|  | 
 | ||||||
|  | Thanks: Nir Soffer | ||||||
|  | https://www.redhat.com/archives/libguestfs/2019-November/thread.html#00220 | ||||||
|  | (cherry picked from commit a9b2637cf4f00fb8a25ffaf31ee83be5fe019ae2) | ||||||
|  | ---
 | ||||||
|  |  plugins/python/example.py               |  20 +++- | ||||||
|  |  plugins/python/nbdkit-python-plugin.pod |  69 +++++++----- | ||||||
|  |  plugins/python/python.c                 | 139 +++++++++++++++++++----- | ||||||
|  |  tests/python-exception.py               |   4 +- | ||||||
|  |  tests/shebang.py                        |   5 +- | ||||||
|  |  tests/test.py                           |  28 +++-- | ||||||
|  |  6 files changed, 190 insertions(+), 75 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/plugins/python/example.py b/plugins/python/example.py
 | ||||||
|  | index 60f9d7f..c04b7e2 100644
 | ||||||
|  | --- a/plugins/python/example.py
 | ||||||
|  | +++ b/plugins/python/example.py
 | ||||||
|  | @@ -34,6 +34,12 @@ import errno
 | ||||||
|  |  disk = bytearray(1024 * 1024) | ||||||
|  |   | ||||||
|  |   | ||||||
|  | +# There are several variants of the API.  nbdkit will call this
 | ||||||
|  | +# function first to determine which one you want to use.  This is the
 | ||||||
|  | +# latest version at the time this example was written.
 | ||||||
|  | +API_VERSION = 2
 | ||||||
|  | +
 | ||||||
|  | +
 | ||||||
|  |  # This just prints the extra command line parameters, but real plugins | ||||||
|  |  # should parse them and reject any unknown parameters. | ||||||
|  |  def config(key, value): | ||||||
|  | @@ -54,20 +60,22 @@ def get_size(h):
 | ||||||
|  |      return len(disk) | ||||||
|  |   | ||||||
|  |   | ||||||
|  | -def pread(h, count, offset):
 | ||||||
|  | +def pread(h, buf, offset, flags):
 | ||||||
|  |      global disk | ||||||
|  | -    return disk[offset:offset+count]
 | ||||||
|  | +    end = offset + len(buf)
 | ||||||
|  | +    buf[:] = disk[offset:end]
 | ||||||
|  | +    # or if reading from a file you can use:
 | ||||||
|  | +    #f.readinto(buf)
 | ||||||
|  |   | ||||||
|  | -
 | ||||||
|  | -def pwrite(h, buf, offset):
 | ||||||
|  | +def pwrite(h, buf, offset, flags):
 | ||||||
|  |      global disk | ||||||
|  |      end = offset + len(buf) | ||||||
|  |      disk[offset:end] = buf | ||||||
|  |   | ||||||
|  |   | ||||||
|  | -def zero(h, count, offset, may_trim):
 | ||||||
|  | +def zero(h, count, offset, flags):
 | ||||||
|  |      global disk | ||||||
|  | -    if may_trim:
 | ||||||
|  | +    if flags & nbdkit.FLAG_MAY_TRIM:
 | ||||||
|  |          disk[offset:offset+count] = bytearray(count) | ||||||
|  |      else: | ||||||
|  |          nbdkit.set_error(errno.EOPNOTSUPP) | ||||||
|  | diff --git a/plugins/python/nbdkit-python-plugin.pod b/plugins/python/nbdkit-python-plugin.pod
 | ||||||
|  | index 3680fd6..4923d9d 100644
 | ||||||
|  | --- a/plugins/python/nbdkit-python-plugin.pod
 | ||||||
|  | +++ b/plugins/python/nbdkit-python-plugin.pod
 | ||||||
|  | @@ -33,11 +33,12 @@ To write a Python nbdkit plugin, you create a Python file which
 | ||||||
|  |  contains at least the following required functions (in the top level | ||||||
|  |  C<__main__> module): | ||||||
|  |   | ||||||
|  | + API_VERSION = 2
 | ||||||
|  |   def open(readonly): | ||||||
|  |     # see below | ||||||
|  |   def get_size(h): | ||||||
|  |     # see below | ||||||
|  | - def pread(h, count, offset):
 | ||||||
|  | + def pread(h, buf, offset, flags):
 | ||||||
|  |     # see below | ||||||
|  |   | ||||||
|  |  Note that the subroutines must have those literal names (like C<open>), | ||||||
|  | @@ -82,6 +83,18 @@ I<--dump-plugin> option, eg:
 | ||||||
|  |   python_version=3.7.0 | ||||||
|  |   python_pep_384_abi_version=3 | ||||||
|  |   | ||||||
|  | +=head2 API versions
 | ||||||
|  | +
 | ||||||
|  | +The nbdkit API has evolved and new versions are released periodically.
 | ||||||
|  | +To ensure backwards compatibility plugins have to opt in to the new
 | ||||||
|  | +version.  From Python you do this by declaring a constant in your
 | ||||||
|  | +module:
 | ||||||
|  | +
 | ||||||
|  | + API_VERSION = 2
 | ||||||
|  | +
 | ||||||
|  | +(where 2 is the latest version at the time this documentation was
 | ||||||
|  | +written).  All newly written Python modules must have this constant.
 | ||||||
|  | +
 | ||||||
|  |  =head2 Executable script | ||||||
|  |   | ||||||
|  |  If you want you can make the script executable and include a "shebang" | ||||||
|  | @@ -199,16 +212,12 @@ contents will be garbage collected.
 | ||||||
|  |   | ||||||
|  |  (Required) | ||||||
|  |   | ||||||
|  | - def pread(h, count, offset):
 | ||||||
|  | -   # construct a buffer of length count bytes and return it
 | ||||||
|  | + def pread(h, buf, offset, flags):
 | ||||||
|  | +   # read into the buffer
 | ||||||
|  |   | ||||||
|  | -The body of your C<pread> function should construct a buffer of length
 | ||||||
|  | -(at least) C<count> bytes.  You should read C<count> bytes from the
 | ||||||
|  | -disk starting at C<offset>.
 | ||||||
|  | -
 | ||||||
|  | -The returned buffer can be any type compatible with the Python 3
 | ||||||
|  | -buffer protocol, such as bytearray, bytes or memoryview
 | ||||||
|  | -(L<https://docs.python.org/3/c-api/buffer.html>)
 | ||||||
|  | +The body of your C<pread> function should read exactly C<len(buf)>
 | ||||||
|  | +bytes of data starting at disk C<offset> and write it into the buffer
 | ||||||
|  | +C<buf>.  C<flags> is always 0.
 | ||||||
|  |   | ||||||
|  |  NBD only supports whole reads, so your function should try to read | ||||||
|  |  the whole region (perhaps requiring a loop).  If the read fails or | ||||||
|  | @@ -219,13 +228,13 @@ C<nbdkit.set_error> first.
 | ||||||
|  |   | ||||||
|  |  (Optional) | ||||||
|  |   | ||||||
|  | - def pwrite(h, buf, offset):
 | ||||||
|  | + def pwrite(h, buf, offset, flags):
 | ||||||
|  |     length = len (buf) | ||||||
|  |     # no return value | ||||||
|  |   | ||||||
|  |  The body of your C<pwrite> function should write the buffer C<buf> to | ||||||
|  |  the disk.  You should write C<count> bytes to the disk starting at | ||||||
|  | -C<offset>.
 | ||||||
|  | +C<offset>.  C<flags> may contain C<nbdkit.FLAG_FUA>.
 | ||||||
|  |   | ||||||
|  |  NBD only supports whole writes, so your function should try to | ||||||
|  |  write the whole region (perhaps requiring a loop).  If the write | ||||||
|  | @@ -236,11 +245,12 @@ fails or is partial, your function should throw an exception,
 | ||||||
|  |   | ||||||
|  |  (Optional) | ||||||
|  |   | ||||||
|  | - def flush(h):
 | ||||||
|  | + def flush(h, flags):
 | ||||||
|  |     # no return value | ||||||
|  |   | ||||||
|  |  The body of your C<flush> function should do a L<sync(2)> or | ||||||
|  |  L<fdatasync(2)> or equivalent on the backing store. | ||||||
|  | +C<flags> is always 0.
 | ||||||
|  |   | ||||||
|  |  If the flush fails, your function should throw an exception, optionally | ||||||
|  |  using C<nbdkit.set_error> first. | ||||||
|  | @@ -249,32 +259,35 @@ using C<nbdkit.set_error> first.
 | ||||||
|  |   | ||||||
|  |  (Optional) | ||||||
|  |   | ||||||
|  | - def trim(h, count, offset):
 | ||||||
|  | + def trim(h, count, offset, flags):
 | ||||||
|  |     # no return value | ||||||
|  |   | ||||||
|  | -The body of your C<trim> function should "punch a hole" in the
 | ||||||
|  | -backing store.  If the trim fails, your function should throw an
 | ||||||
|  | -exception, optionally using C<nbdkit.set_error> first.
 | ||||||
|  | +The body of your C<trim> function should "punch a hole" in the backing
 | ||||||
|  | +store.  C<flags> may contain C<nbdkit.FLAG_FUA>.  If the trim fails,
 | ||||||
|  | +your function should throw an exception, optionally using
 | ||||||
|  | +C<nbdkit.set_error> first.
 | ||||||
|  |   | ||||||
|  |  =item C<zero> | ||||||
|  |   | ||||||
|  |  (Optional) | ||||||
|  |   | ||||||
|  | - def zero(h, count, offset, may_trim):
 | ||||||
|  | + def zero(h, count, offset, flags):
 | ||||||
|  |     # no return value | ||||||
|  |   | ||||||
|  | -The body of your C<zero> function should ensure that C<count> bytes
 | ||||||
|  | -of the disk, starting at C<offset>, will read back as zero.  If
 | ||||||
|  | -C<may_trim> is true, the operation may be optimized as a trim as long
 | ||||||
|  | -as subsequent reads see zeroes.
 | ||||||
|  | +The body of your C<zero> function should ensure that C<count> bytes of
 | ||||||
|  | +the disk, starting at C<offset>, will read back as zero.  C<flags> is
 | ||||||
|  | +a bitmask which may include C<nbdkit.FLAG_MAY_TRIM>,
 | ||||||
|  | +C<nbdkit.FLAG_FUA>, C<nbdkit.FLAG_FAST_ZERO>.
 | ||||||
|  |   | ||||||
|  |  NBD only supports whole writes, so your function should try to | ||||||
|  | -write the whole region (perhaps requiring a loop).  If the write
 | ||||||
|  | -fails or is partial, your function should throw an exception,
 | ||||||
|  | -optionally using C<nbdkit.set_error> first.  In particular, if
 | ||||||
|  | -you would like to automatically fall back to C<pwrite> (perhaps
 | ||||||
|  | -because there is nothing to optimize if C<may_trim> is false),
 | ||||||
|  | -use C<nbdkit.set_error(errno.EOPNOTSUPP)>.
 | ||||||
|  | +write the whole region (perhaps requiring a loop).
 | ||||||
|  | +
 | ||||||
|  | +If the write fails or is partial, your function should throw an
 | ||||||
|  | +exception, optionally using C<nbdkit.set_error> first.  In particular,
 | ||||||
|  | +if you would like to automatically fall back to C<pwrite> (perhaps
 | ||||||
|  | +because there is nothing to optimize if
 | ||||||
|  | +S<C<flags & nbdkit.FLAG_MAY_TRIM>> is false), use
 | ||||||
|  | +S<C<nbdkit.set_error (errno.EOPNOTSUPP)>>.
 | ||||||
|  |   | ||||||
|  |  =back | ||||||
|  |   | ||||||
|  | diff --git a/plugins/python/python.c b/plugins/python/python.c
 | ||||||
|  | index 47da083..0f28595 100644
 | ||||||
|  | --- a/plugins/python/python.c
 | ||||||
|  | +++ b/plugins/python/python.c
 | ||||||
|  | @@ -46,6 +46,8 @@
 | ||||||
|  |  #define PY_SSIZE_T_CLEAN 1 | ||||||
|  |  #include <Python.h> | ||||||
|  |   | ||||||
|  | +#define NBDKIT_API_VERSION 2
 | ||||||
|  | +
 | ||||||
|  |  #include <nbdkit-plugin.h> | ||||||
|  |   | ||||||
|  |  #include "cleanup.h" | ||||||
|  | @@ -60,6 +62,7 @@
 | ||||||
|  |   */ | ||||||
|  |  static const char *script; | ||||||
|  |  static PyObject *module; | ||||||
|  | +static int py_api_version = 1;
 | ||||||
|  |   | ||||||
|  |  static int last_error; | ||||||
|  |   | ||||||
|  | @@ -285,9 +288,14 @@ py_dump_plugin (void)
 | ||||||
|  |    PyObject *fn; | ||||||
|  |    PyObject *r; | ||||||
|  |   | ||||||
|  | +  /* Python version and ABI. */
 | ||||||
|  |    printf ("python_version=%s\n", PY_VERSION); | ||||||
|  |    printf ("python_pep_384_abi_version=%d\n", PYTHON_ABI_VERSION); | ||||||
|  |   | ||||||
|  | +  /* Maximum nbdkit API version supported. */
 | ||||||
|  | +  printf ("nbdkit_python_maximum_api_version=%d\n", NBDKIT_API_VERSION);
 | ||||||
|  | +
 | ||||||
|  | +  /* If the script has a dump_plugin function, call it. */
 | ||||||
|  |    if (script && callback_defined ("dump_plugin", &fn)) { | ||||||
|  |      PyErr_Clear (); | ||||||
|  |   | ||||||
|  | @@ -297,6 +305,30 @@ py_dump_plugin (void)
 | ||||||
|  |    } | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +static int
 | ||||||
|  | +get_py_api_version (void)
 | ||||||
|  | +{
 | ||||||
|  | +  PyObject *obj;
 | ||||||
|  | +  long value;
 | ||||||
|  | +
 | ||||||
|  | +  obj = PyObject_GetAttrString (module, "API_VERSION");
 | ||||||
|  | +  if (obj == NULL)
 | ||||||
|  | +    return 1;                   /* Default to API version 1. */
 | ||||||
|  | +
 | ||||||
|  | +  value = PyLong_AsLong (obj);
 | ||||||
|  | +  Py_DECREF (obj);
 | ||||||
|  | +
 | ||||||
|  | +  if (value < 1 || value > NBDKIT_API_VERSION) {
 | ||||||
|  | +    nbdkit_error ("%s: API_VERSION requested unknown version: %ld.  "
 | ||||||
|  | +                  "This plugin supports API versions between 1 and %d.",
 | ||||||
|  | +                  script, value, NBDKIT_API_VERSION);
 | ||||||
|  | +    return -1;
 | ||||||
|  | +  }
 | ||||||
|  | +
 | ||||||
|  | +  nbdkit_debug ("module requested API_VERSION %ld", value);
 | ||||||
|  | +  return (int) value;
 | ||||||
|  | +}
 | ||||||
|  | +
 | ||||||
|  |  static int | ||||||
|  |  py_config (const char *key, const char *value) | ||||||
|  |  { | ||||||
|  | @@ -359,6 +391,11 @@ py_config (const char *key, const char *value)
 | ||||||
|  |                      "nbdkit requires these callbacks.", script); | ||||||
|  |        return -1; | ||||||
|  |      } | ||||||
|  | +
 | ||||||
|  | +    /* Get the API version. */
 | ||||||
|  | +    py_api_version = get_py_api_version ();
 | ||||||
|  | +    if (py_api_version == -1)
 | ||||||
|  | +      return -1;
 | ||||||
|  |    } | ||||||
|  |    else if (callback_defined ("config", &fn)) { | ||||||
|  |      /* Other parameters are passed to the Python .config callback. */ | ||||||
|  | @@ -469,8 +506,8 @@ py_get_size (void *handle)
 | ||||||
|  |  } | ||||||
|  |   | ||||||
|  |  static int | ||||||
|  | -py_pread (void *handle, void *buf,
 | ||||||
|  | -          uint32_t count, uint64_t offset)
 | ||||||
|  | +py_pread (void *handle, void *buf, uint32_t count, uint64_t offset,
 | ||||||
|  | +          uint32_t flags)
 | ||||||
|  |  { | ||||||
|  |    PyObject *obj = handle; | ||||||
|  |    PyObject *fn; | ||||||
|  | @@ -485,24 +522,40 @@ py_pread (void *handle, void *buf,
 | ||||||
|  |   | ||||||
|  |    PyErr_Clear (); | ||||||
|  |   | ||||||
|  | -  r = PyObject_CallFunction (fn, "OiL", obj, count, offset);
 | ||||||
|  | +  switch (py_api_version) {
 | ||||||
|  | +  case 1:
 | ||||||
|  | +    r = PyObject_CallFunction (fn, "OiL", obj, count, offset);
 | ||||||
|  | +    break;
 | ||||||
|  | +  case 2:
 | ||||||
|  | +    r = PyObject_CallFunction (fn, "ONLI", obj,
 | ||||||
|  | +          PyMemoryView_FromMemory ((char *)buf, count, PyBUF_WRITE),
 | ||||||
|  | +          offset, flags);
 | ||||||
|  | +    break;
 | ||||||
|  | +  default: abort ();
 | ||||||
|  | +  }
 | ||||||
|  |    Py_DECREF (fn); | ||||||
|  |    if (check_python_failure ("pread") == -1) | ||||||
|  |      return ret; | ||||||
|  |   | ||||||
|  | -  if (PyObject_GetBuffer (r, &view, PyBUF_SIMPLE) == -1) {
 | ||||||
|  | -    nbdkit_error ("%s: value returned from pread does not support the "
 | ||||||
|  | -                  "buffer protocol",
 | ||||||
|  | -                  script);
 | ||||||
|  | -    goto out;
 | ||||||
|  | -  }
 | ||||||
|  | +  if (py_api_version == 1) {
 | ||||||
|  | +    /* In API v1 the Python pread function had to return a buffer
 | ||||||
|  | +     * protocol compatible function.  In API v2+ it writes directly to
 | ||||||
|  | +     * the C buffer so this code is not used.
 | ||||||
|  | +     */
 | ||||||
|  | +    if (PyObject_GetBuffer (r, &view, PyBUF_SIMPLE) == -1) {
 | ||||||
|  | +      nbdkit_error ("%s: value returned from pread does not support the "
 | ||||||
|  | +                    "buffer protocol",
 | ||||||
|  | +                    script);
 | ||||||
|  | +      goto out;
 | ||||||
|  | +    }
 | ||||||
|  |   | ||||||
|  | -  if (view.len < count) {
 | ||||||
|  | -    nbdkit_error ("%s: buffer returned from pread is too small", script);
 | ||||||
|  | -    goto out;
 | ||||||
|  | -  }
 | ||||||
|  | +    if (view.len < count) {
 | ||||||
|  | +      nbdkit_error ("%s: buffer returned from pread is too small", script);
 | ||||||
|  | +      goto out;
 | ||||||
|  | +    }
 | ||||||
|  |   | ||||||
|  | -  memcpy (buf, view.buf, count);
 | ||||||
|  | +    memcpy (buf, view.buf, count);
 | ||||||
|  | +  }
 | ||||||
|  |    ret = 0; | ||||||
|  |   | ||||||
|  |  out: | ||||||
|  | @@ -515,8 +568,8 @@ out:
 | ||||||
|  |  } | ||||||
|  |   | ||||||
|  |  static int | ||||||
|  | -py_pwrite (void *handle, const void *buf,
 | ||||||
|  | -           uint32_t count, uint64_t offset)
 | ||||||
|  | +py_pwrite (void *handle, const void *buf, uint32_t count, uint64_t offset,
 | ||||||
|  | +           uint32_t flags)
 | ||||||
|  |  { | ||||||
|  |    PyObject *obj = handle; | ||||||
|  |    PyObject *fn; | ||||||
|  | @@ -525,9 +578,19 @@ py_pwrite (void *handle, const void *buf,
 | ||||||
|  |    if (callback_defined ("pwrite", &fn)) { | ||||||
|  |      PyErr_Clear (); | ||||||
|  |   | ||||||
|  | -    r = PyObject_CallFunction (fn, "ONL", obj,
 | ||||||
|  | +    switch (py_api_version) {
 | ||||||
|  | +    case 1:
 | ||||||
|  | +      r = PyObject_CallFunction (fn, "ONL", obj,
 | ||||||
|  |              PyMemoryView_FromMemory ((char *)buf, count, PyBUF_READ), | ||||||
|  |              offset); | ||||||
|  | +      break;
 | ||||||
|  | +    case 2:
 | ||||||
|  | +      r = PyObject_CallFunction (fn, "ONLI", obj,
 | ||||||
|  | +            PyMemoryView_FromMemory ((char *)buf, count, PyBUF_READ),
 | ||||||
|  | +            offset, flags);
 | ||||||
|  | +      break;
 | ||||||
|  | +    default: abort ();
 | ||||||
|  | +    }
 | ||||||
|  |      Py_DECREF (fn); | ||||||
|  |      if (check_python_failure ("pwrite") == -1) | ||||||
|  |        return -1; | ||||||
|  | @@ -542,7 +605,7 @@ py_pwrite (void *handle, const void *buf,
 | ||||||
|  |  } | ||||||
|  |   | ||||||
|  |  static int | ||||||
|  | -py_flush (void *handle)
 | ||||||
|  | +py_flush (void *handle, uint32_t flags)
 | ||||||
|  |  { | ||||||
|  |    PyObject *obj = handle; | ||||||
|  |    PyObject *fn; | ||||||
|  | @@ -551,7 +614,15 @@ py_flush (void *handle)
 | ||||||
|  |    if (callback_defined ("flush", &fn)) { | ||||||
|  |      PyErr_Clear (); | ||||||
|  |   | ||||||
|  | -    r = PyObject_CallFunctionObjArgs (fn, obj, NULL);
 | ||||||
|  | +    switch (py_api_version) {
 | ||||||
|  | +    case 1:
 | ||||||
|  | +      r = PyObject_CallFunctionObjArgs (fn, obj, NULL);
 | ||||||
|  | +      break;
 | ||||||
|  | +    case 2:
 | ||||||
|  | +      r = PyObject_CallFunction (fn, "OI", obj, flags);
 | ||||||
|  | +      break;
 | ||||||
|  | +    default: abort ();
 | ||||||
|  | +    }
 | ||||||
|  |      Py_DECREF (fn); | ||||||
|  |      if (check_python_failure ("flush") == -1) | ||||||
|  |        return -1; | ||||||
|  | @@ -566,7 +637,7 @@ py_flush (void *handle)
 | ||||||
|  |  } | ||||||
|  |   | ||||||
|  |  static int | ||||||
|  | -py_trim (void *handle, uint32_t count, uint64_t offset)
 | ||||||
|  | +py_trim (void *handle, uint32_t count, uint64_t offset, uint32_t flags)
 | ||||||
|  |  { | ||||||
|  |    PyObject *obj = handle; | ||||||
|  |    PyObject *fn; | ||||||
|  | @@ -575,7 +646,15 @@ py_trim (void *handle, uint32_t count, uint64_t offset)
 | ||||||
|  |    if (callback_defined ("trim", &fn)) { | ||||||
|  |      PyErr_Clear (); | ||||||
|  |   | ||||||
|  | -    r = PyObject_CallFunction (fn, "OiL", obj, count, offset);
 | ||||||
|  | +    switch (py_api_version) {
 | ||||||
|  | +    case 1:
 | ||||||
|  | +      r = PyObject_CallFunction (fn, "OiL", obj, count, offset);
 | ||||||
|  | +      break;
 | ||||||
|  | +    case 2:
 | ||||||
|  | +      r = PyObject_CallFunction (fn, "OiLI", obj, count, offset, flags);
 | ||||||
|  | +      break;
 | ||||||
|  | +    default: abort ();
 | ||||||
|  | +    }
 | ||||||
|  |      Py_DECREF (fn); | ||||||
|  |      if (check_python_failure ("trim") == -1) | ||||||
|  |        return -1; | ||||||
|  | @@ -590,7 +669,7 @@ py_trim (void *handle, uint32_t count, uint64_t offset)
 | ||||||
|  |  } | ||||||
|  |   | ||||||
|  |  static int | ||||||
|  | -py_zero (void *handle, uint32_t count, uint64_t offset, int may_trim)
 | ||||||
|  | +py_zero (void *handle, uint32_t count, uint64_t offset, uint32_t flags)
 | ||||||
|  |  { | ||||||
|  |    PyObject *obj = handle; | ||||||
|  |    PyObject *fn; | ||||||
|  | @@ -600,9 +679,19 @@ py_zero (void *handle, uint32_t count, uint64_t offset, int may_trim)
 | ||||||
|  |      PyErr_Clear (); | ||||||
|  |   | ||||||
|  |      last_error = 0; | ||||||
|  | -    r = PyObject_CallFunction (fn, "OiLO",
 | ||||||
|  | -                               obj, count, offset,
 | ||||||
|  | -                               may_trim ? Py_True : Py_False);
 | ||||||
|  | +    switch (py_api_version) {
 | ||||||
|  | +    case 1: {
 | ||||||
|  | +      int may_trim = flags & NBDKIT_FLAG_MAY_TRIM;
 | ||||||
|  | +      r = PyObject_CallFunction (fn, "OiLO",
 | ||||||
|  | +                                 obj, count, offset,
 | ||||||
|  | +                                 may_trim ? Py_True : Py_False);
 | ||||||
|  | +      break;
 | ||||||
|  | +    }
 | ||||||
|  | +    case 2:
 | ||||||
|  | +      r = PyObject_CallFunction (fn, "OiLI", obj, count, offset, flags);
 | ||||||
|  | +      break;
 | ||||||
|  | +    default: abort ();
 | ||||||
|  | +    }
 | ||||||
|  |      Py_DECREF (fn); | ||||||
|  |      if (last_error == EOPNOTSUPP || last_error == ENOTSUP) { | ||||||
|  |        /* When user requests this particular error, we want to | ||||||
|  | diff --git a/tests/python-exception.py b/tests/python-exception.py
 | ||||||
|  | index d0c79bb..ee4a3f3 100644
 | ||||||
|  | --- a/tests/python-exception.py
 | ||||||
|  | +++ b/tests/python-exception.py
 | ||||||
|  | @@ -62,5 +62,5 @@ def get_size(h):
 | ||||||
|  |      return 0 | ||||||
|  |   | ||||||
|  |   | ||||||
|  | -def pread(h, count, offset):
 | ||||||
|  | -    return ""
 | ||||||
|  | +def pread(h, buf, offset):
 | ||||||
|  | +    buf[:] = bytearray(len(buf))
 | ||||||
|  | diff --git a/tests/shebang.py b/tests/shebang.py
 | ||||||
|  | index 6f33623..0634589 100755
 | ||||||
|  | --- a/tests/shebang.py
 | ||||||
|  | +++ b/tests/shebang.py
 | ||||||
|  | @@ -13,6 +13,7 @@ def get_size(h):
 | ||||||
|  |      return len(disk) | ||||||
|  |   | ||||||
|  |   | ||||||
|  | -def pread(h, count, offset):
 | ||||||
|  | +def pread(h, buf, offset):
 | ||||||
|  |      global disk | ||||||
|  | -    return disk[offset:offset+count]
 | ||||||
|  | +    end = offset + len(buf)
 | ||||||
|  | +    buf[:] = disk[offset:end]
 | ||||||
|  | diff --git a/tests/test.py b/tests/test.py
 | ||||||
|  | index 9a2e947..4db5662 100644
 | ||||||
|  | --- a/tests/test.py
 | ||||||
|  | +++ b/tests/test.py
 | ||||||
|  | @@ -3,6 +3,9 @@ import nbdkit
 | ||||||
|  |  disk = bytearray(1024*1024) | ||||||
|  |   | ||||||
|  |   | ||||||
|  | +API_VERSION = 2
 | ||||||
|  | +
 | ||||||
|  | +
 | ||||||
|  |  def config_complete(): | ||||||
|  |      print ("set_error = %r" % nbdkit.set_error) | ||||||
|  |   | ||||||
|  | @@ -32,25 +35,26 @@ def can_trim(h):
 | ||||||
|  |      return True | ||||||
|  |   | ||||||
|  |   | ||||||
|  | -def pread(h, count, offset):
 | ||||||
|  | +def pread(h, buf, offset, flags):
 | ||||||
|  |      global disk | ||||||
|  | -    return disk[offset:offset+count]
 | ||||||
|  | +    end = offset + len(buf)
 | ||||||
|  | +    buf[:] = disk[offset:end]
 | ||||||
|  |   | ||||||
|  |   | ||||||
|  | -def pwrite(h, buf, offset):
 | ||||||
|  | +def pwrite(h, buf, offset, flags):
 | ||||||
|  |      global disk | ||||||
|  |      end = offset + len(buf) | ||||||
|  |      disk[offset:end] = buf | ||||||
|  |   | ||||||
|  |   | ||||||
|  | -def zero(h, count, offset, may_trim=False):
 | ||||||
|  | +def flush(h, flags):
 | ||||||
|  | +    pass
 | ||||||
|  | +
 | ||||||
|  | +
 | ||||||
|  | +def trim(h, count, offset, flags):
 | ||||||
|  | +    pass
 | ||||||
|  | +
 | ||||||
|  | +
 | ||||||
|  | +def zero(h, count, offset, flags):
 | ||||||
|  |      global disk | ||||||
|  |      disk[offset:offset+count] = bytearray(count) | ||||||
|  | -
 | ||||||
|  | -
 | ||||||
|  | -def flush(h):
 | ||||||
|  | -    pass
 | ||||||
|  | -
 | ||||||
|  | -
 | ||||||
|  | -def trim(h, count, offset):
 | ||||||
|  | -    pass
 | ||||||
|  | -- 
 | ||||||
|  | 2.18.2 | ||||||
|  | 
 | ||||||
							
								
								
									
										98
									
								
								SOURCES/0006-python-Implement-cache.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										98
									
								
								SOURCES/0006-python-Implement-cache.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,98 @@ | |||||||
|  | From c5b1fac4c67078f0164bd23eab6d4d2b8c9830b0 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: "Richard W.M. Jones" <rjones@redhat.com> | ||||||
|  | Date: Thu, 21 Nov 2019 16:42:02 +0000 | ||||||
|  | Subject: [PATCH] python: Implement cache. | ||||||
|  | 
 | ||||||
|  | However this does not implement can_cache, since that is not a simple | ||||||
|  | boolean. | ||||||
|  | 
 | ||||||
|  | (cherry picked from commit e61ffb73c7a0af0c383184fdb8f08d30784a195e) | ||||||
|  | ---
 | ||||||
|  |  plugins/python/nbdkit-python-plugin.pod | 14 ++++++++++- | ||||||
|  |  plugins/python/python.c                 | 31 +++++++++++++++++++++++++ | ||||||
|  |  2 files changed, 44 insertions(+), 1 deletion(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/plugins/python/nbdkit-python-plugin.pod b/plugins/python/nbdkit-python-plugin.pod
 | ||||||
|  | index 4923d9d..0ea8dee 100644
 | ||||||
|  | --- a/plugins/python/nbdkit-python-plugin.pod
 | ||||||
|  | +++ b/plugins/python/nbdkit-python-plugin.pod
 | ||||||
|  | @@ -289,6 +289,19 @@ because there is nothing to optimize if
 | ||||||
|  |  S<C<flags & nbdkit.FLAG_MAY_TRIM>> is false), use | ||||||
|  |  S<C<nbdkit.set_error (errno.EOPNOTSUPP)>>. | ||||||
|  |   | ||||||
|  | +=item C<cache>
 | ||||||
|  | +
 | ||||||
|  | +(Optional)
 | ||||||
|  | +
 | ||||||
|  | + def cache(h, count, offset, flags):
 | ||||||
|  | +   # no return value
 | ||||||
|  | +
 | ||||||
|  | +The body of your C<cache> function should prefetch data in the
 | ||||||
|  | +indicated range.
 | ||||||
|  | +
 | ||||||
|  | +If the cache operation fails, your function should throw an exception,
 | ||||||
|  | +optionally using C<nbdkit.set_error> first.
 | ||||||
|  | +
 | ||||||
|  |  =back | ||||||
|  |   | ||||||
|  |  =head2 Missing callbacks | ||||||
|  | @@ -317,7 +330,6 @@ C<can_zero>,
 | ||||||
|  |  C<can_fast_zero>, | ||||||
|  |  C<can_extents>, | ||||||
|  |  C<can_multi_conn>, | ||||||
|  | -C<cache>,
 | ||||||
|  |  C<extents>. | ||||||
|  |   | ||||||
|  |  These are not yet supported. | ||||||
|  | diff --git a/plugins/python/python.c b/plugins/python/python.c
 | ||||||
|  | index 0f28595..c5cf38e 100644
 | ||||||
|  | --- a/plugins/python/python.c
 | ||||||
|  | +++ b/plugins/python/python.c
 | ||||||
|  | @@ -714,6 +714,36 @@ py_zero (void *handle, uint32_t count, uint64_t offset, uint32_t flags)
 | ||||||
|  |    return -1; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +static int
 | ||||||
|  | +py_cache (void *handle, uint32_t count, uint64_t offset, uint32_t flags)
 | ||||||
|  | +{
 | ||||||
|  | +  PyObject *obj = handle;
 | ||||||
|  | +  PyObject *fn;
 | ||||||
|  | +  PyObject *r;
 | ||||||
|  | +
 | ||||||
|  | +  if (callback_defined ("cache", &fn)) {
 | ||||||
|  | +    PyErr_Clear ();
 | ||||||
|  | +
 | ||||||
|  | +    switch (py_api_version) {
 | ||||||
|  | +    case 1:
 | ||||||
|  | +    case 2:
 | ||||||
|  | +      r = PyObject_CallFunction (fn, "OiLI", obj, count, offset, flags, NULL);
 | ||||||
|  | +      break;
 | ||||||
|  | +    default: abort ();
 | ||||||
|  | +    }
 | ||||||
|  | +    Py_DECREF (fn);
 | ||||||
|  | +    if (check_python_failure ("cache") == -1)
 | ||||||
|  | +      return -1;
 | ||||||
|  | +    Py_DECREF (r);
 | ||||||
|  | +  }
 | ||||||
|  | +  else {
 | ||||||
|  | +    nbdkit_error ("%s not implemented", "cache");
 | ||||||
|  | +    return -1;
 | ||||||
|  | +  }
 | ||||||
|  | +
 | ||||||
|  | +  return 0;
 | ||||||
|  | +}
 | ||||||
|  | +
 | ||||||
|  |  static int | ||||||
|  |  boolean_callback (void *handle, const char *can_fn, const char *plain_fn) | ||||||
|  |  { | ||||||
|  | @@ -799,6 +829,7 @@ static struct nbdkit_plugin plugin = {
 | ||||||
|  |    .flush             = py_flush, | ||||||
|  |    .trim              = py_trim, | ||||||
|  |    .zero              = py_zero, | ||||||
|  | +  .cache             = py_cache,
 | ||||||
|  |  }; | ||||||
|  |   | ||||||
|  |  NBDKIT_REGISTER_PLUGIN (plugin) | ||||||
|  | -- 
 | ||||||
|  | 2.18.2 | ||||||
|  | 
 | ||||||
							
								
								
									
										80
									
								
								SOURCES/0007-python-Implement-can_zero-can_fast_zero.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								SOURCES/0007-python-Implement-can_zero-can_fast_zero.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,80 @@ | |||||||
|  | From 17721b316dd66b0a1ed792eeccd2489fb97828df Mon Sep 17 00:00:00 2001 | ||||||
|  | From: "Richard W.M. Jones" <rjones@redhat.com> | ||||||
|  | Date: Thu, 21 Nov 2019 16:42:59 +0000 | ||||||
|  | Subject: [PATCH] python: Implement can_zero, can_fast_zero. | ||||||
|  | 
 | ||||||
|  | (cherry picked from commit 039f600d2ad7a9ff04523a165eb2fe41b9c87c01) | ||||||
|  | ---
 | ||||||
|  |  plugins/python/nbdkit-python-plugin.pod | 16 ++++++++++++++-- | ||||||
|  |  plugins/python/python.c                 | 14 ++++++++++++++ | ||||||
|  |  2 files changed, 28 insertions(+), 2 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/plugins/python/nbdkit-python-plugin.pod b/plugins/python/nbdkit-python-plugin.pod
 | ||||||
|  | index 0ea8dee..1f1c30f 100644
 | ||||||
|  | --- a/plugins/python/nbdkit-python-plugin.pod
 | ||||||
|  | +++ b/plugins/python/nbdkit-python-plugin.pod
 | ||||||
|  | @@ -208,6 +208,20 @@ contents will be garbage collected.
 | ||||||
|  |   def can_trim(h): | ||||||
|  |     # return a boolean | ||||||
|  |   | ||||||
|  | +=item C<can_zero>
 | ||||||
|  | +
 | ||||||
|  | +(Optional)
 | ||||||
|  | +
 | ||||||
|  | + def can_zero(h):
 | ||||||
|  | +   # return a boolean
 | ||||||
|  | +
 | ||||||
|  | +=item C<can_fast_zero>
 | ||||||
|  | +
 | ||||||
|  | +(Optional)
 | ||||||
|  | +
 | ||||||
|  | + def can_fast_zero(h):
 | ||||||
|  | +   # return a boolean
 | ||||||
|  | +
 | ||||||
|  |  =item C<pread> | ||||||
|  |   | ||||||
|  |  (Required) | ||||||
|  | @@ -326,8 +340,6 @@ C<config_help>,
 | ||||||
|  |  C<magic_config_key>, | ||||||
|  |  C<can_fua>, | ||||||
|  |  C<can_cache>, | ||||||
|  | -C<can_zero>,
 | ||||||
|  | -C<can_fast_zero>,
 | ||||||
|  |  C<can_extents>, | ||||||
|  |  C<can_multi_conn>, | ||||||
|  |  C<extents>. | ||||||
|  | diff --git a/plugins/python/python.c b/plugins/python/python.c
 | ||||||
|  | index c5cf38e..38fc119 100644
 | ||||||
|  | --- a/plugins/python/python.c
 | ||||||
|  | +++ b/plugins/python/python.c
 | ||||||
|  | @@ -797,6 +797,18 @@ py_can_trim (void *handle)
 | ||||||
|  |    return boolean_callback (handle, "can_trim", "trim"); | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +static int
 | ||||||
|  | +py_can_zero (void *handle)
 | ||||||
|  | +{
 | ||||||
|  | +  return boolean_callback (handle, "can_zero", "zero");
 | ||||||
|  | +}
 | ||||||
|  | +
 | ||||||
|  | +static int
 | ||||||
|  | +py_can_fast_zero (void *handle)
 | ||||||
|  | +{
 | ||||||
|  | +  return boolean_callback (handle, "can_fast_zero", NULL);
 | ||||||
|  | +}
 | ||||||
|  | +
 | ||||||
|  |  #define py_config_help \ | ||||||
|  |    "script=<FILENAME>     (required) The Python plugin to run.\n" \ | ||||||
|  |    "[other arguments may be used by the plugin that you load]" | ||||||
|  | @@ -823,6 +835,8 @@ static struct nbdkit_plugin plugin = {
 | ||||||
|  |    .can_write         = py_can_write, | ||||||
|  |    .can_flush         = py_can_flush, | ||||||
|  |    .can_trim          = py_can_trim, | ||||||
|  | +  .can_zero          = py_can_zero,
 | ||||||
|  | +  .can_fast_zero     = py_can_fast_zero,
 | ||||||
|  |   | ||||||
|  |    .pread             = py_pread, | ||||||
|  |    .pwrite            = py_pwrite, | ||||||
|  | -- 
 | ||||||
|  | 2.18.2 | ||||||
|  | 
 | ||||||
							
								
								
									
										65
									
								
								SOURCES/0008-python-Implement-can_multi_conn.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								SOURCES/0008-python-Implement-can_multi_conn.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,65 @@ | |||||||
|  | From 2a85ce81ad95eb2f9b2f29666480b814ea0f80d9 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: "Richard W.M. Jones" <rjones@redhat.com> | ||||||
|  | Date: Thu, 21 Nov 2019 16:46:11 +0000 | ||||||
|  | Subject: [PATCH] python: Implement can_multi_conn. | ||||||
|  | 
 | ||||||
|  | (cherry picked from commit 21dd7bf49d3238c7e75918d4bf324b617f458d83) | ||||||
|  | ---
 | ||||||
|  |  plugins/python/nbdkit-python-plugin.pod | 8 +++++++- | ||||||
|  |  plugins/python/python.c                 | 7 +++++++ | ||||||
|  |  2 files changed, 14 insertions(+), 1 deletion(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/plugins/python/nbdkit-python-plugin.pod b/plugins/python/nbdkit-python-plugin.pod
 | ||||||
|  | index 1f1c30f..b92bb56 100644
 | ||||||
|  | --- a/plugins/python/nbdkit-python-plugin.pod
 | ||||||
|  | +++ b/plugins/python/nbdkit-python-plugin.pod
 | ||||||
|  | @@ -187,6 +187,13 @@ contents will be garbage collected.
 | ||||||
|  |   def is_rotational(h): | ||||||
|  |     # return a boolean | ||||||
|  |   | ||||||
|  | +=item C<can_multi_conn>
 | ||||||
|  | +
 | ||||||
|  | +(Optional)
 | ||||||
|  | +
 | ||||||
|  | + def can_multi_conn(h):
 | ||||||
|  | +   # return a boolean
 | ||||||
|  | +
 | ||||||
|  |  =item C<can_write> | ||||||
|  |   | ||||||
|  |  (Optional) | ||||||
|  | @@ -341,7 +348,6 @@ C<magic_config_key>,
 | ||||||
|  |  C<can_fua>, | ||||||
|  |  C<can_cache>, | ||||||
|  |  C<can_extents>, | ||||||
|  | -C<can_multi_conn>,
 | ||||||
|  |  C<extents>. | ||||||
|  |   | ||||||
|  |  These are not yet supported. | ||||||
|  | diff --git a/plugins/python/python.c b/plugins/python/python.c
 | ||||||
|  | index 38fc119..b186b99 100644
 | ||||||
|  | --- a/plugins/python/python.c
 | ||||||
|  | +++ b/plugins/python/python.c
 | ||||||
|  | @@ -779,6 +779,12 @@ py_is_rotational (void *handle)
 | ||||||
|  |    return boolean_callback (handle, "is_rotational", NULL); | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +static int
 | ||||||
|  | +py_can_multi_conn (void *handle)
 | ||||||
|  | +{
 | ||||||
|  | +  return boolean_callback (handle, "can_multi_conn", NULL);
 | ||||||
|  | +}
 | ||||||
|  | +
 | ||||||
|  |  static int | ||||||
|  |  py_can_write (void *handle) | ||||||
|  |  { | ||||||
|  | @@ -832,6 +838,7 @@ static struct nbdkit_plugin plugin = {
 | ||||||
|  |   | ||||||
|  |    .get_size          = py_get_size, | ||||||
|  |    .is_rotational     = py_is_rotational, | ||||||
|  | +  .can_multi_conn    = py_can_multi_conn,
 | ||||||
|  |    .can_write         = py_can_write, | ||||||
|  |    .can_flush         = py_can_flush, | ||||||
|  |    .can_trim          = py_can_trim, | ||||||
|  | -- 
 | ||||||
|  | 2.18.2 | ||||||
|  | 
 | ||||||
							
								
								
									
										126
									
								
								SOURCES/0009-python-Implement-can_fua-and-can_cache.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										126
									
								
								SOURCES/0009-python-Implement-can_fua-and-can_cache.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,126 @@ | |||||||
|  | From 38124a137974e1433d68732640ca7f88664557da Mon Sep 17 00:00:00 2001 | ||||||
|  | From: "Richard W.M. Jones" <rjones@redhat.com> | ||||||
|  | Date: Fri, 22 Nov 2019 19:25:53 +0000 | ||||||
|  | Subject: [PATCH] python: Implement can_fua and can_cache. | ||||||
|  | 
 | ||||||
|  | (cherry picked from commit 97c46f885edec5a61a96ac86eccb9d8c874c602e) | ||||||
|  | ---
 | ||||||
|  |  plugins/python/nbdkit-python-plugin.pod | 18 +++++++- | ||||||
|  |  plugins/python/python.c                 | 58 +++++++++++++++++++++++++ | ||||||
|  |  2 files changed, 74 insertions(+), 2 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/plugins/python/nbdkit-python-plugin.pod b/plugins/python/nbdkit-python-plugin.pod
 | ||||||
|  | index b92bb56..4065ec7 100644
 | ||||||
|  | --- a/plugins/python/nbdkit-python-plugin.pod
 | ||||||
|  | +++ b/plugins/python/nbdkit-python-plugin.pod
 | ||||||
|  | @@ -229,6 +229,22 @@ contents will be garbage collected.
 | ||||||
|  |   def can_fast_zero(h): | ||||||
|  |     # return a boolean | ||||||
|  |   | ||||||
|  | +=item C<can_fua>
 | ||||||
|  | +
 | ||||||
|  | +(Optional)
 | ||||||
|  | +
 | ||||||
|  | + def can_fua(h):
 | ||||||
|  | +   # return nbdkit.FUA_NONE or nbdkit.FUA_EMULATE
 | ||||||
|  | +   # or nbdkit.FUA_NATIVE
 | ||||||
|  | +
 | ||||||
|  | +=item C<can_cache>
 | ||||||
|  | +
 | ||||||
|  | +(Optional)
 | ||||||
|  | +
 | ||||||
|  | + def can_cache(h):
 | ||||||
|  | +   # return nbdkit.CACHE_NONE or nbdkit.CACHE_EMULATE
 | ||||||
|  | +   # or nbdkit.CACHE_NATIVE
 | ||||||
|  | +
 | ||||||
|  |  =item C<pread> | ||||||
|  |   | ||||||
|  |  (Required) | ||||||
|  | @@ -345,8 +361,6 @@ C<longname>,
 | ||||||
|  |  C<description>, | ||||||
|  |  C<config_help>, | ||||||
|  |  C<magic_config_key>, | ||||||
|  | -C<can_fua>,
 | ||||||
|  | -C<can_cache>,
 | ||||||
|  |  C<can_extents>, | ||||||
|  |  C<extents>. | ||||||
|  |   | ||||||
|  | diff --git a/plugins/python/python.c b/plugins/python/python.c
 | ||||||
|  | index b186b99..5e2e526 100644
 | ||||||
|  | --- a/plugins/python/python.c
 | ||||||
|  | +++ b/plugins/python/python.c
 | ||||||
|  | @@ -815,6 +815,62 @@ py_can_fast_zero (void *handle)
 | ||||||
|  |    return boolean_callback (handle, "can_fast_zero", NULL); | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +static int
 | ||||||
|  | +py_can_fua (void *handle)
 | ||||||
|  | +{
 | ||||||
|  | +  PyObject *obj = handle;
 | ||||||
|  | +  PyObject *fn;
 | ||||||
|  | +  PyObject *r;
 | ||||||
|  | +  int ret;
 | ||||||
|  | +
 | ||||||
|  | +  if (callback_defined ("can_fua", &fn)) {
 | ||||||
|  | +    PyErr_Clear ();
 | ||||||
|  | +
 | ||||||
|  | +    r = PyObject_CallFunctionObjArgs (fn, obj, NULL);
 | ||||||
|  | +    Py_DECREF (fn);
 | ||||||
|  | +    if (check_python_failure ("can_fua") == -1)
 | ||||||
|  | +      return -1;
 | ||||||
|  | +    ret = PyLong_AsLong (r);
 | ||||||
|  | +    Py_DECREF (r);
 | ||||||
|  | +    return ret;
 | ||||||
|  | +  }
 | ||||||
|  | +  /* No Python ‘can_fua’, but check if there's a Python ‘flush’
 | ||||||
|  | +   * callback defined.  (In C modules, nbdkit would do this).
 | ||||||
|  | +   */
 | ||||||
|  | +  else if (callback_defined ("flush", NULL))
 | ||||||
|  | +    return NBDKIT_FUA_EMULATE;
 | ||||||
|  | +  else
 | ||||||
|  | +    return NBDKIT_FUA_NONE;
 | ||||||
|  | +}
 | ||||||
|  | +
 | ||||||
|  | +static int
 | ||||||
|  | +py_can_cache (void *handle)
 | ||||||
|  | +{
 | ||||||
|  | +  PyObject *obj = handle;
 | ||||||
|  | +  PyObject *fn;
 | ||||||
|  | +  PyObject *r;
 | ||||||
|  | +  int ret;
 | ||||||
|  | +
 | ||||||
|  | +  if (callback_defined ("can_cache", &fn)) {
 | ||||||
|  | +    PyErr_Clear ();
 | ||||||
|  | +
 | ||||||
|  | +    r = PyObject_CallFunctionObjArgs (fn, obj, NULL);
 | ||||||
|  | +    Py_DECREF (fn);
 | ||||||
|  | +    if (check_python_failure ("can_cache") == -1)
 | ||||||
|  | +      return -1;
 | ||||||
|  | +    ret = PyLong_AsLong (r);
 | ||||||
|  | +    Py_DECREF (r);
 | ||||||
|  | +    return ret;
 | ||||||
|  | +  }
 | ||||||
|  | +  /* No Python ‘can_cache’, but check if there's a Python ‘cache’
 | ||||||
|  | +   * callback defined.  (In C modules, nbdkit would do this).
 | ||||||
|  | +   */
 | ||||||
|  | +  else if (callback_defined ("cache", NULL))
 | ||||||
|  | +    return NBDKIT_CACHE_NATIVE;
 | ||||||
|  | +  else
 | ||||||
|  | +    return NBDKIT_CACHE_NONE;
 | ||||||
|  | +}
 | ||||||
|  | +
 | ||||||
|  |  #define py_config_help \ | ||||||
|  |    "script=<FILENAME>     (required) The Python plugin to run.\n" \ | ||||||
|  |    "[other arguments may be used by the plugin that you load]" | ||||||
|  | @@ -844,6 +900,8 @@ static struct nbdkit_plugin plugin = {
 | ||||||
|  |    .can_trim          = py_can_trim, | ||||||
|  |    .can_zero          = py_can_zero, | ||||||
|  |    .can_fast_zero     = py_can_fast_zero, | ||||||
|  | +  .can_fua           = py_can_fua,
 | ||||||
|  | +  .can_cache         = py_can_cache,
 | ||||||
|  |   | ||||||
|  |    .pread             = py_pread, | ||||||
|  |    .pwrite            = py_pwrite, | ||||||
|  | -- 
 | ||||||
|  | 2.18.2 | ||||||
|  | 
 | ||||||
							
								
								
									
										597
									
								
								SOURCES/0010-tests-Test-the-Python-plugin-thoroughly.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										597
									
								
								SOURCES/0010-tests-Test-the-Python-plugin-thoroughly.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,597 @@ | |||||||
|  | From 7cb79aef2a12f29f1286caf3858001e47214f871 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: "Richard W.M. Jones" <rjones@redhat.com> | ||||||
|  | Date: Thu, 21 Nov 2019 20:54:41 +0000 | ||||||
|  | Subject: [PATCH] tests: Test the Python plugin thoroughly. | ||||||
|  | 
 | ||||||
|  | This tests the Python plugin thoroughly by issuing client commands | ||||||
|  | through libnbd and checking we get the expected results. | ||||||
|  | 
 | ||||||
|  | (cherry picked from commit 8ead4a82ec3227dbecb6cbfc419f1a18f2817d62) | ||||||
|  | ---
 | ||||||
|  |  .gitignore                  |   1 + | ||||||
|  |  README                      |   2 + | ||||||
|  |  tests/Makefile.am           |  15 +-- | ||||||
|  |  tests/test-lang-plugins.c   |   3 +- | ||||||
|  |  tests/test-python-plugin.py | 133 +++++++++++++++++++++ | ||||||
|  |  tests/test-python.sh        |  49 ++++++++ | ||||||
|  |  tests/test.py               |  60 ---------- | ||||||
|  |  tests/test_python.py        | 222 ++++++++++++++++++++++++++++++++++++ | ||||||
|  |  8 files changed, 413 insertions(+), 72 deletions(-) | ||||||
|  |  create mode 100644 tests/test-python-plugin.py | ||||||
|  |  create mode 100755 tests/test-python.sh | ||||||
|  |  delete mode 100644 tests/test.py | ||||||
|  |  create mode 100755 tests/test_python.py | ||||||
|  | 
 | ||||||
|  | diff --git a/.gitignore b/.gitignore
 | ||||||
|  | index b25ac7f..e25bd99 100644
 | ||||||
|  | --- a/.gitignore
 | ||||||
|  | +++ b/.gitignore
 | ||||||
|  | @@ -71,6 +71,7 @@ Makefile.in
 | ||||||
|  |  /server/synopsis.c | ||||||
|  |  /server/test-public | ||||||
|  |  /stamp-h1 | ||||||
|  | +/tests/__pycache__/
 | ||||||
|  |  /tests/disk | ||||||
|  |  /tests/disk.gz | ||||||
|  |  /tests/disk.xz | ||||||
|  | diff --git a/README b/README
 | ||||||
|  | index 40f4cd3..05f1e06 100644
 | ||||||
|  | --- a/README
 | ||||||
|  | +++ b/README
 | ||||||
|  | @@ -130,6 +130,8 @@ For the Python plugin:
 | ||||||
|  |   | ||||||
|  |   - python development libraries | ||||||
|  |   | ||||||
|  | + - python unittest to run the test suite
 | ||||||
|  | +
 | ||||||
|  |  For the OCaml plugin: | ||||||
|  |   | ||||||
|  |   - OCaml >= 4.02.2 | ||||||
|  | diff --git a/tests/Makefile.am b/tests/Makefile.am
 | ||||||
|  | index d225cc6..09103fb 100644
 | ||||||
|  | --- a/tests/Makefile.am
 | ||||||
|  | +++ b/tests/Makefile.am
 | ||||||
|  | @@ -67,6 +67,7 @@ EXTRA_PROGRAMS =
 | ||||||
|  |  TESTS_ENVIRONMENT = \ | ||||||
|  |  	PATH=$(abs_top_builddir):$(PATH) \ | ||||||
|  |  	SRCDIR=$(srcdir) \ | ||||||
|  | +	PYTHON=$(PYTHON) \
 | ||||||
|  |  	LIBGUESTFS_ATTACH_METHOD=appliance \ | ||||||
|  |  	LIBGUESTFS_DEBUG=1 \ | ||||||
|  |  	LIBGUESTFS_TRACE=1 \ | ||||||
|  | @@ -160,7 +161,9 @@ EXTRA_DIST = \
 | ||||||
|  |  	test-probe-plugin.sh \ | ||||||
|  |  	test-python-exception.sh \ | ||||||
|  |  	test.pl \ | ||||||
|  | -	test.py \
 | ||||||
|  | +	test_python.py \
 | ||||||
|  | +	test-python-plugin.py \
 | ||||||
|  | +	test-python.sh \
 | ||||||
|  |  	test-rate.sh \ | ||||||
|  |  	test-rate-dynamic.sh \ | ||||||
|  |  	test.rb \ | ||||||
|  | @@ -801,18 +804,10 @@ endif HAVE_PERL
 | ||||||
|  |  if HAVE_PYTHON | ||||||
|  |   | ||||||
|  |  TESTS += \ | ||||||
|  | +	test-python.sh \
 | ||||||
|  |  	test-python-exception.sh \ | ||||||
|  |  	test-shebang-python.sh \ | ||||||
|  |  	$(NULL) | ||||||
|  | -LIBGUESTFS_TESTS += test-python
 | ||||||
|  | -
 | ||||||
|  | -test_python_SOURCES = test-lang-plugins.c test.h
 | ||||||
|  | -test_python_CFLAGS = \
 | ||||||
|  | -	-DLANG='"python"' -DSCRIPT='"$(srcdir)/test.py"' \
 | ||||||
|  | -	$(WARNINGS_CFLAGS) \
 | ||||||
|  | -	$(LIBGUESTFS_CFLAGS) \
 | ||||||
|  | -	$(NULL)
 | ||||||
|  | -test_python_LDADD = libtest.la $(LIBGUESTFS_LIBS)
 | ||||||
|  |   | ||||||
|  |  endif HAVE_PYTHON | ||||||
|  |   | ||||||
|  | diff --git a/tests/test-lang-plugins.c b/tests/test-lang-plugins.c
 | ||||||
|  | index ffb1918..93f9938 100644
 | ||||||
|  | --- a/tests/test-lang-plugins.c
 | ||||||
|  | +++ b/tests/test-lang-plugins.c
 | ||||||
|  | @@ -56,8 +56,7 @@ main (int argc, char *argv[])
 | ||||||
|  |     */ | ||||||
|  |    s = getenv ("NBDKIT_VALGRIND"); | ||||||
|  |    if (s && strcmp (s, "1") == 0 && | ||||||
|  | -      (strcmp (LANG, "python") == 0 ||
 | ||||||
|  | -       strcmp (LANG, "ruby") == 0 ||
 | ||||||
|  | +      (strcmp (LANG, "ruby") == 0 ||
 | ||||||
|  |         strcmp (LANG, "tcl") == 0)) { | ||||||
|  |      fprintf (stderr, "%s test skipped under valgrind.\n", LANG); | ||||||
|  |      exit (77);                  /* Tells automake to skip the test. */ | ||||||
|  | diff --git a/tests/test-python-plugin.py b/tests/test-python-plugin.py
 | ||||||
|  | new file mode 100644 | ||||||
|  | index 0000000..8e90bc2
 | ||||||
|  | --- /dev/null
 | ||||||
|  | +++ b/tests/test-python-plugin.py
 | ||||||
|  | @@ -0,0 +1,133 @@
 | ||||||
|  | +# nbdkit test plugin
 | ||||||
|  | +# Copyright (C) 2019 Red Hat Inc.
 | ||||||
|  | +#
 | ||||||
|  | +# Redistribution and use in source and binary forms, with or without
 | ||||||
|  | +# modification, are permitted provided that the following conditions are
 | ||||||
|  | +# met:
 | ||||||
|  | +#
 | ||||||
|  | +# * Redistributions of source code must retain the above copyright
 | ||||||
|  | +# notice, this list of conditions and the following disclaimer.
 | ||||||
|  | +#
 | ||||||
|  | +# * Redistributions in binary form must reproduce the above copyright
 | ||||||
|  | +# notice, this list of conditions and the following disclaimer in the
 | ||||||
|  | +# documentation and/or other materials provided with the distribution.
 | ||||||
|  | +#
 | ||||||
|  | +# * Neither the name of Red Hat nor the names of its contributors may be
 | ||||||
|  | +# used to endorse or promote products derived from this software without
 | ||||||
|  | +# specific prior written permission.
 | ||||||
|  | +#
 | ||||||
|  | +# THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND
 | ||||||
|  | +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 | ||||||
|  | +# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 | ||||||
|  | +# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR
 | ||||||
|  | +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | ||||||
|  | +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | ||||||
|  | +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 | ||||||
|  | +# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 | ||||||
|  | +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 | ||||||
|  | +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 | ||||||
|  | +# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 | ||||||
|  | +# SUCH DAMAGE.
 | ||||||
|  | +
 | ||||||
|  | +"""See test-python.py."""
 | ||||||
|  | +
 | ||||||
|  | +import nbdkit
 | ||||||
|  | +import sys
 | ||||||
|  | +import pickle
 | ||||||
|  | +import base64
 | ||||||
|  | +
 | ||||||
|  | +API_VERSION = 2
 | ||||||
|  | +
 | ||||||
|  | +cfg = {}
 | ||||||
|  | +
 | ||||||
|  | +def config (k, v):
 | ||||||
|  | +    global cfg
 | ||||||
|  | +    if k == "cfg":
 | ||||||
|  | +        cfg = pickle.loads (base64.b64decode (v.encode()))
 | ||||||
|  | +
 | ||||||
|  | +def config_complete ():
 | ||||||
|  | +    print ("set_error = %r" % nbdkit.set_error)
 | ||||||
|  | +
 | ||||||
|  | +def open (readonly):
 | ||||||
|  | +    return {
 | ||||||
|  | +        'disk': bytearray (cfg.get ('size', 0))
 | ||||||
|  | +    }
 | ||||||
|  | +
 | ||||||
|  | +def get_size (h):
 | ||||||
|  | +    return len (h['disk'])
 | ||||||
|  | +
 | ||||||
|  | +def is_rotational (h):
 | ||||||
|  | +    return cfg.get ('is_rotational', False)
 | ||||||
|  | +
 | ||||||
|  | +def can_multi_conn (h):
 | ||||||
|  | +    return cfg.get ('can_multi_conn', False)
 | ||||||
|  | +
 | ||||||
|  | +def can_write (h):
 | ||||||
|  | +    return cfg.get ('can_write', True)
 | ||||||
|  | +
 | ||||||
|  | +def can_flush (h):
 | ||||||
|  | +    return cfg.get ('can_flush', False)
 | ||||||
|  | +
 | ||||||
|  | +def can_trim (h):
 | ||||||
|  | +    return cfg.get ('can_trim', False)
 | ||||||
|  | +
 | ||||||
|  | +def can_zero (h):
 | ||||||
|  | +    return cfg.get ('can_zero', False)
 | ||||||
|  | +
 | ||||||
|  | +def can_fast_zero (h):
 | ||||||
|  | +    return cfg.get ('can_fast_zero', False)
 | ||||||
|  | +
 | ||||||
|  | +def can_fua (h):
 | ||||||
|  | +    fua = cfg.get ('can_fua', "none")
 | ||||||
|  | +    if fua == "none":
 | ||||||
|  | +        return nbdkit.FUA_NONE
 | ||||||
|  | +    elif fua == "emulate":
 | ||||||
|  | +        return nbdkit.FUA_EMULATE
 | ||||||
|  | +    elif fua == "native":
 | ||||||
|  | +        return nbdkit.FUA_NATIVE
 | ||||||
|  | +
 | ||||||
|  | +def can_cache (h):
 | ||||||
|  | +    cache = cfg.get ('can_cache', "none")
 | ||||||
|  | +    if cache == "none":
 | ||||||
|  | +        return nbdkit.CACHE_NONE
 | ||||||
|  | +    elif cache == "emulate":
 | ||||||
|  | +        return nbdkit.CACHE_EMULATE
 | ||||||
|  | +    elif cache == "native":
 | ||||||
|  | +        return nbdkit.CACHE_NATIVE
 | ||||||
|  | +
 | ||||||
|  | +def pread (h, buf, offset, flags):
 | ||||||
|  | +    assert flags == 0
 | ||||||
|  | +    end = offset + len(buf)
 | ||||||
|  | +    buf[:] = h['disk'][offset:end]
 | ||||||
|  | +
 | ||||||
|  | +def pwrite (h, buf, offset, flags):
 | ||||||
|  | +    expect_fua = cfg.get ('pwrite_expect_fua', False)
 | ||||||
|  | +    actual_fua = bool (flags & nbdkit.FLAG_FUA)
 | ||||||
|  | +    assert expect_fua == actual_fua
 | ||||||
|  | +    end = offset + len(buf)
 | ||||||
|  | +    h['disk'][offset:end] = buf
 | ||||||
|  | +
 | ||||||
|  | +def flush (h, flags):
 | ||||||
|  | +    assert flags == 0
 | ||||||
|  | +
 | ||||||
|  | +def trim (h, count, offset, flags):
 | ||||||
|  | +    expect_fua = cfg.get ('trim_expect_fua', False)
 | ||||||
|  | +    actual_fua = bool (flags & nbdkit.FLAG_FUA)
 | ||||||
|  | +    assert expect_fua == actual_fua
 | ||||||
|  | +    h['disk'][offset:offset+count] = bytearray(count)
 | ||||||
|  | +
 | ||||||
|  | +def zero (h, count, offset, flags):
 | ||||||
|  | +    expect_fua = cfg.get ('zero_expect_fua', False)
 | ||||||
|  | +    actual_fua = bool (flags & nbdkit.FLAG_FUA)
 | ||||||
|  | +    assert expect_fua == actual_fua
 | ||||||
|  | +    expect_may_trim = cfg.get ('zero_expect_may_trim', False)
 | ||||||
|  | +    actual_may_trim = bool (flags & nbdkit.FLAG_MAY_TRIM)
 | ||||||
|  | +    assert expect_may_trim == actual_may_trim
 | ||||||
|  | +    expect_fast_zero = cfg.get ('zero_expect_fast_zero', False)
 | ||||||
|  | +    actual_fast_zero = bool (flags & nbdkit.FLAG_FAST_ZERO)
 | ||||||
|  | +    assert expect_fast_zero == actual_fast_zero
 | ||||||
|  | +    h['disk'][offset:offset+count] = bytearray(count)
 | ||||||
|  | +
 | ||||||
|  | +def cache (h, count, offset, flags):
 | ||||||
|  | +    assert flags == 0
 | ||||||
|  | +    # do nothing
 | ||||||
|  | diff --git a/tests/test-python.sh b/tests/test-python.sh
 | ||||||
|  | new file mode 100755 | ||||||
|  | index 0000000..50324d0
 | ||||||
|  | --- /dev/null
 | ||||||
|  | +++ b/tests/test-python.sh
 | ||||||
|  | @@ -0,0 +1,49 @@
 | ||||||
|  | +#!/usr/bin/env bash
 | ||||||
|  | +# nbdkit
 | ||||||
|  | +# Copyright (C) 2019 Red Hat Inc.
 | ||||||
|  | +#
 | ||||||
|  | +# Redistribution and use in source and binary forms, with or without
 | ||||||
|  | +# modification, are permitted provided that the following conditions are
 | ||||||
|  | +# met:
 | ||||||
|  | +#
 | ||||||
|  | +# * Redistributions of source code must retain the above copyright
 | ||||||
|  | +# notice, this list of conditions and the following disclaimer.
 | ||||||
|  | +#
 | ||||||
|  | +# * Redistributions in binary form must reproduce the above copyright
 | ||||||
|  | +# notice, this list of conditions and the following disclaimer in the
 | ||||||
|  | +# documentation and/or other materials provided with the distribution.
 | ||||||
|  | +#
 | ||||||
|  | +# * Neither the name of Red Hat nor the names of its contributors may be
 | ||||||
|  | +# used to endorse or promote products derived from this software without
 | ||||||
|  | +# specific prior written permission.
 | ||||||
|  | +#
 | ||||||
|  | +# THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND
 | ||||||
|  | +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 | ||||||
|  | +# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 | ||||||
|  | +# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR
 | ||||||
|  | +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | ||||||
|  | +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | ||||||
|  | +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 | ||||||
|  | +# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 | ||||||
|  | +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 | ||||||
|  | +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 | ||||||
|  | +# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 | ||||||
|  | +# SUCH DAMAGE.
 | ||||||
|  | +
 | ||||||
|  | +source ./functions.sh
 | ||||||
|  | +set -e
 | ||||||
|  | +set -x
 | ||||||
|  | +
 | ||||||
|  | +requires $PYTHON --version
 | ||||||
|  | +requires $PYTHON -c 'import unittest'
 | ||||||
|  | +requires $PYTHON -c 'import nbd'
 | ||||||
|  | +requires test -f test_python.py
 | ||||||
|  | +requires test -f test-python-plugin.py
 | ||||||
|  | +
 | ||||||
|  | +# Python has proven very difficult to valgrind, therefore it is disabled.
 | ||||||
|  | +if [ "$NBDKIT_VALGRIND" = "1" ]; then
 | ||||||
|  | +    echo "$0: skipping Python test under valgrind."
 | ||||||
|  | +    exit 77
 | ||||||
|  | +fi
 | ||||||
|  | +
 | ||||||
|  | +$PYTHON -m unittest test_python
 | ||||||
|  | diff --git a/tests/test.py b/tests/test.py
 | ||||||
|  | deleted file mode 100644 | ||||||
|  | index 4db5662..0000000
 | ||||||
|  | --- a/tests/test.py
 | ||||||
|  | +++ /dev/null
 | ||||||
|  | @@ -1,60 +0,0 @@
 | ||||||
|  | -import nbdkit
 | ||||||
|  | -
 | ||||||
|  | -disk = bytearray(1024*1024)
 | ||||||
|  | -
 | ||||||
|  | -
 | ||||||
|  | -API_VERSION = 2
 | ||||||
|  | -
 | ||||||
|  | -
 | ||||||
|  | -def config_complete():
 | ||||||
|  | -    print ("set_error = %r" % nbdkit.set_error)
 | ||||||
|  | -
 | ||||||
|  | -
 | ||||||
|  | -def open(readonly):
 | ||||||
|  | -    return 1
 | ||||||
|  | -
 | ||||||
|  | -
 | ||||||
|  | -def get_size(h):
 | ||||||
|  | -    global disk
 | ||||||
|  | -    return len(disk)
 | ||||||
|  | -
 | ||||||
|  | -
 | ||||||
|  | -def can_write(h):
 | ||||||
|  | -    return True
 | ||||||
|  | -
 | ||||||
|  | -
 | ||||||
|  | -def can_flush(h):
 | ||||||
|  | -    return True
 | ||||||
|  | -
 | ||||||
|  | -
 | ||||||
|  | -def is_rotational(h):
 | ||||||
|  | -    return False
 | ||||||
|  | -
 | ||||||
|  | -
 | ||||||
|  | -def can_trim(h):
 | ||||||
|  | -    return True
 | ||||||
|  | -
 | ||||||
|  | -
 | ||||||
|  | -def pread(h, buf, offset, flags):
 | ||||||
|  | -    global disk
 | ||||||
|  | -    end = offset + len(buf)
 | ||||||
|  | -    buf[:] = disk[offset:end]
 | ||||||
|  | -
 | ||||||
|  | -
 | ||||||
|  | -def pwrite(h, buf, offset, flags):
 | ||||||
|  | -    global disk
 | ||||||
|  | -    end = offset + len(buf)
 | ||||||
|  | -    disk[offset:end] = buf
 | ||||||
|  | -
 | ||||||
|  | -
 | ||||||
|  | -def flush(h, flags):
 | ||||||
|  | -    pass
 | ||||||
|  | -
 | ||||||
|  | -
 | ||||||
|  | -def trim(h, count, offset, flags):
 | ||||||
|  | -    pass
 | ||||||
|  | -
 | ||||||
|  | -
 | ||||||
|  | -def zero(h, count, offset, flags):
 | ||||||
|  | -    global disk
 | ||||||
|  | -    disk[offset:offset+count] = bytearray(count)
 | ||||||
|  | diff --git a/tests/test_python.py b/tests/test_python.py
 | ||||||
|  | new file mode 100755 | ||||||
|  | index 0000000..6b9f297
 | ||||||
|  | --- /dev/null
 | ||||||
|  | +++ b/tests/test_python.py
 | ||||||
|  | @@ -0,0 +1,222 @@
 | ||||||
|  | +#!/usr/bin/env python3
 | ||||||
|  | +# nbdkit
 | ||||||
|  | +# Copyright (C) 2019 Red Hat Inc.
 | ||||||
|  | +#
 | ||||||
|  | +# Redistribution and use in source and binary forms, with or without
 | ||||||
|  | +# modification, are permitted provided that the following conditions are
 | ||||||
|  | +# met:
 | ||||||
|  | +#
 | ||||||
|  | +# * Redistributions of source code must retain the above copyright
 | ||||||
|  | +# notice, this list of conditions and the following disclaimer.
 | ||||||
|  | +#
 | ||||||
|  | +# * Redistributions in binary form must reproduce the above copyright
 | ||||||
|  | +# notice, this list of conditions and the following disclaimer in the
 | ||||||
|  | +# documentation and/or other materials provided with the distribution.
 | ||||||
|  | +#
 | ||||||
|  | +# * Neither the name of Red Hat nor the names of its contributors may be
 | ||||||
|  | +# used to endorse or promote products derived from this software without
 | ||||||
|  | +# specific prior written permission.
 | ||||||
|  | +#
 | ||||||
|  | +# THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND
 | ||||||
|  | +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 | ||||||
|  | +# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 | ||||||
|  | +# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR
 | ||||||
|  | +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | ||||||
|  | +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | ||||||
|  | +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 | ||||||
|  | +# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 | ||||||
|  | +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 | ||||||
|  | +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 | ||||||
|  | +# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 | ||||||
|  | +# SUCH DAMAGE.
 | ||||||
|  | +
 | ||||||
|  | +"""
 | ||||||
|  | +This tests the Python plugin thoroughly by issuing client commands
 | ||||||
|  | +through libnbd and checking we get the expected results.  It uses an
 | ||||||
|  | +associated plugin (test-python-plugin.sh).
 | ||||||
|  | +"""
 | ||||||
|  | +
 | ||||||
|  | +import os
 | ||||||
|  | +import sys
 | ||||||
|  | +import nbd
 | ||||||
|  | +import unittest
 | ||||||
|  | +import pickle
 | ||||||
|  | +import base64
 | ||||||
|  | +
 | ||||||
|  | +class Test (unittest.TestCase):
 | ||||||
|  | +    def setUp (self):
 | ||||||
|  | +        self.h = nbd.NBD ()
 | ||||||
|  | +
 | ||||||
|  | +    def tearDown (self):
 | ||||||
|  | +        del self.h
 | ||||||
|  | +
 | ||||||
|  | +    def connect (self, cfg):
 | ||||||
|  | +        cfg = base64.b64encode (pickle.dumps (cfg)).decode()
 | ||||||
|  | +        cmd = ["nbdkit", "-v", "-s", "--exit-with-parent",
 | ||||||
|  | +               "python", "test-python-plugin.py", "cfg=" + cfg]
 | ||||||
|  | +        self.h.connect_command (cmd)
 | ||||||
|  | +
 | ||||||
|  | +    def test_none (self):
 | ||||||
|  | +        """
 | ||||||
|  | +        Test we can send an empty pickled test configuration and do
 | ||||||
|  | +        nothing else.  This is just to ensure the machinery of the
 | ||||||
|  | +        test works.
 | ||||||
|  | +        """
 | ||||||
|  | +        self.connect ({})
 | ||||||
|  | +
 | ||||||
|  | +    def test_size_512 (self):
 | ||||||
|  | +        """Test the size."""
 | ||||||
|  | +        self.connect ({"size": 512})
 | ||||||
|  | +        assert self.h.get_size() == 512
 | ||||||
|  | +
 | ||||||
|  | +    def test_size_1m (self):
 | ||||||
|  | +        """Test the size."""
 | ||||||
|  | +        self.connect ({"size": 1024*1024})
 | ||||||
|  | +        assert self.h.get_size() == 1024*1024
 | ||||||
|  | +
 | ||||||
|  | +    # Test each flag call.
 | ||||||
|  | +    def test_is_rotational_true (self):
 | ||||||
|  | +        self.connect ({"size": 512, "is_rotational": True})
 | ||||||
|  | +        assert self.h.is_rotational()
 | ||||||
|  | +
 | ||||||
|  | +    def test_is_rotational_false (self):
 | ||||||
|  | +        self.connect ({"size": 512, "is_rotational": False})
 | ||||||
|  | +        assert not self.h.is_rotational()
 | ||||||
|  | +
 | ||||||
|  | +    def test_can_multi_conn_true (self):
 | ||||||
|  | +        self.connect ({"size": 512, "can_multi_conn": True})
 | ||||||
|  | +        assert self.h.can_multi_conn()
 | ||||||
|  | +
 | ||||||
|  | +    def test_can_multi_conn_false (self):
 | ||||||
|  | +        self.connect ({"size": 512, "can_multi_conn": False})
 | ||||||
|  | +        assert not self.h.can_multi_conn()
 | ||||||
|  | +
 | ||||||
|  | +    def test_read_write (self):
 | ||||||
|  | +        self.connect ({"size": 512, "can_write": True})
 | ||||||
|  | +        assert not self.h.is_read_only()
 | ||||||
|  | +
 | ||||||
|  | +    def test_read_only (self):
 | ||||||
|  | +        self.connect ({"size": 512, "can_write": False})
 | ||||||
|  | +        assert self.h.is_read_only()
 | ||||||
|  | +
 | ||||||
|  | +    def test_can_flush_true (self):
 | ||||||
|  | +        self.connect ({"size": 512, "can_flush": True})
 | ||||||
|  | +        assert self.h.can_flush()
 | ||||||
|  | +
 | ||||||
|  | +    def test_can_flush_false (self):
 | ||||||
|  | +        self.connect ({"size": 512, "can_flush": False})
 | ||||||
|  | +        assert not self.h.can_flush()
 | ||||||
|  | +
 | ||||||
|  | +    def test_can_trim_true (self):
 | ||||||
|  | +        self.connect ({"size": 512, "can_trim": True})
 | ||||||
|  | +        assert self.h.can_trim()
 | ||||||
|  | +
 | ||||||
|  | +    def test_can_trim_false (self):
 | ||||||
|  | +        self.connect ({"size": 512, "can_trim": False})
 | ||||||
|  | +        assert not self.h.can_trim()
 | ||||||
|  | +
 | ||||||
|  | +    # nbdkit can always zero because it emulates it.
 | ||||||
|  | +    #self.connect ({"size": 512, "can_zero": True})
 | ||||||
|  | +    #assert self.h.can_zero()
 | ||||||
|  | +    #self.connect ({"size": 512, "can_zero": False})
 | ||||||
|  | +    #assert not self.h.can_zero()
 | ||||||
|  | +
 | ||||||
|  | +    def test_can_fast_zero_true (self):
 | ||||||
|  | +        self.connect ({"size": 512, "can_fast_zero": True})
 | ||||||
|  | +        assert self.h.can_fast_zero()
 | ||||||
|  | +
 | ||||||
|  | +    def test_can_fast_zero_false (self):
 | ||||||
|  | +        self.connect ({"size": 512, "can_fast_zero": False})
 | ||||||
|  | +        assert not self.h.can_fast_zero()
 | ||||||
|  | +
 | ||||||
|  | +    def test_can_fua_none (self):
 | ||||||
|  | +        self.connect ({"size": 512, "can_fua": "none"})
 | ||||||
|  | +        assert not self.h.can_fua()
 | ||||||
|  | +
 | ||||||
|  | +    def test_can_fua_emulate (self):
 | ||||||
|  | +        self.connect ({"size": 512, "can_fua": "emulate"})
 | ||||||
|  | +        assert self.h.can_fua()
 | ||||||
|  | +
 | ||||||
|  | +    def test_can_fua_native (self):
 | ||||||
|  | +        self.connect ({"size": 512, "can_fua": "native"})
 | ||||||
|  | +        assert self.h.can_fua()
 | ||||||
|  | +
 | ||||||
|  | +    def test_can_cache_none (self):
 | ||||||
|  | +        self.connect ({"size": 512, "can_cache": "none"})
 | ||||||
|  | +        assert not self.h.can_cache()
 | ||||||
|  | +
 | ||||||
|  | +    def test_can_cache_emulate (self):
 | ||||||
|  | +        self.connect ({"size": 512, "can_cache": "emulate"})
 | ||||||
|  | +        assert self.h.can_cache()
 | ||||||
|  | +
 | ||||||
|  | +    def test_can_cache_native (self):
 | ||||||
|  | +        self.connect ({"size": 512, "can_cache": "native"})
 | ||||||
|  | +        assert self.h.can_cache()
 | ||||||
|  | +
 | ||||||
|  | +    # Not yet implemented: can_extents.
 | ||||||
|  | +
 | ||||||
|  | +    def test_pread (self):
 | ||||||
|  | +        """Test pread."""
 | ||||||
|  | +        self.connect ({"size": 512})
 | ||||||
|  | +        buf = self.h.pread (512, 0)
 | ||||||
|  | +        assert buf == bytearray (512)
 | ||||||
|  | +
 | ||||||
|  | +    # Test pwrite + flags.
 | ||||||
|  | +    def test_pwrite (self):
 | ||||||
|  | +        self.connect ({"size": 512})
 | ||||||
|  | +        buf = bytearray (512)
 | ||||||
|  | +        self.h.pwrite (buf, 0)
 | ||||||
|  | +
 | ||||||
|  | +    def test_pwrite_fua (self):
 | ||||||
|  | +        self.connect ({"size": 512,
 | ||||||
|  | +                       "can_fua": "native",
 | ||||||
|  | +                       "pwrite_expect_fua": True})
 | ||||||
|  | +        buf = bytearray (512)
 | ||||||
|  | +        self.h.pwrite (buf, 0, nbd.CMD_FLAG_FUA)
 | ||||||
|  | +
 | ||||||
|  | +    def test_flush (self):
 | ||||||
|  | +        """Test flush."""
 | ||||||
|  | +        self.connect ({"size": 512, "can_flush": True})
 | ||||||
|  | +        self.h.flush ()
 | ||||||
|  | +
 | ||||||
|  | +    # Test trim + flags.
 | ||||||
|  | +    def test_trim (self):
 | ||||||
|  | +        self.connect ({"size": 512, "can_trim": True})
 | ||||||
|  | +        self.h.trim (512, 0)
 | ||||||
|  | +
 | ||||||
|  | +    def test_trim_fua (self):
 | ||||||
|  | +        self.connect ({"size": 512,
 | ||||||
|  | +                       "can_trim": True,
 | ||||||
|  | +                       "can_fua": "native",
 | ||||||
|  | +                       "trim_expect_fua": True})
 | ||||||
|  | +        self.h.trim (512, 0, nbd.CMD_FLAG_FUA)
 | ||||||
|  | +
 | ||||||
|  | +    # Test zero + flags.
 | ||||||
|  | +    def test_zero (self):
 | ||||||
|  | +        self.connect ({"size": 512, "can_zero": True})
 | ||||||
|  | +        self.h.zero (512, 0, nbd.CMD_FLAG_NO_HOLE)
 | ||||||
|  | +
 | ||||||
|  | +    def test_zero_fua (self):
 | ||||||
|  | +        self.connect ({"size": 512,
 | ||||||
|  | +                       "can_zero": True,
 | ||||||
|  | +                       "can_fua": "native",
 | ||||||
|  | +                       "zero_expect_fua": True})
 | ||||||
|  | +        self.h.zero (512, 0, nbd.CMD_FLAG_NO_HOLE | nbd.CMD_FLAG_FUA)
 | ||||||
|  | +
 | ||||||
|  | +    def test_zero_may_trim (self):
 | ||||||
|  | +        self.connect ({"size": 512,
 | ||||||
|  | +                       "can_zero": True,
 | ||||||
|  | +                       "zero_expect_may_trim": True})
 | ||||||
|  | +        self.h.zero (512, 0, 0) # absence of nbd.CMD_FLAG_NO_HOLE
 | ||||||
|  | +
 | ||||||
|  | +    def test_zero_fast_zero (self):
 | ||||||
|  | +        self.connect ({"size": 512,
 | ||||||
|  | +                       "can_zero": True,
 | ||||||
|  | +                       "can_fast_zero": True,
 | ||||||
|  | +                       "zero_expect_fast_zero": True})
 | ||||||
|  | +        self.h.zero (512, 0, nbd.CMD_FLAG_NO_HOLE | nbd.CMD_FLAG_FAST_ZERO)
 | ||||||
|  | +
 | ||||||
|  | +    def test_cache (self):
 | ||||||
|  | +        """Test cache."""
 | ||||||
|  | +        self.connect ({"size": 512, "can_cache": "native"})
 | ||||||
|  | +        self.h.cache (512, 0)
 | ||||||
|  | -- 
 | ||||||
|  | 2.18.2 | ||||||
|  | 
 | ||||||
							
								
								
									
										790
									
								
								SOURCES/0011-New-filter-extentlist.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										790
									
								
								SOURCES/0011-New-filter-extentlist.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,790 @@ | |||||||
|  | From e744dcb38cc52cbe64977efcdd4bc60e802d1b17 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: "Richard W.M. Jones" <rjones@redhat.com> | ||||||
|  | Date: Thu, 23 Jan 2020 19:52:00 +0000 | ||||||
|  | Subject: [PATCH] New filter: extentlist. | ||||||
|  | 
 | ||||||
|  | Allows a list of extents to be placed on top of an existing plugin. | ||||||
|  | 
 | ||||||
|  | (cherry picked from commit 3e770b6d6620a62546849a2863638041c0b00640) | ||||||
|  | ---
 | ||||||
|  |  TODO                                          |   4 + | ||||||
|  |  configure.ac                                  |   2 + | ||||||
|  |  .../nbdkit-cacheextents-filter.pod            |   1 + | ||||||
|  |  filters/extentlist/Makefile.am                |  67 ++++ | ||||||
|  |  filters/extentlist/extentlist.c               | 326 ++++++++++++++++++ | ||||||
|  |  .../extentlist/nbdkit-extentlist-filter.pod   |  90 +++++ | ||||||
|  |  filters/noextents/nbdkit-noextents-filter.pod |   1 + | ||||||
|  |  tests/Makefile.am                             |   4 + | ||||||
|  |  tests/test-extentlist.sh                      | 175 ++++++++++ | ||||||
|  |  9 files changed, 670 insertions(+) | ||||||
|  |  create mode 100644 filters/extentlist/Makefile.am | ||||||
|  |  create mode 100644 filters/extentlist/extentlist.c | ||||||
|  |  create mode 100644 filters/extentlist/nbdkit-extentlist-filter.pod | ||||||
|  |  create mode 100755 tests/test-extentlist.sh | ||||||
|  | 
 | ||||||
|  | diff --git a/TODO b/TODO
 | ||||||
|  | index d2aca44..2a3e89d 100644
 | ||||||
|  | --- a/TODO
 | ||||||
|  | +++ b/TODO
 | ||||||
|  | @@ -187,6 +187,10 @@ Suggestions for filters
 | ||||||
|  |    MBs of extra data) | ||||||
|  |    https://github.com/facebook/zstd/issues/395#issuecomment-535875379 | ||||||
|  |   | ||||||
|  | +* nbdkit-extentlist-filter could read the extents generated by
 | ||||||
|  | +  qemu-img map, allowing extents to be ported from a qemu block
 | ||||||
|  | +  device.
 | ||||||
|  | +
 | ||||||
|  |  nbdkit-rate-filter: | ||||||
|  |   | ||||||
|  |  * allow other kinds of traffic shaping such as VBR | ||||||
|  | diff --git a/configure.ac b/configure.ac
 | ||||||
|  | index fde498b..41e68de 100644
 | ||||||
|  | --- a/configure.ac
 | ||||||
|  | +++ b/configure.ac
 | ||||||
|  | @@ -896,6 +896,7 @@ filters="\
 | ||||||
|  |          cow \ | ||||||
|  |          delay \ | ||||||
|  |          error \ | ||||||
|  | +        extentlist \
 | ||||||
|  |          fua \ | ||||||
|  |          log \ | ||||||
|  |          nocache \ | ||||||
|  | @@ -979,6 +980,7 @@ AC_CONFIG_FILES([Makefile
 | ||||||
|  |                   filters/cow/Makefile | ||||||
|  |                   filters/delay/Makefile | ||||||
|  |                   filters/error/Makefile | ||||||
|  | +                 filters/extentlist/Makefile
 | ||||||
|  |                   filters/fua/Makefile | ||||||
|  |                   filters/log/Makefile | ||||||
|  |                   filters/nocache/Makefile | ||||||
|  | diff --git a/filters/cacheextents/nbdkit-cacheextents-filter.pod b/filters/cacheextents/nbdkit-cacheextents-filter.pod
 | ||||||
|  | index fdd2285..bb2514a 100644
 | ||||||
|  | --- a/filters/cacheextents/nbdkit-cacheextents-filter.pod
 | ||||||
|  | +++ b/filters/cacheextents/nbdkit-cacheextents-filter.pod
 | ||||||
|  | @@ -52,6 +52,7 @@ C<nbdkit-cacheextents-filter> first appeared in nbdkit 1.14.
 | ||||||
|  |   | ||||||
|  |  L<nbdkit(1)>, | ||||||
|  |  L<nbdkit-cache-filter(1)>, | ||||||
|  | +L<nbdkit-extentlist-filter(1)>,
 | ||||||
|  |  L<nbdkit-readahead-filter(1)>, | ||||||
|  |  L<nbdkit-vddk-plugin(1)>, | ||||||
|  |  L<nbdkit-filter(3)>, | ||||||
|  | diff --git a/filters/extentlist/Makefile.am b/filters/extentlist/Makefile.am
 | ||||||
|  | new file mode 100644 | ||||||
|  | index 0000000..88a9afe
 | ||||||
|  | --- /dev/null
 | ||||||
|  | +++ b/filters/extentlist/Makefile.am
 | ||||||
|  | @@ -0,0 +1,67 @@
 | ||||||
|  | +# nbdkit
 | ||||||
|  | +# Copyright (C) 2019-2020 Red Hat Inc.
 | ||||||
|  | +#
 | ||||||
|  | +# Redistribution and use in source and binary forms, with or without
 | ||||||
|  | +# modification, are permitted provided that the following conditions are
 | ||||||
|  | +# met:
 | ||||||
|  | +#
 | ||||||
|  | +# * Redistributions of source code must retain the above copyright
 | ||||||
|  | +# notice, this list of conditions and the following disclaimer.
 | ||||||
|  | +#
 | ||||||
|  | +# * Redistributions in binary form must reproduce the above copyright
 | ||||||
|  | +# notice, this list of conditions and the following disclaimer in the
 | ||||||
|  | +# documentation and/or other materials provided with the distribution.
 | ||||||
|  | +#
 | ||||||
|  | +# * Neither the name of Red Hat nor the names of its contributors may be
 | ||||||
|  | +# used to endorse or promote products derived from this software without
 | ||||||
|  | +# specific prior written permission.
 | ||||||
|  | +#
 | ||||||
|  | +# THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND
 | ||||||
|  | +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 | ||||||
|  | +# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 | ||||||
|  | +# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR
 | ||||||
|  | +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | ||||||
|  | +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | ||||||
|  | +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 | ||||||
|  | +# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 | ||||||
|  | +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 | ||||||
|  | +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 | ||||||
|  | +# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 | ||||||
|  | +# SUCH DAMAGE.
 | ||||||
|  | +
 | ||||||
|  | +include $(top_srcdir)/common-rules.mk
 | ||||||
|  | +
 | ||||||
|  | +EXTRA_DIST = nbdkit-extentlist-filter.pod
 | ||||||
|  | +
 | ||||||
|  | +filter_LTLIBRARIES = nbdkit-extentlist-filter.la
 | ||||||
|  | +
 | ||||||
|  | +nbdkit_extentlist_filter_la_SOURCES = \
 | ||||||
|  | +	extentlist.c \
 | ||||||
|  | +	$(top_srcdir)/include/nbdkit-filter.h \
 | ||||||
|  | +	$(NULL)
 | ||||||
|  | +
 | ||||||
|  | +nbdkit_extentlist_filter_la_CPPFLAGS = \
 | ||||||
|  | +	-I$(top_srcdir)/include \
 | ||||||
|  | +	-I$(top_srcdir)/common/include \
 | ||||||
|  | +	-I$(top_srcdir)/common/utils \
 | ||||||
|  | +	$(NULL)
 | ||||||
|  | +nbdkit_extentlist_filter_la_CFLAGS = $(WARNINGS_CFLAGS)
 | ||||||
|  | +nbdkit_extentlist_filter_la_LDFLAGS = \
 | ||||||
|  | +	-module -avoid-version -shared \
 | ||||||
|  | +	-Wl,--version-script=$(top_srcdir)/filters/filters.syms \
 | ||||||
|  | +	$(NULL)
 | ||||||
|  | +nbdkit_extentlist_filter_la_LIBADD = \
 | ||||||
|  | +	$(top_builddir)/common/utils/libutils.la \
 | ||||||
|  | +	$(NULL)
 | ||||||
|  | +
 | ||||||
|  | +if HAVE_POD
 | ||||||
|  | +
 | ||||||
|  | +man_MANS = nbdkit-extentlist-filter.1
 | ||||||
|  | +CLEANFILES += $(man_MANS)
 | ||||||
|  | +
 | ||||||
|  | +nbdkit-extentlist-filter.1: nbdkit-extentlist-filter.pod
 | ||||||
|  | +	$(PODWRAPPER) --section=1 --man $@ \
 | ||||||
|  | +	    --html $(top_builddir)/html/$@.html \
 | ||||||
|  | +	    $<
 | ||||||
|  | +
 | ||||||
|  | +endif HAVE_POD
 | ||||||
|  | diff --git a/filters/extentlist/extentlist.c b/filters/extentlist/extentlist.c
 | ||||||
|  | new file mode 100644 | ||||||
|  | index 0000000..5f4990b
 | ||||||
|  | --- /dev/null
 | ||||||
|  | +++ b/filters/extentlist/extentlist.c
 | ||||||
|  | @@ -0,0 +1,326 @@
 | ||||||
|  | +/* nbdkit
 | ||||||
|  | + * Copyright (C) 2019-2020 Red Hat Inc.
 | ||||||
|  | + *
 | ||||||
|  | + * Redistribution and use in source and binary forms, with or without
 | ||||||
|  | + * modification, are permitted provided that the following conditions are
 | ||||||
|  | + * met:
 | ||||||
|  | + *
 | ||||||
|  | + * * Redistributions of source code must retain the above copyright
 | ||||||
|  | + * notice, this list of conditions and the following disclaimer.
 | ||||||
|  | + *
 | ||||||
|  | + * * Redistributions in binary form must reproduce the above copyright
 | ||||||
|  | + * notice, this list of conditions and the following disclaimer in the
 | ||||||
|  | + * documentation and/or other materials provided with the distribution.
 | ||||||
|  | + *
 | ||||||
|  | + * * Neither the name of Red Hat nor the names of its contributors may be
 | ||||||
|  | + * used to endorse or promote products derived from this software without
 | ||||||
|  | + * specific prior written permission.
 | ||||||
|  | + *
 | ||||||
|  | + * THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND
 | ||||||
|  | + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 | ||||||
|  | + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 | ||||||
|  | + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR
 | ||||||
|  | + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | ||||||
|  | + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | ||||||
|  | + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 | ||||||
|  | + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 | ||||||
|  | + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 | ||||||
|  | + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 | ||||||
|  | + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 | ||||||
|  | + * SUCH DAMAGE.
 | ||||||
|  | + */
 | ||||||
|  | +
 | ||||||
|  | +#include <config.h>
 | ||||||
|  | +
 | ||||||
|  | +#include <stdio.h>
 | ||||||
|  | +#include <stdlib.h>
 | ||||||
|  | +#include <stdint.h>
 | ||||||
|  | +#include <inttypes.h>
 | ||||||
|  | +#include <string.h>
 | ||||||
|  | +#include <errno.h>
 | ||||||
|  | +#include <assert.h>
 | ||||||
|  | +
 | ||||||
|  | +#include <nbdkit-filter.h>
 | ||||||
|  | +
 | ||||||
|  | +#include "cleanup.h"
 | ||||||
|  | +#include "minmax.h"
 | ||||||
|  | +
 | ||||||
|  | +#define HOLE (NBDKIT_EXTENT_HOLE|NBDKIT_EXTENT_ZERO)
 | ||||||
|  | +
 | ||||||
|  | +static const char *extentlist;
 | ||||||
|  | +
 | ||||||
|  | +/* List of extents.  Once we've finally parsed them this will be
 | ||||||
|  | + * ordered, non-overlapping and have no gaps.
 | ||||||
|  | + */
 | ||||||
|  | +struct extent {
 | ||||||
|  | +  uint64_t offset, length;
 | ||||||
|  | +  uint32_t type;
 | ||||||
|  | +};
 | ||||||
|  | +static struct extent *extents;
 | ||||||
|  | +static size_t nr_extents, allocated;
 | ||||||
|  | +
 | ||||||
|  | +/* Insert an extent before i.  If i = nr_extents, inserts at the end. */
 | ||||||
|  | +static void
 | ||||||
|  | +insert_extent (size_t i, struct extent new_extent)
 | ||||||
|  | +{
 | ||||||
|  | +  if (nr_extents >= allocated) {
 | ||||||
|  | +    allocated = allocated == 0 ? 1 : allocated * 2;
 | ||||||
|  | +    extents = realloc (extents, (sizeof (struct extent) * allocated));
 | ||||||
|  | +    if (extents == NULL) {
 | ||||||
|  | +      nbdkit_error ("realloc: %m");
 | ||||||
|  | +      exit (EXIT_FAILURE);
 | ||||||
|  | +    }
 | ||||||
|  | +  }
 | ||||||
|  | +  memmove (&extents[i+1], &extents[i],
 | ||||||
|  | +           sizeof (struct extent) * (nr_extents-i));
 | ||||||
|  | +  extents[i] = new_extent;
 | ||||||
|  | +  nr_extents++;
 | ||||||
|  | +}
 | ||||||
|  | +
 | ||||||
|  | +static void
 | ||||||
|  | +extentlist_unload (void)
 | ||||||
|  | +{
 | ||||||
|  | +  free (extents);
 | ||||||
|  | +}
 | ||||||
|  | +
 | ||||||
|  | +/* Called for each key=value passed on the command line. */
 | ||||||
|  | +static int
 | ||||||
|  | +extentlist_config (nbdkit_next_config *next, void *nxdata,
 | ||||||
|  | +                   const char *key, const char *value)
 | ||||||
|  | +{
 | ||||||
|  | +  if (strcmp (key, "extentlist") == 0) {
 | ||||||
|  | +    if (extentlist != NULL) {
 | ||||||
|  | +      nbdkit_error ("extentlist cannot appear twice");
 | ||||||
|  | +      exit (EXIT_FAILURE);
 | ||||||
|  | +    }
 | ||||||
|  | +    extentlist = value;
 | ||||||
|  | +    return 0;
 | ||||||
|  | +  }
 | ||||||
|  | +  else
 | ||||||
|  | +    return next (nxdata, key, value);
 | ||||||
|  | +}
 | ||||||
|  | +
 | ||||||
|  | +static int
 | ||||||
|  | +compare_offsets (const void *ev1, const void *ev2)
 | ||||||
|  | +{
 | ||||||
|  | +  const struct extent *e1 = ev1;
 | ||||||
|  | +  const struct extent *e2 = ev2;
 | ||||||
|  | +
 | ||||||
|  | +  if (e1->offset < e2->offset)
 | ||||||
|  | +    return -1;
 | ||||||
|  | +  else if (e1->offset > e2->offset)
 | ||||||
|  | +    return 1;
 | ||||||
|  | +  else
 | ||||||
|  | +    return 0;
 | ||||||
|  | +}
 | ||||||
|  | +
 | ||||||
|  | +static int
 | ||||||
|  | +compare_ranges (const void *ev1, const void *ev2)
 | ||||||
|  | +{
 | ||||||
|  | +  const struct extent *e1 = ev1;
 | ||||||
|  | +  const struct extent *e2 = ev2;
 | ||||||
|  | +
 | ||||||
|  | +  if (e1->offset < e2->offset)
 | ||||||
|  | +    return -1;
 | ||||||
|  | +  else if (e1->offset >= e2->offset + e2->length)
 | ||||||
|  | +    return 1;
 | ||||||
|  | +  else
 | ||||||
|  | +    return 0;
 | ||||||
|  | +}
 | ||||||
|  | +
 | ||||||
|  | +/* Similar to parse_extents in plugins/sh/methods.c */
 | ||||||
|  | +static void
 | ||||||
|  | +parse_extentlist (void)
 | ||||||
|  | +{
 | ||||||
|  | +  FILE *fp;
 | ||||||
|  | +  CLEANUP_FREE char *line = NULL;
 | ||||||
|  | +  size_t linelen = 0;
 | ||||||
|  | +  ssize_t len;
 | ||||||
|  | +  size_t i;
 | ||||||
|  | +  uint64_t end;
 | ||||||
|  | +
 | ||||||
|  | +  assert (extentlist != NULL);
 | ||||||
|  | +  assert (extents == NULL);
 | ||||||
|  | +  assert (nr_extents == 0);
 | ||||||
|  | +
 | ||||||
|  | +  fp = fopen (extentlist, "r");
 | ||||||
|  | +  if (!fp) {
 | ||||||
|  | +    nbdkit_error ("open: %s: %m", extentlist);
 | ||||||
|  | +    exit (EXIT_FAILURE);
 | ||||||
|  | +  }
 | ||||||
|  | +
 | ||||||
|  | +  while ((len = getline (&line, &linelen, fp)) != -1) {
 | ||||||
|  | +    const char *delim = " \t";
 | ||||||
|  | +    char *sp, *p;
 | ||||||
|  | +    int64_t offset, length;
 | ||||||
|  | +    uint32_t type;
 | ||||||
|  | +
 | ||||||
|  | +    if (len > 0 && line[len-1] == '\n') {
 | ||||||
|  | +      line[len-1] = '\0';
 | ||||||
|  | +      len--;
 | ||||||
|  | +    }
 | ||||||
|  | +
 | ||||||
|  | +    if ((p = strtok_r (line, delim, &sp)) == NULL) {
 | ||||||
|  | +    parse_error:
 | ||||||
|  | +      nbdkit_error ("%s: cannot parse %s", extentlist, line);
 | ||||||
|  | +      exit (EXIT_FAILURE);
 | ||||||
|  | +    }
 | ||||||
|  | +    offset = nbdkit_parse_size (p);
 | ||||||
|  | +    if (offset == -1)
 | ||||||
|  | +      exit (EXIT_FAILURE);
 | ||||||
|  | +
 | ||||||
|  | +    if ((p = strtok_r (NULL, delim, &sp)) == NULL)
 | ||||||
|  | +      goto parse_error;
 | ||||||
|  | +    length = nbdkit_parse_size (p);
 | ||||||
|  | +    if (length == -1)
 | ||||||
|  | +      exit (EXIT_FAILURE);
 | ||||||
|  | +
 | ||||||
|  | +    /* Skip zero length extents.  Makes the rest of the code easier. */
 | ||||||
|  | +    if (length == 0)
 | ||||||
|  | +      continue;
 | ||||||
|  | +
 | ||||||
|  | +    if ((p = strtok_r (NULL, delim, &sp)) == NULL)
 | ||||||
|  | +      /* empty type field means allocated data (0) */
 | ||||||
|  | +      type = 0;
 | ||||||
|  | +    else if (sscanf (p, "%" SCNu32, &type) == 1)
 | ||||||
|  | +      ;
 | ||||||
|  | +    else {
 | ||||||
|  | +      type = 0;
 | ||||||
|  | +      if (strstr (p, "hole") != NULL)
 | ||||||
|  | +        type |= NBDKIT_EXTENT_HOLE;
 | ||||||
|  | +      if (strstr (p, "zero") != NULL)
 | ||||||
|  | +        type |= NBDKIT_EXTENT_ZERO;
 | ||||||
|  | +    }
 | ||||||
|  | +
 | ||||||
|  | +    insert_extent (nr_extents,
 | ||||||
|  | +                   (struct extent){.offset = offset, .length=length,
 | ||||||
|  | +                                   .type=type});
 | ||||||
|  | +  }
 | ||||||
|  | +
 | ||||||
|  | +  fclose (fp);
 | ||||||
|  | +
 | ||||||
|  | +  /* Sort the extents by offset. */
 | ||||||
|  | +  qsort (extents, nr_extents, sizeof (struct extent), compare_offsets);
 | ||||||
|  | +
 | ||||||
|  | +  /* There must not be overlaps at this point. */
 | ||||||
|  | +  end = 0;
 | ||||||
|  | +  for (i = 0; i < nr_extents; ++i) {
 | ||||||
|  | +    if (extents[i].offset < end ||
 | ||||||
|  | +        extents[i].offset + extents[i].length < extents[i].offset) {
 | ||||||
|  | +      nbdkit_error ("extents in the extent list are overlapping");
 | ||||||
|  | +      exit (EXIT_FAILURE);
 | ||||||
|  | +    }
 | ||||||
|  | +    end = extents[i].offset + extents[i].length;
 | ||||||
|  | +  }
 | ||||||
|  | +
 | ||||||
|  | +  /* If there's a gap at the beginning, insert a hole|zero extent. */
 | ||||||
|  | +  if (nr_extents == 0 || extents[0].offset > 0) {
 | ||||||
|  | +    end = nr_extents == 0 ? UINT64_MAX : extents[0].offset;
 | ||||||
|  | +    insert_extent (0, (struct extent){.offset = 0, .length = end,
 | ||||||
|  | +                                      .type = HOLE});
 | ||||||
|  | +  }
 | ||||||
|  | +
 | ||||||
|  | +  /* Now insert hole|zero extents after every extent where there
 | ||||||
|  | +   * is a gap between that extent and the next one.
 | ||||||
|  | +   */
 | ||||||
|  | +  for (i = 0; i < nr_extents-1; ++i) {
 | ||||||
|  | +    end = extents[i].offset + extents[i].length;
 | ||||||
|  | +    if (end < extents[i+1].offset)
 | ||||||
|  | +      insert_extent (i+1, (struct extent){.offset = end,
 | ||||||
|  | +                                          .length = extents[i+1].offset - end,
 | ||||||
|  | +                                          .type = HOLE});
 | ||||||
|  | +  }
 | ||||||
|  | +
 | ||||||
|  | +  /* If there's a gap at the end, insert a hole|zero extent. */
 | ||||||
|  | +  end = extents[nr_extents-1].offset + extents[nr_extents-1].length;
 | ||||||
|  | +  if (end < UINT64_MAX)
 | ||||||
|  | +    insert_extent (nr_extents, (struct extent){.offset = end,
 | ||||||
|  | +                                               .length = UINT64_MAX-end,
 | ||||||
|  | +                                               .type = HOLE});
 | ||||||
|  | +
 | ||||||
|  | +  /* Debug the final list. */
 | ||||||
|  | +  for (i = 0; i < nr_extents; ++i) {
 | ||||||
|  | +    nbdkit_debug ("extentlist: "
 | ||||||
|  | +                  "extent[%zu] = %" PRIu64 "-%" PRIu64 " (length %" PRIu64 ")"
 | ||||||
|  | +                  " type %" PRIu32,
 | ||||||
|  | +                  i, extents[i].offset,
 | ||||||
|  | +                  extents[i].offset + extents[i].length - 1,
 | ||||||
|  | +                  extents[i].length,
 | ||||||
|  | +                  extents[i].type);
 | ||||||
|  | +  }
 | ||||||
|  | +}
 | ||||||
|  | +
 | ||||||
|  | +static int
 | ||||||
|  | +extentlist_config_complete (nbdkit_next_config_complete *next, void *nxdata)
 | ||||||
|  | +{
 | ||||||
|  | +  if (extentlist == NULL) {
 | ||||||
|  | +    nbdkit_error ("you must supply the extentlist parameter "
 | ||||||
|  | +                  "on the command line");
 | ||||||
|  | +    return -1;
 | ||||||
|  | +  }
 | ||||||
|  | +
 | ||||||
|  | +  parse_extentlist ();
 | ||||||
|  | +
 | ||||||
|  | +  return next (nxdata);
 | ||||||
|  | +}
 | ||||||
|  | +
 | ||||||
|  | +static int
 | ||||||
|  | +extentlist_can_extents (struct nbdkit_next_ops *next_ops, void *nxdata,
 | ||||||
|  | +                        void *handle)
 | ||||||
|  | +{
 | ||||||
|  | +  return 1;
 | ||||||
|  | +}
 | ||||||
|  | +
 | ||||||
|  | +/* Use ‘-D extentlist.lookup=1’ to debug the function below. */
 | ||||||
|  | +int extentlist_debug_lookup = 0;
 | ||||||
|  | +
 | ||||||
|  | +/* Read extents. */
 | ||||||
|  | +static int
 | ||||||
|  | +extentlist_extents (struct nbdkit_next_ops *next_ops, void *nxdata,
 | ||||||
|  | +                    void *handle, uint32_t count, uint64_t offset,
 | ||||||
|  | +                    uint32_t flags,
 | ||||||
|  | +                    struct nbdkit_extents *ret_extents,
 | ||||||
|  | +                    int *err)
 | ||||||
|  | +{
 | ||||||
|  | +  const struct extent eoffset = { .offset = offset };
 | ||||||
|  | +  struct extent *p;
 | ||||||
|  | +  ssize_t i;
 | ||||||
|  | +  uint64_t end;
 | ||||||
|  | +
 | ||||||
|  | +  /* Find the starting point in the extents list. */
 | ||||||
|  | +  p = bsearch (&eoffset, extents,
 | ||||||
|  | +               nr_extents, sizeof (struct extent), compare_ranges);
 | ||||||
|  | +  assert (p != NULL);
 | ||||||
|  | +  i = p - extents;
 | ||||||
|  | +
 | ||||||
|  | +  /* Add extents to the output. */
 | ||||||
|  | +  while (count > 0) {
 | ||||||
|  | +    if (extentlist_debug_lookup)
 | ||||||
|  | +      nbdkit_debug ("extentlist lookup: "
 | ||||||
|  | +                    "loop i=%zd count=%" PRIu32 " offset=%" PRIu64,
 | ||||||
|  | +                    i, count, offset);
 | ||||||
|  | +
 | ||||||
|  | +    end = extents[i].offset + extents[i].length;
 | ||||||
|  | +    if (nbdkit_add_extent (ret_extents, offset, end - offset,
 | ||||||
|  | +                           extents[i].type) == -1)
 | ||||||
|  | +      return -1;
 | ||||||
|  | +
 | ||||||
|  | +    count -= MIN (count, end-offset);
 | ||||||
|  | +    offset = end;
 | ||||||
|  | +    i++;
 | ||||||
|  | +  }
 | ||||||
|  | +
 | ||||||
|  | +  return 0;
 | ||||||
|  | +}
 | ||||||
|  | +
 | ||||||
|  | +static struct nbdkit_filter filter = {
 | ||||||
|  | +  .name              = "extentlist",
 | ||||||
|  | +  .longname          = "nbdkit extentlist filter",
 | ||||||
|  | +  .unload            = extentlist_unload,
 | ||||||
|  | +  .config            = extentlist_config,
 | ||||||
|  | +  .config_complete   = extentlist_config_complete,
 | ||||||
|  | +  .can_extents       = extentlist_can_extents,
 | ||||||
|  | +  .extents           = extentlist_extents,
 | ||||||
|  | +};
 | ||||||
|  | +
 | ||||||
|  | +NBDKIT_REGISTER_FILTER(filter)
 | ||||||
|  | diff --git a/filters/extentlist/nbdkit-extentlist-filter.pod b/filters/extentlist/nbdkit-extentlist-filter.pod
 | ||||||
|  | new file mode 100644 | ||||||
|  | index 0000000..adfb4ad
 | ||||||
|  | --- /dev/null
 | ||||||
|  | +++ b/filters/extentlist/nbdkit-extentlist-filter.pod
 | ||||||
|  | @@ -0,0 +1,90 @@
 | ||||||
|  | +=head1 NAME
 | ||||||
|  | +
 | ||||||
|  | +nbdkit-extentlist-filter - place extent list over a plugin
 | ||||||
|  | +
 | ||||||
|  | +=head1 SYNOPSIS
 | ||||||
|  | +
 | ||||||
|  | + nbdkit --filter=extentlist plugin extentlist=FILENAME
 | ||||||
|  | +
 | ||||||
|  | +=head1 DESCRIPTION
 | ||||||
|  | +
 | ||||||
|  | +C<nbdkit-extentlist-filter> is an nbdkit filter lets you place a
 | ||||||
|  | +static list of extents on top of an existing plugin.  Extents record
 | ||||||
|  | +whether or not specific parts of the disk are allocated or sparse.
 | ||||||
|  | +
 | ||||||
|  | +You can use this with plugins which cannot get extent information
 | ||||||
|  | +themselves, but you can get this information from another source.  One
 | ||||||
|  | +place where it is useful is with L<nbdkit-ssh-plugin(1)> because the
 | ||||||
|  | +sftp protocol does not support reading sparseness information, but you
 | ||||||
|  | +may be able to get this information directly from the source disk on
 | ||||||
|  | +the remote server.
 | ||||||
|  | +
 | ||||||
|  | +=head1 FILE FORMAT
 | ||||||
|  | +
 | ||||||
|  | +The list of extents is specified in a text file.  There is one extent
 | ||||||
|  | +specified per line.  Each line has the format:
 | ||||||
|  | +
 | ||||||
|  | + offset length type
 | ||||||
|  | +
 | ||||||
|  | +The C<offset> and C<length> fields may use any format understood by
 | ||||||
|  | +C<nbdkit_parse_size>.  The optional C<type> field may be an integer,
 | ||||||
|  | +missing (same as 0), or a comma-separated list of the words C<hole>
 | ||||||
|  | +and C<zero>.  (The fields correspond to the inputs of the
 | ||||||
|  | +C<nbdkit_add_extent> function, see L<nbdkit-plugin(3)>).
 | ||||||
|  | +
 | ||||||
|  | +An example of a valid set of extents covering a C<10M> disk where the
 | ||||||
|  | +first megabyte only is allocated data:
 | ||||||
|  | +
 | ||||||
|  | + 0  1M
 | ||||||
|  | + 1M 9M  hole,zero
 | ||||||
|  | +
 | ||||||
|  | +Or you could omit the C<hole,zero> extent since any gaps are assumed
 | ||||||
|  | +to be holes with that type:
 | ||||||
|  | +
 | ||||||
|  | + 0  1M
 | ||||||
|  | +
 | ||||||
|  | +The extent list need not cover the whole disk, and does not need to be
 | ||||||
|  | +in ascending order, but it must I<not> contain overlapping extents.
 | ||||||
|  | +
 | ||||||
|  | +=head1 PARAMETERS
 | ||||||
|  | +
 | ||||||
|  | +=over 4
 | ||||||
|  | +
 | ||||||
|  | +=item B<extentlist=>FILENAME
 | ||||||
|  | +
 | ||||||
|  | +Specify the file containing the extent list, in the format described
 | ||||||
|  | +in L</FILE FORMAT> above.
 | ||||||
|  | +
 | ||||||
|  | +=back
 | ||||||
|  | +
 | ||||||
|  | +=head1 FILES
 | ||||||
|  | +
 | ||||||
|  | +=over 4
 | ||||||
|  | +
 | ||||||
|  | +=item F<$filterdir/nbdkit-extentlist-filter.so>
 | ||||||
|  | +
 | ||||||
|  | +The filter.
 | ||||||
|  | +
 | ||||||
|  | +Use C<nbdkit --dump-config> to find the location of C<$filterdir>.
 | ||||||
|  | +
 | ||||||
|  | +=back
 | ||||||
|  | +
 | ||||||
|  | +=head1 VERSION
 | ||||||
|  | +
 | ||||||
|  | +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)>.
 | ||||||
|  | +
 | ||||||
|  | +=head1 AUTHORS
 | ||||||
|  | +
 | ||||||
|  | +Richard W.M. Jones
 | ||||||
|  | +
 | ||||||
|  | +=head1 COPYRIGHT
 | ||||||
|  | +
 | ||||||
|  | +Copyright (C) 2020 Red Hat Inc.
 | ||||||
|  | diff --git a/filters/noextents/nbdkit-noextents-filter.pod b/filters/noextents/nbdkit-noextents-filter.pod
 | ||||||
|  | index 991ecfe..0260a5c 100644
 | ||||||
|  | --- a/filters/noextents/nbdkit-noextents-filter.pod
 | ||||||
|  | +++ b/filters/noextents/nbdkit-noextents-filter.pod
 | ||||||
|  | @@ -47,6 +47,7 @@ C<nbdkit-noextents-filter> first appeared in nbdkit 1.14.
 | ||||||
|  |   | ||||||
|  |  L<nbdkit(1)>, | ||||||
|  |  L<nbdkit-filter(3)>, | ||||||
|  | +L<nbdkit-extentlist-filter(1)>,
 | ||||||
|  |  L<nbdkit-fua-filter(1)>, | ||||||
|  |  L<nbdkit-nocache-filter(1)>, | ||||||
|  |  L<nbdkit-noparallel-filter(1)>, | ||||||
|  | diff --git a/tests/Makefile.am b/tests/Makefile.am
 | ||||||
|  | index 09103fb..b99952f 100644
 | ||||||
|  | --- a/tests/Makefile.am
 | ||||||
|  | +++ b/tests/Makefile.am
 | ||||||
|  | @@ -110,6 +110,7 @@ EXTRA_DIST = \
 | ||||||
|  |  	test-error100.sh \ | ||||||
|  |  	test-error-triggered.sh \ | ||||||
|  |  	test-export-name.sh \ | ||||||
|  | +	test-extentlist.sh \
 | ||||||
|  |  	test-file-extents.sh \ | ||||||
|  |  	test-floppy.sh \ | ||||||
|  |  	test-foreground.sh \ | ||||||
|  | @@ -1009,6 +1010,9 @@ TESTS += \
 | ||||||
|  |  	test-error-triggered.sh \ | ||||||
|  |  	$(NULL) | ||||||
|  |   | ||||||
|  | +# extentlist filter test.
 | ||||||
|  | +TESTS += test-extentlist.sh
 | ||||||
|  | +
 | ||||||
|  |  # fua filter test. | ||||||
|  |  TESTS += test-fua.sh | ||||||
|  |   | ||||||
|  | diff --git a/tests/test-extentlist.sh b/tests/test-extentlist.sh
 | ||||||
|  | new file mode 100755 | ||||||
|  | index 0000000..7d05de4
 | ||||||
|  | --- /dev/null
 | ||||||
|  | +++ b/tests/test-extentlist.sh
 | ||||||
|  | @@ -0,0 +1,175 @@
 | ||||||
|  | +#!/usr/bin/env bash
 | ||||||
|  | +# nbdkit
 | ||||||
|  | +# Copyright (C) 2016-2020 Red Hat Inc.
 | ||||||
|  | +#
 | ||||||
|  | +# Redistribution and use in source and binary forms, with or without
 | ||||||
|  | +# modification, are permitted provided that the following conditions are
 | ||||||
|  | +# met:
 | ||||||
|  | +#
 | ||||||
|  | +# * Redistributions of source code must retain the above copyright
 | ||||||
|  | +# notice, this list of conditions and the following disclaimer.
 | ||||||
|  | +#
 | ||||||
|  | +# * Redistributions in binary form must reproduce the above copyright
 | ||||||
|  | +# notice, this list of conditions and the following disclaimer in the
 | ||||||
|  | +# documentation and/or other materials provided with the distribution.
 | ||||||
|  | +#
 | ||||||
|  | +# * Neither the name of Red Hat nor the names of its contributors may be
 | ||||||
|  | +# used to endorse or promote products derived from this software without
 | ||||||
|  | +# specific prior written permission.
 | ||||||
|  | +#
 | ||||||
|  | +# THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND
 | ||||||
|  | +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 | ||||||
|  | +# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 | ||||||
|  | +# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR
 | ||||||
|  | +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | ||||||
|  | +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | ||||||
|  | +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 | ||||||
|  | +# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 | ||||||
|  | +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 | ||||||
|  | +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 | ||||||
|  | +# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 | ||||||
|  | +# SUCH DAMAGE.
 | ||||||
|  | +
 | ||||||
|  | +# Test the extentlist filter.
 | ||||||
|  | +
 | ||||||
|  | +source ./functions.sh
 | ||||||
|  | +set -e
 | ||||||
|  | +set -x
 | ||||||
|  | +
 | ||||||
|  | +requires jq --version
 | ||||||
|  | +requires qemu-img --version
 | ||||||
|  | +requires qemu-img map --help
 | ||||||
|  | +
 | ||||||
|  | +out=test-extentlist.out
 | ||||||
|  | +input=test-extentlist.in
 | ||||||
|  | +expected=test-extentlist.expected
 | ||||||
|  | +files="$out $input $expected"
 | ||||||
|  | +rm -f $files
 | ||||||
|  | +cleanup_fn rm $files
 | ||||||
|  | +
 | ||||||
|  | +test ()
 | ||||||
|  | +{
 | ||||||
|  | +    nbdkit -v -D extentlist.lookup=1 \
 | ||||||
|  | +           -U - \
 | ||||||
|  | +           --filter=extentlist \
 | ||||||
|  | +           null size=$1 extentlist=$input \
 | ||||||
|  | +           --run 'qemu-img map -f raw --output=json $nbd' |
 | ||||||
|  | +        jq -c '.[] | {start:.start, length:.length, data:.data, zero:.zero}' \
 | ||||||
|  | +           > $out
 | ||||||
|  | +    diff -u $out $expected
 | ||||||
|  | +}
 | ||||||
|  | +
 | ||||||
|  | +# Empty extent list.
 | ||||||
|  | +cat > $input <<'EOF'
 | ||||||
|  | +EOF
 | ||||||
|  | +
 | ||||||
|  | +cat > $expected <<'EOF'
 | ||||||
|  | +{"start":0,"length":0,"data":false,"zero":false}
 | ||||||
|  | +EOF
 | ||||||
|  | +test 0
 | ||||||
|  | +cat > $expected <<'EOF'
 | ||||||
|  | +{"start":0,"length":1048576,"data":false,"zero":true}
 | ||||||
|  | +EOF
 | ||||||
|  | +test 1M
 | ||||||
|  | +
 | ||||||
|  | +# Extent list covering 0-1M with data.
 | ||||||
|  | +cat > $input <<'EOF'
 | ||||||
|  | +0 1M
 | ||||||
|  | +EOF
 | ||||||
|  | +
 | ||||||
|  | +cat > $expected <<'EOF'
 | ||||||
|  | +{"start":0,"length":0,"data":false,"zero":false}
 | ||||||
|  | +EOF
 | ||||||
|  | +test 0
 | ||||||
|  | +cat > $expected <<'EOF'
 | ||||||
|  | +{"start":0,"length":1048576,"data":true,"zero":false}
 | ||||||
|  | +EOF
 | ||||||
|  | +test 1M
 | ||||||
|  | +
 | ||||||
|  | +# Extent list covering 1-2M with data.
 | ||||||
|  | +cat > $input <<'EOF'
 | ||||||
|  | +1M 1M
 | ||||||
|  | +EOF
 | ||||||
|  | +
 | ||||||
|  | +cat > $expected <<'EOF'
 | ||||||
|  | +{"start":0,"length":0,"data":false,"zero":false}
 | ||||||
|  | +EOF
 | ||||||
|  | +test 0
 | ||||||
|  | +cat > $expected <<'EOF'
 | ||||||
|  | +{"start":0,"length":1048576,"data":false,"zero":true}
 | ||||||
|  | +EOF
 | ||||||
|  | +test 1M
 | ||||||
|  | +cat > $expected <<'EOF'
 | ||||||
|  | +{"start":0,"length":1048576,"data":false,"zero":true}
 | ||||||
|  | +{"start":1048576,"length":1048576,"data":true,"zero":false}
 | ||||||
|  | +EOF
 | ||||||
|  | +test 2M
 | ||||||
|  | +cat > $expected <<'EOF'
 | ||||||
|  | +{"start":0,"length":1048576,"data":false,"zero":true}
 | ||||||
|  | +{"start":1048576,"length":1048576,"data":true,"zero":false}
 | ||||||
|  | +{"start":2097152,"length":1048576,"data":false,"zero":true}
 | ||||||
|  | +EOF
 | ||||||
|  | +test 3M
 | ||||||
|  | +
 | ||||||
|  | +# Extent list covering 1-2M with data, but in a more fragmented
 | ||||||
|  | +# way than the above.
 | ||||||
|  | +cat > $input <<'EOF'
 | ||||||
|  | +1024K 512K
 | ||||||
|  | +1536K 512K
 | ||||||
|  | +EOF
 | ||||||
|  | +
 | ||||||
|  | +cat > $expected <<'EOF'
 | ||||||
|  | +{"start":0,"length":0,"data":false,"zero":false}
 | ||||||
|  | +EOF
 | ||||||
|  | +test 0
 | ||||||
|  | +cat > $expected <<'EOF'
 | ||||||
|  | +{"start":0,"length":1048576,"data":false,"zero":true}
 | ||||||
|  | +EOF
 | ||||||
|  | +test 1M
 | ||||||
|  | +cat > $expected <<'EOF'
 | ||||||
|  | +{"start":0,"length":1048576,"data":false,"zero":true}
 | ||||||
|  | +{"start":1048576,"length":1048576,"data":true,"zero":false}
 | ||||||
|  | +EOF
 | ||||||
|  | +test 2M
 | ||||||
|  | +cat > $expected <<'EOF'
 | ||||||
|  | +{"start":0,"length":1048576,"data":false,"zero":true}
 | ||||||
|  | +{"start":1048576,"length":1048576,"data":true,"zero":false}
 | ||||||
|  | +{"start":2097152,"length":1048576,"data":false,"zero":true}
 | ||||||
|  | +EOF
 | ||||||
|  | +test 3M
 | ||||||
|  | +
 | ||||||
|  | +# Adjacent data and holes.
 | ||||||
|  | +cat > $input <<'EOF'
 | ||||||
|  | +0 1M
 | ||||||
|  | +2M 1M
 | ||||||
|  | +4M 1M
 | ||||||
|  | +EOF
 | ||||||
|  | +
 | ||||||
|  | +cat > $expected <<'EOF'
 | ||||||
|  | +{"start":0,"length":0,"data":false,"zero":false}
 | ||||||
|  | +EOF
 | ||||||
|  | +test 0
 | ||||||
|  | +cat > $expected <<'EOF'
 | ||||||
|  | +{"start":0,"length":1048576,"data":true,"zero":false}
 | ||||||
|  | +EOF
 | ||||||
|  | +test 1M
 | ||||||
|  | +cat > $expected <<'EOF'
 | ||||||
|  | +{"start":0,"length":1048576,"data":true,"zero":false}
 | ||||||
|  | +{"start":1048576,"length":1048576,"data":false,"zero":true}
 | ||||||
|  | +EOF
 | ||||||
|  | +test 2M
 | ||||||
|  | +cat > $expected <<'EOF'
 | ||||||
|  | +{"start":0,"length":1048576,"data":true,"zero":false}
 | ||||||
|  | +{"start":1048576,"length":1048576,"data":false,"zero":true}
 | ||||||
|  | +{"start":2097152,"length":1048576,"data":true,"zero":false}
 | ||||||
|  | +EOF
 | ||||||
|  | +test 3M
 | ||||||
|  | +cat > $expected <<'EOF'
 | ||||||
|  | +{"start":0,"length":1048576,"data":true,"zero":false}
 | ||||||
|  | +{"start":1048576,"length":1048576,"data":false,"zero":true}
 | ||||||
|  | +{"start":2097152,"length":1048576,"data":true,"zero":false}
 | ||||||
|  | +{"start":3145728,"length":1048576,"data":false,"zero":true}
 | ||||||
|  | +{"start":4194304,"length":1048576,"data":true,"zero":false}
 | ||||||
|  | +{"start":5242880,"length":1048576,"data":false,"zero":true}
 | ||||||
|  | +EOF
 | ||||||
|  | +test 6M
 | ||||||
|  | -- 
 | ||||||
|  | 2.18.2 | ||||||
|  | 
 | ||||||
							
								
								
									
										125
									
								
								SOURCES/0012-extentlist-Documentation-and-test-fixes.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										125
									
								
								SOURCES/0012-extentlist-Documentation-and-test-fixes.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,125 @@ | |||||||
|  | From 2a3e909e9e1ccb608bde75b76524acd753b33889 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: "Richard W.M. Jones" <rjones@redhat.com> | ||||||
|  | Date: Sat, 25 Jan 2020 11:38:14 +0000 | ||||||
|  | Subject: [PATCH] extentlist: Documentation and test fixes. | ||||||
|  | 
 | ||||||
|  | Updates commit 3e770b6d6620a62546849a2863638041c0b00640. | ||||||
|  | 
 | ||||||
|  | (cherry picked from commit c16709ef663a5ed9fd9ddef4e379f316d84c9a07) | ||||||
|  | ---
 | ||||||
|  |  TODO                                          | 12 +++++++---- | ||||||
|  |  .../extentlist/nbdkit-extentlist-filter.pod   | 21 +++++++++++++------ | ||||||
|  |  plugins/curl/nbdkit-curl-plugin.pod           |  1 + | ||||||
|  |  plugins/ssh/nbdkit-ssh-plugin.pod             |  1 + | ||||||
|  |  tests/test-extentlist.sh                      |  2 +- | ||||||
|  |  5 files changed, 26 insertions(+), 11 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/TODO b/TODO
 | ||||||
|  | index 2a3e89d..e1ac71c 100644
 | ||||||
|  | --- a/TODO
 | ||||||
|  | +++ b/TODO
 | ||||||
|  | @@ -187,10 +187,6 @@ Suggestions for filters
 | ||||||
|  |    MBs of extra data) | ||||||
|  |    https://github.com/facebook/zstd/issues/395#issuecomment-535875379 | ||||||
|  |   | ||||||
|  | -* nbdkit-extentlist-filter could read the extents generated by
 | ||||||
|  | -  qemu-img map, allowing extents to be ported from a qemu block
 | ||||||
|  | -  device.
 | ||||||
|  | -
 | ||||||
|  |  nbdkit-rate-filter: | ||||||
|  |   | ||||||
|  |  * allow other kinds of traffic shaping such as VBR | ||||||
|  | @@ -216,6 +212,14 @@ nbdkit-retry-filter:
 | ||||||
|  |   | ||||||
|  |  * subsecond times | ||||||
|  |   | ||||||
|  | +nbdkit-extentlist-filter:
 | ||||||
|  | +
 | ||||||
|  | +* read the extents generated by qemu-img map, allowing extents to be
 | ||||||
|  | +  ported from a qemu block device
 | ||||||
|  | +
 | ||||||
|  | +* make non-read-only access safe by updating the extent list when the
 | ||||||
|  | +  filter sees writes and trims
 | ||||||
|  | +
 | ||||||
|  |  Filters for security | ||||||
|  |  -------------------- | ||||||
|  |   | ||||||
|  | diff --git a/filters/extentlist/nbdkit-extentlist-filter.pod b/filters/extentlist/nbdkit-extentlist-filter.pod
 | ||||||
|  | index adfb4ad..5d1a38a 100644
 | ||||||
|  | --- a/filters/extentlist/nbdkit-extentlist-filter.pod
 | ||||||
|  | +++ b/filters/extentlist/nbdkit-extentlist-filter.pod
 | ||||||
|  | @@ -4,7 +4,7 @@ nbdkit-extentlist-filter - place extent list over a plugin
 | ||||||
|  |   | ||||||
|  |  =head1 SYNOPSIS | ||||||
|  |   | ||||||
|  | - nbdkit --filter=extentlist plugin extentlist=FILENAME
 | ||||||
|  | + nbdkit -r --filter=extentlist plugin extentlist=FILENAME
 | ||||||
|  |   | ||||||
|  |  =head1 DESCRIPTION | ||||||
|  |   | ||||||
|  | @@ -13,11 +13,20 @@ static list of extents on top of an existing plugin.  Extents record
 | ||||||
|  |  whether or not specific parts of the disk are allocated or sparse. | ||||||
|  |   | ||||||
|  |  You can use this with plugins which cannot get extent information | ||||||
|  | -themselves, but you can get this information from another source.  One
 | ||||||
|  | -place where it is useful is with L<nbdkit-ssh-plugin(1)> because the
 | ||||||
|  | -sftp protocol does not support reading sparseness information, but you
 | ||||||
|  | -may be able to get this information directly from the source disk on
 | ||||||
|  | -the remote server.
 | ||||||
|  | +themselves, but where you can get this information from another
 | ||||||
|  | +source.  One place where it is useful is with L<nbdkit-ssh-plugin(1)>
 | ||||||
|  | +because the sftp protocol does not support reading sparseness
 | ||||||
|  | +information, but you may be able to get this information directly from
 | ||||||
|  | +the source disk on the remote server using commands such as
 | ||||||
|  | +L<xfs_bmap(8)>.  A similar situation applies to
 | ||||||
|  | +L<nbdkit-curl-plugin(1)>.
 | ||||||
|  | +
 | ||||||
|  | +Note that the extent list is read-only.  This filter does not monitor
 | ||||||
|  | +writes and trims in order to update the extent list.  What can happen
 | ||||||
|  | +is that you would write to a “hole” in the disk, but would not be able
 | ||||||
|  | +to read it back because the NBD client would still think that part of
 | ||||||
|  | +the disk is a hole.  So it is generally only safe to use this filter
 | ||||||
|  | +in read-only mode (I<-r> option).
 | ||||||
|  |   | ||||||
|  |  =head1 FILE FORMAT | ||||||
|  |   | ||||||
|  | diff --git a/plugins/curl/nbdkit-curl-plugin.pod b/plugins/curl/nbdkit-curl-plugin.pod
 | ||||||
|  | index 827e0bd..d3c8524 100644
 | ||||||
|  | --- a/plugins/curl/nbdkit-curl-plugin.pod
 | ||||||
|  | +++ b/plugins/curl/nbdkit-curl-plugin.pod
 | ||||||
|  | @@ -182,6 +182,7 @@ L<libcurl(3)>,
 | ||||||
|  |  L<CURLOPT_COOKIE(3)> | ||||||
|  |  L<CURLOPT_VERBOSE(3)>, | ||||||
|  |  L<nbdkit(1)>, | ||||||
|  | +L<nbdkit-extentlist-filter(1)>,
 | ||||||
|  |  L<nbdkit-readahead-filter(1)>, | ||||||
|  |  L<nbdkit-retry-filter(1)>, | ||||||
|  |  L<nbdkit-ssh-plugin(1)>, | ||||||
|  | diff --git a/plugins/ssh/nbdkit-ssh-plugin.pod b/plugins/ssh/nbdkit-ssh-plugin.pod
 | ||||||
|  | index 0a0421d..3fc3146 100644
 | ||||||
|  | --- a/plugins/ssh/nbdkit-ssh-plugin.pod
 | ||||||
|  | +++ b/plugins/ssh/nbdkit-ssh-plugin.pod
 | ||||||
|  | @@ -316,6 +316,7 @@ C<nbdkit-ssh-plugin> first appeared in nbdkit 1.12.
 | ||||||
|  |   | ||||||
|  |  L<nbdkit(1)>, | ||||||
|  |  L<nbdkit-curl-plugin(1)>, | ||||||
|  | +L<nbdkit-extentlist-filter(1)>,
 | ||||||
|  |  L<nbdkit-readahead-filter(1)>, | ||||||
|  |  L<nbdkit-retry-filter(1)>, | ||||||
|  |  L<nbdkit-plugin(3)>, | ||||||
|  | diff --git a/tests/test-extentlist.sh b/tests/test-extentlist.sh
 | ||||||
|  | index 7d05de4..73ce3ca 100755
 | ||||||
|  | --- a/tests/test-extentlist.sh
 | ||||||
|  | +++ b/tests/test-extentlist.sh
 | ||||||
|  | @@ -50,7 +50,7 @@ cleanup_fn rm $files
 | ||||||
|  |  test () | ||||||
|  |  { | ||||||
|  |      nbdkit -v -D extentlist.lookup=1 \ | ||||||
|  | -           -U - \
 | ||||||
|  | +           -r -U - \
 | ||||||
|  |             --filter=extentlist \ | ||||||
|  |             null size=$1 extentlist=$input \ | ||||||
|  |             --run 'qemu-img map -f raw --output=json $nbd' | | ||||||
|  | -- 
 | ||||||
|  | 2.18.2 | ||||||
|  | 
 | ||||||
							
								
								
									
										17
									
								
								SOURCES/nbdkit-1.16.2.tar.gz.sig
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								SOURCES/nbdkit-1.16.2.tar.gz.sig
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,17 @@ | |||||||
|  | -----BEGIN PGP SIGNATURE----- | ||||||
|  | 
 | ||||||
|  | iQJFBAABCAAvFiEE93dPsa0HSn6Mh2fqkXOPc+G3aKAFAl4wFvoRHHJpY2hAYW5u | ||||||
|  | ZXhpYS5vcmcACgkQkXOPc+G3aKASexAAmpZw61rCI7SY8zm4O0gb+pIx7oLYx0Lq | ||||||
|  | 2puIftzxUUw9Q6pFJJyXSvlsvHy3qUF7HiMVdpW61ItIChV1xBDVKEPAacNzsZh4 | ||||||
|  | 30CI7kfJMfj6u+hpOCVlLk4uJFjZkmIpEKkDpEBemxLMME4JsLJdawKzKhjT2PI7 | ||||||
|  | dWMjYkOeD4NkAzQLQGskEswoIgZQ0twuyPUErjEL9fcXw4OjxFvQJG85FsIF2lR6 | ||||||
|  | FUDQg5y9YLzeMJMsjW4rO+LAz2c1mJwYR1EgYP43avm/pJfd1mVQLGRoLb7NwMSw | ||||||
|  | 6mkwhJ4Kvq6BN0PSqpKqQtXZrDoElWN8cVJVf+dAjONcvzYi0gsHWDL+FZ731Q2M | ||||||
|  | s4nq0aRscBTL2DOaE9DzBY2AO1jKUB/+02qRpidWTYBmsmL2QQI8n33Q7JuDuEXX | ||||||
|  | bVm1RDA4ike4PUXXY5KJ6MZhKID5453SVFausFse+u4MCQHQPFYspkXmaNWRhjgs | ||||||
|  | yu2zPc9jHdBkpzNov/CCZoFketFRz/BKexBeH2vcfTYfREVf9lEZi7qEa0kQHDn9 | ||||||
|  | EMTFsCqmGat9TEVbt9t8c/tODTeRE00MFx4gPspzy+m4YP+Gl3ySHsAbPQ90uBGX | ||||||
|  | c8xggwqWXr1GAP5HbAhs/Bs7USrWMMgqii1ppnzoAkHh+j4rsdL4dS2dmhxX756u | ||||||
|  | IKP/JC2oA8U= | ||||||
|  | =mV8z | ||||||
|  | -----END PGP SIGNATURE----- | ||||||
							
								
								
									
										993
									
								
								SPECS/nbdkit.spec
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										993
									
								
								SPECS/nbdkit.spec
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,993 @@ | |||||||
|  | %global _hardened_build 1 | ||||||
|  | 
 | ||||||
|  | %ifarch aarch64 %{arm} x86_64 ppc %{power64} | ||||||
|  | %global have_libguestfs 1 | ||||||
|  | %endif | ||||||
|  | 
 | ||||||
|  | # Architectures where the complete test suite must pass. | ||||||
|  | # | ||||||
|  | # On all other architectures, a simpler test suite must pass.  This | ||||||
|  | # omits any tests that run full qemu, since running qemu under TCG is | ||||||
|  | # often broken on non-x86_64 arches. | ||||||
|  | %global complete_test_arches x86_64 | ||||||
|  | 
 | ||||||
|  | # Disable libvirt on riscv64 for now. | ||||||
|  | %ifnarch riscv64 | ||||||
|  | %global have_libvirt 1 | ||||||
|  | %endif | ||||||
|  | 
 | ||||||
|  | # If we should verify tarball signature with GPGv2. | ||||||
|  | %global verify_tarball_signature 1 | ||||||
|  | 
 | ||||||
|  | # If there are patches which touch autotools files, set this to 1. | ||||||
|  | %global patches_touch_autotools 1 | ||||||
|  | 
 | ||||||
|  | # The source directory. | ||||||
|  | %global source_directory 1.16-stable | ||||||
|  | 
 | ||||||
|  | Name:           nbdkit | ||||||
|  | Version:        1.16.2 | ||||||
|  | Release:        2%{?dist} | ||||||
|  | Summary:        NBD server | ||||||
|  | 
 | ||||||
|  | License:        BSD | ||||||
|  | URL:            https://github.com/libguestfs/nbdkit | ||||||
|  | 
 | ||||||
|  | Source0:        http://libguestfs.org/download/nbdkit/%{source_directory}/%{name}-%{version}.tar.gz | ||||||
|  | %if 0%{verify_tarball_signature} | ||||||
|  | Source1:        http://libguestfs.org/download/nbdkit/%{source_directory}/%{name}-%{version}.tar.gz.sig | ||||||
|  | # Keyring used to verify tarball signature. | ||||||
|  | Source2:        libguestfs.keyring | ||||||
|  | %endif | ||||||
|  | 
 | ||||||
|  | # Patches come from this upstream branch: | ||||||
|  | # https://github.com/libguestfs/nbdkit/tree/rhel-8.2 | ||||||
|  | 
 | ||||||
|  | # Patches. | ||||||
|  | Patch0001:     0001-server-Allow-D-nbdkit.-debug-flags-for-the-core-serv.patch | ||||||
|  | Patch0002:     0002-server-Allow-D-debug-flags-to-contain-dots-for-names.patch | ||||||
|  | Patch0003:     0003-server-Add-D-nbdkit.backend.controlpath-and-D-nbdkit.patch | ||||||
|  | Patch0004:     0004-python-Add-various-constants-to-the-API.patch | ||||||
|  | Patch0005:     0005-python-Implement-nbdkit-API-version-2.patch | ||||||
|  | Patch0006:     0006-python-Implement-cache.patch | ||||||
|  | Patch0007:     0007-python-Implement-can_zero-can_fast_zero.patch | ||||||
|  | Patch0008:     0008-python-Implement-can_multi_conn.patch | ||||||
|  | Patch0009:     0009-python-Implement-can_fua-and-can_cache.patch | ||||||
|  | Patch0010:     0010-tests-Test-the-Python-plugin-thoroughly.patch | ||||||
|  | Patch0011:     0011-New-filter-extentlist.patch | ||||||
|  | Patch0012:     0012-extentlist-Documentation-and-test-fixes.patch | ||||||
|  | 
 | ||||||
|  | %if 0%{patches_touch_autotools} | ||||||
|  | BuildRequires: autoconf, automake, libtool | ||||||
|  | %endif | ||||||
|  | 
 | ||||||
|  | %if 0%{patches_touch_autotools} | ||||||
|  | BuildRequires: autoconf, automake, libtool | ||||||
|  | %endif | ||||||
|  | 
 | ||||||
|  | %if 0%{?rhel} == 8 | ||||||
|  | # On RHEL 8, we cannot build the package on i686 (no virt stack). | ||||||
|  | ExcludeArch:    i686 | ||||||
|  | %endif | ||||||
|  | 
 | ||||||
|  | %ifnarch %{complete_test_arches} | ||||||
|  | BuildRequires:  autoconf, automake, libtool | ||||||
|  | %endif | ||||||
|  | BuildRequires:  /usr/bin/pod2man | ||||||
|  | BuildRequires:  gnutls-devel | ||||||
|  | BuildRequires:  libselinux-devel | ||||||
|  | %if 0%{?have_libguestfs} | ||||||
|  | BuildRequires:  libguestfs-devel | ||||||
|  | %endif | ||||||
|  | %if 0%{?have_libvirt} | ||||||
|  | BuildRequires:  libvirt-devel | ||||||
|  | %endif | ||||||
|  | BuildRequires:  xz-devel | ||||||
|  | BuildRequires:  zlib-devel | ||||||
|  | BuildRequires:  libcurl-devel | ||||||
|  | BuildRequires:  libssh-devel | ||||||
|  | BuildRequires:  e2fsprogs, e2fsprogs-devel | ||||||
|  | BuildRequires:  bash-completion | ||||||
|  | BuildRequires:  perl-devel | ||||||
|  | BuildRequires:  perl(ExtUtils::Embed) | ||||||
|  | BuildRequires:  python3-devel | ||||||
|  | %if 0%{verify_tarball_signature} | ||||||
|  | BuildRequires:  gnupg2 | ||||||
|  | %endif | ||||||
|  | 
 | ||||||
|  | # Only for running the test suite: | ||||||
|  | BuildRequires:  /usr/bin/certtool | ||||||
|  | BuildRequires:  jq | ||||||
|  | BuildRequires:  /usr/bin/nbdsh | ||||||
|  | BuildRequires:  /usr/bin/qemu-img | ||||||
|  | BuildRequires:  /usr/bin/socat | ||||||
|  | BuildRequires:  /usr/sbin/ss | ||||||
|  | BuildRequires:  /usr/bin/ssh-keygen | ||||||
|  | 
 | ||||||
|  | # nbdkit is a metapackage pulling the server and a useful subset | ||||||
|  | # of the plugins and filters. | ||||||
|  | Requires:       nbdkit-server%{?_isa} = %{version}-%{release} | ||||||
|  | Requires:       nbdkit-basic-plugins%{?_isa} = %{version}-%{release} | ||||||
|  | Requires:       nbdkit-basic-filters%{?_isa} = %{version}-%{release} | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | %description | ||||||
|  | NBD is a protocol for accessing block devices (hard disks and | ||||||
|  | disk-like things) over the network. | ||||||
|  | 
 | ||||||
|  | nbdkit is a toolkit for creating NBD servers. | ||||||
|  | 
 | ||||||
|  | The key features are: | ||||||
|  | 
 | ||||||
|  | * Multithreaded NBD server written in C with good performance. | ||||||
|  | 
 | ||||||
|  | * Minimal dependencies for the basic server. | ||||||
|  | 
 | ||||||
|  | * Liberal license (BSD) allows nbdkit to be linked to proprietary | ||||||
|  |   libraries or included in proprietary code. | ||||||
|  | 
 | ||||||
|  | * Well-documented, simple plugin API with a stable ABI guarantee. | ||||||
|  |   Lets you to export "unconventional" block devices easily. | ||||||
|  | 
 | ||||||
|  | * You can write plugins in C or many other languages. | ||||||
|  | 
 | ||||||
|  | * Filters can be stacked in front of plugins to transform the output. | ||||||
|  | 
 | ||||||
|  | In Red Hat Enterprise Linux, '%{name}' is a meta-package which pulls | ||||||
|  | in the core server and a useful subset of plugins and filters. | ||||||
|  | 
 | ||||||
|  | If you want just the server, install '%{name}-server'. | ||||||
|  | 
 | ||||||
|  | To develop plugins, install the '%{name}-devel' package and start by | ||||||
|  | reading the nbdkit(1) and nbdkit-plugin(3) manual pages. | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | %package server | ||||||
|  | Summary:        The %{name} server | ||||||
|  | License:        BSD | ||||||
|  | 
 | ||||||
|  | Conflicts:      nbdkit < 1.12 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | %description server | ||||||
|  | This package contains the %{name} server with no plugins or filters. | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | %package basic-plugins | ||||||
|  | Summary:        Basic plugins for %{name} | ||||||
|  | License:        BSD | ||||||
|  | 
 | ||||||
|  | Requires:       %{name}-server%{?_isa} = %{version}-%{release} | ||||||
|  | Provides:       %{name}-data-plugin = %{version}-%{release} | ||||||
|  | Provides:       %{name}-file-plugin = %{version}-%{release} | ||||||
|  | Provides:       %{name}-floppy-plugin = %{version}-%{release} | ||||||
|  | Provides:       %{name}-full-plugin = %{version}-%{release} | ||||||
|  | Provides:       %{name}-info-plugin = %{version}-%{release} | ||||||
|  | Provides:       %{name}-memory-plugin = %{version}-%{release} | ||||||
|  | Provides:       %{name}-null-plugin = %{version}-%{release} | ||||||
|  | Provides:       %{name}-pattern-plugin = %{version}-%{release} | ||||||
|  | Provides:       %{name}-partitioning-plugin = %{version}-%{release} | ||||||
|  | Provides:       %{name}-random-plugin = %{version}-%{release} | ||||||
|  | Provides:       %{name}-sh-plugin = %{version}-%{release} | ||||||
|  | Provides:       %{name}-split-plugin = %{version}-%{release} | ||||||
|  | Provides:       %{name}-streaming-plugin = %{version}-%{release} | ||||||
|  | Provides:       %{name}-zero-plugin = %{version}-%{release} | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | %description basic-plugins | ||||||
|  | This package contains some basic plugins for %{name} which have only | ||||||
|  | trivial dependencies. | ||||||
|  | 
 | ||||||
|  | nbdkit-data-plugin         Serve small amounts of data from the command line. | ||||||
|  | 
 | ||||||
|  | nbdkit-file-plugin         The normal file plugin for serving files. | ||||||
|  | 
 | ||||||
|  | nbdkit-floppy-plugin       Create a virtual floppy disk from a directory. | ||||||
|  | 
 | ||||||
|  | nbdkit-full-plugin         A virtual disk that returns ENOSPC errors. | ||||||
|  | 
 | ||||||
|  | nbdkit-info-plugin         Serve client and server information. | ||||||
|  | 
 | ||||||
|  | nbdkit-memory-plugin       A virtual memory plugin. | ||||||
|  | 
 | ||||||
|  | nbdkit-null-plugin         A null (bitbucket) plugin. | ||||||
|  | 
 | ||||||
|  | nbdkit-pattern-plugin      Fixed test pattern. | ||||||
|  | 
 | ||||||
|  | nbdkit-partitioning-plugin Create virtual disks from partitions. | ||||||
|  | 
 | ||||||
|  | nbdkit-random-plugin       Random content plugin for testing. | ||||||
|  | 
 | ||||||
|  | nbdkit-sh-plugin           Write plugins as shell scripts or executables. | ||||||
|  | 
 | ||||||
|  | nbdkit-split-plugin        Concatenate one or more files. | ||||||
|  | 
 | ||||||
|  | nbdkit-streaming-plugin    A streaming file serving plugin. | ||||||
|  | 
 | ||||||
|  | nbdkit-zero-plugin         Zero-length plugin for testing. | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | %package example-plugins | ||||||
|  | Summary:        Example plugins for %{name} | ||||||
|  | License:        BSD | ||||||
|  | 
 | ||||||
|  | Requires:       %{name}-server%{?_isa} = %{version}-%{release} | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | %description example-plugins | ||||||
|  | This package contains example plugins for %{name}. | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | # The plugins below have non-trivial dependencies are so are | ||||||
|  | # packaged separately. | ||||||
|  | 
 | ||||||
|  | %package curl-plugin | ||||||
|  | Summary:        HTTP/FTP (cURL) plugin for %{name} | ||||||
|  | License:        BSD | ||||||
|  | 
 | ||||||
|  | Requires:       %{name}-server%{?_isa} = %{version}-%{release} | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | %description curl-plugin | ||||||
|  | This package contains cURL (HTTP/FTP) support for %{name}. | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | %package gzip-plugin | ||||||
|  | Summary:        GZip file serving plugin for %{name} | ||||||
|  | License:        BSD | ||||||
|  | 
 | ||||||
|  | # Upgrade path from RHEL 8.0 | ||||||
|  | Provides:       %{name}-plugin-gzip = %{version}-%{release} | ||||||
|  | Obsoletes:      %{name}-plugin-gzip <= %{version}-%{release} | ||||||
|  | 
 | ||||||
|  | Requires:       %{name}-server%{?_isa} = %{version}-%{release} | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | %description gzip-plugin | ||||||
|  | This package is a gzip file serving plugin for %{name}. | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | %package linuxdisk-plugin | ||||||
|  | Summary:        Virtual Linux disk plugin for %{name} | ||||||
|  | License:        BSD | ||||||
|  | 
 | ||||||
|  | Requires:       %{name}-server%{?_isa} = %{version}-%{release} | ||||||
|  | # for mke2fs | ||||||
|  | Requires:       e2fsprogs | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | %description linuxdisk-plugin | ||||||
|  | This package is a virtual Linux disk plugin for %{name}. | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | %package python-plugin | ||||||
|  | Summary:        Python 3 plugin for %{name} | ||||||
|  | License:        BSD | ||||||
|  | 
 | ||||||
|  | # Upgrade path from RHEL 8.0 | ||||||
|  | Provides:       %{name}-plugin-python-common = %{version}-%{release} | ||||||
|  | Obsoletes:      %{name}-plugin-python-common <= %{version}-%{release} | ||||||
|  | Provides:       %{name}-plugin-python3 = %{version}-%{release} | ||||||
|  | Obsoletes:      %{name}-plugin-python3 <= %{version}-%{release} | ||||||
|  | 
 | ||||||
|  | Requires:       %{name}-server%{?_isa} = %{version}-%{release} | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | %description python-plugin | ||||||
|  | This package lets you write Python 3 plugins for %{name}. | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | %package ssh-plugin | ||||||
|  | Summary:        SSH plugin for %{name} | ||||||
|  | License:        BSD | ||||||
|  | 
 | ||||||
|  | Requires:       %{name}-server%{?_isa} = %{version}-%{release} | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | %description ssh-plugin | ||||||
|  | This package contains SSH support for %{name}. | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | %ifarch %{ix86} x86_64 | ||||||
|  | %package vddk-plugin | ||||||
|  | Summary:        VMware VDDK plugin for %{name} | ||||||
|  | License:        BSD | ||||||
|  | 
 | ||||||
|  | # Upgrade path from RHEL 8.0 | ||||||
|  | Provides:       %{name}-plugin-vddk = %{version}-%{release} | ||||||
|  | Obsoletes:      %{name}-plugin-vddk <= %{version}-%{release} | ||||||
|  | 
 | ||||||
|  | Requires:       %{name}-server%{?_isa} = %{version}-%{release} | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | %description vddk-plugin | ||||||
|  | This package is a plugin for %{name} which connects to | ||||||
|  | VMware VDDK for accessing VMware disks and servers. | ||||||
|  | %endif | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | %package basic-filters | ||||||
|  | Summary:        Basic filters for %{name} | ||||||
|  | License:        BSD | ||||||
|  | 
 | ||||||
|  | Requires:       %{name}-server%{?_isa} = %{version}-%{release} | ||||||
|  | Provides:       %{name}-blocksize-filter = %{version}-%{release} | ||||||
|  | Provides:       %{name}-cache-filter = %{version}-%{release} | ||||||
|  | Provides:       %{name}-cacheextents-filter = %{version}-%{release} | ||||||
|  | Provides:       %{name}-cow-filter = %{version}-%{release} | ||||||
|  | Provides:       %{name}-delay-filter = %{version}-%{release} | ||||||
|  | Provides:       %{name}-error-filter = %{version}-%{release} | ||||||
|  | Provides:       %{name}-extentlist-filter = %{version}-%{release} | ||||||
|  | Provides:       %{name}-fua-filter = %{version}-%{release} | ||||||
|  | Provides:       %{name}-log-filter = %{version}-%{release} | ||||||
|  | Provides:       %{name}-nocache-filter = %{version}-%{release} | ||||||
|  | Provides:       %{name}-noextents-filter = %{version}-%{release} | ||||||
|  | Provides:       %{name}-noparallel-filter = %{version}-%{release} | ||||||
|  | Provides:       %{name}-nozero-filter = %{version}-%{release} | ||||||
|  | Provides:       %{name}-offset-filter = %{version}-%{release} | ||||||
|  | Provides:       %{name}-partition-filter = %{version}-%{release} | ||||||
|  | Provides:       %{name}-rate-filter = %{version}-%{release} | ||||||
|  | Provides:       %{name}-readahead-filter = %{version}-%{release} | ||||||
|  | Provides:       %{name}-retry-filter = %{version}-%{release} | ||||||
|  | Provides:       %{name}-stats-filter = %{version}-%{release} | ||||||
|  | Provides:       %{name}-truncate-filter = %{version}-%{release} | ||||||
|  | 
 | ||||||
|  | %description basic-filters | ||||||
|  | This package contains some basic filters for %{name} which have only | ||||||
|  | trivial dependencies. | ||||||
|  | 
 | ||||||
|  | nbdkit-blocksize-filter    Adjust block size of requests sent to plugins. | ||||||
|  | 
 | ||||||
|  | nbdkit-cache-filter        Server-side cache. | ||||||
|  | 
 | ||||||
|  | nbdkit-cacheextents-filter Cache extents. | ||||||
|  | 
 | ||||||
|  | nbdkit-cow-filter          Copy-on-write overlay for read-only plugins. | ||||||
|  | 
 | ||||||
|  | nbdkit-delay-filter        Inject read and write delays. | ||||||
|  | 
 | ||||||
|  | nbdkit-error-filter        Inject errors. | ||||||
|  | 
 | ||||||
|  | nbdkit-extentlist-filter   Place extent list over a plugin. | ||||||
|  | 
 | ||||||
|  | nbdkit-fua-filter          Modify flush behaviour in plugins. | ||||||
|  | 
 | ||||||
|  | nbdkit-log-filter          Log all transactions to a file. | ||||||
|  | 
 | ||||||
|  | nbdkit-nocache-filter      Disable cache requests in the underlying plugin. | ||||||
|  | 
 | ||||||
|  | nbdkit-noextents-filter    Disable extents in the underlying plugin. | ||||||
|  | 
 | ||||||
|  | nbdkit-noparallel-filter   Serialize requests to the underlying plugin. | ||||||
|  | 
 | ||||||
|  | nbdkit-nozero-filter       Adjust handling of zero requests by plugins. | ||||||
|  | 
 | ||||||
|  | nbdkit-offset-filter       Serve an offset and range. | ||||||
|  | 
 | ||||||
|  | nbdkit-partition-filter    Serve a single partition. | ||||||
|  | 
 | ||||||
|  | nbdkit-rate-filter         Limit bandwidth by connection or server. | ||||||
|  | 
 | ||||||
|  | nbdkit-readahead-filter    Prefetch data when reading sequentially. | ||||||
|  | 
 | ||||||
|  | nbdkit-retry-filter        Reopen connection on error. | ||||||
|  | 
 | ||||||
|  | nbdkit-stats-filter        Display statistics about operations. | ||||||
|  | 
 | ||||||
|  | nbdkit-truncate-filter     Truncate, expand, round up or round down size. | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | %package xz-filter | ||||||
|  | Summary:        XZ filter for %{name} | ||||||
|  | License:        BSD | ||||||
|  | 
 | ||||||
|  | # Upgrade path from RHEL 8.0 | ||||||
|  | Provides:       %{name}-plugin-xz = %{version}-%{release} | ||||||
|  | Obsoletes:      %{name}-plugin-xz <= %{version}-%{release} | ||||||
|  | 
 | ||||||
|  | Requires:       %{name}-server%{?_isa} = %{version}-%{release} | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | %description xz-filter | ||||||
|  | This package is the xz filter for %{name}. | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | %package devel | ||||||
|  | Summary:        Development files and documentation for %{name} | ||||||
|  | License:        BSD | ||||||
|  | 
 | ||||||
|  | Requires:       %{name}-server%{?_isa} = %{version}-%{release} | ||||||
|  | Requires:       pkgconfig | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | %description devel | ||||||
|  | This package contains development files and documentation | ||||||
|  | for %{name}.  Install this package if you want to develop | ||||||
|  | plugins for %{name}. | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | %package bash-completion | ||||||
|  | Summary:       Bash tab-completion for %{name} | ||||||
|  | BuildArch:     noarch | ||||||
|  | Requires:      bash-completion >= 2.0 | ||||||
|  | Requires:      %{name}-server = %{version}-%{release} | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | %description bash-completion | ||||||
|  | Install this package if you want intelligent bash tab-completion | ||||||
|  | for %{name}. | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | %prep | ||||||
|  | %if 0%{verify_tarball_signature} | ||||||
|  | tmphome="$(mktemp -d)" | ||||||
|  | gpgv2 --homedir "$tmphome" --keyring %{SOURCE2} %{SOURCE1} %{SOURCE0} | ||||||
|  | %endif | ||||||
|  | %autosetup -p1 | ||||||
|  | %if 0%{patches_touch_autotools} | ||||||
|  | autoreconf -i | ||||||
|  | %endif | ||||||
|  | 
 | ||||||
|  | %ifnarch %{complete_test_arches} | ||||||
|  | # Simplify the test suite so it doesn't require qemu. | ||||||
|  | sed -i -e '/^if HAVE_LIBGUESTFS/,/^endif HAVE_LIBGUESTFS/d' tests/Makefile.am | ||||||
|  | sed -i -e '/^if HAVE_GUESTFISH/,/^endif HAVE_GUESTFISH/d' tests/Makefile.am | ||||||
|  | autoreconf -i | ||||||
|  | %endif | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | %build | ||||||
|  | %configure \ | ||||||
|  |     PYTHON=%{_bindir}/python3 \ | ||||||
|  |     --disable-static \ | ||||||
|  |     --disable-lua \ | ||||||
|  |     --disable-perl \ | ||||||
|  |     --disable-nbd-plugin \ | ||||||
|  |     --disable-ocaml \ | ||||||
|  |     --disable-ruby \ | ||||||
|  |     --disable-rust \ | ||||||
|  |     --disable-ruby \ | ||||||
|  |     --disable-tcl \ | ||||||
|  |     --without-ext2 \ | ||||||
|  |     --without-iso \ | ||||||
|  |     --without-libguestfs \ | ||||||
|  |     --without-libvirt \ | ||||||
|  |     --with-tls-priority=@NBDKIT,SYSTEM | ||||||
|  | 
 | ||||||
|  | # Verify that it picked the correct version of Python | ||||||
|  | # to avoid RHBZ#1404631 happening again silently. | ||||||
|  | grep '^PYTHON_VERSION = 3' Makefile | ||||||
|  | 
 | ||||||
|  | make %{?_smp_mflags} | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | %install | ||||||
|  | %make_install | ||||||
|  | 
 | ||||||
|  | # Delete libtool crap. | ||||||
|  | find $RPM_BUILD_ROOT -name '*.la' -delete | ||||||
|  | 
 | ||||||
|  | # If cargo happens to be installed on the machine then the | ||||||
|  | # rust plugin is built.  Delete it if this happens. | ||||||
|  | rm -f $RPM_BUILD_ROOT%{_mandir}/man3/nbdkit-rust-plugin.3* | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | %check | ||||||
|  | # Workaround for broken libvirt (RHBZ#1138604). | ||||||
|  | mkdir -p $HOME/.cache/libvirt | ||||||
|  | 
 | ||||||
|  | # tests/test-captive.sh is racy especially on s390x.  We need to | ||||||
|  | # rethink this test upstream. | ||||||
|  | truncate -s 0 tests/test-captive.sh | ||||||
|  | 
 | ||||||
|  | # Temporarily kill tests/test-shutdown.sh because this test is racy on | ||||||
|  | # slow hardware. | ||||||
|  | truncate -s 0 tests/test-shutdown.sh | ||||||
|  | 
 | ||||||
|  | %ifarch s390x | ||||||
|  | # Temporarily kill tests/test-cache-max-size.sh since it fails | ||||||
|  | # sometimes on s390x for unclear reasons. | ||||||
|  | truncate -s 0 tests/test-cache-max-size.sh | ||||||
|  | %endif | ||||||
|  | 
 | ||||||
|  | # Make sure we can see the debug messages (RHBZ#1230160). | ||||||
|  | export LIBGUESTFS_DEBUG=1 | ||||||
|  | export LIBGUESTFS_TRACE=1 | ||||||
|  | 
 | ||||||
|  | make %{?_smp_mflags} check || { | ||||||
|  |     cat tests/test-suite.log | ||||||
|  |     exit 1 | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | %files | ||||||
|  | # metapackage so empty | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | %files server | ||||||
|  | %doc README | ||||||
|  | %license LICENSE | ||||||
|  | %{_sbindir}/nbdkit | ||||||
|  | %dir %{_libdir}/%{name} | ||||||
|  | %dir %{_libdir}/%{name}/plugins | ||||||
|  | %dir %{_libdir}/%{name}/filters | ||||||
|  | %{_mandir}/man1/nbdkit.1* | ||||||
|  | %{_mandir}/man1/nbdkit-captive.1* | ||||||
|  | %{_mandir}/man1/nbdkit-loop.1* | ||||||
|  | %{_mandir}/man1/nbdkit-probing.1* | ||||||
|  | %{_mandir}/man1/nbdkit-protocol.1* | ||||||
|  | %{_mandir}/man1/nbdkit-service.1* | ||||||
|  | %{_mandir}/man1/nbdkit-security.1* | ||||||
|  | %{_mandir}/man1/nbdkit-tls.1* | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | %files basic-plugins | ||||||
|  | %doc README | ||||||
|  | %license LICENSE | ||||||
|  | %{_libdir}/%{name}/plugins/nbdkit-data-plugin.so | ||||||
|  | %{_libdir}/%{name}/plugins/nbdkit-file-plugin.so | ||||||
|  | %{_libdir}/%{name}/plugins/nbdkit-floppy-plugin.so | ||||||
|  | %{_libdir}/%{name}/plugins/nbdkit-full-plugin.so | ||||||
|  | %{_libdir}/%{name}/plugins/nbdkit-info-plugin.so | ||||||
|  | %{_libdir}/%{name}/plugins/nbdkit-memory-plugin.so | ||||||
|  | %{_libdir}/%{name}/plugins/nbdkit-null-plugin.so | ||||||
|  | %{_libdir}/%{name}/plugins/nbdkit-partitioning-plugin.so | ||||||
|  | %{_libdir}/%{name}/plugins/nbdkit-pattern-plugin.so | ||||||
|  | %{_libdir}/%{name}/plugins/nbdkit-random-plugin.so | ||||||
|  | %{_libdir}/%{name}/plugins/nbdkit-sh-plugin.so | ||||||
|  | %{_libdir}/%{name}/plugins/nbdkit-split-plugin.so | ||||||
|  | %{_libdir}/%{name}/plugins/nbdkit-streaming-plugin.so | ||||||
|  | %{_libdir}/%{name}/plugins/nbdkit-zero-plugin.so | ||||||
|  | %{_mandir}/man1/nbdkit-data-plugin.1* | ||||||
|  | %{_mandir}/man1/nbdkit-file-plugin.1* | ||||||
|  | %{_mandir}/man1/nbdkit-floppy-plugin.1* | ||||||
|  | %{_mandir}/man1/nbdkit-full-plugin.1* | ||||||
|  | %{_mandir}/man1/nbdkit-info-plugin.1* | ||||||
|  | %{_mandir}/man1/nbdkit-memory-plugin.1* | ||||||
|  | %{_mandir}/man1/nbdkit-null-plugin.1* | ||||||
|  | %{_mandir}/man1/nbdkit-partitioning-plugin.1* | ||||||
|  | %{_mandir}/man1/nbdkit-pattern-plugin.1* | ||||||
|  | %{_mandir}/man1/nbdkit-random-plugin.1* | ||||||
|  | %{_mandir}/man3/nbdkit-sh-plugin.3* | ||||||
|  | %{_mandir}/man1/nbdkit-split-plugin.1* | ||||||
|  | %{_mandir}/man1/nbdkit-streaming-plugin.1* | ||||||
|  | %{_mandir}/man1/nbdkit-zero-plugin.1* | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | %files example-plugins | ||||||
|  | %doc README | ||||||
|  | %license LICENSE | ||||||
|  | %{_libdir}/%{name}/plugins/nbdkit-example*-plugin.so | ||||||
|  | %{_mandir}/man1/nbdkit-example*-plugin.1* | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | %files curl-plugin | ||||||
|  | %doc README | ||||||
|  | %license LICENSE | ||||||
|  | %{_libdir}/%{name}/plugins/nbdkit-curl-plugin.so | ||||||
|  | %{_mandir}/man1/nbdkit-curl-plugin.1* | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | %files gzip-plugin | ||||||
|  | %doc README | ||||||
|  | %license LICENSE | ||||||
|  | %{_libdir}/%{name}/plugins/nbdkit-gzip-plugin.so | ||||||
|  | %{_mandir}/man1/nbdkit-gzip-plugin.1* | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | %files linuxdisk-plugin | ||||||
|  | %doc README | ||||||
|  | %license LICENSE | ||||||
|  | %{_libdir}/%{name}/plugins/nbdkit-linuxdisk-plugin.so | ||||||
|  | %{_mandir}/man1/nbdkit-linuxdisk-plugin.1* | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | %files python-plugin | ||||||
|  | %doc README | ||||||
|  | %license LICENSE | ||||||
|  | %{_libdir}/%{name}/plugins/nbdkit-python-plugin.so | ||||||
|  | %{_mandir}/man3/nbdkit-python-plugin.3* | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | %files ssh-plugin | ||||||
|  | %doc README | ||||||
|  | %license LICENSE | ||||||
|  | %{_libdir}/%{name}/plugins/nbdkit-ssh-plugin.so | ||||||
|  | %{_mandir}/man1/nbdkit-ssh-plugin.1* | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | %ifarch %{ix86} x86_64 | ||||||
|  | %files vddk-plugin | ||||||
|  | %doc README | ||||||
|  | %license LICENSE | ||||||
|  | %{_libdir}/%{name}/plugins/nbdkit-vddk-plugin.so | ||||||
|  | %{_mandir}/man1/nbdkit-vddk-plugin.1* | ||||||
|  | %endif | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | %files basic-filters | ||||||
|  | %doc README | ||||||
|  | %license LICENSE | ||||||
|  | %{_libdir}/%{name}/filters/nbdkit-blocksize-filter.so | ||||||
|  | %{_libdir}/%{name}/filters/nbdkit-cache-filter.so | ||||||
|  | %{_libdir}/%{name}/filters/nbdkit-cacheextents-filter.so | ||||||
|  | %{_libdir}/%{name}/filters/nbdkit-cow-filter.so | ||||||
|  | %{_libdir}/%{name}/filters/nbdkit-delay-filter.so | ||||||
|  | %{_libdir}/%{name}/filters/nbdkit-error-filter.so | ||||||
|  | %{_libdir}/%{name}/filters/nbdkit-extentlist-filter.so | ||||||
|  | %{_libdir}/%{name}/filters/nbdkit-fua-filter.so | ||||||
|  | %{_libdir}/%{name}/filters/nbdkit-log-filter.so | ||||||
|  | %{_libdir}/%{name}/filters/nbdkit-nocache-filter.so | ||||||
|  | %{_libdir}/%{name}/filters/nbdkit-noextents-filter.so | ||||||
|  | %{_libdir}/%{name}/filters/nbdkit-noparallel-filter.so | ||||||
|  | %{_libdir}/%{name}/filters/nbdkit-nozero-filter.so | ||||||
|  | %{_libdir}/%{name}/filters/nbdkit-offset-filter.so | ||||||
|  | %{_libdir}/%{name}/filters/nbdkit-partition-filter.so | ||||||
|  | %{_libdir}/%{name}/filters/nbdkit-rate-filter.so | ||||||
|  | %{_libdir}/%{name}/filters/nbdkit-readahead-filter.so | ||||||
|  | %{_libdir}/%{name}/filters/nbdkit-retry-filter.so | ||||||
|  | %{_libdir}/%{name}/filters/nbdkit-stats-filter.so | ||||||
|  | %{_libdir}/%{name}/filters/nbdkit-truncate-filter.so | ||||||
|  | %{_mandir}/man1/nbdkit-blocksize-filter.1* | ||||||
|  | %{_mandir}/man1/nbdkit-cache-filter.1* | ||||||
|  | %{_mandir}/man1/nbdkit-cacheextents-filter.1* | ||||||
|  | %{_mandir}/man1/nbdkit-cow-filter.1* | ||||||
|  | %{_mandir}/man1/nbdkit-delay-filter.1* | ||||||
|  | %{_mandir}/man1/nbdkit-error-filter.1* | ||||||
|  | %{_mandir}/man1/nbdkit-extentlist-filter.1* | ||||||
|  | %{_mandir}/man1/nbdkit-fua-filter.1* | ||||||
|  | %{_mandir}/man1/nbdkit-log-filter.1* | ||||||
|  | %{_mandir}/man1/nbdkit-nocache-filter.1* | ||||||
|  | %{_mandir}/man1/nbdkit-noextents-filter.1* | ||||||
|  | %{_mandir}/man1/nbdkit-noparallel-filter.1* | ||||||
|  | %{_mandir}/man1/nbdkit-nozero-filter.1* | ||||||
|  | %{_mandir}/man1/nbdkit-offset-filter.1* | ||||||
|  | %{_mandir}/man1/nbdkit-partition-filter.1* | ||||||
|  | %{_mandir}/man1/nbdkit-rate-filter.1* | ||||||
|  | %{_mandir}/man1/nbdkit-readahead-filter.1* | ||||||
|  | %{_mandir}/man1/nbdkit-retry-filter.1* | ||||||
|  | %{_mandir}/man1/nbdkit-stats-filter.1* | ||||||
|  | %{_mandir}/man1/nbdkit-truncate-filter.1* | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | %files xz-filter | ||||||
|  | %doc README | ||||||
|  | %license LICENSE | ||||||
|  | %{_libdir}/%{name}/filters/nbdkit-xz-filter.so | ||||||
|  | %{_mandir}/man1/nbdkit-xz-filter.1* | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | %files devel | ||||||
|  | %doc BENCHMARKING OTHER_PLUGINS README SECURITY TODO | ||||||
|  | %license LICENSE | ||||||
|  | # Include the source of the example plugins in the documentation. | ||||||
|  | %doc plugins/example*/*.c | ||||||
|  | %doc plugins/python/example.py | ||||||
|  | %doc plugins/sh/example.sh | ||||||
|  | %{_includedir}/nbdkit-common.h | ||||||
|  | %{_includedir}/nbdkit-filter.h | ||||||
|  | %{_includedir}/nbdkit-plugin.h | ||||||
|  | %{_includedir}/nbdkit-version.h | ||||||
|  | %{_includedir}/nbd-protocol.h | ||||||
|  | %{_mandir}/man3/nbdkit-filter.3* | ||||||
|  | %{_mandir}/man3/nbdkit-plugin.3* | ||||||
|  | %{_mandir}/man1/nbdkit-release-notes-1.*.1* | ||||||
|  | %{_libdir}/pkgconfig/nbdkit.pc | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | %files bash-completion | ||||||
|  | %license LICENSE | ||||||
|  | %dir %{_datadir}/bash-completion/completions | ||||||
|  | %{_datadir}/bash-completion/completions/nbdkit | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | %changelog | ||||||
|  | * Mon Apr 27 2020 Danilo C. L. de Paula <ddepaula@redhat.com> - 1.16.2 | ||||||
|  | - Resolves: bz#1810193 | ||||||
|  |   (Upgrade components in virt:rhel module:stream for RHEL-8.3 release) | ||||||
|  | 
 | ||||||
|  | * Fri Jun 28 2019 Danilo de Paula <ddepaula@redhat.com> - 1.4.2-5 | ||||||
|  | - Rebuild all virt packages to fix RHEL's upgrade path | ||||||
|  | - Resolves: rhbz#1695587 | ||||||
|  |   (Ensure modular RPM upgrade path) | ||||||
|  | 
 | ||||||
|  | * Mon Dec 17 2018 Richard W.M. Jones <rjones@redhat.com> - 1.4.2-4 | ||||||
|  | - Remove misguided LDFLAGS hack which removed server hardening. | ||||||
|  |   https://bugzilla.redhat.com/show_bug.cgi?id=1624149#c6 | ||||||
|  |   resolves: rhbz#1624149 | ||||||
|  | 
 | ||||||
|  | * Fri Dec 14 2018 Richard W.M. Jones <rjones@redhat.com> - 1.4.2-3 | ||||||
|  | - Use platform-python | ||||||
|  |   resolves: rhbz#1659159 | ||||||
|  | 
 | ||||||
|  | * Fri Aug 10 2018 Richard W.M. Jones <rjones@redhat.com> - 1.4.2-2 | ||||||
|  | - Add Enhanced Python error reporting | ||||||
|  |   resolves: rhbz#1614750. | ||||||
|  | - Use copy-patches.sh script. | ||||||
|  | 
 | ||||||
|  | * Wed Aug  1 2018 Richard W.M. Jones <rjones@redhat.com> - 1.4.2-1 | ||||||
|  | - New stable version 1.4.2. | ||||||
|  | 
 | ||||||
|  | * Wed Jul 25 2018 Richard W.M. Jones <rjones@redhat.com> - 1.4.1-3 | ||||||
|  | - Enable VDDK plugin on x86-64 only. | ||||||
|  | 
 | ||||||
|  | * Fri Jul 20 2018 Richard W.M. Jones <rjones@redhat.com> - 1.4.1-1 | ||||||
|  | - New upstream version 1.4.1. | ||||||
|  | - Small refactorings in the spec file. | ||||||
|  | 
 | ||||||
|  | * Fri Jul  6 2018 Richard W.M. Jones <rjones@redhat.com> - 1.4.0-1 | ||||||
|  | - New upstream version 1.4.0. | ||||||
|  | - New plugins: random, zero. | ||||||
|  | - New bash tab completion subpackage. | ||||||
|  | - Remove unused build dependencies. | ||||||
|  | 
 | ||||||
|  | * Sun Jul  1 2018 Richard W.M. Jones <rjones@redhat.com> - 1.2.4-3 | ||||||
|  | - Add all upstream patches since 1.2.4 was released. | ||||||
|  | 
 | ||||||
|  | * Tue Jun 12 2018 Richard W.M. Jones <rjones@redhat.com> - 1.2.4-2 | ||||||
|  | - Add all upstream patches since 1.2.4 was released. | ||||||
|  | 
 | ||||||
|  | * Mon Jun 11 2018 Richard W.M. Jones <rjones@redhat.com> - 1.2.4-2 | ||||||
|  | - Disable plugins and filters that we do not want to ship in RHEL 8. | ||||||
|  | 
 | ||||||
|  | * Sat Jun  9 2018 Richard W.M. Jones <rjones@redhat.com> - 1.2.4-1 | ||||||
|  | - New stable version 1.2.4. | ||||||
|  | - Remove upstream patches. | ||||||
|  | - Enable tarball signatures. | ||||||
|  | - Add upstream patch to fix tests when guestfish not available. | ||||||
|  | 
 | ||||||
|  | * Wed Jun  6 2018 Richard W.M. Jones <rjones@redhat.com> - 1.2.3-1 | ||||||
|  | - New stable version 1.2.3. | ||||||
|  | - Add patch to work around libvirt problem with relative socket paths. | ||||||
|  | - Add patch to fix the xz plugin test with recent guestfish. | ||||||
|  | 
 | ||||||
|  | * Sat Apr 21 2018 Richard W.M. Jones <rjones@redhat.com> - 1.2.2-1 | ||||||
|  | - New stable version 1.2.2. | ||||||
|  | 
 | ||||||
|  | * Mon Apr  9 2018 Richard W.M. Jones <rjones@redhat.com> - 1.2.1-1 | ||||||
|  | - New stable version 1.2.1. | ||||||
|  | 
 | ||||||
|  | * Fri Apr  6 2018 Richard W.M. Jones <rjones@redhat.com> - 1.2.0-1 | ||||||
|  | - Move to stable branch version 1.2.0. | ||||||
|  | 
 | ||||||
|  | * Fri Feb 09 2018 Igor Gnatenko <ignatenkobrain@fedoraproject.org> - 1.1.28-5 | ||||||
|  | - Escape macros in %%changelog | ||||||
|  | 
 | ||||||
|  | * Thu Feb 08 2018 Fedora Release Engineering <releng@fedoraproject.org> - 1.1.28-4 | ||||||
|  | - Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild | ||||||
|  | 
 | ||||||
|  | * Wed Jan 31 2018 Igor Gnatenko <ignatenkobrain@fedoraproject.org> - 1.1.28-3 | ||||||
|  | - Switch to %%ldconfig_scriptlets | ||||||
|  | 
 | ||||||
|  | * Fri Jan 26 2018 Richard W.M. Jones <rjones@redhat.com> - 1.1.28-2 | ||||||
|  | - Run a simplified test suite on all arches. | ||||||
|  | 
 | ||||||
|  | * Mon Jan 22 2018 Richard W.M. Jones <rjones@redhat.com> - 1.1.28-1 | ||||||
|  | - New upstream version 1.1.28. | ||||||
|  | - Add two new filters to nbdkit-basic-filters. | ||||||
|  | 
 | ||||||
|  | * Sat Jan 20 2018 Björn Esser <besser82@fedoraproject.org> - 1.1.27-2 | ||||||
|  | - Rebuilt for switch to libxcrypt | ||||||
|  | 
 | ||||||
|  | * Sat Jan 20 2018 Richard W.M. Jones <rjones@redhat.com> - 1.1.27-1 | ||||||
|  | - New upstream version 1.1.27. | ||||||
|  | - Add new subpackage nbdkit-basic-filters containing new filters. | ||||||
|  | 
 | ||||||
|  | * Thu Jan 11 2018 Richard W.M. Jones <rjones@redhat.com> - 1.1.26-2 | ||||||
|  | - Rebuild against updated Ruby. | ||||||
|  | 
 | ||||||
|  | * Sat Dec 23 2017 Richard W.M. Jones <rjones@redhat.com> - 1.1.26-1 | ||||||
|  | - New upstream version 1.1.26. | ||||||
|  | - Add new pkg-config file and dependency. | ||||||
|  | 
 | ||||||
|  | * Wed Dec 06 2017 Richard W.M. Jones <rjones@redhat.com> - 1.1.25-1 | ||||||
|  | - New upstream version 1.1.25. | ||||||
|  | 
 | ||||||
|  | * Tue Dec 05 2017 Richard W.M. Jones <rjones@redhat.com> - 1.1.24-1 | ||||||
|  | - New upstream version 1.1.24. | ||||||
|  | - Add tar plugin (new subpackage nbdkit-plugin-tar). | ||||||
|  | 
 | ||||||
|  | * Tue Dec 05 2017 Richard W.M. Jones <rjones@redhat.com> - 1.1.23-1 | ||||||
|  | - New upstream version 1.1.23. | ||||||
|  | - Add example4 plugin. | ||||||
|  | - Python3 tests require libguestfs so disable on s390x. | ||||||
|  | 
 | ||||||
|  | * Sun Dec 03 2017 Richard W.M. Jones <rjones@redhat.com> - 1.1.22-1 | ||||||
|  | - New upstream version 1.1.22. | ||||||
|  | - Enable tests on Fedora. | ||||||
|  | 
 | ||||||
|  | * Sat Dec 02 2017 Richard W.M. Jones <rjones@redhat.com> - 1.1.20-1 | ||||||
|  | - New upstream version 1.1.20. | ||||||
|  | - Add nbdkit-split-plugin to basic plugins. | ||||||
|  | 
 | ||||||
|  | * Sat Dec 02 2017 Richard W.M. Jones <rjones@redhat.com> - 1.1.19-2 | ||||||
|  | - OCaml 4.06.0 rebuild. | ||||||
|  | 
 | ||||||
|  | * Thu Nov 30 2017 Richard W.M. Jones <rjones@redhat.com> - 1.1.19-1 | ||||||
|  | - New upstream version 1.1.19. | ||||||
|  | - Combine all the simple plugins in %%{name}-basic-plugins. | ||||||
|  | - Add memory and null plugins. | ||||||
|  | - Rename the example plugins subpackage. | ||||||
|  | - Use %%license instead of %%doc for license file. | ||||||
|  | - Remove patches now upstream. | ||||||
|  | 
 | ||||||
|  | * Wed Nov 29 2017 Richard W.M. Jones <rjones@redhat.com> - 1.1.18-4 | ||||||
|  | - Fix Python 3 builds / RHEL macros (RHBZ#1404631). | ||||||
|  | 
 | ||||||
|  | * Tue Nov 21 2017 Richard W.M. Jones <rjones@redhat.com> - 1.1.18-3 | ||||||
|  | - New upstream version 1.1.18. | ||||||
|  | - Add NBD forwarding plugin. | ||||||
|  | - Add libselinux-devel so that SELinux support is enabled in the daemon. | ||||||
|  | - Apply all patches from upstream since 1.1.18. | ||||||
|  | 
 | ||||||
|  | * Fri Oct 20 2017 Richard W.M. Jones <rjones@redhat.com> - 1.1.16-2 | ||||||
|  | - New upstream version 1.1.16. | ||||||
|  | - Disable python3 plugin on RHEL/EPEL <= 7. | ||||||
|  | - Only ship on x86_64 in RHEL/EPEL <= 7. | ||||||
|  | 
 | ||||||
|  | * Wed Sep 27 2017 Richard W.M. Jones <rjones@redhat.com> - 1.1.15-1 | ||||||
|  | - New upstream version 1.1.15. | ||||||
|  | - Enable TLS support. | ||||||
|  | 
 | ||||||
|  | * Fri Sep 01 2017 Richard W.M. Jones <rjones@redhat.com> - 1.1.14-1 | ||||||
|  | - New upstream version 1.1.14. | ||||||
|  | 
 | ||||||
|  | * Fri Aug 25 2017 Richard W.M. Jones <rjones@redhat.com> - 1.1.13-1 | ||||||
|  | - New upstream version 1.1.13. | ||||||
|  | - Remove patches which are all upstream. | ||||||
|  | - Remove grubby hack, should not be needed with modern supermin. | ||||||
|  | 
 | ||||||
|  | * Sat Aug 19 2017 Richard W.M. Jones <rjones@redhat.com> - 1.1.12-13 | ||||||
|  | - Rebuild for OCaml 4.05.0. | ||||||
|  | 
 | ||||||
|  | * Thu Aug 03 2017 Fedora Release Engineering <releng@fedoraproject.org> - 1.1.12-12 | ||||||
|  | - Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Binutils_Mass_Rebuild | ||||||
|  | 
 | ||||||
|  | * Wed Jul 26 2017 Fedora Release Engineering <releng@fedoraproject.org> - 1.1.12-11 | ||||||
|  | - Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Mass_Rebuild | ||||||
|  | 
 | ||||||
|  | * Tue Jun 27 2017 Richard W.M. Jones <rjones@redhat.com> - 1.1.12-10 | ||||||
|  | - Rebuild for OCaml 4.04.2. | ||||||
|  | 
 | ||||||
|  | * Sun Jun 04 2017 Jitka Plesnikova <jplesnik@redhat.com> - 1.1.12-9 | ||||||
|  | - Perl 5.26 rebuild | ||||||
|  | 
 | ||||||
|  | * Mon May 15 2017 Richard W.M. Jones <rjones@redhat.com> - 1.1.12-8 | ||||||
|  | - Rebuild for OCaml 4.04.1. | ||||||
|  | 
 | ||||||
|  | * Fri Feb 10 2017 Fedora Release Engineering <releng@fedoraproject.org> - 1.1.12-7 | ||||||
|  | - Rebuilt for https://fedoraproject.org/wiki/Fedora_26_Mass_Rebuild | ||||||
|  | 
 | ||||||
|  | * Thu Jan 12 2017 Vít Ondruch <vondruch@redhat.com> - 1.1.12-6 | ||||||
|  | - Rebuilt for https://fedoraproject.org/wiki/Changes/Ruby_2.4 | ||||||
|  | 
 | ||||||
|  | * Fri Dec 23 2016 Richard W.M. Jones <rjones@redhat.com> - 1.1.12-5 | ||||||
|  | - Rebuild for Python 3.6 update. | ||||||
|  | 
 | ||||||
|  | * Wed Dec 14 2016 Richard W.M. Jones <rjones@redhat.com> - 1.1.12-4 | ||||||
|  | - Fix python3 subpackage so it really uses python3 (RHBZ#1404631). | ||||||
|  | 
 | ||||||
|  | * Sat Nov 05 2016 Richard W.M. Jones <rjones@redhat.com> - 1.1.12-3 | ||||||
|  | - Rebuild for OCaml 4.04.0. | ||||||
|  | 
 | ||||||
|  | * Mon Oct 03 2016 Richard W.M. Jones <rjones@redhat.com> - 1.1.12-2 | ||||||
|  | - Compile Python 2 and Python 3 versions of the plugin. | ||||||
|  | 
 | ||||||
|  | * Wed Jun 08 2016 Richard W.M. Jones <rjones@redhat.com> - 1.1.12-1 | ||||||
|  | - New upstream version 1.1.12 | ||||||
|  | - Enable Ruby plugin. | ||||||
|  | - Disable tests on Rawhide because libvirt is broken again (RHBZ#1344016). | ||||||
|  | 
 | ||||||
|  | * Wed May 25 2016 Richard W.M. Jones <rjones@redhat.com> - 1.1.11-10 | ||||||
|  | - Add another upstream patch since 1.1.11. | ||||||
|  | 
 | ||||||
|  | * Mon May 23 2016 Richard W.M. Jones <rjones@redhat.com> - 1.1.11-9 | ||||||
|  | - Add all patches upstream since 1.1.11 (fixes RHBZ#1336758). | ||||||
|  | 
 | ||||||
|  | * Tue May 17 2016 Jitka Plesnikova <jplesnik@redhat.com> - 1.1.11-7 | ||||||
|  | - Perl 5.24 rebuild | ||||||
|  | 
 | ||||||
|  | * Wed Mar 09 2016 Richard W.M. Jones <rjones@redhat.com> - 1.1.11-6 | ||||||
|  | - When tests fail, dump out test-suite.log so we can debug it. | ||||||
|  | 
 | ||||||
|  | * Fri Feb 05 2016 Richard W.M. Jones <rjones@redhat.com> - 1.1.11-5 | ||||||
|  | - Don't run tests on x86, because kernel is broken there | ||||||
|  |   (https://bugzilla.redhat.com/show_bug.cgi?id=1302071) | ||||||
|  | 
 | ||||||
|  | * Thu Feb 04 2016 Fedora Release Engineering <releng@fedoraproject.org> - 1.1.11-4 | ||||||
|  | - Rebuilt for https://fedoraproject.org/wiki/Fedora_24_Mass_Rebuild | ||||||
|  | 
 | ||||||
|  | * Mon Jan 11 2016 Richard W.M. Jones <rjones@redhat.com> - 1.1.11-3 | ||||||
|  | - Add support for newstyle NBD protocol (RHBZ#1297100). | ||||||
|  | 
 | ||||||
|  | * Sat Oct 31 2015 Richard W.M. Jones <rjones@redhat.com> - 1.1.11-1 | ||||||
|  | - New upstream version 1.1.11. | ||||||
|  | 
 | ||||||
|  | * Thu Jul 30 2015 Richard W.M. Jones <rjones@redhat.com> - 1.1.10-3 | ||||||
|  | - OCaml 4.02.3 rebuild. | ||||||
|  | 
 | ||||||
|  | * Sat Jun 20 2015 Richard W.M. Jones <rjones@redhat.com> - 1.1.10-2 | ||||||
|  | - Enable libguestfs plugin on aarch64. | ||||||
|  | 
 | ||||||
|  | * Fri Jun 19 2015 Richard W.M. Jones <rjones@redhat.com> - 1.1.10-1 | ||||||
|  | - New upstream version. | ||||||
|  | - Enable now working OCaml plugin (requires OCaml >= 4.02.2). | ||||||
|  | 
 | ||||||
|  | * Wed Jun 17 2015 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 1.1.9-6 | ||||||
|  | - Rebuilt for https://fedoraproject.org/wiki/Fedora_23_Mass_Rebuild | ||||||
|  | 
 | ||||||
|  | * Thu Jun 11 2015 Jitka Plesnikova <jplesnik@redhat.com> - 1.1.9-5 | ||||||
|  | - Perl 5.22 rebuild | ||||||
|  | 
 | ||||||
|  | * Wed Jun 10 2015 Richard W.M. Jones <rjones@redhat.com> - 1.1.9-4 | ||||||
|  | - Enable debugging messages when running make check. | ||||||
|  | 
 | ||||||
|  | * Sat Jun 06 2015 Jitka Plesnikova <jplesnik@redhat.com> - 1.1.9-3 | ||||||
|  | - Perl 5.22 rebuild | ||||||
|  | 
 | ||||||
|  | * Tue Oct 14 2014 Richard W.M. Jones <rjones@redhat.com> - 1.1.9-2 | ||||||
|  | - New upstream version 1.1.9. | ||||||
|  | - Add the streaming plugin. | ||||||
|  | - Include fix for streaming plugin in 1.1.9. | ||||||
|  | 
 | ||||||
|  | * Wed Sep 10 2014 Richard W.M. Jones <rjones@redhat.com> - 1.1.8-4 | ||||||
|  | - Rebuild for updated Perl in Rawhide. | ||||||
|  | - Workaround for broken libvirt (RHBZ#1138604). | ||||||
|  | 
 | ||||||
|  | * Sun Aug 17 2014 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 1.1.8-2 | ||||||
|  | - Rebuilt for https://fedoraproject.org/wiki/Fedora_21_22_Mass_Rebuild | ||||||
|  | 
 | ||||||
|  | * Sat Jun 21 2014 Richard W.M. Jones <rjones@redhat.com> - 1.1.8-1 | ||||||
|  | - New upstream version 1.1.8. | ||||||
|  | - Add support for cURL, and new nbdkit-plugin-curl package. | ||||||
|  | 
 | ||||||
|  | * Fri Jun 20 2014 Richard W.M. Jones <rjones@redhat.com> - 1.1.7-1 | ||||||
|  | - New upstream version 1.1.7. | ||||||
|  | - Remove patches which are now all upstream. | ||||||
|  | 
 | ||||||
|  | * Sat Jun 07 2014 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 1.1.6-5 | ||||||
|  | - Rebuilt for https://fedoraproject.org/wiki/Fedora_21_Mass_Rebuild | ||||||
|  | 
 | ||||||
|  | * Thu Mar 06 2014 Dan Horák <dan[at]danny.cz> - 1.1.6-4 | ||||||
|  | - libguestfs is available only on selected arches | ||||||
|  | 
 | ||||||
|  | * Fri Feb 21 2014 Richard W.M. Jones <rjones@redhat.com> - 1.1.6-3 | ||||||
|  | - Backport some upstream patches, fixing a minor bug and adding more tests. | ||||||
|  | - Enable the tests since kernel bug is fixed. | ||||||
|  | 
 | ||||||
|  | * Sun Feb 16 2014 Richard W.M. Jones <rjones@redhat.com> - 1.1.6-1 | ||||||
|  | - New upstream version 1.1.6. | ||||||
|  | 
 | ||||||
|  | * Sat Feb 15 2014 Richard W.M. Jones <rjones@redhat.com> - 1.1.5-2 | ||||||
|  | - New upstream version 1.1.5. | ||||||
|  | - Enable the new Python plugin. | ||||||
|  | - Perl plugin man page moved to section 3. | ||||||
|  | - Perl now requires ExtUtils::Embed. | ||||||
|  | 
 | ||||||
|  | * Mon Feb 10 2014 Richard W.M. Jones <rjones@redhat.com> - 1.1.4-1 | ||||||
|  | - New upstream version 1.1.4. | ||||||
|  | - Enable the new Perl plugin. | ||||||
|  | 
 | ||||||
|  | * Sun Aug  4 2013 Richard W.M. Jones <rjones@redhat.com> - 1.1.3-1 | ||||||
|  | - New upstream version 1.1.3 which fixes some test problems. | ||||||
|  | - Disable tests because Rawhide kernel is broken (RHBZ#991808). | ||||||
|  | - Remove a single quote from description which confused emacs. | ||||||
|  | - Remove patch, now upstream. | ||||||
|  | 
 | ||||||
|  | * Sat Aug 03 2013 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 1.1.2-4 | ||||||
|  | - Rebuilt for https://fedoraproject.org/wiki/Fedora_20_Mass_Rebuild | ||||||
|  | 
 | ||||||
|  | * Sun Jul 21 2013 Richard W.M. Jones <rjones@redhat.com> - 1.1.2-3 | ||||||
|  | - Fix segfault when IPv6 client is used (RHBZ#986601). | ||||||
|  | 
 | ||||||
|  | * Tue Jul 16 2013 Richard W.M. Jones <rjones@redhat.com> - 1.1.2-2 | ||||||
|  | - New development version 1.1.2. | ||||||
|  | - Disable the tests on Fedora <= 18. | ||||||
|  | 
 | ||||||
|  | * Tue Jun 25 2013 Richard W.M. Jones <rjones@redhat.com> - 1.1.1-1 | ||||||
|  | - New development version 1.1.1. | ||||||
|  | - Add libguestfs plugin. | ||||||
|  | - Run the test suite. | ||||||
|  | 
 | ||||||
|  | * Mon Jun 24 2013 Richard W.M. Jones <rjones@redhat.com> - 1.0.0-4 | ||||||
|  | - Initial release. | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user