[Libguestfs] [PATCH nbdkit] server: Implement minimal implementation of set/list metadata contexts.

Richard W.M. Jones rjones at redhat.com
Fri Mar 8 12:52:48 UTC 2019


None are supported at present, so this always returns an empty list.
---
 docs/nbdkit-protocol.pod |  4 ++
 server/protocol.h        |  2 +
 server/connections.c     | 84 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 90 insertions(+)

diff --git a/docs/nbdkit-protocol.pod b/docs/nbdkit-protocol.pod
index 68438fa..4c65e00 100644
--- a/docs/nbdkit-protocol.pod
+++ b/docs/nbdkit-protocol.pod
@@ -128,6 +128,10 @@ However we don’t expose the capability to send structured replies to
 plugins yet, nor do we send human-readable error messages using this
 facility.
 
+=item Metadata Querying
+
+Supported in nbdkit E<ge> 1.11.8.
+
 =item Block Status
 
 I<Not supported>.
diff --git a/server/protocol.h b/server/protocol.h
index 0aadd46..b03555e 100644
--- a/server/protocol.h
+++ b/server/protocol.h
@@ -105,6 +105,8 @@ extern const char *name_of_nbd_opt (int);
 #define NBD_OPT_INFO               6
 #define NBD_OPT_GO                 7
 #define NBD_OPT_STRUCTURED_REPLY   8
+#define NBD_OPT_LIST_META_CONTEXT  9
+#define NBD_OPT_SET_META_CONTEXT   10
 
 extern const char *name_of_nbd_rep (int);
 #define NBD_REP_ACK          1
diff --git a/server/connections.c b/server/connections.c
index aeb27f8..7e32f00 100644
--- a/server/connections.c
+++ b/server/connections.c
@@ -926,6 +926,90 @@ _negotiate_handshake_newstyle_options (struct connection *conn)
       conn->structured_replies = true;
       break;
 
+    case NBD_OPT_LIST_META_CONTEXT:
+    case NBD_OPT_SET_META_CONTEXT:
+      {
+        uint32_t opt_index;
+        uint32_t exportnamelen;
+        uint32_t nr_queries;
+        uint32_t querylen;
+        const char *what;
+
+        optname = name_of_nbd_opt (option);
+        if (conn_recv_full (conn, data, optlen, "read: %s: %m", optname) == -1)
+          return -1;
+
+        if (!conn->structured_replies) {
+          if (send_newstyle_option_reply (conn, option, NBD_REP_ERR_INVALID)
+              == -1)
+            return -1;
+          continue;
+        }
+
+        /* Minimum length of the option payload is the 32 bit export
+         * name plus a zero length export name plus 32 bit number of
+         * queries followed by no queries.
+         */
+        what = "optlen < 8";
+        if (optlen < 8) {
+        opt_meta_invalid_option_len:
+          debug ("newstyle negotiation: %s: invalid option length: %s",
+                 optname, what);
+
+          if (send_newstyle_option_reply (conn, option, NBD_REP_ERR_INVALID)
+              == -1)
+            return -1;
+          continue;
+        }
+
+        /* Discard the export name. */
+        memcpy (&exportnamelen, &data[0], 4);
+        exportnamelen = be32toh (exportnamelen);
+        opt_index = 4 + exportnamelen;
+
+        /* Read the number of queries. */
+        what = "reading number of queries";
+        if (opt_index+4 > optlen)
+          goto opt_meta_invalid_option_len;
+        memcpy (&nr_queries, &data[opt_index], 4);
+        nr_queries = be32toh (nr_queries);
+        opt_index += 4;
+
+        /* nr_queries == 0 means return all meta contexts. */
+        if (nr_queries == 0) {
+          /* Nothing is supported now. */
+          if (send_newstyle_option_reply (conn, option, NBD_REP_ACK) == -1)
+            return -1;
+        }
+        else {
+          /* Read and answer each query. */
+          while (nr_queries > 0) {
+            what = "reading query string length";
+            if (opt_index+4 > optlen)
+              goto opt_meta_invalid_option_len;
+            memcpy (&querylen, &data[opt_index], 4);
+            querylen = be32toh (querylen);
+            opt_index += 4;
+            what = "reading query string";
+            if (opt_index + querylen > optlen)
+              goto opt_meta_invalid_option_len;
+
+            debug ("newstyle negotiation: %s: %s %.*s",
+                   optname,
+                   option == NBD_OPT_LIST_META_CONTEXT ? "query" : "set",
+                   (int) querylen, &data[opt_index]);
+
+            /* Ignore query - nothing is supported. */
+
+            opt_index += querylen;
+            nr_queries--;
+          }
+          if (send_newstyle_option_reply (conn, option, NBD_REP_ACK) == -1)
+            return -1;
+        }
+      }
+      break;
+
     default:
       /* Unknown option. */
       if (send_newstyle_option_reply (conn, option, NBD_REP_ERR_UNSUP) == -1)
-- 
2.20.1




More information about the Libguestfs mailing list