[Libguestfs] [nbdkit PATCH v3 07/15] filters: Expose new .can_zero callback

Eric Blake eblake at redhat.com
Thu Mar 8 23:03:03 UTC 2018


While our plugin code always advertises WRITE_ZEROES on writable
connections (because we can emulate .zero by calling .pwrite),
it is conceivable that a filter may want to explicitly avoid
advertising particular bits.  More to the point, an upcoming
patch will add a 'nozero' filter that hides WRITE_ZEROES support,
at least for the purposes of timing comparisons between server
emulation and the client having to send zeroes over the wire.

This change alters filter API; but given that we've already bumped
the API in a previous patch, we can group all of the API changes
within the same release without having to bump the #define value
in this patch.

Signed-off-by: Eric Blake <eblake at redhat.com>
---
 docs/nbdkit-filter.pod  | 20 +++++++++++++++++++-
 include/nbdkit-filter.h |  3 +++
 src/filters.c           | 16 ++++++++++++++--
 filters/log/log.c       |  7 ++++---
 4 files changed, 40 insertions(+), 6 deletions(-)

diff --git a/docs/nbdkit-filter.pod b/docs/nbdkit-filter.pod
index 32d50cb..3af97b0 100644
--- a/docs/nbdkit-filter.pod
+++ b/docs/nbdkit-filter.pod
@@ -353,7 +353,8 @@ calls.
  int (*can_trim) (struct nbdkit_next_ops *next_ops, void *nxdata,
                   void *handle);

-These intercept the corresponding plugin methods.
+These intercept the corresponding plugin methods, and control feature
+bits advertised to the client.

 If there is an error, the callback should call C<nbdkit_error> with an
 error message and return C<-1>.  If these functions are called more
@@ -361,6 +362,23 @@ than once for the same connection, they should return the same value;
 similarly, the filter may cache the results of each counterpart in
 C<next_ops> for a given connection rather than repeating calls.

+=head2 C<.can_zero>
+
+ int (*can_zero) (struct nbdkit_next_ops *next_ops, void *nxdata,
+                  void *handle);
+
+This controls whether write zero support will be advertised to the
+client.  This function has no counterpart in plugins, because nbdkit
+can always emulate zero by using pwrite; but a filter may want to
+force different handling than the nbdkit implementation.  If this
+callback is omitted, the default returned for the plugin layer is
+true.
+
+If there is an error, the callback should call C<nbdkit_error> with an
+error message and return C<-1>.  Like the other initial queries
+documented above, caching the return value of this function is
+allowed.
+
 =head2 C<.pread>

  int (*pread) (struct nbdkit_next_ops *next_ops, void *nxdata,
diff --git a/include/nbdkit-filter.h b/include/nbdkit-filter.h
index 95be130..533713b 100644
--- a/include/nbdkit-filter.h
+++ b/include/nbdkit-filter.h
@@ -57,6 +57,7 @@ struct nbdkit_next_ops {
   int (*can_flush) (void *nxdata);
   int (*is_rotational) (void *nxdata);
   int (*can_trim) (void *nxdata);
+  int (*can_zero) (void *nxdata);

   int (*pread) (void *nxdata, void *buf, uint32_t count, uint64_t offset,
                 uint32_t flags, int *err);
@@ -115,6 +116,8 @@ struct nbdkit_filter {
                         void *handle);
   int (*can_trim) (struct nbdkit_next_ops *next_ops, void *nxdata,
                    void *handle);
+  int (*can_zero) (struct nbdkit_next_ops *next_ops, void *nxdata,
+                   void *handle);

   int (*pread) (struct nbdkit_next_ops *next_ops, void *nxdata,
                 void *handle, void *buf, uint32_t count, uint64_t offset,
diff --git a/src/filters.c b/src/filters.c
index 0cf7594..491c676 100644
--- a/src/filters.c
+++ b/src/filters.c
@@ -287,6 +287,13 @@ next_can_trim (void *nxdata)
   return b_conn->b->can_trim (b_conn->b, b_conn->conn);
 }

+static int
+next_can_zero (void *nxdata)
+{
+  struct b_conn *b_conn = nxdata;
+  return b_conn->b->can_zero (b_conn->b, b_conn->conn);
+}
+
 static int
 next_pread (void *nxdata, void *buf, uint32_t count, uint64_t offset,
             uint32_t flags, int *err)
@@ -334,6 +341,7 @@ static struct nbdkit_next_ops next_ops = {
   .can_flush = next_can_flush,
   .is_rotational = next_is_rotational,
   .can_trim = next_can_trim,
+  .can_zero = next_can_zero,
   .pread = next_pread,
   .pwrite = next_pwrite,
   .flush = next_flush,
@@ -450,11 +458,15 @@ static int
 filter_can_zero (struct backend *b, struct connection *conn)
 {
   struct backend_filter *f = container_of (b, struct backend_filter, backend);
+  void *handle = connection_get_handle (conn, f->backend.i);
+  struct b_conn nxdata = { .b = f->backend.next, .conn = conn };

   debug ("can_zero");

-  /* TODO expose this to filters */
-  return f->backend.next->can_zero (f->backend.next, conn);
+  if (f->filter.can_zero)
+    return f->filter.can_zero (&next_ops, &nxdata, handle);
+  else
+    return f->backend.next->can_zero (f->backend.next, conn);
 }

 static int
diff --git a/filters/log/log.c b/filters/log/log.c
index 58fd4f8..2dd61c0 100644
--- a/filters/log/log.c
+++ b/filters/log/log.c
@@ -235,13 +235,14 @@ log_prepare (struct nbdkit_next_ops *next_ops, void *nxdata, void *handle)
   int f = next_ops->can_flush (nxdata);
   int r = next_ops->is_rotational (nxdata);
   int t = next_ops->can_trim (nxdata);
+  int z = next_ops->can_zero (nxdata);

-  if (size < 0 || w < 0 || f < 0 || r < 0 || t < 0)
+  if (size < 0 || w < 0 || f < 0 || r < 0 || t < 0 || z < 0)
     return -1;

-  /* TODO expose can_zero, can_fua to filters */
+  /* TODO expose can_fua to filters */
   output (h, "Connect", 0, "size=0x%" PRIx64 " write=%d flush=%d "
-          "rotational=%d trim=%d" /* zero=? fua=? */, size, w, f, r, t);
+          "rotational=%d trim=%d zero=%d" /* fua=? */, size, w, f, r, t, z);
   return 0;
 }

-- 
2.14.3




More information about the Libguestfs mailing list