[Libguestfs] [RFC nbdkit PATCH] server: Allow --run with --vsock

Eric Blake eblake at redhat.com
Fri Jul 10 17:46:45 UTC 2020


Now that kernels support vsock loopback, we have no reason to forbid
--vsock with --run.

Signed-off-by: Eric Blake <eblake at redhat.com>
---

I'm hoping to commit something like this, but right now, the testsuite
is failing more times than it succeeds, with:

+ port=1082294412
+ nbdkit --vsock --port 1082294412 memory 1M --run 'sleep 1; nbdsh -u "$uri" -c "$check"'
...
libnbd: debug: nbdsh: nbd_connect_uri: enter: uri="nbd+vsock://1:1082294412"
libnbd: debug: nbdsh: nbd_connect_uri: event CmdConnectSockAddr: START -> CONNECT.START
libnbd: debug: nbdsh: nbd_connect_uri: poll start: events=4
libnbd: debug: nbdsh: nbd_connect_uri: poll end: r=1 revents=c
libnbd: debug: nbdsh: nbd_connect_uri: event NotifyWrite: CONNECT.START -> CONNECT.CONNECTING
libnbd: debug: nbdsh: nbd_connect_uri: transition: CONNECT.CONNECTING -> DEAD
libnbd: debug: nbdsh: nbd_connect_uri: leave: error="nbd_connect_uri: connect: Connection reset by peer"

but when I try the same from the command line in isolation:

$ ./nbdkit --vsock --port=12345 memory 1m --run 'nbdsh -u $uri -c "print(h.get_size())"'
1048576

I wonder if there is some sort of race where an existing vsock on a
different port is interfering (since the test opens up a background
server on one port before the one-liner attempt on a different port).


 docs/nbdkit-captive.pod |  3 ++-
 server/internal.h       |  1 +
 server/captive.c        | 46 +++++++++++++++++++++--------------------
 server/main.c           |  3 +--
 tests/test-vsock.sh     | 21 +++++++++++++------
 5 files changed, 43 insertions(+), 31 deletions(-)

diff --git a/docs/nbdkit-captive.pod b/docs/nbdkit-captive.pod
index 09628367..7f942f95 100644
--- a/docs/nbdkit-captive.pod
+++ b/docs/nbdkit-captive.pod
@@ -54,7 +54,8 @@ option to set the preferred export name, this is included in the URI.

 An older URL that refers to the nbdkit port or socket in a manner
 specific to certain tools.  This form does not include an export name,
-even if B<-e> was used.
+even if B<-e> was used.  This variable is empty when using vsock
+loopback (when the B<--vsock> option is used, only C<$uri> is valid).

 Note there is some magic here, since qemu and guestfish URLs have a
 different format, so nbdkit tries to guess which you are running.  If
diff --git a/server/internal.h b/server/internal.h
index 68c53366..1dd84ccb 100644
--- a/server/internal.h
+++ b/server/internal.h
@@ -129,6 +129,7 @@ extern bool tls_verify_peer;
 extern char *unixsocket;
 extern const char *user, *group;
 extern bool verbose;
+extern bool vsock;
 extern int saved_stdin;
 extern int saved_stdout;

diff --git a/server/captive.c b/server/captive.c
index f8107604..a5b227c4 100644
--- a/server/captive.c
+++ b/server/captive.c
@@ -72,7 +72,7 @@ run_command (void)
   /* Construct $uri. */
   fprintf (fp, "uri=");
   if (port) {
-    fprintf (fp, "nbd://localhost:");
+    fprintf (fp, vsock ? "nbd+vsock://1:" : "nbd://localhost:");
     shell_quote (port, fp);
     if (strcmp (exportname, "") != 0) {
       putc ('/', fp);
@@ -99,29 +99,31 @@ run_command (void)
    * different syntax, so try to guess which one we need.
    */
   fprintf (fp, "nbd=");
-  if (strstr (run, "guestfish")) {
-    if (port) {
-      fprintf (fp, "nbd://localhost:");
-      shell_quote (port, fp);
+  if (!vsock) {
+    if (strstr (run, "guestfish")) {
+      if (port) {
+        fprintf (fp, "nbd://localhost:");
+        shell_quote (port, fp);
+      }
+      else if (unixsocket) {
+        fprintf (fp, "nbd://\\?socket=");
+        shell_quote (unixsocket, fp);
+      }
+      else
+        abort ();
     }
-    else if (unixsocket) {
-      fprintf (fp, "nbd://\\?socket=");
-      shell_quote (unixsocket, fp);
+    else /* qemu */ {
+      if (port) {
+        fprintf (fp, "nbd:localhost:");
+        shell_quote (port, fp);
+      }
+      else if (unixsocket) {
+        fprintf (fp, "nbd:unix:");
+        shell_quote (unixsocket, fp);
+      }
+      else
+        abort ();
     }
-    else
-      abort ();
-  }
-  else /* qemu */ {
-    if (port) {
-      fprintf (fp, "nbd:localhost:");
-      shell_quote (port, fp);
-    }
-    else if (unixsocket) {
-      fprintf (fp, "nbd:unix:");
-      shell_quote (unixsocket, fp);
-    }
-    else
-      abort ();
   }
   putc ('\n', fp);

diff --git a/server/main.c b/server/main.c
index c432f5bd..dfa81a85 100644
--- a/server/main.c
+++ b/server/main.c
@@ -545,8 +545,7 @@ main (int argc, char *argv[])
       (listen_stdin && run) ||
       (listen_stdin && dump_plugin) ||
       (vsock && unixsocket) ||
-      (vsock && listen_stdin) ||
-      (vsock && run)) {
+      (vsock && listen_stdin)) {
     fprintf (stderr,
              "%s: --dump-plugin, -p, --run, -s, -U or --vsock options "
              "cannot be used in this combination\n",
diff --git a/tests/test-vsock.sh b/tests/test-vsock.sh
index 54115e78..13c1c29d 100755
--- a/tests/test-vsock.sh
+++ b/tests/test-vsock.sh
@@ -57,16 +57,25 @@ files="vsock.pid"
 rm -f $files
 cleanup_fn rm -f $files

-# Run nbdkit.
-start_nbdkit -P vsock.pid --vsock --port $port memory 1M
-
-export port
-nbdsh -c - <<'EOF'
+# An nbdsh script for connecting to vsock
+export connect='
 import os

 # 1 = VMADDR_CID_LOCAL
 h.connect_vsock (1, int (os.environ["port"]))
+'

+export check='
 size = h.get_size ()
 assert size == 1048576
-EOF
+'
+
+# Run nbdkit.
+start_nbdkit -P vsock.pid --vsock --port $port memory 1M
+
+export port
+nbdsh -c "$connect" -c "$check"
+
+# Repeat on a different port, testing interaction with --run
+port=$((port + 1))
+nbdkit --vsock --port $port memory 1M --run 'nbdsh -u "$uri" -c "$check"'
-- 
2.27.0




More information about the Libguestfs mailing list