[Libguestfs] [nbdkit PATCH 1/2] perl: Support zero callback

Eric Blake eblake at redhat.com
Tue Jan 24 03:13:24 UTC 2017


Add a perl language binding for the .zero callback, used for
implementing NBD_CMD_WRITE_ZEROES.  Unlike the pwrite callback
with no return type, and unlike C where we can manipulate errno,
we need a way to distinguish between hard error (the usual die),
and the fallback error (return false so the binding can turn it
into EOPNOTSUPP), so success requires returning true.

Signed-off-by: Eric Blake <eblake at redhat.com>
---
 plugins/perl/nbdkit-perl-plugin.pod | 25 +++++++++++++++++++++++++
 plugins/perl/perl.c                 | 37 +++++++++++++++++++++++++++++++++++++
 2 files changed, 62 insertions(+)

diff --git a/plugins/perl/nbdkit-perl-plugin.pod b/plugins/perl/nbdkit-perl-plugin.pod
index 3d0ce14..39df7b1 100644
--- a/plugins/perl/nbdkit-perl-plugin.pod
+++ b/plugins/perl/nbdkit-perl-plugin.pod
@@ -271,6 +271,31 @@ store.

 If there is an error, the function should call C<die>.

+=item C<zero>
+
+(Optional)
+
+ sub zero
+ {
+    my $handle = shift;
+    my $count = shift;
+    my $offset = shift;
+    my $may_trim = shift;
+    my $bool = ...;
+    return $bool;
+ }
+
+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. Return true if the write was
+successful, and false to trigger a graceful fallback to C<pwrite>.
+
+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, and you do not want the fallback to C<pwrite>, your function
+should C<die>.
+
 =back

 =head2 MISSING CALLBACKS
diff --git a/plugins/perl/perl.c b/plugins/perl/perl.c
index 935e1ba..ba42864 100644
--- a/plugins/perl/perl.c
+++ b/plugins/perl/perl.c
@@ -494,6 +494,42 @@ perl_can_trim (void *handle)
 }

 static int
+perl_zero (void *handle, uint32_t count, uint64_t offset, int may_trim)
+{
+  dSP;
+  SV *sv;
+  int r = 0;
+
+  if (callback_defined ("zero")) {
+    ENTER;
+    SAVETMPS;
+    PUSHMARK (SP);
+    XPUSHs (handle);
+    XPUSHs (sv_2mortal (newSViv (count)));
+    XPUSHs (sv_2mortal (newSViv (offset)));
+    XPUSHs (sv_2mortal (newSViv (may_trim)));
+    PUTBACK;
+    call_pv ("zero", G_EVAL|G_SCALAR);
+    SPAGAIN;
+    sv = POPs;
+    r = SvIV (sv);
+    PUTBACK;
+    FREETMPS;
+    LEAVE;
+
+    if (check_perl_failure () == -1)
+      return -1;
+
+    if (r)
+      return 0;
+  }
+
+  nbdkit_debug ("zero falling back to pwrite");
+  errno = EOPNOTSUPP;
+  return -1;
+}
+
+static int
 perl_is_rotational (void *handle)
 {
   dSP;
@@ -614,6 +650,7 @@ static struct nbdkit_plugin plugin = {
   .pwrite            = perl_pwrite,
   .flush             = perl_flush,
   .trim              = perl_trim,
+  .zero              = perl_zero,
 };

 NBDKIT_REGISTER_PLUGIN(plugin)
-- 
2.9.3




More information about the Libguestfs mailing list