[Libguestfs] [nbdkit PATCH v2 02/17] plugins: Expose more thread_model details in --dump-plugin

Eric Blake eblake at redhat.com
Fri Aug 2 19:26:03 UTC 2019


When we added .thread_model to plugins, we forgot to expose
has_thread_model in the --dump-plugin output.  What's more, it is
useful to determine if the plugin itself is aware of tighter
restrictions imposed by dynamic choices, by outputting both
'max_thread_model' (what the plugin was compiled as) and
'thread_model' (the resulting model based on runtime knowledge).

Note that this means that a plugin's .thread_model can be called prior
to .config, so the sh plugin must be prepared for a missing script.
In fact, exposing additional information during --dump-plugin will
make it easier for a future patch to make sh default to PARALLEL, and
still have introspection on which model will actually be used.

Fixes: 9911a9d3
Signed-off-by: Eric Blake <eblake at redhat.com>
---
 docs/nbdkit-plugin.pod          | 11 +++++---
 plugins/sh/nbdkit-sh-plugin.pod |  3 +-
 plugins/sh/sh.c                 |  3 ++
 server/plugins.c                | 49 ++++++++++++++++++++-------------
 tests/test-dump-plugin.sh       | 31 ++++++++++++++++++++-
 5 files changed, 72 insertions(+), 25 deletions(-)

diff --git a/docs/nbdkit-plugin.pod b/docs/nbdkit-plugin.pod
index 8ce702da..fe9ada87 100644
--- a/docs/nbdkit-plugin.pod
+++ b/docs/nbdkit-plugin.pod
@@ -128,16 +128,19 @@ is called once just after the plugin is loaded into memory.

 C<.config> is called zero or more times during command line parsing.
 C<.config_complete> is called once after all configuration information
-has been passed to the plugin.
+has been passed to the plugin (but not during C<nbdkit --dump-plugin>).

 Both are called after loading the plugin but before any connections
 are accepted.

 =item C<.thread_model>

-C<.thread_model> is called once after all configuration information
-has been passed to the plugin, and before any connections are
-accepted.
+In normal operation, C<.thread_model> is called once after
+C<.config_complete> has validated all configuration information, and
+before any connections are accepted.  However, during C<nbdkit
+--dump-plugin>, it is called after any C<.config> calls but without
+C<.config_complete> (so a plugin which determines the results from a
+script must be prepared for a missing script).

 =item C<.open>

diff --git a/plugins/sh/nbdkit-sh-plugin.pod b/plugins/sh/nbdkit-sh-plugin.pod
index dfa086b5..41b9e7c7 100644
--- a/plugins/sh/nbdkit-sh-plugin.pod
+++ b/plugins/sh/nbdkit-sh-plugin.pod
@@ -191,7 +191,8 @@ C<"serialize_requests">, or C<"parallel">.
 This method is I<not> required; if omitted, then the plugin will be
 executed under the default sh thread model (currently
 C<"serialize_all_requests">, which implies this callback only makes a
-difference with an output of C<"serialize_connections">).  If an error
+difference with an output of C<"serialize_connections">; look for
+'max_thread_model' in C<nbdkit --dump-plugin sh>).  If an error
 occurs, the script should output an error message and exit with status
 C<1>; unrecognized output is ignored.

diff --git a/plugins/sh/sh.c b/plugins/sh/sh.c
index e3d3c2f1..5869d9a4 100644
--- a/plugins/sh/sh.c
+++ b/plugins/sh/sh.c
@@ -273,6 +273,9 @@ sh_thread_model (void)
   size_t slen;
   int r;

+  if (!script)
+    return THREAD_MODEL;
+
   switch (call_read (&s, &slen, args)) {
   case OK:
     if (slen > 0 && s[slen-1] == '\n')
diff --git a/server/plugins.c b/server/plugins.c
index 9da0361b..3bb20c93 100644
--- a/server/plugins.c
+++ b/server/plugins.c
@@ -140,6 +140,33 @@ plugin_version (struct backend *b)
   return p->plugin.version;
 }

