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