[Libguestfs] [PATCH nbdkit 4/6] eval, sh: Implement block_size method

Richard W.M. Jones rjones at redhat.com
Wed Feb 16 16:20:39 UTC 2022


The main reason to implement block_size in these plugins first is so
we then have an easy way to implement tests of the feature.
---
 plugins/eval/nbdkit-eval-plugin.pod |  2 +
 plugins/sh/nbdkit-sh-plugin.pod     | 10 +++++
 plugins/sh/methods.h                |  3 ++
 plugins/eval/eval.c                 |  2 +
 plugins/sh/methods.c                | 66 +++++++++++++++++++++++++++++
 plugins/sh/sh.c                     |  1 +
 6 files changed, 84 insertions(+)

diff --git a/plugins/eval/nbdkit-eval-plugin.pod b/plugins/eval/nbdkit-eval-plugin.pod
index 22167ec5..fa9784ae 100644
--- a/plugins/eval/nbdkit-eval-plugin.pod
+++ b/plugins/eval/nbdkit-eval-plugin.pod
@@ -70,6 +70,8 @@ features):
 
 =item B<after_fork=>SCRIPT
 
+=item B<block_size=>SCRIPT
+
 =item B<cache=>SCRIPT
 
 =item B<can_cache=>SCRIPT
diff --git a/plugins/sh/nbdkit-sh-plugin.pod b/plugins/sh/nbdkit-sh-plugin.pod
index c4cb9fac..aede1c65 100644
--- a/plugins/sh/nbdkit-sh-plugin.pod
+++ b/plugins/sh/nbdkit-sh-plugin.pod
@@ -372,6 +372,16 @@ L<nbdkit-plugin(3)/PARSING SIZE PARAMETERS>).
 
 This method is required.
 
+=item C<block_size>
+
+ /path/to/script block_size <handle>
+
+This script should print three numbers on stdout, separated by
+whitespace.  These are (in order) the minimum block size, the
+preferred block size, and the maximum block size.  You can print the
+sizes in bytes or use any format understood by C<nbdkit_parse_size>
+such as C<1M> (see L<nbdkit-plugin(3)/PARSING SIZE PARAMETERS>).
+
 =item C<can_write>
 
 =item C<can_flush>
diff --git a/plugins/sh/methods.h b/plugins/sh/methods.h
index 42eb560c..d405ef00 100644
--- a/plugins/sh/methods.h
+++ b/plugins/sh/methods.h
@@ -51,6 +51,9 @@ extern void *sh_open (int readonly);
 extern void sh_close (void *handle);
 extern const char *sh_export_description (void *handle);
 extern int64_t sh_get_size (void *handle);
+extern int sh_block_size (void *handle,
+                          uint32_t *minimum, uint32_t *preferred,
+                          uint32_t *maximum);
 extern int sh_pread (void *handle, void *buf, uint32_t count, uint64_t offset,
                      uint32_t flags);
 extern int sh_pwrite (void *handle, const void *buf, uint32_t count,
diff --git a/plugins/eval/eval.c b/plugins/eval/eval.c
index b312a59c..8ce7a650 100644
--- a/plugins/eval/eval.c
+++ b/plugins/eval/eval.c
@@ -55,6 +55,7 @@ static char *missing;
 
 static const char *known_methods[] = {
   "after_fork",
+  "block_size",
   "cache",
   "can_cache",
   "can_extents",
@@ -402,6 +403,7 @@ static struct nbdkit_plugin plugin = {
 
   .export_description = sh_export_description,
   .get_size           = sh_get_size,
+  .block_size         = sh_block_size,
   .can_write          = sh_can_write,
   .can_flush          = sh_can_flush,
   .is_rotational      = sh_is_rotational,
diff --git a/plugins/sh/methods.c b/plugins/sh/methods.c
index 51bc89e5..1216c212 100644
--- a/plugins/sh/methods.c
+++ b/plugins/sh/methods.c
@@ -526,6 +526,72 @@ sh_get_size (void *handle)
   }
 }
 
+int
+sh_block_size (void *handle,
+               uint32_t *minimum, uint32_t *preferred, uint32_t *maximum)
+{
+  const char *method = "block_size";
+  const char *script = get_script (method);
+  struct sh_handle *h = handle;
+  const char *args[] = { script, method, h->h, NULL };
+  CLEANUP_FREE char *s = NULL;
+  size_t slen;
+  const char *delim = " \t\n";
+  char *sp, *p;
+  int64_t r;
+
+  switch (call_read (&s, &slen, args)) {
+  case OK:
+    if ((p = strtok_r (s, delim, &sp)) == NULL) {
+    parse_error:
+      nbdkit_error ("%s: %s method cannot be parsed", script, method);
+      return -1;
+    }
+    r = nbdkit_parse_size (p);
+    if (r == -1 || r > UINT32_MAX)
+      goto parse_error;
+    *minimum = r;
+
+    if ((p = strtok_r (NULL, delim, &sp)) == NULL)
+      goto parse_error;
+    r = nbdkit_parse_size (p);
+    if (r == -1 || r > UINT32_MAX)
+      goto parse_error;
+    *preferred = r;
+
+    if ((p = strtok_r (NULL, delim, &sp)) == NULL)
+      goto parse_error;
+    r = nbdkit_parse_size (p);
+    if (r == -1 || r > UINT32_MAX)
+      goto parse_error;
+    *maximum = r;
+
+#if 0
+    nbdkit_debug ("setting block_size: "
+                  "minimum=%" PRIu32 " "
+                  "preferred=%" PRIu32 " "
+                  "maximum=%" PRIu32,
+                  *minimum, *preferred, *maximum);
+#endif
+    return 0;
+
+  case MISSING:
+    *minimum = *preferred = *maximum = 0;
+    return 0;
+
+  case ERROR:
+    return -1;
+
+  case RET_FALSE:
+    nbdkit_error ("%s: %s method returned unexpected code (3/false)",
+                  script, method);
+    errno = EIO;
+    return -1;
+
+  default: abort ();
+  }
+}
+
 int
 sh_pread (void *handle, void *buf, uint32_t count, uint64_t offset,
           uint32_t flags)
diff --git a/plugins/sh/sh.c b/plugins/sh/sh.c
index db75d386..35972104 100644
--- a/plugins/sh/sh.c
+++ b/plugins/sh/sh.c
@@ -307,6 +307,7 @@ static struct nbdkit_plugin plugin = {
 
   .export_description = sh_export_description,
   .get_size           = sh_get_size,
+  .block_size         = sh_block_size,
   .can_write          = sh_can_write,
   .can_flush          = sh_can_flush,
   .is_rotational      = sh_is_rotational,
-- 
2.35.1




More information about the Libguestfs mailing list