+/* Map thread model to a string */
+static void
+plugin_dump_thread_model (const char *prefix, int model)
+{
+  flockfile (stdout);
+  printf ("%s=", prefix);
+  switch (model) {
+  case NBDKIT_THREAD_MODEL_SERIALIZE_CONNECTIONS:
+    printf ("serialize_connections");
+    break;
+  case NBDKIT_THREAD_MODEL_SERIALIZE_ALL_REQUESTS:
+    printf ("serialize_all_requests");
+    break;
+  case NBDKIT_THREAD_MODEL_SERIALIZE_REQUESTS:
+    printf ("serialize_requests");
+    break;
+  case NBDKIT_THREAD_MODEL_PARALLEL:
+    printf ("parallel");
+    break;
+  default:
+    printf ("%d # unknown thread model!", model);
+    break;
+  }
+  printf ("\n");
+  funlockfile (stdout);
+}
+
 /* This implements the --dump-plugin option. */
 static void
 plugin_dump_fields (struct backend *b)
@@ -157,25 +184,8 @@ plugin_dump_fields (struct backend *b)

   printf ("api_version=%d\n", p->plugin._api_version);
   printf ("struct_size=%" PRIu64 "\n", p->plugin._struct_size);
-  printf ("thread_model=");
-  switch (p->plugin._thread_model) {
-  case NBDKIT_THREAD_MODEL_SERIALIZE_CONNECTIONS:
-    printf ("serialize_connections");
-    break;
-  case NBDKIT_THREAD_MODEL_SERIALIZE_ALL_REQUESTS:
-    printf ("serialize_all_requests");
-    break;
-  case NBDKIT_THREAD_MODEL_SERIALIZE_REQUESTS:
-    printf ("serialize_requests");
-    break;
-  case NBDKIT_THREAD_MODEL_PARALLEL:
-    printf ("parallel");
-    break;
-  default:
-    printf ("%d # unknown thread model!", p->plugin._thread_model);
-    break;
-  }
-  printf ("\n");
+  plugin_dump_thread_model ("max_thread_model", p->plugin._thread_model);
+  plugin_dump_thread_model ("thread_model", backend->thread_model (backend));
   printf ("errno_is_preserved=%d\n", !!p->plugin.errno_is_preserved);
   if (p->plugin.magic_config_key)
     printf ("magic_config_key=%s\n", p->plugin.magic_config_key);
@@ -213,6 +223,7 @@ plugin_dump_fields (struct backend *b)
   HAS (extents);
   HAS (can_cache);
   HAS (cache);
+  HAS (thread_model);
 #undef HAS

   /* Custom fields. */
diff --git a/tests/test-dump-plugin.sh b/tests/test-dump-plugin.sh
index 1d58a3a3..982d5062 100755
--- a/tests/test-dump-plugin.sh
+++ b/tests/test-dump-plugin.sh
@@ -1,6 +1,6 @@
 #!/usr/bin/env bash
 # nbdkit
-# Copyright (C) 2014 Red Hat Inc.
+# Copyright (C) 2014-2019 Red Hat Inc.
 #
 # Redistribution and use in source and binary forms, with or without
 # modification, are permitted provided that the following conditions are
@@ -68,3 +68,32 @@ do_test ()
     esac
 }
 foreach_plugin do_test
+
+# Test that --dump-plugin can be used to introspect a resulting dynamic
+# thread model.
+out=$({
+    # sh does not yet support parallel
+    nbdkit --dump-plugin sh
+    # Here, the script further reduces things
+    nbdkit --dump-plugin sh - <<\EOF
+case $1 in
+    get_size) echo 1M ;;
+    thread_model) echo serialize_connections ;;
+    *) exit 2 ;;
+esac
+EOF
+    # Here, the filter further reduces things
+    nbdkit --dump-plugin --filter=noparallel sh serialize=connections
+} | grep thread_model)
+exp="max_thread_model=serialize_all_requests
+thread_model=serialize_all_requests
+has_thread_model=1
+max_thread_model=serialize_all_requests
+thread_model=serialize_connections
+has_thread_model=1
+max_thread_model=serialize_all_requests
+thread_model=serialize_connections
+has_thread_model=1"
+if [ "$out" != "$exp" ]; then
+    echo "thread_model mismatch"; exit 1
+fi
-- 
2.20.1




More information about the Libguestfs mailing list