@@ -617,6 +617,36 @@ static int nbd_negotiate_handle_info(NBDClient *client, uint16_t myflags,
return rc;
}
+ /* Send NBD_INFO_TRIM_SIZE always. */
+ /* minimum - Hard-code to 4096 for now, matching preferred block.
+ * TODO: consult blk_bs(blk)->bl.pdiscard_alignment? */
+ sizes[0] = 4096;
+ /* maximum - < 2G (then block layer fragments to bl.max_pdiscard). */
+ sizes[1] = QEMU_ALIGN_DOWN(BDRV_REQUEST_MAX_BYTES, sizes[0]);
+ trace_nbd_negotiate_handle_info_trim_size(sizes[0], sizes[1]);
+ cpu_to_be32s(&sizes[0]);
+ cpu_to_be32s(&sizes[1]);
+ rc = nbd_negotiate_send_info(client, NBD_INFO_TRIM_SIZE,
+ 2 * sizeof(sizes[0]), sizes, errp);
+ if (rc < 0) {
+ return rc;
+ }
+
+ /* Send NBD_INFO_ZERO_SIZE always. */
+ /* minimum - Hard-code to 4096 for now, matching preferred block.
+ * TODO: consult blk_bs(blk)->bl.pwrite_zeroes_alignment? */
+ sizes[0] = 4096;
+ /* maximum - < 2G (then block layer fragments to bl.max_pwrite_zeroes). */
+ sizes[1] = QEMU_ALIGN_DOWN(BDRV_REQUEST_MAX_BYTES, sizes[0]);
+ trace_nbd_negotiate_handle_info_zero_size(sizes[0], sizes[1]);
+ cpu_to_be32s(&sizes[0]);
+ cpu_to_be32s(&sizes[1]);
+ rc = nbd_negotiate_send_info(client, NBD_INFO_ZERO_SIZE,
+ 2 * sizeof(sizes[0]), sizes, errp);
+ if (rc < 0) {
+ return rc;
+ }
+
/* Send NBD_INFO_EXPORT always */
trace_nbd_negotiate_new_style_size_flags(exp->size,
exp->nbdflags | myflags);
@@ -46,6 +46,8 @@ nbd_negotiate_send_info(int info, const char *name, uint32_t length) "Sending NB
nbd_negotiate_handle_info_requests(int requests) "Client requested %d items of info"
nbd_negotiate_handle_info_request(int request, const char *name) "Client requested info %d (%s)"
nbd_negotiate_handle_info_block_size(uint32_t minimum, uint32_t preferred, uint32_t maximum) "advertising minimum 0x%" PRIx32 ", preferred 0x%" PRIx32 ", maximum 0x%" PRIx32
+nbd_negotiate_handle_info_trim_size(uint32_t minimum, uint32_t maximum) "advertising minimum 0x%" PRIx32 ", maximum 0x%" PRIx32
+nbd_negotiate_handle_info_zero_size(uint32_t minimum, uint32_t maximum) "advertising minimum 0x%" PRIx32 ", maximum 0x%" PRIx32
nbd_negotiate_handle_starttls(void) "Setting up TLS"
nbd_negotiate_handle_starttls_handshake(void) "Starting TLS handshake"
nbd_negotiate_meta_context(const char *optname, const char *export, uint32_t queries) "Client requested %s for export %s, with %" PRIu32 " queries"
The NBD spec is clarifying [1] that a server may want to advertise different limits for READ/WRITE (in our case, 32M) than for TRIM/ZERO (in our case, nearly 4G). Implement the server side support for these alternate limits, by always advertising the new information (a compliant client must ignore a gratuitous advertisement if it is unknown). [1] https://lists.debian.org/nbd/2018/03/msg00048.html Signed-off-by: Eric Blake <eblake@redhat.com> --- The given URL for the NBD spec was v3; it will change to be a v4 version of that patch in part to point back to this qemu commit as a proof of implementation. --- nbd/server.c | 30 ++++++++++++++++++++++++++++++ nbd/trace-events | 2 ++ 2 files changed, 32 insertions(+)