It's easy to expose new callbacks to sh plugins. I have no idea how any plugin would actually usefully cache anything in shell (you can't really store it in a shell variable, since a new shell process is started for each command); but if nothing else, this allows a user to implement .can_cache returning true to bypass nbdkit's normal fallback to .pread.
The shell plugin, coupled with Rich's work on libnbd as a client-side library for actually exercising calls to NBD_CMD_CACHE, will be a useful way to prove that cache commands even make it through the stack. (Remember, qemu 3.0 was released with a fatally flawed NBD_CMD_CACHE server implementation, because there were no open source clients at the time that could actually send the command to test the server with). Signed-off-by: Eric Blake <[email protected]> --- plugins/sh/nbdkit-sh-plugin.pod | 12 +++++++++- plugins/sh/sh.c | 40 +++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 1 deletion(-) diff --git a/plugins/sh/nbdkit-sh-plugin.pod b/plugins/sh/nbdkit-sh-plugin.pod index 8af88b4..bfd58ab 100644 --- a/plugins/sh/nbdkit-sh-plugin.pod +++ b/plugins/sh/nbdkit-sh-plugin.pod @@ -218,9 +218,11 @@ This method is required. =item C<can_extents> +=item C<can_cache> + Unlike in other languages, you B<must> provide the C<can_*> methods otherwise they are assumed to all return false and your C<pwrite>, -C<flush>, C<trim>, C<zero> and C<extents> methods will never be +C<flush>, C<trim>, C<zero>, C<extents>, and C<cache> methods will never be called. The reason for this is obscure: In other languages we can detect if (eg) a C<pwrite> method is defined and synthesize an appropriate response if no actual C<can_write> method is defined. @@ -232,6 +234,7 @@ possible with this plugin. /path/to/script can_trim <handle> /path/to/script can_zero <handle> /path/to/script can_extents <handle> + /path/to/script can_cache <handle> The script should exit with code C<0> for true or code C<3> for false. @@ -334,6 +337,13 @@ Unlike in other languages, if you provide an C<extents> method you B<must> also provide a C<can_extents> method which exits with code C<0> (true). +=item C<cache> + + /path/to/script cache <handle> <count> <offset> + +Unlike in other languages, if you provide a C<cache> method you B<must> +also provide a C<can_cache> method which exits with code C<0> (true). + =back =head2 Missing callbacks diff --git a/plugins/sh/sh.c b/plugins/sh/sh.c index a5beb57..7aded44 100644 --- a/plugins/sh/sh.c +++ b/plugins/sh/sh.c @@ -578,6 +578,12 @@ sh_can_multi_conn (void *handle) return boolean_method (handle, "can_multi_conn"); } +static int +sh_can_cache (void *handle) +{ + return boolean_method (handle, "can_cache"); +} + static int sh_flush (void *handle, uint32_t flags) { @@ -782,6 +788,38 @@ sh_extents (void *handle, uint32_t count, uint64_t offset, uint32_t flags, } } +static int +sh_cache (void *handle, uint32_t count, uint64_t offset, uint32_t flags) +{ + char *h = handle; + char cbuf[32], obuf[32]; + const char *args[] = { script, "cache", h, cbuf, obuf, NULL }; + + snprintf (cbuf, sizeof cbuf, "%" PRIu32, count); + snprintf (obuf, sizeof obuf, "%" PRIu64, offset); + assert (!flags); + + switch (call (args)) { + case OK: + return 0; + + case MISSING: + /* Ignore lack of cache callback. */ + return 0; + + case ERROR: + return -1; + + case RET_FALSE: + nbdkit_error ("%s: %s method returned unexpected code (3/false)", + script, "cache"); + errno = EIO; + return -1; + + default: abort (); + } +} + #define sh_config_help \ "script=<FILENAME> (required) The shell script to run.\n" \ "[other arguments may be used by the plugin that you load]" @@ -812,6 +850,7 @@ static struct nbdkit_plugin plugin = { .can_extents = sh_can_extents, .can_fua = sh_can_fua, .can_multi_conn = sh_can_multi_conn, + .can_cache = sh_can_cache, .pread = sh_pread, .pwrite = sh_pwrite, @@ -819,6 +858,7 @@ static struct nbdkit_plugin plugin = { .trim = sh_trim, .zero = sh_zero, .extents = sh_extents, + .cache = sh_cache, .errno_is_preserved = 1, }; -- 2.20.1 _______________________________________________ Libguestfs mailing list [email protected] https://www.redhat.com/mailman/listinfo/libguestfs
