[Libguestfs] [PATCH nbdkit v2 3/7] server: protocol: Send reply to NBD_INFO_BLOCK_SIZE if requested

Richard W.M. Jones rjones at redhat.com
Thu Feb 17 14:36:44 UTC 2022


If the client requests NBD_INFO_BLOCK_SIZE, _and_ either the plugin or
a filter provides this information, then send a reply.  Otherwise
ignore the client request.
---
 server/protocol-handshake-newstyle.c | 69 ++++++++++++++++++++++++++--
 TODO                                 |  3 +-
 2 files changed, 66 insertions(+), 6 deletions(-)

diff --git a/server/protocol-handshake-newstyle.c b/server/protocol-handshake-newstyle.c
index 5c073af6..f3cba48f 100644
--- a/server/protocol-handshake-newstyle.c
+++ b/server/protocol-handshake-newstyle.c
@@ -195,6 +195,38 @@ send_newstyle_option_reply_info_str (uint32_t option, uint32_t reply,
   return 0;
 }
 
+/* Send reply containing NBD_INFO_BLOCK_SIZE. */
+static int
+send_newstyle_option_reply_info_block_size (uint32_t option, uint32_t reply,
+                                            uint16_t info,
+                                            uint32_t minimum,
+                                            uint32_t preferred,
+                                            uint32_t maximum)
+{
+  GET_CONN;
+  struct nbd_fixed_new_option_reply fixed_new_option_reply;
+  struct nbd_fixed_new_option_reply_info_block_size block_size;
+
+  fixed_new_option_reply.magic = htobe64 (NBD_REP_MAGIC);
+  fixed_new_option_reply.option = htobe32 (option);
+  fixed_new_option_reply.reply = htobe32 (reply);
+  fixed_new_option_reply.replylen = htobe32 (14);
+  block_size.info = htobe16 (info);
+  block_size.minimum = htobe32 (minimum);
+  block_size.preferred = htobe32 (preferred);
+  block_size.maximum = htobe32 (maximum);
+
+  if (conn->send (&fixed_new_option_reply,
+                  sizeof fixed_new_option_reply, SEND_MORE) == -1 ||
+      conn->send (&block_size,
+                  sizeof block_size, 0) == -1) {
+    nbdkit_error ("write: %s: %m", name_of_nbd_opt (option));
+    return -1;
+  }
+
+  return 0;
+}
+
 static int
 send_newstyle_option_reply_meta_context (uint32_t option, uint32_t reply,
                                          uint32_t context_id,
@@ -589,10 +621,10 @@ negotiate_handshake_newstyle_options (void)
                                                     exportsize) == -1)
           return -1;
 
-        /* For now we send NBD_INFO_NAME and NBD_INFO_DESCRIPTION if
-         * requested, and ignore all other info requests (including
-         * NBD_INFO_EXPORT if it was requested, because we replied
-         * already above).
+        /* For now we send NBD_INFO_NAME, NBD_INFO_DESCRIPTION and
+         * NBD_INFO_BLOCK_SIZE if requested, and ignore all other info
+         * requests (including NBD_INFO_EXPORT if it was requested,
+         * because we replied already above).
          */
         for (i = 0; i < nrinfos; ++i) {
           memcpy (&info, &data[4 + exportnamelen + 2 + i*2], 2);
@@ -637,6 +669,35 @@ negotiate_handshake_newstyle_options (void)
                 return -1;
             }
             break;
+          case NBD_INFO_BLOCK_SIZE:
+            {
+              uint32_t minimum, preferred, maximum;
+              int r = backend_block_size (conn->top_context,
+                                          &minimum, &preferred, &maximum);
+
+              if (r == -1) {
+                debug ("newstyle negotiation: %s: "
+                       "NBD_INFO_BLOCK_SIZE: error from plugin, "
+                       "ignoring client request",
+                       optname);
+                break;
+              }
+              if (minimum == 0) {
+                debug ("newstyle negotiation: %s: "
+                       "NBD_INFO_BLOCK_SIZE: client requested but "
+                       "no plugin or filter provided block size information, "
+                       "ignoring client request",
+                       optname);
+                break;
+              }
+              if (send_newstyle_option_reply_info_block_size
+                  (option,
+                   NBD_REP_INFO,
+                   NBD_INFO_BLOCK_SIZE,
+                   minimum, preferred, maximum) == -1)
+                return -1;
+            }
+            break;
           default:
             debug ("newstyle negotiation: %s: "
                    "ignoring NBD_INFO_* request %u (%s)",
diff --git a/TODO b/TODO
index a4a0e0e7..35e68d15 100644
--- a/TODO
+++ b/TODO
@@ -31,8 +31,7 @@ General ideas for improvements
   https://www.redhat.com/archives/libguestfs/2018-January/msg00149.html
 
 * More NBD protocol features.  The currently missing features are
-  structured replies for sparse reads, block size constraints, and
-  online resize.
+  structured replies for sparse reads, and online resize.
 
 * Add a callback to let plugins request minimum alignment for the
   buffer to pread/pwrite; useful for a plugin utilizing O_DIRECT or
-- 
2.35.1




More information about the Libguestfs mailing list