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 <[email protected]> --- 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 _______________________________________________ Libguestfs mailing list [email protected] https://www.redhat.com/mailman/listinfo/libguestfs
