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